diff --git a/data/themes/default/metronome.png b/data/themes/default/metronome.png new file mode 100644 index 00000000000..e20815a213d Binary files /dev/null and b/data/themes/default/metronome.png differ diff --git a/include/MainWindow.h b/include/MainWindow.h index f3b93740f10..186369a0deb 100644 --- a/include/MainWindow.h +++ b/include/MainWindow.h @@ -185,6 +185,8 @@ public slots: QMenu * m_viewMenu; + ToolButton * m_metronomeToggle; + private slots: void browseHelp(); void fillTemplatesMenu(); @@ -193,6 +195,7 @@ private slots: void updateRecentlyOpenedProjectsMenu(); void updateViewMenu( void ); void updateConfig( QAction * _who ); + void onToggleMetronome(); void autoSave(); diff --git a/include/Mixer.h b/include/Mixer.h index 3f0ea0fb671..d2bf15864a5 100644 --- a/include/Mixer.h +++ b/include/Mixer.h @@ -355,6 +355,9 @@ class EXPORT Mixer : public QObject void changeQuality( const struct qualitySettings & _qs ); + inline bool isMetronomeActive() const { return m_metronomeActive; } + inline void setMetronomeActive(bool value = true) { m_metronomeActive = value; } + signals: void qualitySettingsChanged(); @@ -457,6 +460,8 @@ class EXPORT Mixer : public QObject MixerProfiler m_profiler; + bool m_metronomeActive; + friend class Engine; friend class MixerWorkerThread; diff --git a/src/core/Mixer.cpp b/src/core/Mixer.cpp index 06e9fabf8f2..948a4790f96 100644 --- a/src/core/Mixer.cpp +++ b/src/core/Mixer.cpp @@ -73,7 +73,8 @@ Mixer::Mixer( bool renderOnly ) : m_audioDev( NULL ), m_oldAudioDev( NULL ), m_globalMutex( QMutex::Recursive ), - m_profiler() + m_profiler(), + m_metronomeActive(false) { for( int i = 0; i < 2; ++i ) { @@ -318,18 +319,25 @@ const surroundSampleFrame * Mixer::renderNextBuffer() static Song::PlayPos last_metro_pos = -1; - Song::PlayPos p = Engine::getSong()->getPlayPos( - Song::Mode_PlayPattern ); - if( Engine::getSong()->playMode() == Song::Mode_PlayPattern && - gui->pianoRoll()->isRecording() == true && + Song *song = Engine::getSong(); + + Song::PlayModes currentPlayMode = song->playMode(); + Song::PlayPos p = song->getPlayPos( currentPlayMode ); + + bool playModeSupportsMetronome = currentPlayMode == Song::Mode_PlayPattern || + currentPlayMode == Song::Mode_PlaySong || + currentPlayMode == Song::Mode_PlayBB; + + if( playModeSupportsMetronome && m_metronomeActive && !song->isExporting() && p != last_metro_pos ) { - if ( p.getTicks() % (MidiTime::ticksPerTact() / 1 ) == 0 ) + tick_t ticksPerTact = MidiTime::ticksPerTact(); + if ( p.getTicks() % (ticksPerTact / 1 ) == 0 ) { addPlayHandle( new SamplePlayHandle( "misc/metronome02.ogg" ) ); } - else if ( p.getTicks() % (MidiTime::ticksPerTact() / - Engine::getSong()->getTimeSigModel().getNumerator() ) == 0 ) + else if ( p.getTicks() % (ticksPerTact / + song->getTimeSigModel().getNumerator() ) == 0 ) { addPlayHandle( new SamplePlayHandle( "misc/metronome01.ogg" ) ); } @@ -337,9 +345,11 @@ const surroundSampleFrame * Mixer::renderNextBuffer() } lockInputFrames(); + // swap buffer m_inputBufferWrite = ( m_inputBufferWrite + 1 ) % 2; m_inputBufferRead = ( m_inputBufferRead + 1 ) % 2; + // clear new write buffer m_inputBufferFrames[ m_inputBufferWrite ] = 0; unlockInputFrames(); @@ -383,10 +393,11 @@ const surroundSampleFrame * Mixer::renderNextBuffer() clearAudioBuffer( m_writeBuf, m_framesPerPeriod ); // prepare master mix (clear internal buffers etc.) - Engine::fxMixer()->prepareMasterMix(); + FxMixer * fxMixer = Engine::fxMixer(); + fxMixer->prepareMasterMix(); // create play-handles for new notes, samples etc. - Engine::getSong()->processNextBuffer(); + song->processNextBuffer(); // add all play-handles that have to be added m_playHandleMutex.lock(); @@ -432,7 +443,7 @@ const surroundSampleFrame * Mixer::renderNextBuffer() // STAGE 3: do master mix in FX mixer - Engine::fxMixer()->masterMix( m_writeBuf ); + fxMixer->masterMix( m_writeBuf ); unlock(); diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index 389dcd75ec2..09a62935224 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -78,7 +78,8 @@ MainWindow::MainWindow() : m_recentlyOpenedProjectsMenu( NULL ), m_toolsMenu( NULL ), m_autoSaveTimer( this ), - m_viewMenu( NULL ) + m_viewMenu( NULL ), + m_metronomeToggle( 0 ) { setAttribute( Qt::WA_DeleteOnClose ); @@ -430,6 +431,13 @@ void MainWindow::finalize() this, SLOT( enterWhatsThisMode() ), m_toolBar ); + m_metronomeToggle = new ToolButton( + embed::getIconPixmap( "metronome" ), + tr( "Toggle metronome" ), + this, SLOT( onToggleMetronome() ), + m_toolBar ); + m_metronomeToggle->setCheckable(true); + m_metronomeToggle->setChecked(Engine::mixer()->isMetronomeActive()); m_toolBarLayout->setColumnMinimumWidth( 0, 5 ); m_toolBarLayout->addWidget( project_new, 0, 1 ); @@ -439,6 +447,7 @@ void MainWindow::finalize() m_toolBarLayout->addWidget( project_save, 0, 5 ); m_toolBarLayout->addWidget( project_export, 0, 6 ); m_toolBarLayout->addWidget( whatsthis, 0, 7 ); + m_toolBarLayout->addWidget( m_metronomeToggle, 0, 8 ); // window-toolbar @@ -1209,6 +1218,17 @@ void MainWindow::updateConfig( QAction * _who ) } + +void MainWindow::onToggleMetronome() +{ + Mixer * mixer = Engine::mixer(); + + mixer->setMetronomeActive( m_metronomeToggle->isChecked() ); +} + + + + void MainWindow::toggleControllerRack() { toggleWindow( gui->getControllerRackView() ); diff --git a/src/gui/editors/SongEditor.cpp b/src/gui/editors/SongEditor.cpp index f4616c47e4b..993f3cf342d 100644 --- a/src/gui/editors/SongEditor.cpp +++ b/src/gui/editors/SongEditor.cpp @@ -111,7 +111,7 @@ SongEditor::SongEditor( Song * _song ) : // add some essential widgets to global tool-bar QWidget * tb = gui->mainWindow()->toolBar(); - gui->mainWindow()->addSpacingToToolBar( 10 ); + gui->mainWindow()->addSpacingToToolBar( 40 ); m_tempoSpinBox = new LcdSpinBox( 3, tb, tr( "Tempo" ) ); m_tempoSpinBox->setModel( &m_song->m_tempoModel );