196int main(
int argc,
char *argv[])
202 if ( AttachConsole(ATTACH_PARENT_PROCESS)) {
203 freopen(
"CONOUT$",
"w", stdout);
204 freopen(
"CONOUT$",
"w", stderr);
205 freopen(
"CONIN$",
"w", stdin);
210#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)
211 QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
212 QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
216 QCoreApplication *pBootStrApp =
new QCoreApplication( argc, argv );
220 QCommandLineParser parser;
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" );
226 parser.setApplicationDescription( aboutText );
228 QStringList availableAudioDrivers;
229#ifdef H2CORE_HAVE_JACK
230 availableAudioDrivers <<
"jack";
232#ifdef H2CORE_HAVE_ALSA
233 availableAudioDrivers <<
"alsa";
235#ifdef H2CORE_HAVE_OSS
236 availableAudioDrivers <<
"oss";
238#ifdef H2CORE_HAVE_PULSEAUDIO
239 availableAudioDrivers <<
"pulseaudio";
241#ifdef H2CORE_HAVE_PORTAUDIO
242 availableAudioDrivers <<
"portaudio";
244#ifdef H2CORE_HAVE_COREAUDIO
245 availableAudioDrivers <<
"coreaudio";
247 availableAudioDrivers <<
"auto";
249 QCommandLineOption audioDriverOption( QStringList() <<
"d" <<
"driver",
250 QString(
"Use the selected audio driver (%1)" )
251 .arg( availableAudioDrivers.join(
", " ) ),
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)");
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" );
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 );
293 if( parser.isSet(verboseOption) ){
294 if( !sVerbosityString.isEmpty() )
307 foreach ( sArg, parser.positionalArguments() ) {
309 sSongFilename = sArg;
315 sPlaylistFilename = sArg;
319 std::cout << aboutText.toStdString();
322 QString sInitialisingCrashContext(
"Initialising Hydrogen" );
331 if( sSysDataPath.length() == 0 ) {
340 ___INFOLOG( QString(
"Using QT version ") + QString( qVersion() ) );
346#if QT_VERSION >= QT_VERSION_CHECK( 5, 14, 0)
348 Qt::HighDpiScaleFactorRoundingPolicy policy;
352 policy = Qt::HighDpiScaleFactorRoundingPolicy::RoundPreferFloor;
355 policy = Qt::HighDpiScaleFactorRoundingPolicy::PassThrough;
358 policy = Qt::HighDpiScaleFactorRoundingPolicy::Ceil;
361 QGuiApplication::setHighDpiScaleFactorRoundingPolicy( policy );
365 if ( !sUiLayout.isEmpty() ) {
366 if ( sUiLayout ==
"tabbed" ) {
373#ifdef H2CORE_HAVE_LASH
379 if( ! sDrumkitName.isEmpty() ){
384 if ( sSelectedDriver ==
"auto" ) {
386 }
else if ( sSelectedDriver ==
"jack" ) {
388 }
else if ( sSelectedDriver ==
"oss" ) {
390 }
else if ( sSelectedDriver ==
"alsa" ) {
392 }
else if ( sSelectedDriver ==
"pulseaudio" ) {
394 }
else if ( sSelectedDriver ==
"coreaudio" ) {
396 }
else if ( sSelectedDriver ==
"portaudio" ) {
398 }
else if ( ! sSelectedDriver.isEmpty() ) {
399 ___WARNINGLOG( QString(
"Unknown driver [%1]. The 'auto' driver will be used instead" )
400 .arg( sSelectedDriver ) );
408 pQApp->setApplicationName(
"Hydrogen" );
413 pQApp->processEvents();
416 pQApp->setFont( QFont( family, 10 ) );
418 QTranslator qttor(
nullptr );
419 QTranslator tor(
nullptr );
420 QLocale locale = QLocale::system();
421 if ( locale != QLocale::c() ) {
422 QStringList languages;
424 if ( !sPreferredLanguage.isNull() ) {
425 languages << sPreferredLanguage;
427 languages << locale.uiLanguages();
429 QLibraryInfo::location(QLibraryInfo::TranslationsPath) ) ) {
430 pQApp->installTranslator( &qttor );
432 ___INFOLOG( QString(
"Warning: No Qt translation for locale %1 found.").arg(locale.name()));
436 QString sTranslationFile(
"hydrogen" );
439 ___INFOLOG(
"Using locale: " + sTranslationPath );
441 ___INFOLOG(
"Warning: no locale found: " + sTranslationPath );
444 ___INFOLOG(
"Warning: error loading locale: " + sTranslationPath );
447 pQApp->installTranslator( &tor );
450 if ( !sStyle.isEmpty() ) {
451 pQApp->setStyle( sStyle );
459 QMessageBox::critical(
nullptr,
"Hydrogen",
460 QString( QT_TRANSLATE_NOOP(
"Startup",
"No [hydrogen.conf] file found. Hydrogen was not installed properly. Aborting..." ) ) );
470 ___ERRORLOG(
"No preferences file found. Aborting..." );
476#ifdef H2CORE_HAVE_APPIMAGE
489 QString sCurrentDir = QDir::currentPath();
490 QDir::setCurrent( QCoreApplication::applicationDirPath() );
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 );
507#ifdef H2CORE_HAVE_OSC
510 if ( bNoSplash || getenv(
"NSM_URL" ) ) {
517#ifndef H2CORE_HAVE_OSC
521#ifdef H2CORE_HAVE_LASH
526 if (lash_event && lash_event_get_type(lash_event) == LASH_Restore_File)
532 sSongFilename.append( QString::fromLocal8Bit(lash_event_get_string(lash_event)) );
533 sSongFilename.append(
"/hydrogen.h2song");
537 lash_event_destroy(lash_event);
542 lash_event_destroy(lash_event);
555 pHydrogen->startNsmClient();
563 if ( pHydrogen->getAudioOutput() ==
nullptr ) {
566 QApplication::setOverrideCursor( Qt::WaitCursor );
567 pHydrogen->restartDrivers();
568 QApplication::restoreOverrideCursor();
575 pSplash->finish( pMainForm );
577 if( ! sPlaylistFilename.isEmpty() ){
578 bool loadlist = pHydrogenApp->getPlayListDialog()->loadListByFileName( sPlaylistFilename );
587 if( ! sDrumkitToLoad.isEmpty() ) {
588 pHydrogen->getCoreActionController()->setDrumkit( sDrumkitToLoad );
600 if ( sShotList != QString() ) {
610 if ( pHydrogen->getSong()->getFilename() !=
612#ifdef H2CORE_HAVE_OSC
621 pHydrogen->setIsModified(
true );
625 pHydrogen->setIsModified(
false );
628 pHydrogen->setIsModified(
false );
636 QString sShutdownCrashContext(
"Shutting down Hydrogen" );
650 std::cout <<
"\nBye..." << std::endl;
659 std::cerr <<
"[main] Exception: " << ex.what() << std::endl;
662 std::cerr <<
"[main] Unknown exception X-(" << std::endl;