1 #include "util/cmdlineargs.h"
2 
3 #include <stdio.h>
4 
5 #include <QStandardPaths>
6 
7 #include "config.h"
8 #include "defs_urls.h"
9 #include "sources/soundsourceproxy.h"
10 #include "util/versionstore.h"
11 
CmdlineArgs()12 CmdlineArgs::CmdlineArgs()
13         : m_startInFullscreen(false), // Initialize vars
14           m_midiDebug(false),
15           m_developer(false),
16           m_safeMode(false),
17           m_debugAssertBreak(false),
18           m_settingsPathSet(false),
19           m_logLevel(mixxx::kLogLevelDefault),
20           m_logFlushLevel(mixxx::kLogFlushLevelDefault),
21 // We are not ready to switch to XDG folders under Linux, so keeping $HOME/.mixxx as preferences folder. see lp:1463273
22 #ifdef MIXXX_SETTINGS_PATH
23           m_settingsPath(QDir::homePath().append("/").append(MIXXX_SETTINGS_PATH)) {
24 #else
25 #ifdef __LINUX__
26 #error "We are not ready to switch to XDG folders under Linux"
27 #endif
28 
29           // TODO(XXX) Trailing slash not needed anymore as we switches from String::append
30           // to QDir::filePath elsewhere in the code. This is candidate for removal.
31           m_settingsPath(
32                   QStandardPaths::writableLocation(QStandardPaths::DataLocation)
33                           .append("/")) {
34 #endif
35 }
36 
37 bool CmdlineArgs::Parse(int &argc, char **argv) {
38     bool logLevelSet = false;
39     for (int i = 0; i < argc; ++i) {
40         if (   argv[i] == QString("-h")
41             || argv[i] == QString("--h")
42             || argv[i] == QString("--help")) {
43             return false; // Display Help Message
44         }
45 
46         if (argv[i]==QString("-f").toLower() || argv[i]==QString("--f") || argv[i]==QString("--fullScreen"))
47         {
48             m_startInFullscreen = true;
49         } else if (argv[i] == QString("--locale") && i+1 < argc) {
50             m_locale = argv[i+1];
51         } else if (argv[i] == QString("--settingsPath") && i+1 < argc) {
52             m_settingsPath = QString::fromLocal8Bit(argv[i+1]);
53             // TODO(XXX) Trailing slash not needed anymore as we switches from String::append
54             // to QDir::filePath elsewhere in the code. This is candidate for removal.
55             if (!m_settingsPath.endsWith("/")) {
56                 m_settingsPath.append("/");
57             }
58             m_settingsPathSet = true;
59         } else if (argv[i] == QString("--resourcePath") && i+1 < argc) {
60             m_resourcePath = QString::fromLocal8Bit(argv[i+1]);
61             i++;
62         } else if (argv[i] == QString("--timelinePath") && i+1 < argc) {
63             m_timelinePath = QString::fromLocal8Bit(argv[i+1]);
64             i++;
65         } else if (argv[i] == QString("--logLevel") && i+1 < argc) {
66             logLevelSet = true;
67             auto level = QLatin1String(argv[i+1]);
68             if (level == "trace") {
69                 m_logLevel = mixxx::LogLevel::Trace;
70             } else if (level == "debug") {
71                 m_logLevel = mixxx::LogLevel::Debug;
72             } else if (level == "info") {
73                 m_logLevel = mixxx::LogLevel::Info;
74             } else if (level == "warning") {
75                 m_logLevel = mixxx::LogLevel::Warning;
76             } else if (level == "critical") {
77                 m_logLevel = mixxx::LogLevel::Critical;
78             } else {
79                 fputs("\nlogLevel argument wasn't 'trace', 'debug', 'info', 'warning', or 'critical'! Mixxx will only output\n\
80 warnings and errors to the console unless this is set properly.\n", stdout);
81             }
82             i++;
83         } else if (argv[i] == QString("--logFlushLevel") && i+1 < argc) {
84             auto level = QLatin1String(argv[i+1]);
85             if (level == "trace") {
86                 m_logFlushLevel = mixxx::LogLevel::Trace;
87             } else if (level == "debug") {
88                 m_logFlushLevel = mixxx::LogLevel::Debug;
89             } else if (level == "info") {
90                 m_logFlushLevel = mixxx::LogLevel::Info;
91             } else if (level == "warning") {
92                 m_logFlushLevel = mixxx::LogLevel::Warning;
93             } else if (level == "critical") {
94                 m_logFlushLevel = mixxx::LogLevel::Critical;
95             } else {
96                 fputs("\nlogFushLevel argument wasn't 'trace', 'debug', 'info', 'warning', or 'critical'! Mixxx will only flush messages to mixxx.log\n\
97 when a critical error occurs unless this is set properly.\n", stdout);
98             }
99             i++;
100         } else if (QString::fromLocal8Bit(argv[i]).contains("--midiDebug", Qt::CaseInsensitive) ||
101                    QString::fromLocal8Bit(argv[i]).contains("--controllerDebug", Qt::CaseInsensitive)) {
102             m_midiDebug = true;
103         } else if (QString::fromLocal8Bit(argv[i]).contains("--developer", Qt::CaseInsensitive)) {
104             m_developer = true;
105         } else if (QString::fromLocal8Bit(argv[i]).contains("--safeMode", Qt::CaseInsensitive)) {
106             m_safeMode = true;
107         } else if (QString::fromLocal8Bit(argv[i]).contains("--debugAssertBreak", Qt::CaseInsensitive)) {
108             m_debugAssertBreak = true;
109         } else if (i > 0) {
110             // Don't try to load the program name to a deck
111             m_musicFiles += QString::fromLocal8Bit(argv[i]);
112         }
113     }
114 
115     // If --logLevel was unspecified and --developer is enabled then set
116     // logLevel to debug.
117     if (m_developer && !logLevelSet) {
118         m_logLevel = mixxx::LogLevel::Debug;
119     }
120 
121     return true;
122 }
123 
124 void CmdlineArgs::printUsage() {
125     fputs(VersionStore::applicationName().toLocal8Bit().constData(), stdout);
126     fputs(" v", stdout);
127     fputs(VersionStore::version().toLocal8Bit().constData(), stdout);
128     fputs(" - Command line options", stdout);
129     fputs("\n(These are case-sensitive.)\n\n\
130 [FILE]                  Load the specified music file(s) at start-up.\n\
131                         Each file you specify will be loaded into the\n\
132                         next virtual deck.\n", stdout);
133     fputs("\
134 \n\
135 --resourcePath PATH     Top-level directory where Mixxx should look\n\
136                         for its resource files such as MIDI mappings,\n\
137                         overriding the default installation location.\n\
138 \n\
139 --settingsPath PATH     Top-level directory where Mixxx should look\n\
140                         for settings. Default is:\n", stdout);
141     fprintf(stdout, "\
142                         %s\n", getSettingsPath().toLocal8Bit().constData());
143     fputs("\
144 \n\
145 --controllerDebug       Causes Mixxx to display/log all of the controller\n\
146                         data it receives and script functions it loads\n\
147 \n\
148 --developer             Enables developer-mode. Includes extra log info,\n\
149                         stats on performance, and a Developer tools menu.\n\
150 \n\
151 --safeMode              Enables safe-mode. Disables OpenGL waveforms,\n\
152                         and spinning vinyl widgets. Try this option if\n\
153                         Mixxx is crashing on startup.\n\
154 \n\
155 --locale LOCALE         Use a custom locale for loading translations\n\
156                         (e.g 'fr')\n\
157 \n\
158 -f, --fullScreen        Starts Mixxx in full-screen mode\n\
159 \n\
160 --logLevel LEVEL        Sets the verbosity of command line logging\n\
161                         critical - Critical/Fatal only\n\
162                         warning  - Above + Warnings\n\
163                         info     - Above + Informational messages\n\
164                         debug    - Above + Debug/Developer messages\n\
165                         trace    - Above + Profiling messages\n\
166 \n\
167 --logFlushLevel LEVEL   Sets the the logging level at which the log buffer\n\
168                         is flushed to mixxx.log. LEVEL is one of the values\n\
169                         defined at --logLevel above.\n\
170 \n"
171 #ifdef MIXXX_BUILD_DEBUG
172 "\
173 --debugAssertBreak      Breaks (SIGINT) Mixxx, if a DEBUG_ASSERT\n\
174                         evaluates to false. Under a debugger you can\n\
175                         continue afterwards.\
176 \n"
177 #endif
178 "\
179 -h, --help              Display this help message and exit", stdout);
180 
181     fputs("\n\n(For more information, see " MIXXX_MANUAL_COMMANDLINEOPTIONS_URL ")\n", stdout);
182 }
183