hydrogen 1.2.3
HydrogenApp.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 <core/config.h>
24#include <core/Version.h>
25#include <core/Hydrogen.h>
26#include <core/EventQueue.h>
27#include <core/FX/LadspaFX.h>
30
31#include "HydrogenApp.h"
32#include "CommonStrings.h"
34#include "MainForm.h"
35#include "PlayerControl.h"
36#include "AudioEngineInfoForm.h"
37#include "FilesystemInfoForm.h"
38#include "LadspaFXProperties.h"
39#include "InstrumentRack.h"
40#include "Director.h"
41
52#include "Mixer/Mixer.h"
53#include "Mixer/MixerLine.h"
54#include "UndoActions.h"
55
58
59#include "Widgets/InfoBar.h"
60
61#include <QtGui>
62#include <QtWidgets>
63
64
65using namespace H2Core;
66
67
69
71 : m_pMainForm( pMainForm )
72 , m_pMixer( nullptr )
73 , m_pPatternEditorPanel( nullptr )
74 , m_pAudioEngineInfoForm( nullptr )
75 , m_pSongEditorPanel( nullptr )
76 , m_pPlayerControl( nullptr )
77 , m_pPlaylistDialog( nullptr )
78 , m_pSampleEditor( nullptr )
79 , m_pDirector( nullptr )
80 , m_nPreferencesUpdateTimeout( 100 )
81 , m_bufferedChanges( H2Core::Preferences::Changes::None )
82{
83 m_pInstance = this;
84
85 m_pEventQueueTimer = new QTimer(this);
86 connect( m_pEventQueueTimer, SIGNAL( timeout() ), this, SLOT( onEventQueueTimer() ) );
88
89 // Wait for m_nPreferenceUpdateTimeout milliseconds of no update
90 // signal before propagating the update. Else importing/resetting a
91 // theme will slow down the GUI significantly.
92 m_pPreferencesUpdateTimer = new QTimer( this );
93 m_pPreferencesUpdateTimer->setSingleShot( true );
94 connect( m_pPreferencesUpdateTimer, SIGNAL(timeout()), this, SLOT(propagatePreferences()) );
95
96 m_pCommonStrings = std::make_shared<CommonStrings>();
97
98 //setup the undo stack
99 m_pUndoStack = new QUndoStack( this );
100
102
104
106
107 // restore audio engine form properties
109 WindowProperties audioEngineInfoProp = pPref->getAudioEngineInfoProperties();
110 setWindowProperties( m_pAudioEngineInfoForm, audioEngineInfoProp, SetX + SetY );
111
113
114 m_pPlaylistDialog = new PlaylistDialog( nullptr );
115 WindowProperties playlistDialogProp = pPref->getPlaylistDialogProperties();
116 setWindowProperties( m_pPlaylistDialog, playlistDialogProp, SetAll );
117
118 m_pDirector = new Director( nullptr );
119 WindowProperties directorProp = pPref->getDirectorProperties();
120 setWindowProperties( m_pDirector, directorProp, SetAll );
121
122 // Initially keyboard cursor is hidden.
124
125 // Since HydrogenApp does implement some handler functions for
126 // Events as well, it should be registered as an Eventlistener
127 // itself.
128 addEventListener( this );
129
130 connect( this, &HydrogenApp::preferencesChanged,
132 connect( this, &HydrogenApp::preferencesChanged,
134}
135
136void HydrogenApp::setWindowProperties( QWidget *pWindow, WindowProperties &prop, unsigned flags ) {
137 if ( flags & SetVisible ) {
138 if ( prop.visible) {
139 pWindow->show();
140 } else {
141 pWindow->hide();
142 }
143 }
144
145 // Preserve the current values of anything we're not setting.
146 QRect oldGeometry = pWindow->geometry();
147 if ( prop.m_geometry.size() == 0 ) {
148 // No geometry saved in preferences. Most likely an old preferences file. Set the size and shape
149 pWindow->resize( prop.width, prop.height );
150 pWindow->move( prop.x, prop.y );
151 prop.m_geometry = pWindow->saveGeometry();
152 }
153
154 // restore geometry will also ensure things are visible if screen geometry has changed.
155 pWindow->restoreGeometry( prop.m_geometry );
156
157 // For anything that we're not setting, restore the previous values.
158 QRect newGeometry = pWindow->geometry();
159 if ( !( flags & SetX ) ) {
160 newGeometry.setX( oldGeometry.x() );
161 }
162 if ( !( flags & SetY ) ) {
163 newGeometry.setY( oldGeometry.y() );
164 }
165 if ( !( flags & SetWidth ) ) {
166 newGeometry.setWidth( oldGeometry.width() );
167 }
168 if ( !( flags & SetHeight ) ) {
169 newGeometry.setHeight( oldGeometry.height() );
170 }
171
172 // If a window is fixed-size, don't restore it full-screen (macOS sometimes does this, annoyingly)
173 if ( pWindow->minimumSize() == pWindow->maximumSize() ) {
174 if ( pWindow->isFullScreen()) {
175 pWindow->showNormal();
176 }
177 }
178
179 if ( oldGeometry != newGeometry ) {
180 pWindow->setGeometry( newGeometry );
181 }
182}
183
184
186 WindowProperties prop;
187 prop.x = pWindow->x();
188 prop.y = pWindow->y();
189 prop.height = pWindow->height();
190 prop.width = pWindow->width();
191 prop.visible = pWindow->isVisible();
192 prop.m_geometry = pWindow->saveGeometry();
193
194 return prop;
195}
196
197
199{
200 INFOLOG( "[~HydrogenApp]" );
201 m_pEventQueueTimer->stop();
202
203
204 //delete the undo tmp directory
206
209 delete m_pMixer;
210 delete m_pPlaylistDialog;
211 delete m_pDirector;
212 delete m_pSampleEditor;
213
214 if ( m_pTab ) {
215 delete m_pTab;
216 }
217 if ( m_pSplitter ) {
218 delete m_pSplitter;
219 }
220
221 #ifdef H2CORE_HAVE_LADSPA
222 for (uint nFX = 0; nFX < MAX_FX; nFX++) {
223 delete m_pLadspaFXProperties[nFX];
224 }
225 #endif
226
227 Hydrogen *pHydrogen = Hydrogen::get_instance();
228 if (pHydrogen) {
229 // Hydrogen calls removeSong on from its destructor, so here we just delete the objects:
230 delete pHydrogen;
231 }
232
233 m_pInstance = nullptr;
234
235}
236
237
238
240{
243
244 // MAINFORM
245 WindowProperties mainFormProp = pPref->getMainFormProperties();
247
248 m_pSplitter = new QSplitter( nullptr );
249 m_pSplitter->setOrientation( Qt::Vertical );
250 m_pSplitter->setOpaqueResize( true );
251
252 m_pTab = new QTabWidget( nullptr );
253 m_pTab->setObjectName( "TabbedInterface" );
254
255 // SONG EDITOR
256 if( layout == InterfaceTheme::Layout::SinglePane ) {
258 } else {
260 }
261 // trigger a relocation to sync the transport position of the
262 // editors in the panel.
264
265 WindowProperties songEditorProp = pPref->getSongEditorProperties();
267
268 if( layout == InterfaceTheme::Layout::Tabbed ) {
269 m_pTab->addTab( m_pSongEditorPanel, tr("Song Editor") );
270 }
271
272 // this HBox will contain the InstrumentRack and the Pattern editor
273 QWidget *pSouthPanel = new QWidget( m_pSplitter );
274 pSouthPanel->setObjectName( "SouthPanel" );
275 QHBoxLayout *pEditorHBox = new QHBoxLayout();
276 pEditorHBox->setSpacing( 5 );
277 pEditorHBox->setMargin( 0 );
278 pSouthPanel->setLayout( pEditorHBox );
279
280 // INSTRUMENT RACK
281 m_pInstrumentRack = new InstrumentRack( nullptr );
282 WindowProperties instrumentRackProp = pPref->getInstrumentRackProperties();
283 m_pInstrumentRack->setHidden( !instrumentRackProp.visible );
284
285 if( layout == InterfaceTheme::Layout::Tabbed ){
286 m_pTab->setMovable( false );
287 m_pTab->setTabsClosable( false );
288 m_pTab->addTab( pSouthPanel, tr( "Instrument + Pattern") );
289 }
290
291 // PATTERN EDITOR
293 // Sync the playhead position in all editors all objects are available.
295 WindowProperties patternEditorProp = pPref->getPatternEditorProperties();
297
298 pEditorHBox->addWidget( m_pPatternEditorPanel );
299 pEditorHBox->addWidget( m_pInstrumentRack );
300
301 // PLayer control
302 m_pPlayerControl = new PlayerControl( nullptr );
303
304
305 QWidget *mainArea = new QWidget( m_pMainForm ); // this is the main widget
306 m_pMainForm->setCentralWidget( mainArea );
307
308 // LAYOUT!!
309 m_pMainVBox = new QVBoxLayout();
310 m_pMainVBox->setSpacing( 1 );
311 m_pMainVBox->setMargin( 0 );
312 m_pMainVBox->addWidget( m_pPlayerControl );
313
314 m_pMainVBox->addSpacing( 3 );
315
316 if( layout == InterfaceTheme::Layout::SinglePane ) {
317 m_pMainVBox->addWidget( m_pSplitter );
318 } else {
319 m_pMainVBox->addWidget( m_pTab );
320
321 }
322
323 mainArea->setLayout( m_pMainVBox );
324
325
326
327
328 // MIXER
329 m_pMixer = new Mixer(nullptr);
330 m_pMixer->setObjectName( "Mixer" );
331 WindowProperties mixerProp = pPref->getMixerProperties();
332
333 if ( layout != InterfaceTheme::Layout::SinglePane ) {
334 mixerProp.visible = false;
335 }
336 setWindowProperties( m_pMixer, mixerProp );
337
338 if( layout == InterfaceTheme::Layout::Tabbed ){
339 m_pTab->addTab(m_pMixer,tr("Mixer"));
340 }
341
343
344#ifdef H2CORE_HAVE_LADSPA
345 // LADSPA FX
346 for (uint nFX = 0; nFX < MAX_FX; nFX++) {
347 m_pLadspaFXProperties[nFX] = new LadspaFXProperties( nullptr, nFX );
348 m_pLadspaFXProperties[nFX]->hide();
349 WindowProperties prop = pPref->getLadspaProperties(nFX);
350 setWindowProperties( m_pLadspaFXProperties[ nFX ], prop, SetWidth + SetHeight );
351 }
352#endif
353
354 if( layout == InterfaceTheme::Layout::Tabbed ){
355 m_pTab->setCurrentIndex( Preferences::get_instance()->getLastOpenTab() );
356 QObject::connect(m_pTab, SIGNAL(currentChanged(int)),this,SLOT(currentTabChanged(int)));
357 }
358}
359
360
362 InfoBar *pInfoBar = new InfoBar();
363 m_pMainVBox->insertWidget( 1, pInfoBar );
364 return pInfoBar;
365}
366
367
368
373
375{
376#ifdef H2CORE_HAVE_LADSPA
377 for (uint nFX = 0; nFX < MAX_FX; nFX++) {
378 m_pLadspaFXProperties[nFX]->close();
379 }
380#endif
381}
382
383bool HydrogenApp::openSong( QString sFilename ) {
384 auto pHydrogen = Hydrogen::get_instance();
385 auto pCoreActionController = pHydrogen->getCoreActionController();
386
387 // Check whether there is an autosave file next to it
388 // containing newer content.
389 QFileInfo fileInfo( sFilename );
390
391 // Ensure the path to the file is not relative.
392 if ( fileInfo.isRelative() ) {
393 sFilename = fileInfo.absoluteFilePath();
394 }
395
396 // In case the user did open a hidden file, the baseName()
397 // will be an empty string.
398 QString sBaseName( fileInfo.completeBaseName() );
399 if ( sBaseName.startsWith( "." ) ) {
400 sBaseName.remove( 0, 1 );
401 }
402
403 // Hidden autosave file (recent version)
404 QFileInfo autoSaveFileRecent( QString( "%1/.%2.autosave.h2song" )
405 .arg( fileInfo.absoluteDir().absolutePath() )
406 .arg( sBaseName ) );
407 // Visible autosave file (older version)
408 QFileInfo autoSaveFileOld( QString( "%1/%2.autosave.h2song" )
409 .arg( fileInfo.absoluteDir().absolutePath() )
410 .arg( sBaseName ) );
411 QString sRecoverFilename = "";
412 if ( autoSaveFileRecent.exists() &&
413 autoSaveFileRecent.lastModified() >
414 fileInfo.lastModified() ) {
415 sRecoverFilename = autoSaveFileRecent.absoluteFilePath();
416 } else if ( autoSaveFileOld.exists() &&
417 autoSaveFileOld.lastModified() >
418 fileInfo.lastModified() ) {
419 sRecoverFilename = autoSaveFileOld.absoluteFilePath();
420 }
421
422 if ( ! sRecoverFilename.isEmpty() ) {
423 QMessageBox msgBox;
424 // Not commonized in CommmonStrings as it is required before
425 // HydrogenApp was instantiated.
426 msgBox.setText( tr( "There are unsaved changes." ) );
427 msgBox.setInformativeText( tr( "Do you want to recover them?" ) );
428 msgBox.setStandardButtons( QMessageBox::Ok | QMessageBox::Discard );
429 msgBox.setDefaultButton( QMessageBox::Discard );
430 msgBox.setWindowTitle( "Hydrogen" );
431 msgBox.setIcon( QMessageBox::Question );
432 int nRet = msgBox.exec();
433
434 if ( nRet == QMessageBox::Discard ) {
435 sRecoverFilename = "";
436 }
437 }
438
439 if ( ! pCoreActionController->openSong( sFilename, sRecoverFilename ) ) {
440 QMessageBox msgBox;
441 // Not commonized in CommmonStrings as it is required before
442 // HydrogenApp was instantiated.
443 msgBox.setText( tr( "Error loading song." ) );
444 msgBox.setWindowTitle( "Hydrogen" );
445 msgBox.setIcon( QMessageBox::Warning );
446 msgBox.exec();
447 return false;
448 }
449
450 return true;
451}
452
453bool HydrogenApp::openSong( std::shared_ptr<Song> pSong ) {
454
455 auto pCoreActionController = Hydrogen::get_instance()->getCoreActionController();
456 if ( ! pCoreActionController->openSong( pSong ) ) {
457 QMessageBox msgBox;
458 // Not commonized in CommmonStrings as it is required before
459 // HydrogenApp was instantiated.
460 msgBox.setText( tr( "Error loading song." ) );
461 msgBox.setWindowTitle( "Hydrogen" );
462 msgBox.setIcon( QMessageBox::Warning );
463 msgBox.exec();
464 return false;
465 }
466
467 return true;
468}
469
471 auto pHydrogen = Hydrogen::get_instance();
472 auto pCoreActionController = pHydrogen->getCoreActionController();
473
474 // Check whether there is an autosave file next to it
475 // containing newer content.
476 QString sFilename( H2Core::Filesystem::empty_song_path() );
477 QFileInfo fileInfo( sFilename );
478
479 // In case the user did open a hidden file, the baseName()
480 // will be an empty string.
481 QString sBaseName( fileInfo.completeBaseName() );
482 if ( sBaseName.startsWith( "." ) ) {
483 sBaseName.remove( 0, 1 );
484 }
485
486 QFileInfo autoSaveFile( QString( "%1/.%2.autosave.h2song" )
487 .arg( fileInfo.absoluteDir().absolutePath() )
488 .arg( sBaseName ) );
489 QString sRecoverFilename = "";
490
491 // Since there is no original file we can not check whether these
492 // changes have been done "recently". It's up to the calling
493 // function to ensure the corresponding empty song was indeed the
494 // last one opened by the user.
495 if ( autoSaveFile.exists() ) {
496 sRecoverFilename = autoSaveFile.absoluteFilePath();
497 }
498
499 if ( ! sRecoverFilename.isEmpty() ) {
500 QMessageBox msgBox;
501 // Not commonized in CommmonStrings as it is required before
502 // HydrogenApp was instantiated.
503 msgBox.setText( tr( "There are unsaved changes." ) );
504 msgBox.setInformativeText( tr( "Do you want to recover them?" ) );
505 msgBox.setStandardButtons( QMessageBox::Ok | QMessageBox::Discard );
506 msgBox.setDefaultButton( QMessageBox::Discard );
507 msgBox.setWindowTitle( "Hydrogen" );
508 msgBox.setIcon( QMessageBox::Question );
509 int nRet = msgBox.exec();
510
511 if ( nRet == QMessageBox::Discard ) {
512 sRecoverFilename = "";
513 }
514 }
515
516 if ( sRecoverFilename.isEmpty() ) {
517 return false;
518 }
519
520 if ( ! pCoreActionController->openSong( sFilename, sRecoverFilename ) ) {
521 QMessageBox msgBox;
522 // Not commonized in CommmonStrings as it is required before
523 // HydrogenApp was instantiated.
524 msgBox.setText( tr( "Error loading song." ) );
525 msgBox.setWindowTitle( "Hydrogen" );
526 msgBox.setIcon( QMessageBox::Warning );
527 msgBox.exec();
528 return false;
529 }
530
531 // The song has not been properly saved yet. Also this prevents
532 // the autosave file we just loaded from being removed in case the
533 // user decides to quit and reopen Hydrogen right after this call
534 // without introducing any changes.
535 pHydrogen->setIsModified( true );
536
537 return true;
538}
539
541{
542 /*
543 * Switch to Mixer tab with alt+m in tabbed mode,
544 * otherwise open mixer window
545 */
546
548
549 if ( layout == InterfaceTheme::Layout::Tabbed ) {
550 m_pTab->setCurrentIndex( 2 );
551 } else {
552 m_pMixer->setVisible( show );
553 }
554
556}
557
559{
560 /*
561 * Switch to pattern editor/instrument tab in tabbed mode,
562 * otherwise hide instrument panel
563 */
564
566
567 if ( layout == InterfaceTheme::Layout::Tabbed ) {
568 m_pTab->setCurrentIndex( 1 );
569 getInstrumentRack()->setHidden( show );
570 } else {
571 getInstrumentRack()->setHidden( show );
572 }
574}
575
576
577
579{
580 PreferencesDialog preferencesDialog(m_pMainForm);
581 preferencesDialog.exec();
582}
583
584
585
586
587void HydrogenApp::showStatusBarMessage( const QString& sMessage, const QString& sCaller )
588{
589 if ( m_pPlayerControl != nullptr ) {
590 m_pPlayerControl->showStatusBarMessage( sMessage, sCaller );
591 }
592}
593
595 const auto pAudioDriver = Hydrogen::get_instance()->getAudioOutput();
596 if ( pAudioDriver == nullptr ) {
597 ERRORLOG( "AudioDriver is not ready!" );
598 return;
599 }
600 showStatusBarMessage( QString( "XRUNS [%1]!!!" ) .arg( pAudioDriver->getXRuns() ) );
601}
602
604{
605 auto pSong = Hydrogen::get_instance()->getSong();
606 if ( pSong == nullptr ) {
607 ERRORLOG( "invalid song" );
608 assert(pSong);
609 return;
610 }
611
612 QString sTitle = Filesystem::untitled_song_name();
613
614 QString sSongName( pSong->getName() );
615 QString sFilePath( pSong->getFilename() );
616
617 if ( sFilePath == Filesystem::empty_song_path() ||
618 sFilePath.isEmpty() ) {
619 // An empty song is _not_ associated with a file. Therefore,
620 // we mustn't show the file name.
621 if ( ! sSongName.isEmpty() ) {
622 sTitle = sSongName;
623 }
624 } else {
625 QFileInfo fileInfo( sFilePath );
626
627 if ( sSongName == Filesystem::untitled_song_name() ||
628 sSongName == fileInfo.completeBaseName() ) {
629 // The user did not alter the default name of the song or
630 // set the song name but also named the corresponding file
631 // accordingly. We'll just show the file name to avoid
632 // duplication.
633 sTitle = fileInfo.fileName();
634
635 } else {
636 // The user did set the song name but used a different
637 // name for the corresponding file. We'll show both to
638 // make this mismatch transparent.
639 sTitle = QString( "%1 [%2]" ).arg( sSongName )
640 .arg( fileInfo.fileName() );
641 }
642 }
643
644 if( pSong->getIsModified() ){
645 sTitle.append( " (" + tr( "modified" ) + ")" );
646 }
647
648 m_pMainForm->setWindowTitle( ( "Hydrogen " + QString( get_version().c_str()) +
649 QString( " - " ) + sTitle ) );
650}
651
652
658
664
666{
667 if ( m_pPlaylistDialog->isVisible() ) {
668 m_pPlaylistDialog->hide();
669 } else {
670 m_pPlaylistDialog->show();
671 }
673}
674
675
677{
678 if ( m_pDirector->isVisible() ) {
679 m_pDirector->hide();
680 } else {
681 m_pDirector->show();
682 }
684}
685
686
687void HydrogenApp::showSampleEditor( QString name, int mSelectedComponemt, int mSelectedLayer )
688{
689
690 if ( m_pSampleEditor ){
691 QApplication::setOverrideCursor(Qt::WaitCursor);
692 m_pSampleEditor->close();
693 delete m_pSampleEditor;
694 m_pSampleEditor = nullptr;
695 QApplication::restoreOverrideCursor();
696 }
697 QApplication::setOverrideCursor(Qt::WaitCursor);
698 m_pSampleEditor = new SampleEditor( nullptr, mSelectedComponemt, mSelectedLayer, name );
699 m_pSampleEditor->show();
700 QApplication::restoreOverrideCursor();
701}
702
704 showStatusBarMessage( QString( tr( "Drumkit [%1] loaded from [%2]" )
705 .arg( Hydrogen::get_instance()->getLastLoadedDrumkitName() )
706 .arg( Hydrogen::get_instance()->getLastLoadedDrumkitPath() ) ) );
707}
708
713
715{
716 // use the timer to do schedule instrument slaughter;
718
719 Event event;
720 while ( ( event = pQueue->pop_event() ).type != EVENT_NONE ) {
721
722 // Provide the event to all EventListeners registered to
723 // HydrogenApp. By registering itself as EventListener and
724 // implementing at least on the methods used below a
725 // particular GUI component can react on specific events.
726 for (int i = 0; i < (int)m_EventListeners.size(); i++ ) {
727 EventListener *pListener = m_EventListeners[ i ];
728
729 switch ( event.type ) {
730 case EVENT_STATE:
731 pListener->stateChangedEvent( static_cast<H2Core::AudioEngine::State>(event.value) );
732 break;
733
735 pListener->playingPatternsChangedEvent();
736 break;
737
739 pListener->nextPatternsChangedEvent();
740 break;
741
743 pListener->patternModifiedEvent();
744 break;
745
747 pListener->songModifiedEvent();
748 break;
749
751 pListener->selectedPatternChangedEvent();
752 break;
753
756 break;
757
759 pListener->instrumentParametersChangedEvent( event.value );
760 break;
761
763 pListener->midiActivityEvent();
764 break;
765
766 case EVENT_NOTEON:
767 pListener->noteOnEvent( event.value );
768 break;
769
770 case EVENT_ERROR:
771 pListener->errorEvent( event.value );
772 break;
773
774 case EVENT_XRUN:
775 pListener->XRunEvent();
776 break;
777
778 case EVENT_METRONOME:
779 pListener->metronomeEvent( event.value );
780 break;
781
782 case EVENT_PROGRESS:
783 pListener->progressEvent( event.value );
784 break;
785
787 pListener->jacksessionEvent( event.value );
788 break;
789
791 pListener->playlistLoadSongEvent( event.value );
792 break;
793
794 case EVENT_UNDO_REDO:
795 pListener->undoRedoActionEvent( event.value );
796 break;
797
799 pListener->tempoChangedEvent( event.value );
800 break;
801
803 pListener->updatePreferencesEvent( event.value );
804 break;
805
807 pListener->updateSongEvent( event.value );
808 break;
809
810 case EVENT_QUIT:
811 pListener->quitEvent( event.value );
812 break;
813
815 pListener->timelineActivationEvent();
816 break;
817
819 pListener->timelineUpdateEvent( event.value );
820 break;
821
823 pListener->jackTransportActivationEvent();
824 break;
825
828 break;
829
831 pListener->songModeActivationEvent();
832 break;
833
835 pListener->stackedModeActivationEvent( event.value );
836 break;
837
839 pListener->loopModeActivationEvent();
840 break;
841
843 pListener->actionModeChangeEvent( event.value );
844 break;
845
847 pListener->gridCellToggledEvent();
848 break;
849
851 pListener->drumkitLoadedEvent();
852 break;
853
855 pListener->patternEditorLockedEvent();
856 break;
857
858 case EVENT_RELOCATION:
859 pListener->relocationEvent();
860 break;
861
863 pListener->bbtChangedEvent();
864 break;
865
867 pListener->songSizeChangedEvent();
868 break;
869
871 pListener->driverChangedEvent();
872 break;
873
875 pListener->playbackTrackChangedEvent();
876 break;
877
879 pListener->soundLibraryChangedEvent();
880 break;
881
882 case EVENT_NEXT_SHOT:
883 pListener->nextShotEvent();
884 break;
885
887 pListener->midiMapChangedEvent();
888 break;
889
890 default:
891 ERRORLOG( QString("[onEventQueueTimer] Unhandled event: %1").arg( event.type ) );
892 }
893 }
894
895 }
896
897 // midi notes
898 while( !pQueue->m_addMidiNoteVector.empty() ){
899 std::shared_ptr<Song> pSong = Hydrogen::get_instance()->getSong();
900 auto pInstrument = pSong->getInstrumentList()->
901 get( pQueue->m_addMidiNoteVector[0].m_row );
902
903 // find if a (pitch matching) note is already present
904 Note* pOldNote = pSong->getPatternList()->get( pQueue->m_addMidiNoteVector[0].m_pattern )->
905 find_note( pQueue->m_addMidiNoteVector[0].m_column,
906 pQueue->m_addMidiNoteVector[0].m_column,
907 pInstrument,
908 pQueue->m_addMidiNoteVector[0].nk_noteKeyVal,
909 pQueue->m_addMidiNoteVector[0].no_octaveKeyVal );
910
911 auto pUndoStack = HydrogenApp::get_instance()->m_pUndoStack;
912 pUndoStack->beginMacro( tr( "Input Midi Note" ) );
913 if( pOldNote ) { // note found => remove it
915 pOldNote->get_instrument_id(),
916 pQueue->m_addMidiNoteVector[0].m_pattern,
917 pOldNote->get_length(),
918 pOldNote->get_velocity(),
919 pOldNote->getPan(),
920 pOldNote->get_lead_lag(),
921 pOldNote->get_key(),
922 pOldNote->get_octave(),
923 pOldNote->get_probability(),
924 /*isDelete*/ true,
925 /*hearNote*/ false,
926 /*isMidi*/ false,
927 /*isInstrumentMode*/ false,
928 /*isNoteOff*/ false );
929 pUndoStack->push( action );
930 }
931
932 // add the new note
934 pQueue->m_addMidiNoteVector[0].m_row,
935 pQueue->m_addMidiNoteVector[0].m_pattern,
936 pQueue->m_addMidiNoteVector[0].m_length,
937 pQueue->m_addMidiNoteVector[0].f_velocity,
938 pQueue->m_addMidiNoteVector[0].f_pan,
939 0.0,
940 pQueue->m_addMidiNoteVector[0].nk_noteKeyVal,
941 pQueue->m_addMidiNoteVector[0].no_octaveKeyVal,
942 1.0f,
943 /*isDelete*/ false,
944 /*hearNote*/ false,
945 pQueue->m_addMidiNoteVector[0].b_isMidi,
946 pQueue->m_addMidiNoteVector[0].b_isInstrumentMode,
947 /*isNoteOff*/ false );
948 pUndoStack->push( action );
949 pUndoStack->endMacro();
950 pQueue->m_addMidiNoteVector.erase( pQueue->m_addMidiNoteVector.begin() );
951 }
952}
953
954
956{
957 if (pListener) {
958 m_EventListeners.push_back( pListener );
959 }
960}
961
962
964{
965 for ( uint i = 0; i < m_EventListeners.size(); i++ ) {
966 if ( pListener == m_EventListeners[ i ] ) {
967 m_EventListeners.erase( m_EventListeners.begin() + i );
968 }
969 }
970}
971
980
982
983 QString sPreferencesFilename;
984
985 // Local path of the preferences used during session management.
986 const QString sPreferencesOverwritePath =
988 if ( sPreferencesOverwritePath.isEmpty() ) {
989 sPreferencesFilename = Filesystem::usr_config_path();
990 } else {
991 sPreferencesFilename = sPreferencesOverwritePath;
992 }
993
994 if ( nValue == 0 ) {
995 showStatusBarMessage( tr("Preferences saved.") +
996 QString(" Into: ") + sPreferencesFilename );
997 } else if ( nValue == 1 ) {
998
999 // Since the Preferences have changed, we also have to reflect
1000 // these changes in the GUI - its format, colors, fonts,
1001 // selections etc.
1002 // But we won't change the layout!
1005
1006 WindowProperties audioEngineInfoProp = pPref->getAudioEngineInfoProperties();
1008
1009 // MAINFORM
1010 WindowProperties mainFormProp = pPref->getMainFormProperties();
1011 setWindowProperties( m_pMainForm, mainFormProp );
1012
1013 m_pSplitter->setOrientation( Qt::Vertical );
1014 m_pSplitter->setOpaqueResize( true );
1015
1016 // SONG EDITOR
1017 WindowProperties songEditorProp = pPref->getSongEditorProperties();
1019
1020 // PATTERN EDITOR
1021 WindowProperties patternEditorProp = pPref->getPatternEditorProperties();
1023
1024 WindowProperties instrumentRackProp = pPref->getInstrumentRackProperties();
1025 m_pInstrumentRack->setHidden( !instrumentRackProp.visible );
1026
1027 WindowProperties mixerProp = pPref->getMixerProperties();
1028 if ( layout != InterfaceTheme::Layout::SinglePane ) {
1029 mixerProp.visible = false;
1030 }
1031 setWindowProperties( m_pMixer, mixerProp );
1032
1034
1035 WindowProperties playlistDialogProp = pPref->getPlaylistDialogProperties();
1036 setWindowProperties( m_pPlaylistDialog, playlistDialogProp, SetAll );
1037
1038 WindowProperties directorProp = pPref->getDirectorProperties();
1039 setWindowProperties( m_pDirector, directorProp, SetAll );
1040
1041#ifdef H2CORE_HAVE_LADSPA
1042 // LADSPA FX
1043 for (uint nFX = 0; nFX < MAX_FX; nFX++) {
1044 m_pLadspaFXProperties[nFX]->hide();
1045 WindowProperties prop = pPref->getLadspaProperties(nFX);
1046 setWindowProperties( m_pLadspaFXProperties[ nFX ], prop, SetX + SetY );
1047 }
1048#endif
1049
1050 // Inform the user about which file was loaded.
1051 showStatusBarMessage( tr("Preferences loaded.") +
1052 QString(" From: ") + sPreferencesFilename );
1053
1054
1055 } else {
1056 ERRORLOG( QString( "Unknown event parameter [%1] in HydrogenApp::updatePreferencesEvent" )
1057 .arg( nValue ) );
1058 }
1059
1060}
1061
1063
1064 auto pHydrogen = Hydrogen::get_instance();
1065 auto pSong = pHydrogen->getSong();
1066 if ( pSong == nullptr ) {
1067 return;
1068 }
1069
1070 if ( nValue == 0 ) {
1071 // Cleanup
1073 m_pUndoStack->clear();
1074
1075 // Update GUI components
1077
1078 } else if ( nValue == 1 ) {
1079
1080 QString sFilename = pSong->getFilename();
1081
1082 // Song was saved.
1083 showStatusBarMessage( tr("Song saved as: ") + sFilename );
1085
1086 } else if ( nValue == 2 ) {
1087
1088 // The event was triggered before the Song was fully loaded by
1089 // the core. It's most likely to be present by now, but it's
1090 // probably better to avoid displaying its path just to be
1091 // sure.
1092 QMessageBox::information( m_pMainForm, "Hydrogen", tr("Song is read-only.\nUse 'Save as' to enable autosave." ) );
1093 }
1094}
1095
1097 if ( m_pPreferencesUpdateTimer->isActive() ) {
1099 }
1101 // Ensure the provided changes will be propagated too.
1102
1103 if ( ! ( m_bufferedChanges & changes ) ) {
1105
1106 }
1107}
1108
1113
1114bool HydrogenApp::checkDrumkitLicense( std::shared_ptr<H2Core::Drumkit> pDrumkit ) {
1115
1116 auto pPref = H2Core::Preferences::get_instance();
1117
1118 if ( ! pPref->m_bShowExportDrumkitLicenseWarning &&
1119 ! pPref->m_bShowExportDrumkitCopyleftWarning &&
1120 ! pPref->m_bShowExportDrumkitAttributionWarning ) {
1121 return true;
1122 }
1123
1124 auto pCommonStrings = HydrogenApp::get_instance()->getCommonStrings();
1125
1126 auto drumkitLicense = pDrumkit->get_license();
1127 auto contentVector = pDrumkit->summarizeContent();
1128
1129 QStringList additionalLicenses;
1130 bool bCopyleftLicenseFound = drumkitLicense.isCopyleft();
1131 bool bAttributionRequired = drumkitLicense.hasAttribution();
1132
1133 for ( const auto& ccontent : contentVector ) {
1134 QString sSampleLicense = QString( "%1 (by %2)" )
1135 .arg( ccontent->m_license.getLicenseString() )
1136 .arg( ccontent->m_license.getCopyrightHolder() );
1137
1138 if ( ccontent->m_license != drumkitLicense &&
1139 ! additionalLicenses.contains( sSampleLicense ) ) {
1140 additionalLicenses << sSampleLicense;
1141
1142 bCopyleftLicenseFound = bCopyleftLicenseFound ||
1143 ccontent->m_license.isCopyleft();
1144 bAttributionRequired = bAttributionRequired ||
1145 ccontent->m_license.hasAttribution();
1146 }
1147 }
1148
1149 if ( additionalLicenses.size() > 0 &&
1150 pPref->m_bShowExportDrumkitLicenseWarning ) {
1151
1152 QString sMsg = tr( "Some sample licenses deviate from the one assigned to the overall drumkit [%1] and will be overwritten. Are you sure?" )
1153 .arg( drumkitLicense.getLicenseString() );
1154
1155 sMsg.append( "\n" );
1156 for ( const auto& sLicense : additionalLicenses ) {
1157 sMsg.append( QString( "\n- %1" ).arg( sLicense ) );
1158 }
1159
1160 QMessageBox licenseWarning;
1161 licenseWarning.setWindowTitle( pCommonStrings->getLicenseWarningWindowTitle() );
1162 licenseWarning.setText( sMsg );
1163 licenseWarning.addButton( pCommonStrings->getButtonOk(),
1164 QMessageBox::AcceptRole );
1165 auto pMuteButton =
1166 licenseWarning.addButton( pCommonStrings->getMutableDialog(),
1167 QMessageBox::YesRole );
1168 auto pRejectButton =
1169 licenseWarning.addButton( pCommonStrings->getButtonCancel(),
1170 QMessageBox::RejectRole );
1171
1172 licenseWarning.exec();
1173
1174 if ( licenseWarning.clickedButton() == pMuteButton ) {
1175 pPref->m_bShowExportDrumkitLicenseWarning = false;
1176 }
1177 else if ( licenseWarning.clickedButton() == pRejectButton ) {
1178 ERRORLOG( "Aborted on overwriting licenses" );
1179 return false;
1180 }
1181 }
1182
1183 if ( bCopyleftLicenseFound &&
1184 pPref->m_bShowExportDrumkitCopyleftWarning ) {
1185 QMessageBox copyleftWarning;
1186 copyleftWarning.setWindowTitle( pCommonStrings->getLicenseWarningWindowTitle() );
1187 copyleftWarning.setText( pCommonStrings->getLicenseCopyleftWarning() );
1188 copyleftWarning.addButton( pCommonStrings->getButtonOk(),
1189 QMessageBox::AcceptRole );
1190 auto pMuteButton =
1191 copyleftWarning.addButton( pCommonStrings->getMutableDialog(),
1192 QMessageBox::YesRole );
1193 auto pRejectButton =
1194 copyleftWarning.addButton( pCommonStrings->getButtonCancel(),
1195 QMessageBox::RejectRole );
1196
1197 copyleftWarning.exec();
1198
1199 if ( copyleftWarning.clickedButton() == pMuteButton ) {
1200 pPref->m_bShowExportDrumkitCopyleftWarning = false;
1201 }
1202 else if ( copyleftWarning.clickedButton() == pRejectButton ) {
1203 ERRORLOG( "Aborted on copyleft licenses" );
1204 return false;
1205 }
1206 }
1207
1208 if ( bAttributionRequired &&
1209 pPref->m_bShowExportDrumkitAttributionWarning ) {
1210 QMessageBox attributionWarning;
1211 attributionWarning.setWindowTitle( pCommonStrings->getLicenseWarningWindowTitle() );
1212 attributionWarning.setText( pCommonStrings->getLicenseAttributionWarning() );
1213 attributionWarning.addButton( pCommonStrings->getButtonOk(),
1214 QMessageBox::AcceptRole );
1215 auto pMuteButton =
1216 attributionWarning.addButton( pCommonStrings->getMutableDialog(),
1217 QMessageBox::YesRole );
1218 auto pRejectButton =
1219 attributionWarning.addButton( pCommonStrings->getButtonCancel(),
1220 QMessageBox::RejectRole );
1221
1222 attributionWarning.exec();
1223
1224 if ( attributionWarning.clickedButton() == pMuteButton ) {
1225 pPref->m_bShowExportDrumkitAttributionWarning = false;
1226 }
1227 else if ( attributionWarning.clickedButton() == pRejectButton ) {
1228 ERRORLOG( "Aborted on attribution licenses" );
1229 return false;
1230 }
1231 }
1232
1233 return true;
1234}
1235
1239 getMetronomeInstrument()->set_volume(
1240 Preferences::get_instance()->m_fMetronomeVolume );
1241 }
1242}
constexpr uint16_t QUEUE_TIMER_PERIOD
Amount of time to pass between successive calls to HydrogenApp::onEventQueueTimer() in milliseconds.
Definition HydrogenApp.h:46
#define INFOLOG(x)
Definition Object.h:237
#define ERRORLOG(x)
Definition Object.h:239
Audio Engine information form.
virtual void tempoChangedEvent(int nValue)
virtual void midiActivityEvent()
virtual void metronomeEvent(int nValue)
virtual void actionModeChangeEvent(int nValue)
virtual void timelineActivationEvent()
virtual void midiMapChangedEvent()
virtual void jackTransportActivationEvent()
virtual void loopModeActivationEvent()
virtual void instrumentParametersChangedEvent(int nInstrumentNumber)
virtual void relocationEvent()
virtual void songModeActivationEvent()
virtual void updatePreferencesEvent(int nValue)
virtual void playbackTrackChangedEvent()
virtual void stateChangedEvent(H2Core::AudioEngine::State state)
virtual void noteOnEvent(int nInstrument)
virtual void soundLibraryChangedEvent()
virtual void nextShotEvent()
virtual void bbtChangedEvent()
virtual void selectedInstrumentChangedEvent()
virtual void patternModifiedEvent()
virtual void playingPatternsChangedEvent()
virtual void stackedModeActivationEvent(int nValue)
virtual void nextPatternsChangedEvent()
virtual void jackTimebaseStateChangedEvent()
virtual void patternEditorLockedEvent()
virtual void XRunEvent()
virtual void progressEvent(int nValue)
virtual void errorEvent(int nErrorCode)
virtual void playlistLoadSongEvent(int nIndex)
virtual void timelineUpdateEvent(int nValue)
virtual void selectedPatternChangedEvent()
virtual void updateSongEvent(int nValue)
virtual void undoRedoActionEvent(int nValue)
virtual void jacksessionEvent(int nValue)
virtual void songSizeChangedEvent()
virtual void songModifiedEvent()
virtual void quitEvent(int nValue)
virtual void gridCellToggledEvent()
virtual void drumkitLoadedEvent()
virtual void driverChangedEvent()
bool locateToColumn(int nPatternGroup)
Relocates transport to the beginning of a particular column/Pattern group.
Object handling the communication between the core of Hydrogen and its GUI.
Definition EventQueue.h:211
static EventQueue * get_instance()
Returns a pointer to the current EventQueue singleton stored in __instance.
Definition EventQueue.h:224
std::vector< AddMidiNoteVector > m_addMidiNoteVector
Definition EventQueue.h:274
Event pop_event()
Reads out the next event of the EventQueue.
Basic building block for the communication between the core of Hydrogen and its GUI.
Definition EventQueue.h:186
EventType type
Specifies the context the event is create in and which function should be triggered to handle it.
Definition EventQueue.h:190
int value
Additional information to describe the actual context of the engine.
Definition EventQueue.h:193
static QString usr_config_path()
returns user config path
static QString untitled_song_name()
returns untitled song name
static const QString & getPreferencesOverwritePath()
Definition Filesystem.h:540
static bool rm(const QString &path, bool recursive=false, bool bSilent=false)
remove a path
static QString empty_song_path()
Provides the full path to the current empty song.
static QString tmp_dir()
returns temp path
Hydrogen Audio Engine.
Definition Hydrogen.h:54
std::shared_ptr< Song > getSong() const
Get the current song.
Definition Hydrogen.h:122
static Hydrogen * get_instance()
Returns the current Hydrogen instance __instance.
Definition Hydrogen.h:83
AudioEngine * getAudioEngine() const
Definition Hydrogen.h:649
AudioOutput * getAudioOutput() const
Used to display audio driver info.
Definition Hydrogen.cpp:719
CoreActionController * getCoreActionController() const
Definition Hydrogen.h:639
A note plays an associated instrument with a velocity left and right pan.
Definition Note.h:102
int get_position() const
__position accessor
Definition Note.h:535
Octave get_octave()
__octave accessor
Definition Note.h:677
float get_lead_lag() const
__lead_lag accessor
Definition Note.h:550
int get_length() const
__length accessor
Definition Note.h:560
float get_velocity() const
__velocity accessor
Definition Note.h:540
Key get_key()
__key accessor
Definition Note.h:672
float get_probability() const
Definition Note.h:610
float getPan() const
get pan of the note.
Definition Note.h:545
int get_instrument_id() const
__instrument_id accessor
Definition Note.h:515
Manager for User Preferences File (singleton)
Definition Preferences.h:78
WindowProperties getAudioEngineInfoProperties()
static Preferences * get_instance()
Returns a pointer to the current Preferences singleton stored in __instance.
void setLastOpenTab(int n)
WindowProperties getMainFormProperties()
InterfaceTheme::Layout getDefaultUILayout()
WindowProperties getDirectorProperties()
WindowProperties getMixerProperties()
Changes
Bitwise or-able options showing which part of the Preferences were altered using the PreferencesDialo...
@ AudioTab
Any option in the Audio tab appeared.
WindowProperties getPatternEditorProperties()
WindowProperties getLadspaProperties(unsigned nFX)
WindowProperties getInstrumentRackProperties()
WindowProperties getSongEditorProperties()
WindowProperties getPlaylistDialogProperties()
AudioEngineInfoForm * m_pAudioEngineInfoForm
void updateWindowTitle()
void addEventListener(EventListener *pListener)
static HydrogenApp * get_instance()
Returns the instance of HydrogenApp class.
std::shared_ptr< CommonStrings > getCommonStrings()
std::shared_ptr< CommonStrings > m_pCommonStrings
InfoBar * addInfoBar()
int m_nPreferencesUpdateTimeout
QUndoStack * m_pUndoStack
Director * m_pDirector
void showAudioEngineInfoForm()
QSplitter * m_pSplitter
void showFilesystemInfoForm()
SongEditorPanel * m_pSongEditorPanel
InstrumentRack * getInstrumentRack()
void closeFXProperties()
virtual void updatePreferencesEvent(int nValue) override
Handles the loading and saving of the H2Core::Preferences from the core part of H2Core::Hydrogen.
static bool openSong(QString sFilename)
void onPreferencesChanged(H2Core::Preferences::Changes changes)
PlayerControl * m_pPlayerControl
PlaylistDialog * m_pPlaylistDialog
virtual void updateSongEvent(int nValue) override
Refreshes and updates the GUI after the Song was changed in the core part of Hydrogen.
static bool checkDrumkitLicense(std::shared_ptr< H2Core::Drumkit > pDrumkit)
void showDirector()
PatternEditorPanel * m_pPatternEditorPanel
void showStatusBarMessage(const QString &sMessage, const QString &sCaller="")
QVBoxLayout * m_pMainVBox
QTimer * m_pPreferencesUpdateTimer
std::vector< EventListener * > m_EventListeners
virtual void drumkitLoadedEvent() override
void showMixer(bool bShow)
void showPlaylistDialog()
void onEventQueueTimer()
Function called every QUEUE_TIMER_PERIOD millisecond to pop all Events from the EventQueue and invoke...
void preferencesChanged(H2Core::Preferences::Changes changes)
Propagates a change in the Preferences through the GUI.
void changePreferences(H2Core::Preferences::Changes changes)
Propagates a change in the Preferences through the GUI.
QTimer * m_pEventQueueTimer
void showInstrumentPanel(bool)
void showSampleEditor(QString name, int mSelectedComponemt, int mSelectedLayer)
static bool recoverEmptySong()
Specialized version of openSong( QString sFilename ) trying to open the autosave file corresponding t...
void currentTabChanged(int)
void removeEventListener(EventListener *pListener)
virtual void songModifiedEvent() override
InstrumentRack * m_pInstrumentRack
virtual void XRunEvent() override
H2Core::WindowProperties getWindowProperties(QWidget *pWindow)
virtual ~HydrogenApp()
Mixer * m_pMixer
void showPreferencesDialog()
void cleanupTemporaryFiles()
Removes temporary files that were created for undo'ing things.
H2Core::Preferences::Changes m_bufferedChanges
void setWindowProperties(QWidget *pWindow, H2Core::WindowProperties &prop, unsigned flags=SetAll)
MainForm * m_pMainForm
SampleEditor * m_pSampleEditor
QTabWidget * m_pTab
void setupSinglePanedInterface()
void propagatePreferences()
HydrogenApp(MainForm *pMainForm)
FilesystemInfoForm * m_pFilesystemInfoForm
static HydrogenApp * m_pInstance
HydrogenApp instance.
bool m_bHideKeyboardCursor
debug only
Definition MainForm.h:47
void update_instrument_checkbox(bool show)
void update_mixer_checkbox()
void onPreferencesChanged(H2Core::Preferences::Changes changes)
void update_director_checkbox()
void update_playlist_checkbox()
Definition Mixer.h:44
void updateMixer()
Definition Mixer.cpp:408
Pattern Editor Panel.
PatternEditorRuler * getPatternEditorRuler()
void updatePosition(bool bForce=false)
Queries the audio engine to update the current position of the playhead.
void showStatusBarMessage(const QString &msg, const QString &sCaller="")
This dialog is used to use the H2PlayList.
Preferences Dialog.
This dialog is used to preview audiofiles.
#define MAX_FX
Maximum number of effects.
Definition config.dox:83
@ EVENT_RELOCATION
Triggered in case there is a relocation of the transport position while trasnsport is not rolling.
Definition EventQueue.h:166
@ EVENT_XRUN
Definition EventQueue.h:85
@ EVENT_PLAYBACK_TRACK_CHANGED
Definition EventQueue.h:175
@ EVENT_INSTRUMENT_PARAMETERS_CHANGED
Some parameters of an instrument have been changed.
Definition EventQueue.h:83
@ EVENT_METRONOME
Triggered when a metronome note is passed to the H2Core::Sampler.
Definition EventQueue.h:97
@ EVENT_UNDO_REDO
Definition EventQueue.h:101
@ EVENT_PLAYLIST_LOADSONG
Definition EventQueue.h:100
@ EVENT_DRUMKIT_LOADED
A the current drumkit was replaced by a new one.
Definition EventQueue.h:158
@ EVENT_STATE
Definition EventQueue.h:43
@ EVENT_JACK_TRANSPORT_ACTIVATION
Toggles the button indicating the usage Jack transport.
Definition EventQueue.h:141
@ EVENT_PLAYING_PATTERNS_CHANGED
The list of currently played patterns (AudioEngine::getPlayingPatterns()) did change.
Definition EventQueue.h:57
@ EVENT_TEMPO_CHANGED
Definition EventQueue.h:103
@ EVENT_ACTION_MODE_CHANGE
Switches between select mode (0) and draw mode (1) in the *SongEditor.
Definition EventQueue.h:152
@ EVENT_SELECTED_INSTRUMENT_CHANGED
Definition EventQueue.h:77
@ EVENT_PATTERN_MODIFIED
A pattern was added, deleted, or modified.
Definition EventQueue.h:68
@ EVENT_TIMELINE_ACTIVATION
Enables/disables the usage of the Timeline.
Definition EventQueue.h:136
@ EVENT_SOUND_LIBRARY_CHANGED
Definition EventQueue.h:176
@ EVENT_TIMELINE_UPDATE
Tells the GUI some parts of the Timeline (tempo markers or tags) were modified.
Definition EventQueue.h:139
@ EVENT_NEXT_SHOT
Definition EventQueue.h:177
@ EVENT_SONG_SIZE_CHANGED
Definition EventQueue.h:173
@ EVENT_UPDATE_SONG
Event triggering HydrogenApp::updateSongEvent() whenever the Song was changed outside of the GUI,...
Definition EventQueue.h:128
@ EVENT_BBT_CHANGED
The coarse grained transport position in beats and bars did change.
Definition EventQueue.h:172
@ EVENT_LOOP_MODE_ACTIVATION
Toggles the button indicating the usage loop mode.
Definition EventQueue.h:150
@ EVENT_NOTEON
Definition EventQueue.h:86
@ EVENT_MIDI_ACTIVITY
Definition EventQueue.h:84
@ EVENT_MIDI_MAP_CHANGED
Definition EventQueue.h:178
@ EVENT_GRID_CELL_TOGGLED
Definition EventQueue.h:153
@ EVENT_NONE
Fallback event.
Definition EventQueue.h:42
@ EVENT_NEXT_PATTERNS_CHANGED
Used in Song::PatternMode::Stacked to indicate that a either AudioEngine::getNextPatterns() did chang...
Definition EventQueue.h:64
@ EVENT_SONG_MODIFIED
Definition EventQueue.h:102
@ EVENT_QUIT
Triggering HydrogenApp::quitEvent() and enables a shutdown of the entire application via the command ...
Definition EventQueue.h:133
@ EVENT_PROGRESS
Definition EventQueue.h:98
@ EVENT_ERROR
Definition EventQueue.h:87
@ EVENT_UPDATE_PREFERENCES
Event triggering the loading or saving of the H2Core::Preferences whenever they were changed outside ...
Definition EventQueue.h:116
@ EVENT_JACK_TIMEBASE_STATE_CHANGED
Toggles the button indicating the usage Jack timebase master and informs the GUI about a state change...
Definition EventQueue.h:144
@ EVENT_PATTERN_EDITOR_LOCKED
Locks the PatternEditor on the pattern currently played back.
Definition EventQueue.h:160
@ EVENT_JACK_SESSION
Definition EventQueue.h:99
@ EVENT_SONG_MODE_ACTIVATION
Definition EventQueue.h:145
@ EVENT_SELECTED_PATTERN_CHANGED
Another pattern was selected via MIDI or the GUI without affecting the audio transport.
Definition EventQueue.h:76
@ EVENT_DRIVER_CHANGED
Definition EventQueue.h:174
@ EVENT_STACKED_MODE_ACTIVATION
Song::PatternMode::Stacked (0) or Song::PatternMode::Selected (1) was activated.
Definition EventQueue.h:148
std::string get_version()
Returns the current Hydrogen version string.
Definition Version.cpp:30