hydrogen 1.2.3
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-2024 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 <QtGui>
24#include <QtWidgets>
25#include <QLibraryInfo>
26#include <QProcess>
27#include <QSslSocket>
28
29#include <core/config.h>
30#include <core/Version.h>
32#include <getopt.h>
33
34#include "ShotList.h"
35#include "SplashScreen.h"
36#include "HydrogenApp.h"
37#include "MainForm.h"
39#include "Skin.h"
40#include "Reporter.h"
41
42#ifdef H2CORE_HAVE_LASH
44#endif
45
46#ifdef WIN32
47#include <windows.h>
48#include <stdio.h>
49#endif
50
51#include <core/MidiMap.h>
53#include <core/Hydrogen.h>
54#include <core/Globals.h>
55#include <core/EventQueue.h>
57#include <core/H2Exception.h>
61#include <core/Logger.h>
62
63#ifdef H2CORE_HAVE_OSC
64#include <core/NsmClient.h>
65#endif
66
67#include <signal.h>
68#include <iostream>
69#include <map>
70#include <set>
71
72#ifdef HAVE_EXECINFO_H
73#include <execinfo.h>
74#endif
75
76namespace H2Core {
78};
79
80// Handle a fatal signal, allowing the logger to complete any outstanding messages before re-raising the
81// signal to allow normal termination.
82static void handleFatalSignal( int nSignal )
83{
84 // First disable signal handler to allow normal termination
85 signal( nSignal, SIG_DFL );
86
87 // Report current context to the crash reporter
89
90 ___ERRORLOG( QString( "Fatal signal %1" ).arg( nSignal ) );
91
92#ifdef HAVE_EXECINFO_H
93 // Print out stack backtrace if we can
94 const int nMaxFrames = 128;
95 void *frames[ nMaxFrames ];
96 int nFrames = backtrace( frames, nMaxFrames );
97 char **symbols = backtrace_symbols( frames, nFrames );
98 for ( int i = 0; i < nFrames; i++ ) {
99 ___ERRORLOG( QString("%1").arg( symbols[i] ) );
100 }
101#endif
102
103 // Allow logger to complete
105 if ( pLogger ) {
106 delete pLogger;
107 }
108
109 raise( nSignal );
110}
111
113{
114#ifndef WIN32
115 struct sigaction usr1;
116
117 usr1.sa_handler = MainForm::usr1SignalHandler;
118 sigemptyset(&usr1.sa_mask);
119 usr1.sa_flags = 0;
120 usr1.sa_flags |= SA_RESTART;
121
122 if (sigaction(SIGUSR1, &usr1, nullptr) > 0) {
123 return 1;
124 }
125
126#endif
127
128 for ( int nSignal : { SIGSEGV, SIGILL, SIGFPE, SIGABRT,
129#ifndef WIN32
130 SIGBUS, SIGTRAP
131#endif
132 } ) {
133 signal( nSignal, handleFatalSignal );
134 }
135
136 return 0;
137}
138
139static void setApplicationIcon(QApplication *app)
140{
141 QIcon icon;
142 icon.addFile(Skin::getImagePath() + "/icon16.png", QSize(16, 16));
143 icon.addFile(Skin::getImagePath() + "/icon24.png", QSize(24, 24));
144 icon.addFile(Skin::getImagePath() + "/icon32.png", QSize(32, 32));
145 icon.addFile(Skin::getImagePath() + "/icon48.png", QSize(48, 48));
146 icon.addFile(Skin::getImagePath() + "/icon64.png", QSize(64, 64));
147 app->setWindowIcon(icon);
148}
149
150
151// QApplication class.
152class H2QApplication : public QApplication {
153
155 QWidget *m_pMainForm;
156
157public:
158 H2QApplication( int &argc, char **argv )
159 : QApplication(argc, argv) {
160 m_pMainForm = nullptr;
161 }
162
163 bool event( QEvent *e ) override
164 {
165 if ( e->type() == QEvent::FileOpen ) {
166 QFileOpenEvent *fe = dynamic_cast<QFileOpenEvent*>( e );
167 assert( fe != nullptr );
168
169 if ( m_pMainForm ) {
170 // Forward to MainForm if it's initialised and ready to handle a FileOpenEvent.
171 QApplication::sendEvent( m_pMainForm, e );
172 } else {
173 // Keep requested file until ready
174 m_sInitialFileOpen = fe->file();
175 }
176 return true;
177 }
178 return QApplication::event( e );
179 }
180
181 // Set the MainForm pointer and forward any requested open event.
182 void setMainForm( QWidget *pMainForm )
183 {
184 m_pMainForm = pMainForm;
185 if ( !m_sInitialFileOpen.isEmpty() ) {
186 QFileOpenEvent ev( m_sInitialFileOpen );
187 QApplication::sendEvent( m_pMainForm, &ev );
188
189 }
190 }
191};
192
193
194
195
196int main(int argc, char *argv[])
197{
198
199#ifdef WIN32
200 // In case Hydrogen was started using a CLI attach its output to
201 // the latter.
202 if ( AttachConsole(ATTACH_PARENT_PROCESS)) {
203 freopen("CONOUT$", "w", stdout);
204 freopen("CONOUT$", "w", stderr);
205 freopen("CONIN$", "w", stdin);
206 }
207#endif
208 Reporter::spawn( argc, argv );
209 try {
210#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)
211 QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
212 QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
213#endif
214
215 // Create bootstrap QApplication to get H2 Core set up with correct Filesystem paths before starting GUI application.
216 QCoreApplication *pBootStrApp = new QCoreApplication( argc, argv );
217 pBootStrApp->setApplicationVersion( QString::fromStdString( H2Core::get_version() ) );
218
219
220 QCommandLineParser parser;
221
222 QString aboutText = QString( "\nHydrogen " ) + QString::fromStdString( H2Core::get_version() ) + QString( " [" ) + QString::fromStdString( __DATE__ ) + QString( "] [http://www.hydrogen-music.org]" ) +
223 QString( "\nCopyright 2002-2008 Alessandro Cominu\nCopyright 2008-2024 The hydrogen development team" ) +
224 QString( "\nHydrogen comes with ABSOLUTELY NO WARRANTY\nThis is free software, and you are welcome to redistribute it under certain conditions. See the file COPYING for details.\n" );
225
226 parser.setApplicationDescription( aboutText );
227
228 QStringList availableAudioDrivers;
229#ifdef H2CORE_HAVE_JACK
230 availableAudioDrivers << "jack";
231#endif
232#ifdef H2CORE_HAVE_ALSA
233 availableAudioDrivers << "alsa";
234#endif
235#ifdef H2CORE_HAVE_OSS
236 availableAudioDrivers << "oss";
237#endif
238#ifdef H2CORE_HAVE_PULSEAUDIO
239 availableAudioDrivers << "pulseaudio";
240#endif
241#ifdef H2CORE_HAVE_PORTAUDIO
242 availableAudioDrivers << "portaudio";
243#endif
244#ifdef H2CORE_HAVE_COREAUDIO
245 availableAudioDrivers << "coreaudio";
246#endif
247 availableAudioDrivers << "auto";
248
249 QCommandLineOption audioDriverOption( QStringList() << "d" << "driver",
250 QString( "Use the selected audio driver (%1)" )
251 .arg( availableAudioDrivers.join( ", " ) ),
252 "Audiodriver");
253 QCommandLineOption installDrumkitOption( QStringList() << "i" << "install", "Install a drumkit (*.h2drumkit)" , "File");
254 QCommandLineOption noSplashScreenOption( QStringList() << "n" << "nosplash", "Hide splash screen" );
255 QCommandLineOption playlistFileNameOption( QStringList() << "p" << "playlist", "Load a playlist (*.h2playlist) at startup", "File" );
256 QCommandLineOption systemDataPathOption( QStringList() << "P" << "data", "Use an alternate system data path", "Path" );
257 QCommandLineOption songFileOption( QStringList() << "s" << "song", "Load a song (*.h2song) at startup", "File" );
258 QCommandLineOption kitOption( QStringList() << "k" << "kit", "Load a drumkit at startup", "DrumkitName" );
259 QCommandLineOption verboseOption( QStringList() << "V" << "verbose", "Level, if present, may be None, Error, Warning, Info, Debug, Constructors, Locks, or 0xHHHH", "Level" );
260 QCommandLineOption shotListOption( QStringList() << "t" << "shotlist", "Shot list of widgets to grab", "ShotList" );
261 QCommandLineOption uiLayoutOption( QStringList() << "layout", "UI layout ('tabbed' or 'single')", "Layout" );
262 QCommandLineOption noReporterOption( QStringList() << "child", "Child process (no crash reporter)");
263
264 parser.addHelpOption();
265 parser.addVersionOption();
266 parser.addOption( audioDriverOption );
267 parser.addOption( installDrumkitOption );
268 parser.addOption( noSplashScreenOption );
269 parser.addOption( playlistFileNameOption );
270 parser.addOption( systemDataPathOption );
271 parser.addOption( songFileOption );
272 parser.addOption( kitOption );
273 parser.addOption( verboseOption );
274 parser.addOption( shotListOption );
275 parser.addOption( uiLayoutOption );
276 parser.addOption( noReporterOption );
277 parser.addPositionalArgument( "file", "Song, playlist or Drumkit file" );
278
279 // Evaluate the options
280 parser.process( *pBootStrApp );
281 QString sSelectedDriver = parser.value( audioDriverOption );
282 QString sDrumkitName = parser.value( installDrumkitOption );
283 bool bNoSplash = parser.isSet( noSplashScreenOption );
284 QString sPlaylistFilename = parser.value( playlistFileNameOption );
285 QString sSysDataPath = parser.value( systemDataPathOption );
286 QString sSongFilename = parser.value ( songFileOption );
287 QString sDrumkitToLoad = parser.value( kitOption );
288 QString sVerbosityString = parser.value( verboseOption );
289 QString sShotList = parser.value( shotListOption );
290 QString sUiLayout = parser.value( uiLayoutOption );
291
292 unsigned logLevelOpt = H2Core::Logger::Error;
293 if( parser.isSet(verboseOption) ){
294 if( !sVerbosityString.isEmpty() )
295 {
296 logLevelOpt = H2Core::Logger::parse_log_level( sVerbosityString.toLocal8Bit() );
297 } else {
299 }
300 }
301
302 // Operating system GUIs typically pass documents to open as
303 // simple positional arguments to the process command
304 // line. Handling this here enables "Open with" as well as
305 // default document bindings to work.
306 QString sArg;
307 foreach ( sArg, parser.positionalArguments() ) {
308 if ( sArg.endsWith( H2Core::Filesystem::songs_ext ) ) {
309 sSongFilename = sArg;
310 }
311 if ( sArg.endsWith( H2Core::Filesystem::drumkit_ext ) ) {
312 sDrumkitName = sArg;
313 }
314 if ( sArg.endsWith( H2Core::Filesystem::playlist_ext ) ) {
315 sPlaylistFilename = sArg;
316 }
317 }
318
319 std::cout << aboutText.toStdString();
320
322 QString sInitialisingCrashContext( "Initialising Hydrogen" );
323 H2Core::Logger::setCrashContext( &sInitialisingCrashContext );
324
325 // Man your battle stations... this is not a drill.
327 H2Core::Logger::set_bit_mask( logLevelOpt );
330
331 if( sSysDataPath.length() == 0 ) {
333 } else {
334 H2Core::Filesystem::bootstrap( pLogger, sSysDataPath );
335 }
338 // See below for H2Core::Hydrogen.
339
340 ___INFOLOG( QString("Using QT version ") + QString( qVersion() ) );
341 ___INFOLOG( "Using data path: " + H2Core::Filesystem::sys_data_path() );
342
344 pPref->setH2ProcessName( QString(argv[0]) );
345
346#if QT_VERSION >= QT_VERSION_CHECK( 5, 14, 0)
347 /* Apply user-specified rounding policy. This is mostly to handle non-integral factors on Windows. */
348 Qt::HighDpiScaleFactorRoundingPolicy policy;
349
350 switch ( pPref->getUIScalingPolicy() ) {
352 policy = Qt::HighDpiScaleFactorRoundingPolicy::RoundPreferFloor;
353 break;
355 policy = Qt::HighDpiScaleFactorRoundingPolicy::PassThrough;
356 break;
358 policy = Qt::HighDpiScaleFactorRoundingPolicy::Ceil;
359 break;
360 }
361 QGuiApplication::setHighDpiScaleFactorRoundingPolicy( policy );
362#endif
363
364 // Force layout
365 if ( !sUiLayout.isEmpty() ) {
366 if ( sUiLayout == "tabbed" ) {
368 } else {
370 }
371 }
372
373#ifdef H2CORE_HAVE_LASH
374
375 LashClient::create_instance("hydrogen", "Hydrogen", &argc, &argv);
376 LashClient* pLashClient = LashClient::get_instance();
377
378#endif
379 if( ! sDrumkitName.isEmpty() ){
380 H2Core::Drumkit::install( sDrumkitName );
381 exit(0);
382 }
383
384 if ( sSelectedDriver == "auto" ) {
385 pPref->m_sAudioDriver = "Auto";
386 } else if ( sSelectedDriver == "jack" ) {
387 pPref->m_sAudioDriver = "JACK";
388 } else if ( sSelectedDriver == "oss" ) {
389 pPref->m_sAudioDriver = "OSS";
390 } else if ( sSelectedDriver == "alsa" ) {
391 pPref->m_sAudioDriver = "ALSA";
392 } else if ( sSelectedDriver == "pulseaudio" ) {
393 pPref->m_sAudioDriver = "PulseAudio";
394 } else if ( sSelectedDriver == "coreaudio" ) {
395 pPref->m_sAudioDriver = "CoreAudio";
396 } else if ( sSelectedDriver == "portaudio" ) {
397 pPref->m_sAudioDriver = "PortAudio";
398 } else if ( ! sSelectedDriver.isEmpty() ) {
399 ___WARNINGLOG( QString( "Unknown driver [%1]. The 'auto' driver will be used instead" )
400 .arg( sSelectedDriver ) );
401 pPref->m_sAudioDriver = "Auto";
402 }
403
404
405 // Bootstrap is complete, start GUI
406 delete pBootStrApp;
407 H2QApplication* pQApp = new H2QApplication( argc, argv );
408 pQApp->setApplicationName( "Hydrogen" );
409 pQApp->setApplicationVersion( QString::fromStdString( H2Core::get_version() ) );
410
411 // Process any pending events before showing splash screen. This allows macOS to show previous-crash
412 // warning dialogs before they are covered by the splash screen.
413 pQApp->processEvents();
414
415 QString family = pPref->getApplicationFontFamily();
416 pQApp->setFont( QFont( family, 10 ) );
417
418 QTranslator qttor( nullptr );
419 QTranslator tor( nullptr );
420 QLocale locale = QLocale::system();
421 if ( locale != QLocale::c() ) {
422 QStringList languages;
423 QString sPreferredLanguage = pPref->getPreferredLanguage();
424 if ( !sPreferredLanguage.isNull() ) {
425 languages << sPreferredLanguage;
426 }
427 languages << locale.uiLanguages();
428 if ( H2Core::Translations::loadTranslation( languages, qttor, QString( "qt" ),
429 QLibraryInfo::location(QLibraryInfo::TranslationsPath) ) ) {
430 pQApp->installTranslator( &qttor );
431 } else {
432 ___INFOLOG( QString("Warning: No Qt translation for locale %1 found.").arg(locale.name()));
433 }
434
435 QString sTranslationPath = H2Core::Filesystem::i18n_dir();
436 QString sTranslationFile( "hydrogen" );
437 bool bTransOk = H2Core::Translations::loadTranslation( languages, tor, sTranslationFile, sTranslationPath );
438 if (bTransOk) {
439 ___INFOLOG( "Using locale: " + sTranslationPath );
440 } else {
441 ___INFOLOG( "Warning: no locale found: " + sTranslationPath );
442 }
443 if (tor.isEmpty()) {
444 ___INFOLOG( "Warning: error loading locale: " + sTranslationPath );
445 }
446 }
447 pQApp->installTranslator( &tor );
448
449 QString sStyle = pPref->getQTStyle();
450 if ( !sStyle.isEmpty() ) {
451 pQApp->setStyle( sStyle );
452 }
453
454 Skin::setPalette( pQApp );
455 setApplicationIcon(pQApp);
456
457 if ( ! pPref->getLoadingSuccessful() ) {
458
459 QMessageBox::critical( nullptr, "Hydrogen",
460 QString( QT_TRANSLATE_NOOP( "Startup", "No [hydrogen.conf] file found. Hydrogen was not installed properly. Aborting..." ) ) );
461
462 // Neither the Preferences on system level nor the ones at
463 // user level could be loaded successfully. Hydrogen was
464 // most probably not installed properly. Abort.
465 delete pQApp;
466 delete pPref;
467
468 delete MidiMap::get_instance();
469
470 ___ERRORLOG( "No preferences file found. Aborting..." );
472
473 exit( 1 );
474 }
475
476#ifdef H2CORE_HAVE_APPIMAGE
477 // Within an AppImage we provide our own version of Qt. But we
478 // also have to ensure to provide an OpenSSL shared object
479 // compatible with that particular version. As shipping
480 // `libssl.so` and `libcrypto.so` is discouraged and
481 // blacklisted by `linuxdeploy-qt`, we manually put them in
482 // the application folder. This way Qt tries to load the
483 // system's libraries first and only falls back to the ones we
484 // provide in case it couldn't find it.
485 //
486 // With the following logs we can determine if a fallback did
487 // happen.
488
489 QString sCurrentDir = QDir::currentPath();
490 QDir::setCurrent( QCoreApplication::applicationDirPath() );
491 QProcess process;
492 process.start( "openssl", QStringList( "version" ));
493 process.waitForFinished(-1);
494 QString sStdout = process.readAllStandardOutput();
495 ___INFOLOG( QString( "current: %1, application: %2" ).arg( sCurrentDir )
496 .arg( QCoreApplication::applicationDirPath() ) );
497 ___INFOLOG( QString( "OpenSSL supported: [%1], version OS: [%2], Qt runtime: [%3], Qt build: [%4]" )
498 .arg( QSslSocket::supportsSsl() )
499 .arg( sStdout.trimmed() )
500 .arg( QSslSocket::sslLibraryVersionString() )
501 .arg( QSslSocket::sslLibraryBuildVersionString() ) );
502 QDir::setCurrent( sCurrentDir );
503#endif
504
505 SplashScreen *pSplash = new SplashScreen();
506
507#ifdef H2CORE_HAVE_OSC
508 // Check for being under session management without the
509 // NsmClient class available yet.
510 if ( bNoSplash || getenv( "NSM_URL" ) ) {
511 pSplash->hide();
512 }
513 else {
514 pSplash->show();
515 }
516#endif
517#ifndef H2CORE_HAVE_OSC
518 pSplash->show();
519#endif
520
521#ifdef H2CORE_HAVE_LASH
522 if ( H2Core::Preferences::get_instance()->useLash() ){
523 if (pLashClient->isConnected())
524 {
525 lash_event_t* lash_event = pLashClient->getNextEvent();
526 if (lash_event && lash_event_get_type(lash_event) == LASH_Restore_File)
527 {
528 // notify client that this project was not a new one
529 pLashClient->setNewProject(false);
530
531 sSongFilename = "";
532 sSongFilename.append( QString::fromLocal8Bit(lash_event_get_string(lash_event)) );
533 sSongFilename.append("/hydrogen.h2song");
534
535 //H2Core::Logger::get_instance()->log("[LASH] Restore file: " + sSongFilename);
536
537 lash_event_destroy(lash_event);
538 }
539 else if (lash_event)
540 {
541 //H2Core::Logger::get_instance()->log("[LASH] ERROR: Instead of restore file got event: " + lash_event_get_type(lash_event));
542 lash_event_destroy(lash_event);
543 }
544 }
545 }
546#endif
547
548 // Hydrogen here to honor all preferences.
550 auto pHydrogen = H2Core::Hydrogen::get_instance();
551
552 // Tell Hydrogen it was started via the QT5 GUI.
553 pHydrogen->setGUIState( H2Core::Hydrogen::GUIState::notReady );
554
555 pHydrogen->startNsmClient();
556
557 // If the NSM_URL variable is present, Hydrogen will not
558 // initialize the audio driver and leaves this to the callback
559 // function nsm_open_cb of the NSM client (which will be
560 // called by now). However, the presence of the environmental
561 // variable does not guarantee for a session management and if
562 // no audio driver is initialized yet, we will do it here.
563 if ( pHydrogen->getAudioOutput() == nullptr ) {
564 // Starting drivers can take some time, so show the wait cursor to let the user know that, yes,
565 // we're definitely busy.
566 QApplication::setOverrideCursor( Qt::WaitCursor );
567 pHydrogen->restartDrivers();
568 QApplication::restoreOverrideCursor();
569 }
570
571 MainForm *pMainForm = new MainForm( pQApp, sSongFilename );
572 auto pHydrogenApp = HydrogenApp::get_instance();
573 pMainForm->show();
574
575 pSplash->finish( pMainForm );
576
577 if( ! sPlaylistFilename.isEmpty() ){
578 bool loadlist = pHydrogenApp->getPlayListDialog()->loadListByFileName( sPlaylistFilename );
579 if ( loadlist ){
581 } else {
582 ___ERRORLOG ( "Error loading the playlist" );
583 }
584 }
585
586
587 if( ! sDrumkitToLoad.isEmpty() ) {
588 pHydrogen->getCoreActionController()->setDrumkit( sDrumkitToLoad );
589 }
590
591 // Write the changes in the Preferences to disk to make them
592 // accessible in the PreferencesDialog.
593 pPref->savePreferences();
594
595 pQApp->setMainForm( pMainForm );
596
597 // Tell the core that the GUI is now fully loaded and ready.
598 pHydrogen->setGUIState( H2Core::Hydrogen::GUIState::ready );
599
600 if ( sShotList != QString() ) {
601 ShotList *sl = new ShotList( sShotList );
602 sl->shoot();
603 }
604
605 // All GUI setup is complete, any spurious widget-driven
606 // flagging of song modified state will be complete, so clear
607 // the modification flag. This does not apply in case we are
608 // restoring unsaved changes applied to an empty song during
609 // the previous session.
610 if ( pHydrogen->getSong()->getFilename() !=
612#ifdef H2CORE_HAVE_OSC
613 // Mark empty song created in a new NSM session modified
614 // in order to emphasis that an initial song save is
615 // required to generate the song file and link the
616 // associated drumkit in the session folder.
617 if ( NsmClient::get_instance() != nullptr &&
618 NsmClient::get_instance()->getIsNewSession() ) {
619
621 pHydrogen->setIsModified( true );
622 }
623 else {
625 pHydrogen->setIsModified( false );
626 }
627#else
628 pHydrogen->setIsModified( false );
629#endif
630 }
631
633
634 pQApp->exec();
635
636 QString sShutdownCrashContext( "Shutting down Hydrogen" );
637 H2Core::Logger::setCrashContext( &sShutdownCrashContext );
638
639 pPref->savePreferences();
640 delete pSplash;
641 delete pMainForm;
642 delete pQApp;
643 delete pPref;
645
646 delete MidiMap::get_instance();
648
649 ___INFOLOG( "Quitting..." );
650 std::cout << "\nBye..." << std::endl;
652
655 }
656
657 }
658 catch ( const H2Core::H2Exception& ex ) {
659 std::cerr << "[main] Exception: " << ex.what() << std::endl;
660 }
661 catch (...) {
662 std::cerr << "[main] Unknown exception X-(" << std::endl;
663 }
664
665 return 0;
666}
667
#define ___WARNINGLOG(x)
Definition Object.h:256
#define ___INFOLOG(x)
Definition Object.h:255
#define ___ERRORLOG(x)
Definition Object.h:257
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:61
static bool install(const QString &sSourcePath, const QString &sTargetPath="", bool bSilent=false)
Extract a .h2drumkit file.
Definition Drumkit.cpp:565
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 QString empty_song_path()
Provides the full path to the current empty song.
static bool bootstrap(Logger *logger, const QString &sys_path=nullptr)
check user and system filesystem usability
static const QString playlist_ext
Definition Filesystem.h:90
static QString i18n_dir()
returns internationalization path
static const QString drumkit_ext
Definition Filesystem.h:91
static const QString songs_ext
Definition Filesystem.h:87
@ notReady
There is a GUI but it is not ready yet (during startup).
@ ready
There is a working GUI.
static void create_instance()
Creates all the instances used within Hydrogen in the right order.
Definition Hydrogen.cpp:181
static Hydrogen * get_instance()
Returns the current Hydrogen instance __instance.
Definition Hydrogen.h:83
Class for writing logs to the console.
Definition Logger.h:42
static Logger * create_instance(const QString &sLogFilePath=QString(), bool bUseStdout=true)
If __instance equals 0, a new H2Core::Logger singleton will be created and stored in it.
Definition Logger.cpp:107
bool should_log(unsigned lvl) const
return true if the level is set in the bitmask
Definition Logger.h:83
static Logger * get_instance()
Returns a pointer to the current H2Core::Logger singleton stored in __instance.
Definition Logger.h:74
static void set_bit_mask(unsigned msk)
set the bitmask
Definition Logger.h:88
static unsigned parse_log_level(const char *lvl)
parse a log level string and return the corresponding bit mask
Definition Logger.cpp:208
static void setCrashContext(QString *pContext)
Definition Logger.h:135
void setNextSongByNumber(int SongNumber)
Definition Playlist.cpp:197
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:78
static Preferences * get_instance()
Returns a pointer to the current Preferences singleton stored in __instance.
const QString & getApplicationFontFamily() const
const QString & getQTStyle()
QString m_sAudioDriver
Audio driver.
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.
const QString & getPreferredLanguage()
bool getLoadingSuccessful() const
InterfaceTheme::ScalingPolicy getUIScalingPolicy()
void setDefaultUILayout(InterfaceTheme::Layout layout)
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:154
QWidget * m_pMainForm
Definition main.cpp:155
bool event(QEvent *e) override
Definition main.cpp:163
H2QApplication(int &argc, char **argv)
Definition main.cpp:158
void setMainForm(QWidget *pMainForm)
Definition main.cpp:182
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:252
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
static void report(void)
Report some crash details in a crashing child (mostly, the Logger 'crash context' string)
Definition Reporter.cpp:89
static void spawn(int argc, char *argv[])
Potentially spawn child process.
Definition Reporter.cpp:215
Shot List.
Definition ShotList.h:49
void shoot(QString s)
Definition ShotList.cpp:86
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:196
static int setup_unix_signal_handlers()
Definition main.cpp:112
static void setApplicationIcon(QApplication *app)
Definition main.cpp:139
static void handleFatalSignal(int nSignal)
Definition main.cpp:82
std::string get_version()
Returns the current Hydrogen version string.
Definition Version.cpp:30
void init_gui_object_map()