diff --git a/CMakeLists.txt b/CMakeLists.txt index d04318e51..d9fe8202e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -573,15 +573,20 @@ ADD_SUBDIRECTORY(doc) # install tasks ADD_SUBDIRECTORY(cmake/install) -ADD_CUSTOM_COMMAND(OUTPUT "${CMAKE_BINARY_DIR}/lmms.1.gz" - COMMAND gzip -c ${CMAKE_SOURCE_DIR}/doc/lmms.1 > ${CMAKE_BINARY_DIR}/lmms.1.gz - DEPENDS "${CMAKE_SOURCE_DIR}/doc/lmms.1" - COMMENT "Generating lmms.1.gz" - VERBATIM) +FIND_PACKAGE(UnixCommands) +IF(GZIP) + ADD_CUSTOM_COMMAND(OUTPUT "${CMAKE_BINARY_DIR}/lmms.1.gz" + COMMAND ${GZIP} -c ${CMAKE_SOURCE_DIR}/doc/lmms.1 > ${CMAKE_BINARY_DIR}/lmms.1.gz + DEPENDS "${CMAKE_SOURCE_DIR}/doc/lmms.1" + COMMENT "Generating lmms.1.gz" + VERBATIM) -ADD_CUSTOM_TARGET(manpage ALL - DEPENDS "${CMAKE_BINARY_DIR}/lmms.1.gz") + ADD_CUSTOM_TARGET(manpage ALL + DEPENDS "${CMAKE_BINARY_DIR}/lmms.1.gz") +ELSEIF(UNIX) + MESSAGE(FATAL_ERROR "Can't find gzip required for generating lmms.1.gz") +ENDIF() # install headers diff --git a/cmake/install/CMakeLists.txt b/cmake/install/CMakeLists.txt index e123ae384..cd4100c9b 100644 --- a/cmake/install/CMakeLists.txt +++ b/cmake/install/CMakeLists.txt @@ -32,7 +32,7 @@ IF(LMMS_BUILD_WIN32 OR LMMS_INSTALL_DEPENDENCIES) TARGETS ${PLUGINS_BUILT} DESTINATION ${PLUGIN_DEP_DESTINATION} LIB_DIRS ${LIB_DIRS} "${PLUGIN_DIR}" "${PLUGIN_DIR}/optional" - SEARCH_PATH "${PLUGIN_DIR}" "${PLUGIN_DIR}/optional" + SEARCH_PATHS "${PLUGIN_DIR}" "${PLUGIN_DIR}/optional" ) ENDIF() diff --git a/cmake/modules/InstallTargetDependencies.cmake b/cmake/modules/InstallTargetDependencies.cmake index 9665a0b87..8e48c9ef7 100644 --- a/cmake/modules/InstallTargetDependencies.cmake +++ b/cmake/modules/InstallTargetDependencies.cmake @@ -12,12 +12,13 @@ SET(DEFAULT_SEARCH_SUFFIXES "bin" "lib" "../bin") # DESTINATION: directory path to install the binaries to. # LIB_DIRS: list of paths for looking up dependencies. # LIB_DIRS_SUFFIXES: list of possible suffixes for LIB_DIRS entries. +# SEARCH_PATHS: list of library search paths on runtime # NO_DEFAULT_PATHS: supply this value to avoid adding DEFAULT_SEARCH_DIRECTORIES # to LIB_DIRS and DEFAULT_SEARCH_SUFFIXES to LIB_DIRS_SUFFIXES. FUNCTION(INSTALL_TARGET_DEPENDENCIES) set(options NO_DEFAULT_PATHS) set(oneValueArgs NAME) - set(multiValueArgs TARGETS DESTINATION LIB_DIRS_SUFFIXES LIB_DIRS) + set(multiValueArgs TARGETS DESTINATION LIB_DIRS_SUFFIXES LIB_DIRS SEARCH_PATHS) cmake_parse_arguments(DEPS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} ) diff --git a/data/themes/classic/style.css b/data/themes/classic/style.css index 97d68f6e3..3fbb2e6fb 100644 --- a/data/themes/classic/style.css +++ b/data/themes/classic/style.css @@ -159,7 +159,7 @@ GroupBox { /* main toolbar oscilloscope - can have transparent bg now */ -VisualizationWidget { +Oscilloscope { background: none; border: none; qproperty-normalColor: rgb(71, 253, 133); diff --git a/data/themes/default/style.css b/data/themes/default/style.css index f95469201..bedb8ea32 100644 --- a/data/themes/default/style.css +++ b/data/themes/default/style.css @@ -191,7 +191,7 @@ GroupBox { /* main toolbar oscilloscope - can have transparent bg now */ -VisualizationWidget { +Oscilloscope { background: none; border: none; qproperty-normalColor: rgb(71, 253, 133); diff --git a/include/InstrumentTrack.h b/include/InstrumentTrack.h index f2602686b..b30d5cb21 100644 --- a/include/InstrumentTrack.h +++ b/include/InstrumentTrack.h @@ -214,6 +214,10 @@ public: void setPreviewMode( const bool ); + bool isPreviewMode() const + { + return m_previewMode; + } signals: void instrumentChanged(); @@ -230,6 +234,9 @@ protected: return "instrumenttrack"; } + // get the name of the instrument in the saved data + QString getSavedInstrumentName(const QDomElement & thisElement) const; + protected slots: void updateBaseNote(); diff --git a/include/VisualizationWidget.h b/include/Oscilloscope.h similarity index 83% rename from include/VisualizationWidget.h rename to include/Oscilloscope.h index 85825975a..49db1393b 100644 --- a/include/VisualizationWidget.h +++ b/include/Oscilloscope.h @@ -1,5 +1,5 @@ /* - * VisualizationWidget.h - widget for visualization of sound-data + * Oscilloscope.h * * Copyright (c) 2005-2008 Tobias Doerffel * @@ -23,8 +23,8 @@ */ -#ifndef _VISUALIZATION_WIDGET -#define _VISUALIZATION_WIDGET +#ifndef _OSCILLOSCOPE +#define _OSCILLOSCOPE #include #include @@ -32,21 +32,16 @@ #include "lmms_basics.h" -class VisualizationWidget : public QWidget +class Oscilloscope : public QWidget { Q_OBJECT public: Q_PROPERTY( QColor normalColor READ normalColor WRITE setNormalColor ) Q_PROPERTY( QColor warningColor READ warningColor WRITE setWarningColor ) Q_PROPERTY( QColor clippingColor READ clippingColor WRITE setClippingColor ) - enum visualizationTypes - { - Simple // add more here - } ; - VisualizationWidget( const QPixmap & _bg, QWidget * _parent, - visualizationTypes _vtype = Simple ); - virtual ~VisualizationWidget(); + Oscilloscope( QWidget * _parent ); + virtual ~Oscilloscope(); void setActive( bool _active ); @@ -72,7 +67,7 @@ private: QColor const & determineLineColor(float level) const; private: - QPixmap s_background; + QPixmap m_background; QPointF * m_points; sampleFrame * m_buffer; diff --git a/include/PianoRoll.h b/include/PianoRoll.h index 8421392c3..5859594f6 100644 --- a/include/PianoRoll.h +++ b/include/PianoRoll.h @@ -283,6 +283,7 @@ private: QList m_markedSemiTones; QMenu * m_semiToneMarkerMenu; // when you right click on the key area + int m_pianoKeySelected; PianoRoll(); PianoRoll( const PianoRoll & ); diff --git a/include/SetupDialog.h b/include/SetupDialog.h index 9f9ae1b3f..80a22d69c 100644 --- a/include/SetupDialog.h +++ b/include/SetupDialog.h @@ -74,6 +74,7 @@ private slots: void toggleNoteLabels(bool enabled); void toggleCompactTrackButtons(bool enabled); void toggleOneInstrumentTrackWindow(bool enabled); + void toggleSideBarOnRight(bool enabled); void toggleMMPZ(bool enabled); void toggleDisableBackup(bool enabled); void toggleOpenLastProject(bool enabled); @@ -130,6 +131,7 @@ private: bool m_printNoteLabels; bool m_compactTrackButtons; bool m_oneInstrumentTrackWindow; + bool m_sideBarOnRight; bool m_MMPZ; bool m_disableBackup; bool m_openLastProject; diff --git a/plugins/Amplifier/Amplifier.cpp b/plugins/Amplifier/Amplifier.cpp index d90ea55b3..cc2a63304 100644 --- a/plugins/Amplifier/Amplifier.cpp +++ b/plugins/Amplifier/Amplifier.cpp @@ -83,7 +83,6 @@ bool AmplifierEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames ) for( fpp_t f = 0; f < frames; ++f ) { // qDebug( "offset %d, value %f", f, m_ampControls.m_volumeModel.value( f ) ); - outSum += buf[f][0]*buf[f][0] + buf[f][1]*buf[f][1]; sample_t s[2] = { buf[f][0], buf[f][1] }; @@ -123,6 +122,7 @@ bool AmplifierEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames ) buf[f][0] = d * buf[f][0] + w * s[0]; buf[f][1] = d * buf[f][1] + w * s[1]; + outSum += buf[f][0] * buf[f][0] + buf[f][1] * buf[f][1]; } checkGate( outSum / frames ); diff --git a/plugins/BassBooster/BassBooster.cpp b/plugins/BassBooster/BassBooster.cpp index 6fdb1671c..535834aae 100644 --- a/plugins/BassBooster/BassBooster.cpp +++ b/plugins/BassBooster/BassBooster.cpp @@ -100,13 +100,13 @@ bool BassBoosterEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames //float gain = gainBuffer ? gainBuffer[f] : gain; m_bbFX.leftFX().setGain( gain ); m_bbFX.rightFX().setGain( gain); - outSum += buf[f][0]*buf[f][0] + buf[f][1]*buf[f][1]; sample_t s[2] = { buf[f][0], buf[f][1] }; m_bbFX.nextSample( s[0], s[1] ); buf[f][0] = d * buf[f][0] + w * s[0]; buf[f][1] = d * buf[f][1] + w * s[1]; + outSum += buf[f][0] * buf[f][0] + buf[f][1] * buf[f][1]; } checkGate( outSum / frames ); diff --git a/plugins/Bitcrush/BitcrushControls.cpp b/plugins/Bitcrush/BitcrushControls.cpp index 6aafd0b19..f768be4b8 100644 --- a/plugins/Bitcrush/BitcrushControls.cpp +++ b/plugins/Bitcrush/BitcrushControls.cpp @@ -40,7 +40,7 @@ BitcrushControls::BitcrushControls( BitcrushEffect * eff ) : m_outClip( 0.0f, -20.0f, 20.0f, 0.1f, this, tr( "Output clip" ) ), m_rate( 44100.f, 20.f, 44100.f, 1.0f, this, tr( "Sample rate" ) ), m_stereoDiff( 0.f, 0.f, 50.f, 0.1f, this, tr( "Stereo difference" ) ), - m_levels( 256.f, 1.f, 256.f, 1.0f, this, tr( "Levels" ) ), + m_levels( 256.f, 1.f, 256.f, 0.01f, this, tr( "Levels" ) ), m_rateEnabled( true, this, tr( "Rate enabled" ) ), m_depthEnabled( true, this, tr( "Depth enabled" ) ) { diff --git a/plugins/CrossoverEQ/CrossoverEQ.cpp b/plugins/CrossoverEQ/CrossoverEQ.cpp index e7d3dce7d..e2090980a 100644 --- a/plugins/CrossoverEQ/CrossoverEQ.cpp +++ b/plugins/CrossoverEQ/CrossoverEQ.cpp @@ -191,12 +191,12 @@ bool CrossoverEQEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames double outSum = 0.0; for( int f = 0; f < frames; ++f ) { - outSum = buf[f][0] * buf[f][0] + buf[f][1] * buf[f][1]; buf[f][0] = d * buf[f][0] + w * m_work[f][0]; buf[f][1] = d * buf[f][1] + w * m_work[f][1]; + outSum += buf[f][0] * buf[f][0] + buf[f][1] * buf[f][1]; } - checkGate( outSum ); + checkGate( outSum / frames ); return isRunning(); } diff --git a/plugins/DualFilter/DualFilter.cpp b/plugins/DualFilter/DualFilter.cpp index 5b8b7a622..b4e11ccb3 100644 --- a/plugins/DualFilter/DualFilter.cpp +++ b/plugins/DualFilter/DualFilter.cpp @@ -193,11 +193,11 @@ bool DualFilterEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames s[0] += ( s2[0] * mix2 ); s[1] += ( s2[1] * mix2 ); } - outSum += buf[f][0]*buf[f][0] + buf[f][1]*buf[f][1]; // do another mix with dry signal buf[f][0] = d * buf[f][0] + w * s[0]; buf[f][1] = d * buf[f][1] + w * s[1]; + outSum += buf[f][0] * buf[f][0] + buf[f][1] * buf[f][1]; //increment pointers cut1Ptr += cut1Inc; diff --git a/plugins/audio_file_processor/audio_file_processor.cpp b/plugins/audio_file_processor/audio_file_processor.cpp index 7a6eb66ac..c8850392e 100644 --- a/plugins/audio_file_processor/audio_file_processor.cpp +++ b/plugins/audio_file_processor/audio_file_processor.cpp @@ -253,17 +253,16 @@ void audioFileProcessor::loadSettings( const QDomElement & _this ) m_loopModel.loadSettings( _this, "looped" ); m_ampModel.loadSettings( _this, "amp" ); m_endPointModel.loadSettings( _this, "eframe" ); + m_startPointModel.loadSettings( _this, "sframe" ); // compat code for not having a separate loopback point - if( _this.hasAttribute( "lframe" ) ) + if (_this.hasAttribute("lframe") || !(_this.firstChildElement("lframe").isNull())) { m_loopPointModel.loadSettings( _this, "lframe" ); - m_startPointModel.loadSettings( _this, "sframe" ); } else { m_loopPointModel.loadSettings( _this, "sframe" ); - m_startPointModel.setValue( m_loopPointModel.value() ); } m_reverseModel.loadSettings( _this, "reversed" ); diff --git a/plugins/dynamics_processor/dynamics_processor.cpp b/plugins/dynamics_processor/dynamics_processor.cpp index 8c02b827d..9bf7d9b3c 100644 --- a/plugins/dynamics_processor/dynamics_processor.cpp +++ b/plugins/dynamics_processor/dynamics_processor.cpp @@ -215,10 +215,10 @@ bool dynProcEffect::processAudioBuffer( sampleFrame * _buf, s[0] *= outputGain; s[1] *= outputGain; - out_sum += _buf[f][0]*_buf[f][0] + _buf[f][1]*_buf[f][1]; // mix wet/dry signals _buf[f][0] = d * _buf[f][0] + w * s[0]; _buf[f][1] = d * _buf[f][1] + w * s[1]; + out_sum += _buf[f][0] * _buf[f][0] + _buf[f][1] * _buf[f][1]; } checkGate( out_sum / _frames ); diff --git a/plugins/vestige/vestige.cpp b/plugins/vestige/vestige.cpp index 31f359e2a..c0d101784 100644 --- a/plugins/vestige/vestige.cpp +++ b/plugins/vestige/vestige.cpp @@ -196,9 +196,15 @@ void vestigeInstrument::loadSettings( const QDomElement & _this ) { m_plugin->loadSettings( _this ); - if ( _this.attribute( "guivisible" ).toInt() ) { + if (instrumentTrack() != NULL && instrumentTrack()->isPreviewMode()) + { + m_plugin->hideUI(); + } + else if (_this.attribute( "guivisible" ).toInt()) + { m_plugin->showUI(); - } else { + } else + { m_plugin->hideUI(); } @@ -320,12 +326,17 @@ void vestigeInstrument::loadFile( const QString & _file ) { m_pluginMutex.lock(); const bool set_ch_name = ( m_plugin != NULL && - instrumentTrack()->name() == m_plugin->name() ) || - instrumentTrack()->name() == InstrumentTrack::tr( "Default preset" ) || - instrumentTrack()->name() == displayName(); + instrumentTrack()->name() == m_plugin->name() ) || + instrumentTrack()->name() == InstrumentTrack::tr( "Default preset" ) || + instrumentTrack()->name() == displayName(); m_pluginMutex.unlock(); + // if the same is loaded don't load again (for preview) + if (instrumentTrack() != NULL && instrumentTrack()->isPreviewMode() && + m_pluginDLL == SampleBuffer::tryToMakeRelative( _file )) + return; + if ( m_plugin != NULL ) { closePlugin(); @@ -352,8 +363,11 @@ void vestigeInstrument::loadFile( const QString & _file ) return; } - m_plugin->createUI(nullptr); - m_plugin->showUI(); + if ( !(instrumentTrack() != NULL && instrumentTrack()->isPreviewMode())) + { + m_plugin->createUI(nullptr); + m_plugin->showUI(); + } if( set_ch_name ) { diff --git a/plugins/waveshaper/waveshaper.cpp b/plugins/waveshaper/waveshaper.cpp index 3f9d3e19f..a3bf2ddfb 100644 --- a/plugins/waveshaper/waveshaper.cpp +++ b/plugins/waveshaper/waveshaper.cpp @@ -140,10 +140,10 @@ bool waveShaperEffect::processAudioBuffer( sampleFrame * _buf, s[0] *= *outputPtr; s[1] *= *outputPtr; - out_sum += _buf[f][0]*_buf[f][0] + _buf[f][1]*_buf[f][1]; // mix wet/dry signals _buf[f][0] = d * _buf[f][0] + w * s[0]; _buf[f][1] = d * _buf[f][1] + w * s[1]; + out_sum += _buf[f][0] * _buf[f][0] + _buf[f][1] * _buf[f][1]; outputPtr += outputInc; inputPtr += inputInc; diff --git a/src/3rdparty/CMakeLists.txt b/src/3rdparty/CMakeLists.txt index 01cf80dee..a5ba31c3a 100644 --- a/src/3rdparty/CMakeLists.txt +++ b/src/3rdparty/CMakeLists.txt @@ -1,8 +1,3 @@ -set(CMAKE_C_FLAGS "") -set(CMAKE_CXX_FLAGS "") -set(CMAKE_C_FLAGS_DEBUG "") -set(CMAKE_CXX_FLAGS_DEBUG "") - IF(LMMS_BUILD_LINUX AND WANT_VST) set(BUILD_SHARED_LIBS OFF) add_subdirectory(qt5-x11embed) diff --git a/src/3rdparty/rpmalloc/CMakeLists.txt b/src/3rdparty/rpmalloc/CMakeLists.txt index 23d1551c2..3b3afa6d3 100644 --- a/src/3rdparty/rpmalloc/CMakeLists.txt +++ b/src/3rdparty/rpmalloc/CMakeLists.txt @@ -1,5 +1,3 @@ -set(CMAKE_C_FLAGS "-std=c11") - add_library(rpmalloc STATIC rpmalloc/rpmalloc/rpmalloc.c rpmalloc/rpmalloc/rpmalloc.h @@ -9,6 +7,14 @@ target_include_directories(rpmalloc PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/rpmalloc/rpmalloc ) +set_property(TARGET rpmalloc PROPERTY C_STANDARD 11) + +IF(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") + target_compile_options(rpmalloc + PRIVATE -Wno-unused-variable + ) +endif() + if (NOT LMMS_BUILD_WIN32) target_compile_definitions(rpmalloc PRIVATE -D_GNU_SOURCE diff --git a/src/core/DrumSynth.cpp b/src/core/DrumSynth.cpp index c41de1fd4..859fe403f 100644 --- a/src/core/DrumSynth.cpp +++ b/src/core/DrumSynth.cpp @@ -325,6 +325,8 @@ int DrumSynth::GetDSFileSamples(QString dsfile, int16_t *&wave, int channels, sa timestretch = .01f * mem_time * GetPrivateProfileFloat(sec,"Stretch",100.0,dsfile); if(timestretch<0.2f) timestretch=0.2f; if(timestretch>10.f) timestretch=10.f; + // the unit of envelope lengths is a sample in 44100Hz sample rate, so correct it + timestretch *= Fs / 44100.f; DGain = 1.0f; //leave this here! DGain = (float)powf(10.0, 0.05 * GetPrivateProfileFloat(sec,"Level",0,dsfile)); diff --git a/src/core/PresetPreviewPlayHandle.cpp b/src/core/PresetPreviewPlayHandle.cpp index df45eabe4..ce918a85a 100644 --- a/src/core/PresetPreviewPlayHandle.cpp +++ b/src/core/PresetPreviewPlayHandle.cpp @@ -156,19 +156,9 @@ PresetPreviewPlayHandle::PresetPreviewPlayHandle( const QString & _preset_file, dataFileCreated = true; } - // vestige previews are bug prone; fallback on 3xosc with volume of 0 - // without an instrument in preview track, it will segfault - if(dataFile->content().elementsByTagName( "vestige" ).length() == 0 ) - { - s_previewTC->previewInstrumentTrack()-> - loadTrackSpecificSettings( - dataFile->content().firstChild().toElement() ); - } - else - { - s_previewTC->previewInstrumentTrack()->loadInstrument("tripleoscillator"); - s_previewTC->previewInstrumentTrack()->setVolume( 0 ); - } + s_previewTC->previewInstrumentTrack()->loadTrackSpecificSettings( + dataFile->content().firstChild().toElement()); + if( dataFileCreated ) { delete dataFile; diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index dbdcc5d84..a340867a8 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -77,6 +77,7 @@ SET(LMMS_SRCS gui/widgets/MeterDialog.cpp gui/widgets/MidiPortMenu.cpp gui/widgets/NStateButton.cpp + gui/widgets/Oscilloscope.cpp gui/widgets/PixmapButton.cpp gui/widgets/ProjectNotes.cpp gui/widgets/RenameDialog.cpp @@ -93,7 +94,6 @@ SET(LMMS_SRCS gui/widgets/ToolTip.cpp gui/widgets/TrackLabelButton.cpp gui/widgets/TrackRenameLineEdit.cpp - gui/widgets/VisualizationWidget.cpp gui/widgets/StepRecorderWidget.cpp PARENT_SCOPE diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index 3eb532981..bf8863ec6 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -117,6 +117,7 @@ MainWindow::MainWindow() : splitter->setChildrenCollapsible( false ); ConfigManager* confMgr = ConfigManager::inst(); + bool sideBarOnRight = confMgr->value("ui", "sidebaronright").toInt(); emit initProgress(tr("Preparing plugin browser")); sideBar->appendTab( new PluginBrowser( splitter ) ); @@ -171,7 +172,7 @@ MainWindow::MainWindow() : embed::getIconPixmap( "computer" ).transformed( QTransform().rotate( 90 ) ), splitter, dirs_as_items) ); - m_workspace = new QMdiArea( splitter ); + m_workspace = new QMdiArea(splitter); // Load background emit initProgress(tr("Loading background picture")); @@ -194,9 +195,15 @@ MainWindow::MainWindow() : m_workspace->setHorizontalScrollBarPolicy( Qt::ScrollBarAsNeeded ); m_workspace->setVerticalScrollBarPolicy( Qt::ScrollBarAsNeeded ); - hbox->addWidget( sideBar ); - hbox->addWidget( splitter ); - + hbox->addWidget(sideBar); + hbox->addWidget(splitter); + // If the user wants the sidebar on the right, we move the workspace and + // the splitter to the "left" side, or the first widgets in their list + if (sideBarOnRight) + { + splitter->insertWidget(0, m_workspace); + hbox->insertWidget(0, splitter); + } // create global-toolbar at the top of our window m_toolBar = new QWidget( main_widget ); diff --git a/src/gui/SetupDialog.cpp b/src/gui/SetupDialog.cpp index 885f43dec..6de547b5a 100644 --- a/src/gui/SetupDialog.cpp +++ b/src/gui/SetupDialog.cpp @@ -100,6 +100,8 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) : "ui", "compacttrackbuttons").toInt()), m_oneInstrumentTrackWindow(ConfigManager::inst()->value( "ui", "oneinstrumenttrackwindow").toInt()), + m_sideBarOnRight(ConfigManager::inst()->value( + "ui", "sidebaronright").toInt()), m_MMPZ(!ConfigManager::inst()->value( "app", "nommpz").toInt()), m_disableBackup(!ConfigManager::inst()->value( @@ -229,6 +231,8 @@ SetupDialog::SetupDialog(ConfigTabs tab_to_open) : m_compactTrackButtons, SLOT(toggleCompactTrackButtons(bool)), true); addLedCheckBox("Enable one instrument-track-window mode", gui_tw, counter, m_oneInstrumentTrackWindow, SLOT(toggleOneInstrumentTrackWindow(bool)), true); + addLedCheckBox("Show sidebar on the right-hand side", gui_tw, counter, + m_sideBarOnRight, SLOT(toggleSideBarOnRight(bool)), true); gui_tw->setFixedHeight(YDelta + YDelta * counter); @@ -876,6 +880,8 @@ void SetupDialog::accept() QString::number(m_compactTrackButtons)); ConfigManager::inst()->setValue("ui", "oneinstrumenttrackwindow", QString::number(m_oneInstrumentTrackWindow)); + ConfigManager::inst()->setValue("ui", "sidebaronright", + QString::number(m_sideBarOnRight)); ConfigManager::inst()->setValue("app", "nommpz", QString::number(!m_MMPZ)); ConfigManager::inst()->setValue("app", "disablebackup", @@ -980,6 +986,12 @@ void SetupDialog::toggleOneInstrumentTrackWindow(bool enabled) } +void SetupDialog::toggleSideBarOnRight(bool enabled) +{ + m_sideBarOnRight = enabled; +} + + void SetupDialog::toggleMMPZ(bool enabled) { m_MMPZ = enabled; diff --git a/src/gui/editors/PianoRoll.cpp b/src/gui/editors/PianoRoll.cpp index 0eb5df163..4682b3f20 100644 --- a/src/gui/editors/PianoRoll.cpp +++ b/src/gui/editors/PianoRoll.cpp @@ -521,7 +521,7 @@ void PianoRoll::changeNoteEditMode( int i ) void PianoRoll::markSemiTone( int i ) { - const int key = getKey( mapFromGlobal( m_semiToneMarkerMenu->pos() ).y() ); + const int key = m_pianoKeySelected; const InstrumentFunctionNoteStacking::Chord * chord = nullptr; switch( static_cast( i ) ) @@ -1868,6 +1868,7 @@ void PianoRoll::mousePressEvent(QMouseEvent * me ) if( me->buttons() == Qt::RightButton ) { // right click - tone marker contextual menu + m_pianoKeySelected = getKey( me->y() ); m_semiToneMarkerMenu->popup( mapToGlobal( QPoint( me->x(), me->y() ) ) ); } else if( me->buttons() == Qt::LeftButton ) @@ -1938,8 +1939,9 @@ void PianoRoll::mouseDoubleClickEvent(QMouseEvent * me ) { const Note * closest = NULL; int closest_dist = 9999999; - // if we caught multiple notes, find the closest... - if( nv.size() > 1 ) + // if we caught multiple notes and we're not editing a + // selection, find the closest... + if( nv.size() > 1 && !isSelection() ) { for ( const Note * i : nv ) { @@ -2870,7 +2872,12 @@ void PianoRoll::paintEvent(QPaintEvent * pe ) break; } // start drawing at the bottom - int key_line_y = keyAreaBottom() - 1; + int key_line_y = qMin(keyAreaBottom() - 1, m_keyLineHeight * NumKeys); + // we need to set m_notesEditHeight here because it needs to fill in the + // rest of the window if key_line_y is bound to m_keyLineHeight * NumKeys + if (key_line_y == m_keyLineHeight * NumKeys) { + m_notesEditHeight = height() - (PR_TOP_MARGIN + m_keyLineHeight * NumKeys); + } // used for aligning black-keys later int first_white_key_height = m_whiteKeySmallHeight; // key-counter - only needed for finding out whether the processed @@ -2996,9 +3003,10 @@ void PianoRoll::paintEvent(QPaintEvent * pe ) key = m_startKey; keys_processed = 0; int white_cnt = 0; + key_line_y = qMin(keyAreaBottom(), m_keyLineHeight * NumKeys); // and go! - for( int y = keyAreaBottom() + y_offset; + for( int y = key_line_y + y_offset; y > PR_TOP_MARGIN; ++keys_processed ) { // check for black key that is only half visible on the bottom @@ -3064,16 +3072,16 @@ void PianoRoll::paintEvent(QPaintEvent * pe ) // erase the area below the piano, because there might be keys that // should be only half-visible - p.fillRect( QRect( 0, keyAreaBottom(), - WHITE_KEY_WIDTH, noteEditBottom() - keyAreaBottom() ), bgColor ); + p.fillRect( QRect( 0, key_line_y, + WHITE_KEY_WIDTH, noteEditBottom() - key_line_y ), bgColor ); // display note editing info QFont f = p.font(); f.setBold( false ); p.setFont( pointSize<10>( f ) ); p.setPen( noteModeColor() ); - p.drawText( QRect( 0, keyAreaBottom(), - WHITE_KEY_WIDTH, noteEditBottom() - keyAreaBottom() ), + p.drawText( QRect( 0, key_line_y, + WHITE_KEY_WIDTH, noteEditBottom() - key_line_y ), Qt::AlignCenter | Qt::TextWordWrap, m_nemStr.at( m_noteEditMode ) + ":" ); @@ -3114,7 +3122,7 @@ void PianoRoll::paintEvent(QPaintEvent * pe ) // Draw horizontal lines key = m_startKey; - for( int y = keyAreaBottom() - 1; y > PR_TOP_MARGIN; + for( int y = key_line_y - 1; y > PR_TOP_MARGIN; y -= m_keyLineHeight ) { if( static_cast( key % KeysPerOctave ) == Key_C ) @@ -3173,10 +3181,10 @@ void PianoRoll::paintEvent(QPaintEvent * pe ) for( int i = 0; i < m_markedSemiTones.size(); i++ ) { const int key_num = m_markedSemiTones.at( i ); - const int y = keyAreaBottom() + 5 + const int y = key_line_y + 5 - m_keyLineHeight * ( key_num - m_startKey + 1 ); - if( y > keyAreaBottom() ) + if( y > key_line_y ) { break; } @@ -3204,14 +3212,14 @@ void PianoRoll::paintEvent(QPaintEvent * pe ) qSwap( sel_key_start, sel_key_end ); } - int y_base = keyAreaBottom() - 1; + int y_base = key_line_y - 1; if( hasValidPattern() ) { p.setClipRect( WHITE_KEY_WIDTH, PR_TOP_MARGIN, width() - WHITE_KEY_WIDTH, height() - PR_TOP_MARGIN ); - const int visible_keys = ( keyAreaBottom()-keyAreaTop() ) / + const int visible_keys = ( key_line_y-keyAreaTop() ) / m_keyLineHeight + 2; QPolygonF editHandles; @@ -3438,13 +3446,13 @@ void PianoRoll::paintEvent(QPaintEvent * pe ) if( hasValidPattern() ) { int key_num = getKey( mapFromGlobal( QCursor::pos() ).y() ); - p.fillRect( 10, keyAreaBottom() + 3 - m_keyLineHeight * + p.fillRect( 10, key_line_y + 3 - m_keyLineHeight * ( key_num - m_startKey + 1 ), width() - 10, m_keyLineHeight - 7, currentKeyCol ); } // bar to resize note edit area p.setClipRect( 0, 0, width(), height() ); - p.fillRect( QRect( 0, keyAreaBottom(), + p.fillRect( QRect( 0, key_line_y, width()-PR_RIGHT_MARGIN, NOTE_EDIT_RESIZE_BAR ), editAreaCol ); const QPixmap * cursor = NULL; diff --git a/src/gui/editors/SongEditor.cpp b/src/gui/editors/SongEditor.cpp index ba7cd6f82..716b2f734 100644 --- a/src/gui/editors/SongEditor.cpp +++ b/src/gui/editors/SongEditor.cpp @@ -46,7 +46,7 @@ #include "TextFloat.h" #include "TimeLineWidget.h" #include "ToolTip.h" -#include "VisualizationWidget.h" +#include "Oscilloscope.h" #include "TimeDisplayWidget.h" #include "AudioDevice.h" #include "PianoRoll.h" @@ -210,15 +210,14 @@ SongEditor::SongEditor( Song * song ) : gui->mainWindow()->addSpacingToToolBar( 10 ); - // create widget for visualization- and cpu-load-widget + // create widget for oscilloscope- and cpu-load-widget QWidget * vc_w = new QWidget( tb ); QVBoxLayout * vcw_layout = new QVBoxLayout( vc_w ); vcw_layout->setMargin( 0 ); vcw_layout->setSpacing( 0 ); - //vcw_layout->addStretch(); - vcw_layout->addWidget( new VisualizationWidget( - embed::getIconPixmap( "output_graph" ), vc_w ) ); + vcw_layout->addStretch(); + vcw_layout->addWidget( new Oscilloscope( vc_w ) ); vcw_layout->addWidget( new CPULoadWidget( vc_w ) ); vcw_layout->addStretch(); diff --git a/src/gui/widgets/VisualizationWidget.cpp b/src/gui/widgets/Oscilloscope.cpp similarity index 79% rename from src/gui/widgets/VisualizationWidget.cpp rename to src/gui/widgets/Oscilloscope.cpp index 9a4d8b235..1b1e18365 100644 --- a/src/gui/widgets/VisualizationWidget.cpp +++ b/src/gui/widgets/Oscilloscope.cpp @@ -1,5 +1,5 @@ /* - * VisualizationWidget.cpp - widget for visualization of sound-data + * Oscilloscope.cpp * * Copyright (c) 2005-2009 Tobias Doerffel * @@ -26,7 +26,7 @@ #include #include -#include "VisualizationWidget.h" +#include "Oscilloscope.h" #include "GuiApplication.h" #include "gui_templates.h" #include "MainWindow.h" @@ -35,20 +35,19 @@ #include "Engine.h" #include "ToolTip.h" #include "Song.h" +#include "embed.h" - -VisualizationWidget::VisualizationWidget( const QPixmap & _bg, QWidget * _p, - visualizationTypes _vtype ) : +Oscilloscope::Oscilloscope( QWidget * _p ) : QWidget( _p ), - s_background( _bg ), + m_background( embed::getIconPixmap( "output_graph" ) ), m_points( new QPointF[Engine::mixer()->framesPerPeriod()] ), m_active( false ), m_normalColor(71, 253, 133), m_warningColor(255, 192, 64), m_clippingColor(255, 64, 64) { - setFixedSize( s_background.width(), s_background.height() ); + setFixedSize( m_background.width(), m_background.height() ); setAttribute( Qt::WA_OpaquePaintEvent, true ); setActive( ConfigManager::inst()->value( "ui", "displaywaveform").toInt() ); @@ -64,7 +63,7 @@ VisualizationWidget::VisualizationWidget( const QPixmap & _bg, QWidget * _p, -VisualizationWidget::~VisualizationWidget() +Oscilloscope::~Oscilloscope() { delete[] m_buffer; delete[] m_points; @@ -73,7 +72,7 @@ VisualizationWidget::~VisualizationWidget() -void VisualizationWidget::updateAudioBuffer( const surroundSampleFrame * buffer ) +void Oscilloscope::updateAudioBuffer( const surroundSampleFrame * buffer ) { if( !Engine::getSong()->isExporting() ) { @@ -85,7 +84,7 @@ void VisualizationWidget::updateAudioBuffer( const surroundSampleFrame * buffer -void VisualizationWidget::setActive( bool _active ) +void Oscilloscope::setActive( bool _active ) { m_active = _active; if( m_active ) @@ -112,42 +111,42 @@ void VisualizationWidget::setActive( bool _active ) } -QColor const & VisualizationWidget::normalColor() const +QColor const & Oscilloscope::normalColor() const { return m_normalColor; } -void VisualizationWidget::setNormalColor(QColor const & normalColor) +void Oscilloscope::setNormalColor(QColor const & normalColor) { m_normalColor = normalColor; } -QColor const & VisualizationWidget::warningColor() const +QColor const & Oscilloscope::warningColor() const { return m_warningColor; } -void VisualizationWidget::setWarningColor(QColor const & warningColor) +void Oscilloscope::setWarningColor(QColor const & warningColor) { m_warningColor = warningColor; } -QColor const & VisualizationWidget::clippingColor() const +QColor const & Oscilloscope::clippingColor() const { return m_clippingColor; } -void VisualizationWidget::setClippingColor(QColor const & clippingColor) +void Oscilloscope::setClippingColor(QColor const & clippingColor) { m_clippingColor = clippingColor; } -void VisualizationWidget::paintEvent( QPaintEvent * ) +void Oscilloscope::paintEvent( QPaintEvent * ) { QPainter p( this ); - p.drawPixmap( 0, 0, s_background ); + p.drawPixmap( 0, 0, m_background ); if( m_active && !Engine::getSong()->isExporting() ) { @@ -195,7 +194,7 @@ void VisualizationWidget::paintEvent( QPaintEvent * ) -void VisualizationWidget::mousePressEvent( QMouseEvent * _me ) +void Oscilloscope::mousePressEvent( QMouseEvent * _me ) { if( _me->button() == Qt::LeftButton ) { @@ -204,7 +203,7 @@ void VisualizationWidget::mousePressEvent( QMouseEvent * _me ) } -QColor const & VisualizationWidget::determineLineColor(float level) const +QColor const & Oscilloscope::determineLineColor(float level) const { if( level < 0.9f ) { diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index 9d1a66b9d..f8cded6d7 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -771,7 +771,11 @@ void InstrumentTrack::saveTrackSpecificSettings( QDomDocument& doc, QDomElement void InstrumentTrack::loadTrackSpecificSettings( const QDomElement & thisElement ) { - silenceAllNotes( true ); + // don't delete instrument in preview mode if it's the same + // we can't do this for other situations due to some issues with linked models + bool reuseInstrument = m_previewMode && m_instrument && m_instrument->nodeName() == getSavedInstrumentName(thisElement); + // remove the InstrumentPlayHandle if and only if we need to delete the instrument + silenceAllNotes(!reuseInstrument); lock(); @@ -815,33 +819,39 @@ void InstrumentTrack::loadTrackSpecificSettings( const QDomElement & thisElement { m_audioPort.effects()->restoreState( node.toElement() ); } - else if( node.nodeName() == "instrument" ) + else if(node.nodeName() == "instrument") { typedef Plugin::Descriptor::SubPluginFeatures::Key PluginKey; - PluginKey key( node.toElement().elementsByTagName( "key" ).item( 0 ).toElement() ); + PluginKey key(node.toElement().elementsByTagName("key").item(0).toElement()); - delete m_instrument; - m_instrument = NULL; - m_instrument = Instrument::instantiate( - node.toElement().attribute( "name" ), this, &key); - m_instrument->restoreState( node.firstChildElement() ); - - emit instrumentChanged(); + if (reuseInstrument) + { + m_instrument->restoreState(node.firstChildElement()); + } + else + { + delete m_instrument; + m_instrument = NULL; + m_instrument = Instrument::instantiate( + node.toElement().attribute("name"), this, &key); + m_instrument->restoreState(node.firstChildElement()); + emit instrumentChanged(); + } } // compat code - if node-name doesn't match any known // one, we assume that it is an instrument-plugin // which we'll try to load - else if( AutomationPattern::classNodeName() != node.nodeName() && + else if(AutomationPattern::classNodeName() != node.nodeName() && ControllerConnection::classNodeName() != node.nodeName() && - !node.toElement().hasAttribute( "id" ) ) + !node.toElement().hasAttribute( "id" )) { delete m_instrument; m_instrument = NULL; m_instrument = Instrument::instantiate( node.nodeName(), this, nullptr, true); - if( m_instrument->nodeName() == node.nodeName() ) + if (m_instrument->nodeName() == node.nodeName()) { - m_instrument->restoreState( node.toElement() ); + m_instrument->restoreState(node.toElement()); } emit instrumentChanged(); } @@ -863,6 +873,19 @@ void InstrumentTrack::setPreviewMode( const bool value ) +QString InstrumentTrack::getSavedInstrumentName(const QDomElement &thisElement) const +{ + QDomElement elem = thisElement.firstChildElement("instrument"); + if (!elem.isNull()) + { + return elem.attribute("name"); + } + return ""; +} + + + + Instrument * InstrumentTrack::loadInstrument(const QString & _plugin_name, const Plugin::Descriptor::SubPluginFeatures::Key *key, bool keyFromDnd) {