diff --git a/.appveyor.yml b/.appveyor.yml index 3cb5d9a93..3b632d1f3 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -1,6 +1,6 @@ clone_depth: 1 version: "{build}" -image: Visual Studio 2015 +image: Visual Studio 2017 platform: - x86 - x64 @@ -16,7 +16,7 @@ build_script: - cd build - ps: $env:CMAKE_PLATFORM="$(if ($env:PLATFORM -eq 'x64') { 'x64' } else { '' })" - ps: $env:QT_SUFFIX="$(if ($env:PLATFORM -eq 'x64') { '_64' } else { '' })" - - cmake -DUSE_COMPILE_CACHE=ON -DCACHE_TOOL=%APPVEYOR_BUILD_FOLDER%/clcache.4.1.0/clcache-4.1.0/clcache.exe -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_PREFIX_PATH=c:/Qt/5.9/msvc2015%QT_SUFFIX%;c:/tools/vcpkg/installed/%PLATFORM%-windows -DCMAKE_GENERATOR_PLATFORM="%CMAKE_PLATFORM%" .. + - cmake -DUSE_COMPILE_CACHE=ON -DCACHE_TOOL=%APPVEYOR_BUILD_FOLDER%/clcache.4.1.0/clcache-4.1.0/clcache.exe -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_PREFIX_PATH=c:/Qt/5.12/msvc2017%QT_SUFFIX%;c:/tools/vcpkg/installed/%PLATFORM%-windows -DCMAKE_GENERATOR_PLATFORM="%CMAKE_PLATFORM%" .. - cmake --build . -- /maxcpucount:4 - cmake --build . --target tests cache: diff --git a/include/MainWindow.h b/include/MainWindow.h index 531cdfd52..74e569653 100644 --- a/include/MainWindow.h +++ b/include/MainWindow.h @@ -148,7 +148,6 @@ public slots: void emptySlot(); void createNewProject(); - void createNewProjectFromTemplate( QAction * _idx ); void openProject(); bool saveProject(); bool saveProjectAs(); @@ -204,10 +203,6 @@ private: QWidget * m_toolBar; QGridLayout * m_toolBarLayout; - QMenu * m_templatesMenu; - QMenu * m_recentlyOpenedProjectsMenu; - int m_custom_templates_count; - struct keyModifiers { keyModifiers() : @@ -240,10 +235,7 @@ private: private slots: void browseHelp(); - void fillTemplatesMenu(); - void openRecentlyOpenedProject( QAction * _action ); void showTool( QAction * _idx ); - void updateRecentlyOpenedProjectsMenu(); void updateViewMenu( void ); void updateConfig( QAction * _who ); void onToggleMetronome(); diff --git a/include/RecentProjectsMenu.h b/include/RecentProjectsMenu.h new file mode 100644 index 000000000..b3837ee2e --- /dev/null +++ b/include/RecentProjectsMenu.h @@ -0,0 +1,17 @@ +#ifndef RECENTPROJECTSMENU_H +#define RECENTPROJECTSMENU_H + +#include + +class RecentProjectsMenu : public QMenu +{ + Q_OBJECT +public: + RecentProjectsMenu(QWidget *parent = nullptr); + +private slots: + void fillMenu(); + void openProject(QAction * _action ); +}; + +#endif // RECENTPROJECTSMENU_H diff --git a/include/TemplatesMenu.h b/include/TemplatesMenu.h new file mode 100644 index 000000000..049f1f47e --- /dev/null +++ b/include/TemplatesMenu.h @@ -0,0 +1,21 @@ +#ifndef TEMPLATESMENU_H +#define TEMPLATESMENU_H + +#include +#include + +class TemplatesMenu : public QMenu +{ + Q_OBJECT +public: + TemplatesMenu(QWidget *parent = nullptr); + virtual ~TemplatesMenu() = default; + +private slots: + static void createNewProjectFromTemplate(QAction * _action); + void fillTemplatesMenu(); + void addTemplatesFromDir( const QDir& dir ); + +}; + +#endif // TEMPLATESMENU_H diff --git a/plugins/monstro/Monstro.cpp b/plugins/monstro/Monstro.cpp index acfd59b29..efb351fc8 100644 --- a/plugins/monstro/Monstro.cpp +++ b/plugins/monstro/Monstro.cpp @@ -328,7 +328,7 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf ) float o1l_f; float o1r_f; float o1l_p = m_osc1l_phase + o1lpo; // we add phase offset here so we don't have to do it every frame - float o1r_p = m_osc1r_phase + o1rpo; // then substract it again after loop... + float o1r_p = m_osc1r_phase + o1rpo; // then subtract it again after loop... float o1_pw; // osc2 vars diff --git a/plugins/sf2_player/sf2_player.cpp b/plugins/sf2_player/sf2_player.cpp index 53d639f84..cc2575d2b 100644 --- a/plugins/sf2_player/sf2_player.cpp +++ b/plugins/sf2_player/sf2_player.cpp @@ -267,6 +267,43 @@ void sf2Instrument::loadFile( const QString & _file ) // soundfont for the first time fails updateSampleRate(); } + + // setting the first bank and patch number that is found + auto sSoundCount = ::fluid_synth_sfcount( m_synth ); + for ( int i = 0; i < sSoundCount; ++i ) { + int iBank = 0; + int iProg = 0; + fluid_sfont_t *pSoundFont = ::fluid_synth_get_sfont( m_synth, i ); + + if ( pSoundFont ) { +#ifdef CONFIG_FLUID_BANK_OFFSET + int iBankOff = ::fluid_synth_get_bank_offset( m_synth, fluid_sfont_get_id( pSoundFont ) ); +#endif + + fluid_sfont_iteration_start( pSoundFont ); +#if FLUIDSYNTH_VERSION_MAJOR < 2 + fluid_preset_t preset; + fluid_preset_t *pCurPreset = &preset; +#else + fluid_preset_t *pCurPreset; +#endif + + if ( ( pCurPreset = fluid_sfont_iteration_next_wrapper( pSoundFont, pCurPreset ) ) ) { + iBank = fluid_preset_get_banknum( pCurPreset ); + iProg = fluid_preset_get_num( pCurPreset ); + +#ifdef CONFIG_FLUID_BANK_OFFSET + iBank += iBankOff; +#endif + + ::fluid_synth_bank_select( m_synth, 1, iBank ); + ::fluid_synth_program_change( m_synth, 1, iProg ); + m_bankNum.setValue( iBank ); + m_patchNum.setValue ( iProg ); + break; + } + } + } } @@ -678,7 +715,6 @@ void sf2Instrument::noteOff( SF2PluginData * n ) fluid_synth_noteoff( m_synth, m_channel, n->midiNote ); m_synthMutex.unlock(); } - } @@ -694,7 +730,6 @@ void sf2Instrument::play( sampleFrame * _working_buffer ) m_synthMutex.lock(); fluid_synth_pitch_bend( m_synth, m_channel, m_lastMidiPitch ); m_synthMutex.unlock(); - } const int currentMidiPitchRange = instrumentTrack()->midiPitchRange(); @@ -1006,7 +1041,6 @@ sf2InstrumentView::sf2InstrumentView( Instrument * _instrument, QWidget * _paren setPalette( pal ); updateFilename(); - } @@ -1045,7 +1079,6 @@ void sf2InstrumentView::modelChanged() connect( k, SIGNAL( fileLoading() ), this, SLOT( invalidateFile() ) ); updateFilename(); - } @@ -1157,6 +1190,3 @@ PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *m, void * ) } - - - diff --git a/plugins/sid/envelope.cc b/plugins/sid/envelope.cc index 7be289c53..e466bd67d 100644 --- a/plugins/sid/envelope.cc +++ b/plugins/sid/envelope.cc @@ -134,7 +134,7 @@ reg16 EnvelopeGenerator::rate_counter_period[] = { // of ENV3 with another timed loop to fully synchronize with ENV3. // // At the first period when an exponential counter period larger than one -// is used (decay or relase), one extra cycle is spent before the envelope is +// is used (decay or release), one extra cycle is spent before the envelope is // decremented. The envelope output is then delayed one cycle until the state // is changed to attack. Now one cycle less will be spent before the envelope // is incremented, and the situation is normalized. diff --git a/src/core/audio/AudioPulseAudio.cpp b/src/core/audio/AudioPulseAudio.cpp index 050086c60..857ef981b 100644 --- a/src/core/audio/AudioPulseAudio.cpp +++ b/src/core/audio/AudioPulseAudio.cpp @@ -139,7 +139,7 @@ static void stream_state_callback( pa_stream *s, void * userdata ) case PA_STREAM_FAILED: default: - qCritical( "Stream errror: %s\n", + qCritical( "Stream error: %s\n", pa_strerror(pa_context_errno( pa_stream_get_context( s ) ) ) ); } diff --git a/src/core/main.cpp b/src/core/main.cpp index f579ec8f6..1a1d61d8c 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -165,7 +165,7 @@ void printHelp() " rendertracks [options...] Render each track to a different file\n" " upgrade [out] Upgrade file and save as \n" " Standard out is used if no output file\n" - " is specifed\n" + " is specified\n" "\nGlobal options:\n" " --allowroot Bypass root user startup check (use with\n" " caution).\n" diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index f17ef105f..af316fddb 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -43,6 +43,9 @@ SET(LMMS_SRCS gui/editors/PianoRoll.cpp gui/editors/SongEditor.cpp + gui/menus/RecentProjectsMenu.cpp + gui/menus/TemplatesMenu.cpp + gui/widgets/AutomatableButton.cpp gui/widgets/AutomatableSlider.cpp gui/widgets/CaptionMenu.cpp diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index cc5f48874..0914d1685 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -57,10 +57,12 @@ #include "ProjectJournal.h" #include "ProjectNotes.h" #include "ProjectRenderer.h" +#include "RecentProjectsMenu.h" #include "RemotePlugin.h" #include "SetupDialog.h" #include "SideBar.h" #include "SongEditor.h" +#include "TemplatesMenu.h" #include "TextFloat.h" #include "TimeLineWidget.h" #include "ToolButton.h" @@ -88,8 +90,6 @@ void disableAutoKeyAccelerators(QWidget* mainWindow) MainWindow::MainWindow() : m_workspace( NULL ), - m_templatesMenu( NULL ), - m_recentlyOpenedProjectsMenu( NULL ), m_toolsMenu( NULL ), m_autoSaveTimer( this ), m_viewMenu( NULL ), @@ -277,25 +277,15 @@ void MainWindow::finalize() this, SLOT( createNewProject() ), QKeySequence::New ); - m_templatesMenu = new QMenu( tr("New from template"), this ); - connect( m_templatesMenu, SIGNAL( aboutToShow() ), SLOT( fillTemplatesMenu() ) ); - connect( m_templatesMenu, SIGNAL( triggered( QAction * ) ), - SLOT( createNewProjectFromTemplate( QAction * ) ) ); - - project_menu->addMenu(m_templatesMenu); + auto templates_menu = new TemplatesMenu( this ); + project_menu->addMenu(templates_menu); project_menu->addAction( embed::getIconPixmap( "project_open" ), tr( "&Open..." ), this, SLOT( openProject() ), QKeySequence::Open ); - m_recentlyOpenedProjectsMenu = project_menu->addMenu( - embed::getIconPixmap( "project_open_recent" ), - tr( "&Recently Opened Projects" ) ); - connect( m_recentlyOpenedProjectsMenu, SIGNAL( aboutToShow() ), - this, SLOT( updateRecentlyOpenedProjectsMenu() ) ); - connect( m_recentlyOpenedProjectsMenu, SIGNAL( triggered( QAction * ) ), - this, SLOT( openRecentlyOpenedProject( QAction * ) ) ); + project_menu->addMenu(new RecentProjectsMenu(this)); project_menu->addAction( embed::getIconPixmap( "project_save" ), tr( "&Save" ), @@ -429,7 +419,7 @@ void MainWindow::finalize() tr( "Create new project from template" ), this, SLOT( emptySlot() ), m_toolBar ); - project_new_from_template->setMenu( m_templatesMenu ); + project_new_from_template->setMenu( templates_menu ); project_new_from_template->setPopupMode( ToolButton::InstantPopup ); ToolButton * project_open = new ToolButton( @@ -443,7 +433,7 @@ void MainWindow::finalize() embed::getIconPixmap( "project_open_recent" ), tr( "Recently opened projects" ), this, SLOT( emptySlot() ), m_toolBar ); - project_open_recent->setMenu( m_recentlyOpenedProjectsMenu ); + project_open_recent->setMenu( new RecentProjectsMenu(this) ); project_open_recent->setPopupMode( ToolButton::InstantPopup ); ToolButton * project_save = new ToolButton( @@ -625,7 +615,7 @@ SubWindow* MainWindow::addWindowedWidget(QWidget *w, Qt::WindowFlags windowFlags SubWindow *win = new SubWindow(m_workspace->viewport(), windowFlags); win->setAttribute(Qt::WA_DeleteOnClose); win->setWidget(w); - if (w->sizeHint().isValid()) {win->resize(w->sizeHint());} + if (w && w->sizeHint().isValid()) {win->resize(w->sizeHint());} m_workspace->addSubWindow(win); return win; } @@ -809,24 +799,6 @@ void MainWindow::createNewProject() -void MainWindow::createNewProjectFromTemplate( QAction * _idx ) -{ - if( m_templatesMenu && mayChangeProject(true) ) - { - int indexOfTemplate = m_templatesMenu->actions().indexOf( _idx ); - bool isFactoryTemplate = indexOfTemplate >= m_custom_templates_count; - QString dirBase = isFactoryTemplate ? - ConfigManager::inst()->factoryTemplatesDir() : - ConfigManager::inst()->userTemplateDir(); - - const QString f = dirBase + _idx->text().replace("&&", "&") + ".mpt"; - Engine::getSong()->createNewProjectFromTemplate(f); - } -} - - - - void MainWindow::openProject() { if( mayChangeProject(false) ) @@ -851,56 +823,6 @@ void MainWindow::openProject() -void MainWindow::updateRecentlyOpenedProjectsMenu() -{ - m_recentlyOpenedProjectsMenu->clear(); - QStringList rup = ConfigManager::inst()->recentlyOpenedProjects(); - -// The file history goes 50 deep but we only show the 15 -// most recent ones that we can open and omit .mpt files. - int shownInMenu = 0; - for( QStringList::iterator it = rup.begin(); it != rup.end(); ++it ) - { - QFileInfo recentFile( *it ); - if ( recentFile.exists() && - *it != ConfigManager::inst()->recoveryFile() ) - { - if( recentFile.suffix().toLower() == "mpt" ) - { - continue; - } - - m_recentlyOpenedProjectsMenu->addAction( - embed::getIconPixmap( "project_file" ), it->replace("&", "&&") ); -#ifdef LMMS_BUILD_APPLE - m_recentlyOpenedProjectsMenu->actions().last()->setIconVisibleInMenu(false); // QTBUG-44565 workaround - m_recentlyOpenedProjectsMenu->actions().last()->setIconVisibleInMenu(true); -#endif - shownInMenu++; - if( shownInMenu >= 15 ) - { - return; - } - } - } -} - - - -void MainWindow::openRecentlyOpenedProject( QAction * _action ) -{ - if ( mayChangeProject(true) ) - { - const QString f = _action->text().replace("&&", "&"); - setCursor( Qt::WaitCursor ); - Engine::getSong()->loadProject( f ); - setCursor( Qt::ArrowCursor ); - } -} - - - - bool MainWindow::saveProject() { if( Engine::getSong()->projectFileName() == "" ) @@ -1448,40 +1370,6 @@ void MainWindow::timerEvent( QTimerEvent * _te) -void MainWindow::fillTemplatesMenu() -{ - m_templatesMenu->clear(); - - auto addTemplatesFromDir = [this]( QDir dir ) { - QStringList templates = dir.entryList( QStringList( "*.mpt" ), - QDir::Files | QDir::Readable ); - - if ( templates.size() && ! m_templatesMenu->actions().isEmpty() ) - { - m_templatesMenu->addSeparator(); - } - - for( QStringList::iterator it = templates.begin(); - it != templates.end(); ++it ) - { - m_templatesMenu->addAction( - embed::getIconPixmap( "project_file" ), - ( *it ).left( ( *it ).length() - 4 ).replace("&", "&&") ); -#ifdef LMMS_BUILD_APPLE - m_templatesMenu->actions().last()->setIconVisibleInMenu(false); // QTBUG-44565 workaround - m_templatesMenu->actions().last()->setIconVisibleInMenu(true); -#endif - } - - return templates.size(); - }; - - m_custom_templates_count = addTemplatesFromDir( ConfigManager::inst()->userTemplateDir() ); - addTemplatesFromDir( ConfigManager::inst()->factoryProjectsDir() + "templates" ); -} - - - void MainWindow::showTool( QAction * _idx ) { diff --git a/src/gui/TrackContainerView.cpp b/src/gui/TrackContainerView.cpp index 7c69d5eb8..649323c07 100644 --- a/src/gui/TrackContainerView.cpp +++ b/src/gui/TrackContainerView.cpp @@ -226,10 +226,9 @@ void TrackContainerView::scrollToTrackView( TrackView * _tv ) void TrackContainerView::realignTracks() { - QWidget * content = m_scrollArea->widget(); - content->setFixedWidth( width() - - m_scrollArea->verticalScrollBar()->width() ); - content->setFixedHeight( content->minimumSizeHint().height() ); + m_scrollArea->widget()->setFixedWidth(width()); + m_scrollArea->widget()->setFixedHeight( + m_scrollArea->widget()->minimumSizeHint().height()); for( trackViewList::iterator it = m_trackViews.begin(); it != m_trackViews.end(); ++it ) @@ -488,7 +487,6 @@ TrackContainerView::scrollArea::scrollArea( TrackContainerView * _parent ) : { setFrameStyle( QFrame::NoFrame ); setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff ); - setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOn ); } diff --git a/src/gui/menus/RecentProjectsMenu.cpp b/src/gui/menus/RecentProjectsMenu.cpp new file mode 100644 index 000000000..6f32b0df5 --- /dev/null +++ b/src/gui/menus/RecentProjectsMenu.cpp @@ -0,0 +1,78 @@ +#include "RecentProjectsMenu.h" + +#include + +#include "ConfigManager.h" +#include "Engine.h" +#include "Song.h" + +#include "embed.h" +#include "GuiApplication.h" +#include "MainWindow.h" + +RecentProjectsMenu::RecentProjectsMenu(QWidget *parent) : + QMenu(tr( "&Recently Opened Projects" ), parent) +{ + setIcon(embed::getIconPixmap( "project_open_recent" )); + + connect( this, SIGNAL( aboutToShow() ), + this, SLOT(fillMenu() ) ); + connect( this, SIGNAL( triggered( QAction * ) ), + this, SLOT(openProject(QAction * ) ) ); +} + + + + +void RecentProjectsMenu::fillMenu() +{ + clear(); + QStringList rup = ConfigManager::inst()->recentlyOpenedProjects(); + + auto projectFileIcon = embed::getIconPixmap( "project_file" ); + + // The file history goes 50 deep but we only show the 15 + // most recent ones that we can open and omit .mpt files. + int shownInMenu = 0; + for(QString& fileName : rup) + { + QFileInfo recentFile(fileName); + if (!recentFile.exists() || + fileName == ConfigManager::inst()->recoveryFile() ) + { + continue; + } + + if( recentFile.suffix().toLower() == "mpt" ) + { + continue; + } + + addAction(projectFileIcon, fileName.replace("&", "&&") ); +#ifdef LMMS_BUILD_APPLE + actions().last()->setIconVisibleInMenu(false); // QTBUG-44565 workaround + actions().last()->setIconVisibleInMenu(true); +#endif + + shownInMenu++; + if( shownInMenu >= 15 ) + { + break; + } + } +} + + + + +void RecentProjectsMenu::openProject(QAction * _action ) +{ + auto mainWindow = gui->mainWindow(); + if (mainWindow->mayChangeProject(true)) + { + const QString f = _action->text().replace("&&", "&"); + mainWindow->setCursor( Qt::WaitCursor ); + Engine::getSong()->loadProject( f ); + mainWindow->setCursor( Qt::ArrowCursor ); + } +} diff --git a/src/gui/menus/TemplatesMenu.cpp b/src/gui/menus/TemplatesMenu.cpp new file mode 100644 index 000000000..5fb740203 --- /dev/null +++ b/src/gui/menus/TemplatesMenu.cpp @@ -0,0 +1,67 @@ +#include "TemplatesMenu.h" + +#include "ConfigManager.h" +#include "Engine.h" +#include "Song.h" + +#include "embed.h" +#include "GuiApplication.h" +#include "MainWindow.h" + +TemplatesMenu::TemplatesMenu(QWidget *parent) : + QMenu(tr("New from template"), parent) +{ + connect( this, SIGNAL( aboutToShow() ), SLOT( fillTemplatesMenu() ) ); + connect( this, SIGNAL( triggered( QAction * ) ), + SLOT( createNewProjectFromTemplate( QAction * ) ) ); +} + + + + +void TemplatesMenu::createNewProjectFromTemplate(QAction * _action) +{ + if( gui->mainWindow()->mayChangeProject(true) ) + { + const QString& templateFilePath = _action->data().toString(); + Engine::getSong()->createNewProjectFromTemplate(templateFilePath); + } +} + + + + + +void TemplatesMenu::fillTemplatesMenu() +{ + clear(); + + addTemplatesFromDir(ConfigManager::inst()->userTemplateDir()); + addTemplatesFromDir(ConfigManager::inst()->factoryProjectsDir() + "templates"); +} + + + + +void TemplatesMenu::addTemplatesFromDir( const QDir& dir ) { + QFileInfoList templates = dir.entryInfoList( QStringList( "*.mpt" ), + QDir::Files | QDir::Readable ); + + if (!templates.empty() && !actions().isEmpty()) + { + addSeparator(); + } + + auto projectFileIcon = embed::getIconPixmap( "project_file" ); + + for(const QFileInfo& templateFile : templates) + { + auto action = addAction(projectFileIcon, + templateFile.completeBaseName().replace("&", "&&")); + action->setData(templateFile.absoluteFilePath()); +#ifdef LMMS_BUILD_APPLE + action->setIconVisibleInMenu(false); // QTBUG-44565 workaround + action->setIconVisibleInMenu(true); +#endif + } +} diff --git a/src/gui/widgets/EnvelopeAndLfoView.cpp b/src/gui/widgets/EnvelopeAndLfoView.cpp index cdad83d4f..4635dc831 100644 --- a/src/gui/widgets/EnvelopeAndLfoView.cpp +++ b/src/gui/widgets/EnvelopeAndLfoView.cpp @@ -419,8 +419,8 @@ void EnvelopeAndLfoView::paintEvent( QPaintEvent * ) p.fillRect( x5, y_base - 1, 2, 2, end_points_color ); - int LFO_GRAPH_W = s_lfoGraph->width() - 3; // substract border - int LFO_GRAPH_H = s_lfoGraph->height() - 6; // substract border + int LFO_GRAPH_W = s_lfoGraph->width() - 3; // subtract border + int LFO_GRAPH_H = s_lfoGraph->height() - 6; // subtract border int graph_x_base = LFO_GRAPH_X + 2; int graph_y_base = LFO_GRAPH_Y + 3 + LFO_GRAPH_H / 2; diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index 931e3d327..730ab97bd 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -652,8 +652,11 @@ bool InstrumentTrack::play( const MidiTime & _start, const fpp_t _frames, for( tcoVector::Iterator it = tcos.begin(); it != tcos.end(); ++it ) { Pattern* p = dynamic_cast( *it ); - // everything which is not a pattern or muted won't be played - if( p == NULL || ( *it )->isMuted() ) + // everything which is not a pattern won't be played + // A pattern playing in the Piano Roll window will always play + if(p == NULL || + (Engine::getSong()->playMode() != Song::Mode_PlayPattern + && (*it)->isMuted())) { continue; }