hydrogen 1.2.6
main.cpp
Go to the documentation of this file.
1/*
2 * Hydrogen
3 * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
4 * Copyright(c) 2008-2025 The hydrogen development team [hydrogen-devel@lists.sourceforge.net]
5 *
6 * http://www.hydrogen-music.org
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY, without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see https://www.gnu.org/licenses
20 *
21 */
22
23#include <core/config.h>
24#include <core/Version.h>
26#include <getopt.h>
27
28#include <QtGui>
29#include <QtWidgets>
30#include <QLibraryInfo>
31#include <QProcess>
32#include <QSslSocket>
33
34#ifndef H2CORE_HAVE_QT6
35 #include <QTextCodec>
36#endif
37
38#include "ShotList.h"
39#include "SplashScreen.h"
40#include "HydrogenApp.h"
41#include "MainForm.h"
43#include "Parser.h"
44#include "Skin.h"
45#include "Reporter.h"
46
47#ifdef H2CORE_HAVE_LASH
49#endif
50
51#ifdef WIN32
52#include <windows.h>
53#include <stdio.h>
54#endif
55
56#include <core/MidiMap.h>
58#include <core/Hydrogen.h>
59#include <core/Globals.h>
60#include <core/EventQueue.h>
62#include <core/H2Exception.h>
66#include <core/Logger.h>
67#include <core/Version.h>
68
69#ifdef H2CORE_HAVE_OSC
70#include <core/NsmClient.h>
71#endif
72
73#include <signal.h>
74#include <iostream>
75#include <map>
76#include <set>
77
78#ifdef HAVE_EXECINFO_H
79#include <execinfo.h>
80#endif
81
82namespace H2Core {
84};
85
86// Handle a fatal signal, allowing the logger to complete any outstanding messages before re-raising the
87// signal to allow normal termination.
88static void handleFatalSignal( int nSignal )
89{
90 // First disable signal handler to allow normal termination
91 signal( nSignal, SIG_DFL );
92
93 // Report current context to the crash reporter
95
96 ___ERRORLOG( QString( "Fatal signal %1" ).arg( nSignal ) );
97
98#ifdef HAVE_EXECINFO_H
99 // Print out stack backtrace if we can
100 const int nMaxFrames = 128;
101 void *frames[ nMaxFrames ];
102 int nFrames = backtrace( frames, nMaxFrames );
103 char **symbols = backtrace_symbols( frames, nFrames );
104 for ( int i = 0; i < nFrames; i++ ) {
105 ___ERRORLOG( QString("%1").arg( symbols[i] ) );
106 }
107#endif
108
109 // Allow logger to complete
111 if ( pLogger ) {
112 delete pLogger;
113 }
114
115 raise( nSignal );
116}
117
119{
120#ifndef WIN32
121 struct sigaction usr1;
122
123 usr1.sa_handler = MainForm::usr1SignalHandler;
124 sigemptyset(&usr1.sa_mask);
125 usr1.sa_flags = 0;
126 usr1.sa_flags |= SA_RESTART;
127
128 if (sigaction(SIGUSR1, &usr1, nullptr) > 0) {
129 return 1;
130 }
131
132#endif
133
134 for ( int nSignal : { SIGSEGV, SIGILL, SIGFPE, SIGABRT,
135#ifndef WIN32
136 SIGBUS, SIGTRAP
137#endif
138 } ) {
139 signal( nSignal, handleFatalSignal );
140 }
141
142 return 0;
143}
144
145static void setApplicationIcon(QApplication *app)
146{
147 QIcon icon;
148 icon.addFile(Skin::getImagePath() + "/icon16.png", QSize(16, 16));
149 icon.addFile(Skin::getImagePath() + "/icon24.png", QSize(24, 24));
150 icon.addFile(Skin::getImagePath() + "/icon32.png", QSize(32, 32));
151 icon.addFile(Skin::getImagePath() + "/icon48.png", QSize(48, 48));
152 icon.addFile(Skin::getImagePath() + "/icon64.png", QSize(64, 64));
153 app->setWindowIcon(icon);
154}
155
156
157// QApplication class.
158class H2QApplication : public QApplication {
159
161 QWidget *m_pMainForm;
162
163public:
164 H2QApplication( int &argc, char **argv )
165 : QApplication(argc, argv) {
166 m_pMainForm = nullptr;
167 }
168
169 bool event( QEvent *e ) override
170 {
171 if ( e->type() == QEvent::FileOpen ) {
172 QFileOpenEvent *fe = dynamic_cast<QFileOpenEvent*>( e );
173 assert( fe != nullptr );
174
175 if ( m_pMainForm ) {
176 // Forward to MainForm if it's initialised and ready to handle a FileOpenEvent.
177 QApplication::sendEvent( m_pMainForm, e );
178 } else {
179 // Keep requested file until ready
180 m_sInitialFileOpen = fe->file();
181 }
182 return true;
183 }
184 return QApplication::event( e );
185 }
186
187 // Set the MainForm pointer and forward any requested open event.
188 void setMainForm( QWidget *pMainForm )
189 {
190 m_pMainForm = pMainForm;
191 if ( !m_sInitialFileOpen.isEmpty() ) {
192 QFileOpenEvent ev( m_sInitialFileOpen );
193 QApplication::sendEvent( m_pMainForm, &ev );
194
195 }
196 }
197};
198
199
200
201
202int main(int argc, char *argv[])
203{
204
205#ifdef WIN32
206 // In case Hydrogen was started using a CLI attach its output to
207 // the latter.
208 if ( AttachConsole(ATTACH_PARENT_PROCESS)) {
209 freopen("CONOUT$", "w", stdout);
210 freopen("CONOUT$", "w", stderr);
211 freopen("CONIN$", "w", stdin);
212 }
213#endif
214 Reporter::spawn( argc, argv );
215 try {
216#ifndef H2CORE_HAVE_QT6
217 #if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)
218 QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
219 QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
220 #endif
221#endif
222 // Create bootstrap QApplication to get H2 Core set up with correct Filesystem paths before starting GUI application.
223 QCoreApplication *pBootStrApp = new QCoreApplication( argc, argv );
224
225 Parser parser;
226 if ( ! parser.parse( argc, argv ) ) {
227 std::cerr << "Error: Unable to parse CLI arguments. Abort..."
228 << std::endl;
229 exit( 1 );
230 }
231
232 QString sSongFilename = parser.getSongFilename();
233
234 std::cout << H2Core::getAboutText().toStdString();
235
237 QString sInitialisingCrashContext( "Initialising Hydrogen" );
238 H2Core::Logger::setCrashContext( &sInitialisingCrashContext );
239
240 // Man your battle stations... this is not a drill.
241 auto pLogger = H2Core::Logger::bootstrap(
242 parser.getLogLevel(), parser.getLogFile(), true,
243 parser.getLogTimestamps(), parser.getLogColors() );
245 pLogger, pLogger->should_log( H2Core::Logger::Debug ) );
246
248 pLogger, parser.getSysDataPath(), parser.getUsrDataPath(),
249 parser.getConfigFilePath(), parser.getLogFile() );
252 // See below for H2Core::Hydrogen.
253
254 ___INFOLOG( QString("Using QT version ") + QString( qVersion() ) );
255#ifdef H2CORE_HAVE_QT6
256 const QString sEncoding = QLocale::system().name();
257#else
258 const QString sEncoding = QTextCodec::codecForLocale()->name();
259#endif
260 ___INFOLOG( QString( "System encoding: [%1]" ).arg( sEncoding ) );
261 ___INFOLOG( "Using data path: " + H2Core::Filesystem::sys_data_path() );
262
264 pPref->setH2ProcessName( QString(argv[0]) );
265
266#if QT_VERSION >= QT_VERSION_CHECK( 5, 14, 0)
267 /* Apply user-specified rounding policy. This is mostly to handle non-integral factors on Windows. */
268 Qt::HighDpiScaleFactorRoundingPolicy policy;
269
270 switch ( pPref->getUIScalingPolicy() ) {
272 policy = Qt::HighDpiScaleFactorRoundingPolicy::RoundPreferFloor;
273 break;
275 policy = Qt::HighDpiScaleFactorRoundingPolicy::PassThrough;
276 break;
278 policy = Qt::HighDpiScaleFactorRoundingPolicy::Ceil;
279 break;
280 }
281 QGuiApplication::setHighDpiScaleFactorRoundingPolicy( policy );
282#endif
283
284 // Force layout
285 if ( ! parser.getUiLayout().isEmpty() ) {
286 if ( parser.getUiLayout() == "tabbed" ) {
288 } else {
290 }
291 }
292
293 if ( parser.getOscPort() != -1 ) {
294 pPref->m_nOscTemporaryPort = parser.getOscPort();
295 }
296
297#ifdef H2CORE_HAVE_LASH
298
299 LashClient::create_instance("hydrogen", "Hydrogen", &argc, &argv);
300 LashClient* pLashClient = LashClient::get_instance();
301
302#endif
303 if( ! parser.getInstallDrumkitPath().isEmpty() ){
305 ___ERRORLOG( QString( "Unable to install drumkit [%1]" )
306 .arg( parser.getInstallDrumkitPath() ) );
307 exit( 1 );
308 }
309 exit( 0 );
310 }
311
312 if ( ! parser.getAudioDriver().isEmpty() ) {
313 pPref->m_audioDriver =
315 }
316
317 delete pBootStrApp;
318 H2QApplication* pQApp = new H2QApplication( argc, argv );
319 pQApp->setApplicationName( "Hydrogen" );
320 pQApp->setApplicationVersion( QString::fromStdString( H2Core::get_version() ) );
321
322 // Process any pending events before showing splash screen. This allows macOS to show previous-crash
323 // warning dialogs before they are covered by the splash screen.
324 pQApp->processEvents();
325
326 QString family = pPref->getApplicationFontFamily();
327 pQApp->setFont( QFont( family, 10 ) );
328
329 QTranslator qttor( nullptr );
330 QTranslator tor( nullptr );
331 QLocale locale = QLocale::system();
332 if ( locale != QLocale::c() ) {
333 QStringList languages;
334 QString sPreferredLanguage = pPref->getPreferredLanguage();
335 if ( !sPreferredLanguage.isNull() ) {
336 languages << sPreferredLanguage;
337 }
338 languages << locale.uiLanguages();
339 if ( H2Core::Translations::loadTranslation( languages, qttor, QString( "qt" ),
340#ifdef H2CORE_HAVE_QT6
341 QLibraryInfo::path(QLibraryInfo::TranslationsPath) ) ) {
342#else
343 QLibraryInfo::location(QLibraryInfo::TranslationsPath) ) ) {
344#endif
345 pQApp->installTranslator( &qttor );
346 } else {
347 ___INFOLOG( QString("Warning: No Qt translation for locale %1 found.").arg(locale.name()));
348 }
349
350 QString sTranslationPath = H2Core::Filesystem::i18n_dir();
351 QString sTranslationFile( "hydrogen" );
352 bool bTransOk = H2Core::Translations::loadTranslation( languages, tor, sTranslationFile, sTranslationPath );
353 if (bTransOk) {
354 ___INFOLOG( "Using locale: " + sTranslationPath );
355 } else {
356 ___INFOLOG( "Warning: no locale found: " + sTranslationPath );
357 }
358 if (tor.isEmpty()) {
359 ___INFOLOG( "Warning: error loading locale: " + sTranslationPath );
360 }
361 }
362 pQApp->installTranslator( &tor );
363
364 QString sStyle = pPref->getQTStyle();
365 if ( !sStyle.isEmpty() ) {
366 pQApp->setStyle( sStyle );
367 }
368
369 Skin::setPalette( pQApp );
370 setApplicationIcon(pQApp);
371
372 if ( ! pPref->getLoadingSuccessful() ) {
373
374 QMessageBox::critical( nullptr, "Hydrogen",
375 QString( QT_TRANSLATE_NOOP( "Startup", "No [hydrogen.conf] file found. Hydrogen was not installed properly. Aborting..." ) ) );
376
377 // Neither the Preferences on system level nor the ones at
378 // user level could be loaded successfully. Hydrogen was
379 // most probably not installed properly. Abort.
380 delete pQApp;
381 delete pPref;
382
383 delete MidiMap::get_instance();
384
385 ___ERRORLOG( "No preferences file found. Aborting..." );
387
388 exit( 1 );
389 }
390
391#ifdef H2CORE_HAVE_APPIMAGE
392 // Within an AppImage we provide our own version of Qt. But we
393 // also have to ensure to provide an OpenSSL shared object
394 // compatible with that particular version. As shipping
395 // `libssl.so` and `libcrypto.so` is discouraged and
396 // blacklisted by `linuxdeploy-qt`, we manually put them in
397 // the application folder. This way Qt tries to load the
398 // system's libraries first and only falls back to the ones we
399 // provide in case it couldn't find it.
400 //
401 // With the following logs we can determine if a fallback did
402 // happen.
403
404 QString sCurrentDir = QDir::currentPath();
405 QDir::setCurrent( QCoreApplication::applicationDirPath() );
406 QProcess process;
407 process.start( "openssl", QStringList( "version" ));
408 process.waitForFinished(-1);
409 QString sStdout = process.readAllStandardOutput();
410 ___INFOLOG( QString( "current: %1, application: %2" ).arg( sCurrentDir )
411 .arg( QCoreApplication::applicationDirPath() ) );
412 ___INFOLOG( QString( "OpenSSL supported: [%1], version OS: [%2], Qt runtime: [%3], Qt build: [%4]" )
413 .arg( QSslSocket::supportsSsl() )
414 .arg( sStdout.trimmed() )
415 .arg( QSslSocket::sslLibraryVersionString() )
416 .arg( QSslSocket::sslLibraryBuildVersionString() ) );
417 QDir::setCurrent( sCurrentDir );
418#endif
419
420 SplashScreen *pSplash = new SplashScreen();
421
422#ifdef H2CORE_HAVE_OSC
423 // Check for being under session management without the
424 // NsmClient class available yet.
425 if ( parser.getNoSplashScreen() || getenv( "NSM_URL" ) ) {
426 pSplash->hide();
427 }
428 else {
429 pSplash->show();
430 }
431#endif
432#ifndef H2CORE_HAVE_OSC
433 pSplash->show();
434#endif
435
436#ifdef H2CORE_HAVE_LASH
437 if ( H2Core::Preferences::get_instance()->useLash() ){
438 if (pLashClient->isConnected())
439 {
440 lash_event_t* lash_event = pLashClient->getNextEvent();
441 if (lash_event && lash_event_get_type(lash_event) == LASH_Restore_File)
442 {
443 // notify client that this project was not a new one
444 pLashClient->setNewProject(false);
445
446 sSongFilename = "";
447 sSongFilename.append( QString::fromLocal8Bit(lash_event_get_string(lash_event)) );
448 sSongFilename.append("/hydrogen.h2song");
449
450 //H2Core::Logger::get_instance()->log("[LASH] Restore file: " + sSongFilename);
451
452 lash_event_destroy(lash_event);
453 }
454 else if (lash_event)
455 {
456 //H2Core::Logger::get_instance()->log("[LASH] ERROR: Instead of restore file got event: " + lash_event_get_type(lash_event));
457 lash_event_destroy(lash_event);
458 }
459 }
460 }
461#endif
462
463 // Hydrogen here to honor all preferences.
465 auto pHydrogen = H2Core::Hydrogen::get_instance();
466
467 // Tell Hydrogen it was started via the QT5 GUI.
468 pHydrogen->setGUIState( H2Core::Hydrogen::GUIState::notReady );
469
470 pHydrogen->startNsmClient();
471
472 // If the NSM_URL variable is present, Hydrogen will not
473 // initialize the audio driver and leaves this to the callback
474 // function nsm_open_cb of the NSM client (which will be
475 // called by now). However, the presence of the environmental
476 // variable does not guarantee for a session management and if
477 // no audio driver is initialized yet, we will do it here.
478 if ( pHydrogen->getAudioOutput() == nullptr ) {
479 // Starting drivers can take some time, so show the wait cursor to let the user know that, yes,
480 // we're definitely busy.
481 QApplication::setOverrideCursor( Qt::WaitCursor );
482 pHydrogen->restartDrivers();
483 QApplication::restoreOverrideCursor();
484 }
485
486 MainForm *pMainForm = new MainForm( pQApp, sSongFilename );
487 auto pHydrogenApp = HydrogenApp::get_instance();
488 pMainForm->show();
489
490 pSplash->finish( pMainForm );
491
492 if( ! parser.getPlaylistFilename().isEmpty() ){
493 bool bLoadlist = pHydrogenApp->getPlayListDialog()->loadListByFileName(
494 parser.getPlaylistFilename() );
495 if ( bLoadlist ){
497 } else {
498 ___ERRORLOG ( "Error loading the playlist" );
499 }
500 }
501
502
503 if( ! parser.getDrumkitToLoad().isEmpty() ) {
504 pHydrogen->getCoreActionController()->setDrumkit(
505 parser.getDrumkitToLoad() );
506 }
507
508 // Write the changes in the Preferences to disk to make them
509 // accessible in the PreferencesDialog.
510 pPref->savePreferences();
511
512 pQApp->setMainForm( pMainForm );
513
514 // Tell the core that the GUI is now fully loaded and ready.
515 pHydrogen->setGUIState( H2Core::Hydrogen::GUIState::ready );
516
517 if ( ! parser.getShotList().isEmpty() ) {
518 ShotList *sl = new ShotList( parser.getShotList() );
519 sl->shoot();
520 }
521
522 // All GUI setup is complete, any spurious widget-driven
523 // flagging of song modified state will be complete, so clear
524 // the modification flag. This does not apply in case we are
525 // restoring unsaved changes applied to an empty song during
526 // the previous session.
527 if ( pHydrogen->getSong()->getFilename() !=
529#ifdef H2CORE_HAVE_OSC
530 // Mark empty song created in a new NSM session modified
531 // in order to emphasis that an initial song save is
532 // required to generate the song file and link the
533 // associated drumkit in the session folder.
534 if ( NsmClient::get_instance() != nullptr &&
535 NsmClient::get_instance()->getIsNewSession() ) {
536
538 pHydrogen->setIsModified( true );
539 }
540 else {
542 pHydrogen->setIsModified( false );
543 }
544#else
545 pHydrogen->setIsModified( false );
546#endif
547 }
548
550
551 pQApp->exec();
552
553 QString sShutdownCrashContext( "Shutting down Hydrogen" );
554 H2Core::Logger::setCrashContext( &sShutdownCrashContext );
555
556 pPref->savePreferences();
557 delete pSplash;
558 delete pMainForm;
559 delete pQApp;
560 delete pPref;
562
563 delete MidiMap::get_instance();
565
566 ___INFOLOG( "Quitting..." );
567 std::cout << "\nBye..." << std::endl;
569
572 }
573
574 }
575 catch ( const H2Core::H2Exception& ex ) {
576 std::cerr << "[main] Exception: " << ex.what() << std::endl;
577 return 1;
578 }
579 catch (...) {
580 std::cerr << "[main] Unknown exception X-(" << std::endl;
581 return 1;
582 }
583
584 return 0;
585}
586
#define ___INFOLOG(x)
Definition Object.h:258
#define ___ERRORLOG(x)
Definition Object.h:260
static void write_objects_map_to_cerr()
output objects map to stderr
Definition Object.h:95
static bool count_active()
Definition Object.h:85
static int bootstrap(Logger *logger, bool count=false)
must be called before any Object instantiation !
Definition Object.cpp:66
static bool install(const QString &sSourcePath, const QString &sTargetPath="", QString *pInstalledPath=nullptr, bool *pEncodingIssuesDetected=nullptr, bool bSilent=false)
Extract a .h2drumkit file.
Definition Drumkit.cpp:721
static EventQueue * get_instance()
Returns a pointer to the current EventQueue singleton stored in __instance.
Definition EventQueue.h:224
static QString sys_data_path()
returns system data path
static bool bootstrap(Logger *logger, const QString &sSysDataPath="", const QString &sUsrDataPath="", const QString &sUserConfigFile="", const QString &sLogFile="")
check user and system filesystem usability
static QString empty_song_path()
Provides the full path to the current empty song.
static QString i18n_dir()
returns internationalization path
@ notReady
There is a GUI but it is not ready yet (during startup).
Definition Hydrogen.h:401
@ ready
There is a working GUI.
Definition Hydrogen.h:405
static void create_instance()
Creates all the instances used within Hydrogen in the right order.
Definition Hydrogen.cpp:184
static Hydrogen * get_instance()
Returns the current Hydrogen instance __instance.
Definition Hydrogen.h:84
Class for writing logs to the console.
Definition Logger.h:41
static Logger * bootstrap(unsigned msk, const QString &sLogFilePath=QString(), bool bUseStdout=true, bool bLogTimestamps=false, bool bLogColors=true)
create the logger instance if not exists, set the log level and return the instance
Definition Logger.cpp:136
static Logger * get_instance()
Returns a pointer to the current H2Core::Logger singleton stored in __instance.
Definition Logger.h:81
static void setCrashContext(QString *pContext)
Definition Logger.h:144
void setNextSongByNumber(int SongNumber)
Definition Playlist.cpp:207
static Playlist * get_instance()
Returns a pointer to the current Playlist singleton stored in __instance.
Definition Playlist.h:60
Manager for User Preferences File (singleton)
Definition Preferences.h:79
static AudioDriver parseAudioDriver(const QString &sDriver)
static Preferences * get_instance()
Returns a pointer to the current Preferences singleton stored in __instance.
const QString & getApplicationFontFamily() const
const QString & getQTStyle()
bool savePreferences()
Save the preferences file.
static void create_instance()
If __instance equals 0, a new Preferences singleton will be created and stored in it.
AudioDriver m_audioDriver
Audio driver.
const QString & getPreferredLanguage()
bool getLoadingSuccessful() const
InterfaceTheme::ScalingPolicy getUIScalingPolicy()
void setDefaultUILayout(InterfaceTheme::Layout layout)
int m_nOscTemporaryPort
In case m_nOscServerPort is already occupied by another client, the alternative - random - port numbe...
void setH2ProcessName(const QString &processName)
static bool loadTranslation(QStringList languages, QTranslator &tor, QString sFileName, QString sDirectory=H2Core::Filesystem::i18n_dir())
QString m_sInitialFileOpen
Definition main.cpp:160
QWidget * m_pMainForm
Definition main.cpp:161
bool event(QEvent *e) override
Definition main.cpp:169
H2QApplication(int &argc, char **argv)
Definition main.cpp:164
void setMainForm(QWidget *pMainForm)
Definition main.cpp:188
static HydrogenApp * get_instance()
Returns the instance of HydrogenApp class.
static void create_instance(const char *lashClass, const char *viewName, int *argc, char ***argv)
static reference of LashClient class (Singleton)
lash_event_t * getNextEvent()
bool isConnected()
static LashClient * get_instance()
Definition LashClient.h:39
void setNewProject(bool value)
debug only
Definition MainForm.h:47
static void usr1SignalHandler(int unused)
static MidiActionManager * get_instance()
Returns a pointer to the current MidiActionManager singleton stored in __instance.
Definition MidiAction.h:255
static void create_instance()
If __instance equals 0, a new MidiMap singleton will be created and stored in it.
Definition MidiMap.cpp:64
static MidiMap * get_instance()
Returns a pointer to the current MidiMap singleton stored in __instance.
Definition MidiMap.h:65
void sendDirtyState(const bool isDirty)
Informs the NSM server whether the current H2Core::Song is modified or not.
static NsmClient * get_instance()
Definition NsmClient.h:84
Reusable parser for provided command line arguments.
Definition Parser.h:46
int getOscPort() const
Definition Parser.h:82
bool getLogColors() const
Definition Parser.h:72
const QString & getUiLayout() const
Definition Parser.h:80
const QString & getLogFile() const
Definition Parser.h:68
const QString & getShotList() const
Definition Parser.h:87
const QString & getSysDataPath() const
Definition Parser.h:74
const QString & getDrumkitToLoad() const
Definition Parser.h:60
unsigned getLogLevel() const
Definition Parser.h:66
const QString & getInstallDrumkitPath() const
Definition Parser.h:63
const QString & getSongFilename() const
Definition Parser.h:58
const QString & getAudioDriver() const
Definition Parser.h:54
bool getNoSplashScreen() const
Definition Parser.h:84
bool parse(int argc, char *argv[])
Definition Parser.cpp:40
bool getLogTimestamps() const
Definition Parser.h:70
const QString & getPlaylistFilename() const
Definition Parser.h:56
const QString & getConfigFilePath() const
Definition Parser.h:78
const QString & getUsrDataPath() const
Definition Parser.h:76
static void report(void)
Report some crash details in a crashing child (mostly, the Logger 'crash context' string)
Definition Reporter.cpp:98
static void spawn(int argc, char *argv[])
Potentially spawn child process.
Definition Reporter.cpp:225
Shot List.
Definition ShotList.h:53
void shoot(QString s)
Definition ShotList.cpp:91
static void setPalette(QApplication *pQApp)
Function used to update the global palette of the QApplication.
Definition Skin.cpp:106
static QString getImagePath()
Definition Skin.h:36
int main(int argc, char *argv[])
Definition main.cpp:202
static int setup_unix_signal_handlers()
Definition main.cpp:118
static void setApplicationIcon(QApplication *app)
Definition main.cpp:145
static void handleFatalSignal(int nSignal)
Definition main.cpp:88
QString getAboutText()
Definition Version.cpp:54
std::string get_version()
Returns the current Hydrogen version string.
Definition Version.cpp:30
void init_gui_object_map()