diff --git a/.github/no-response.yml b/.github/no-response.yml new file mode 100644 index 000000000..476165408 --- /dev/null +++ b/.github/no-response.yml @@ -0,0 +1,2 @@ +# Label requiring a response +responseRequiredLabel: "response required" diff --git a/.travis/osx..install.sh b/.travis/osx..install.sh index 4542c7059..4f92db746 100755 --- a/.travis/osx..install.sh +++ b/.travis/osx..install.sh @@ -2,7 +2,7 @@ set -e -PACKAGES="cmake pkg-config libogg libvorbis lame libsndfile libsamplerate jack sdl libgig libsoundio stk portaudio node fltk qt5" +PACKAGES="cmake pkg-config libogg libvorbis lame libsndfile libsamplerate jack sdl libgig libsoundio stk fluid-synth portaudio node fltk qt5" if "${TRAVIS}"; then PACKAGES="$PACKAGES ccache" @@ -19,9 +19,4 @@ brew install $PACKAGES # fftw tries to install gcc which conflicts with travis brew install fftw --ignore-dependencies -# Recompile fluid-synth without CoreAudio per issues #649 -# Ruby formula must be a URL - -brew install --build-from-source "https://gist.githubusercontent.com/tresf/c9260c43270abd4ce66ff40359588435/raw/fluid-synth.rb" - sudo npm install -g appdmg diff --git a/CMakeLists.txt b/CMakeLists.txt index dde248972..6c67e9316 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,8 +22,7 @@ INCLUDE(FindPkgConfig) STRING(TOUPPER "${CMAKE_PROJECT_NAME}" PROJECT_NAME_UCASE) -# Updated by maintenance tasks -SET(PROJECT_YEAR 2017) +SET(PROJECT_YEAR 2018) SET(PROJECT_AUTHOR "LMMS Developers") SET(PROJECT_URL "https://lmms.io") @@ -521,6 +520,22 @@ FILE(REMOVE include/lmmsconfig.h) FILE(GLOB LMMS_INCLUDES "${CMAKE_SOURCE_DIR}/include/*.h") LIST(SORT LMMS_INCLUDES) +# Get list of all committers from git history, ordered by number of commits. +# The CONTRIBUTORS file is used by AboutDialog. This information can be provided +# with -DCONTRIBUTORS=/path/to/CONTRIBUTORS instead. For instance, to generate +# this file for version 1.1.3, the command is: +# git shortlog -sne v1.1.3 | cut -c8- +FIND_PACKAGE(Git) +IF(GIT_FOUND AND NOT CONTRIBUTORS) + SET(CONTRIBUTORS "${CMAKE_BINARY_DIR}/CONTRIBUTORS") + EXECUTE_PROCESS( + COMMAND "${GIT_EXECUTABLE}" shortlog -sne + COMMAND cut -c8- + OUTPUT_FILE "${CONTRIBUTORS}" + WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" + TIMEOUT 1) +ENDIF() + # we somehow have to make LMMS-binary depend on MOC-files ADD_FILE_DEPENDENCIES("${CMAKE_BINARY_DIR}/lmmsconfig.h") diff --git a/cmake/build_win32.sh b/cmake/build_win32.sh index e647f7c09..6fbf5287b 100755 --- a/cmake/build_win32.sh +++ b/cmake/build_win32.sh @@ -25,7 +25,7 @@ if [ -z "$MSYSCON" ]; then TOOLCHAIN="$DIR/toolchains/Ubuntu-MinGW-W64-$ARCH.cmake" fi else - CMAKE_OPTS="$CMAKE_OPTS -DLMMS_BUILD_MSYS=1" + TOOLCHAIN="$DIR/toolchains/MSYS-$ARCH.cmake" fi export PATH=$MINGW/bin:$PATH diff --git a/cmake/modules/FindWine.cmake b/cmake/modules/FindWine.cmake index 939961c12..9967dd9ba 100644 --- a/cmake/modules/FindWine.cmake +++ b/cmake/modules/FindWine.cmake @@ -9,7 +9,7 @@ LIST(APPEND CMAKE_PREFIX_PATH /opt/wine-stable /opt/wine-devel /opt/wine-staging /usr/lib/wine/) -FIND_PATH(WINE_INCLUDE_DIR windows/windows.h PATH_SUFFIXES wine) +FIND_PATH(WINE_INCLUDE_DIR windows/windows.h PATH_SUFFIXES wine wine/wine) FIND_LIBRARY(WINE_LIBRARY NAMES wine PATH_SUFFIXES wine i386-linux-gnu/wine) FIND_PROGRAM(WINE_CXX NAMES wineg++ winegcc winegcc64 winegcc32 winegcc-stable diff --git a/cmake/toolchains/MSYS-32.cmake b/cmake/toolchains/MSYS-32.cmake index d016e3ffd..698dd5437 100644 --- a/cmake/toolchains/MSYS-32.cmake +++ b/cmake/toolchains/MSYS-32.cmake @@ -1,2 +1,4 @@ -INCLUDE(common/Win32) -SET(LMMS_BUILD_MSYS 1) +INCLUDE(${CMAKE_CURRENT_LIST_DIR}/common/MSYS.cmake) +INCLUDE(${CMAKE_CURRENT_LIST_DIR}/common/Win32.cmake) + +SET(MINGW_PREFIX /mingw32) \ No newline at end of file diff --git a/cmake/toolchains/MSYS-64.cmake b/cmake/toolchains/MSYS-64.cmake index bce085b2d..8becd51b3 100644 --- a/cmake/toolchains/MSYS-64.cmake +++ b/cmake/toolchains/MSYS-64.cmake @@ -1,6 +1,5 @@ -INCLUDE(MSYS-32) -INCLUDE(Win64) -SET(LMMS_BUILD_MSYS 1) +INCLUDE(${CMAKE_CURRENT_LIST_DIR}/common/MSYS.cmake) +INCLUDE(${CMAKE_CURRENT_LIST_DIR}/common/Win64.cmake) SET(MINGW_PREFIX /mingw64) SET(MINGW_PREFIX32 /mingw32) diff --git a/cmake/toolchains/common/MSYS.cmake b/cmake/toolchains/common/MSYS.cmake index d31f60e6d..dc295d670 100644 --- a/cmake/toolchains/common/MSYS.cmake +++ b/cmake/toolchains/common/MSYS.cmake @@ -2,6 +2,7 @@ SET(CMAKE_FIND_ROOT_PATH ${MINGW_PREFIX}) SET(CMAKE_INSTALL_PREFIX ${MINGW_PREFIX}) + # Windows msys mingw ships with a mostly-suitable preconfigured environment SET(STRIP ${MINGW_PREFIX}/bin/strip) SET(CMAKE_RC_COMPILER ${MINGW_PREFIX}/bin/windres) @@ -31,4 +32,6 @@ SET(QT_OVERRIDE_LIBRARIES IF(LMMS_BUILD_MSYS AND CMAKE_BUILD_TYPE STREQUAL "Debug") # Override Qt debug libraries with release versions SET(QT_LIBRARIES "${QT_OVERRIDE_LIBRARIES}") -ENDIF() \ No newline at end of file +ENDIF() + +SET(LMMS_BUILD_MSYS 1) \ No newline at end of file diff --git a/data/themes/classic/style.css b/data/themes/classic/style.css index cf5c22400..1cf9375bc 100644 --- a/data/themes/classic/style.css +++ b/data/themes/classic/style.css @@ -127,7 +127,7 @@ PianoRoll { qproperty-noteBorders: true; /* boolean property, set false to have borderless notes */ qproperty-selectedNoteColor: rgb( 0, 125, 255 ); qproperty-barColor: #4afd85; - qproperty-markedSemitoneColor: rgba( 40, 40, 40, 200 ); + qproperty-markedSemitoneColor: rgba( 0, 255, 200, 60 ); /* Grid colors */ qproperty-lineColor: rgba( 128, 128, 128, 80 ); qproperty-beatLineColor: rgba( 128, 128, 128, 160 ); diff --git a/data/themes/default/style.css b/data/themes/default/style.css index 701583433..a4a31ab6b 100644 --- a/data/themes/default/style.css +++ b/data/themes/default/style.css @@ -144,9 +144,9 @@ PianoRoll { qproperty-noteColor: #0bd556; qproperty-noteOpacity: 165; qproperty-noteBorders: false; /* boolean property, set false to have borderless notes */ - qproperty-selectedNoteColor: #006b65; + qproperty-selectedNoteColor: #064d79; qproperty-barColor: #078f3a; - qproperty-markedSemitoneColor: #06170E; + qproperty-markedSemitoneColor: rgba(255, 255, 255, 30); /* Grid colors */ qproperty-lineColor: #292929; qproperty-beatLineColor: #2d6b45; diff --git a/doc/CONTRIBUTORS b/doc/CONTRIBUTORS deleted file mode 100644 index e69de29bb..000000000 diff --git a/include/AutomatableModelView.h b/include/AutomatableModelView.h index ead5d81af..3b320434f 100644 --- a/include/AutomatableModelView.h +++ b/include/AutomatableModelView.h @@ -36,7 +36,7 @@ class EXPORT AutomatableModelView : public ModelView { public: AutomatableModelView( Model* model, QWidget* _this ); - virtual ~AutomatableModelView(); + virtual ~AutomatableModelView() = default; // some basic functions for convenience AutomatableModel* modelUntyped() diff --git a/include/AutomationPattern.h b/include/AutomationPattern.h index 0af7ea4fa..89dcfed7c 100644 --- a/include/AutomationPattern.h +++ b/include/AutomationPattern.h @@ -54,7 +54,7 @@ public: AutomationPattern( AutomationTrack * _auto_track ); AutomationPattern( const AutomationPattern & _pat_to_copy ); - virtual ~AutomationPattern(); + virtual ~AutomationPattern() = default; bool addObject( AutomatableModel * _obj, bool _search_dup = true ); diff --git a/include/AutomationTrack.h b/include/AutomationTrack.h index 733f5941c..195c21e9d 100644 --- a/include/AutomationTrack.h +++ b/include/AutomationTrack.h @@ -35,7 +35,7 @@ class AutomationTrack : public Track Q_OBJECT public: AutomationTrack( TrackContainer* tc, bool _hidden = false ); - virtual ~AutomationTrack(); + virtual ~AutomationTrack() = default; virtual bool play( const MidiTime & _start, const fpp_t _frames, const f_cnt_t _frame_base, int _tco_num = -1 ); @@ -63,7 +63,7 @@ class AutomationTrackView : public TrackView { public: AutomationTrackView( AutomationTrack* at, TrackContainerView* tcv ); - virtual ~AutomationTrackView(); + virtual ~AutomationTrackView() = default; virtual void dragEnterEvent( QDragEnterEvent * _dee ); virtual void dropEvent( QDropEvent * _de ); diff --git a/include/BBTrack.h b/include/BBTrack.h index aafeeaf71..9e72c4f04 100644 --- a/include/BBTrack.h +++ b/include/BBTrack.h @@ -41,7 +41,7 @@ class BBTCO : public TrackContentObject { public: BBTCO( Track * _track ); - virtual ~BBTCO(); + virtual ~BBTCO() = default; virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent ); virtual void loadSettings( const QDomElement & _this ); @@ -90,7 +90,7 @@ class BBTCOView : public TrackContentObjectView Q_OBJECT public: BBTCOView( TrackContentObject * _tco, TrackView * _tv ); - virtual ~BBTCOView(); + virtual ~BBTCOView() = default; QColor color() const { diff --git a/include/Fader.h b/include/Fader.h index be165f234..80359b4c6 100644 --- a/include/Fader.h +++ b/include/Fader.h @@ -68,7 +68,7 @@ public: Fader( FloatModel * _model, const QString & _name, QWidget * _parent ); Fader( FloatModel * _model, const QString & _name, QWidget * _parent, QPixmap * back, QPixmap * leds, QPixmap * knob ); - virtual ~Fader(); + virtual ~Fader() = default; void init(FloatModel * model, QString const & name); diff --git a/include/FileBrowser.h b/include/FileBrowser.h index f3daa48d1..91a58831d 100644 --- a/include/FileBrowser.h +++ b/include/FileBrowser.h @@ -51,7 +51,7 @@ public: FileBrowser( const QString & directories, const QString & filter, const QString & title, const QPixmap & pm, QWidget * parent, bool dirs_as_items = false, bool recurse = false ); - virtual ~FileBrowser(); + virtual ~FileBrowser() = default; private slots: void reloadTree( void ); @@ -85,7 +85,7 @@ class FileBrowserTreeWidget : public QTreeWidget Q_OBJECT public: FileBrowserTreeWidget( QWidget * parent ); - virtual ~FileBrowserTreeWidget(); + virtual ~FileBrowserTreeWidget() = default; protected: diff --git a/include/FxLine.h b/include/FxLine.h index 46490044f..5bb04da2f 100644 --- a/include/FxLine.h +++ b/include/FxLine.h @@ -79,6 +79,10 @@ public: static const int FxLineHeight; + void renameChannel(); + + bool eventFilter (QObject *dist, QEvent *event); + private: void drawFxLine( QPainter* p, const FxLine *fxLine, bool isActive, bool sendToThis, bool receiveFromThis ); QString elideName( const QString & name ); @@ -98,7 +102,6 @@ private: QGraphicsView * m_view; private slots: - void renameChannel(); void renameFinished(); void removeChannel(); void removeUnusedChannels(); diff --git a/include/FxMixerView.h b/include/FxMixerView.h index 973195bb3..30c759838 100644 --- a/include/FxMixerView.h +++ b/include/FxMixerView.h @@ -100,6 +100,8 @@ public: void moveChannelLeft(int index, int focusIndex); void moveChannelRight(int index); + void renameChannel(int index); + // make sure the display syncs up with the fx mixer. // useful for loading projects void refreshDisplay(); diff --git a/include/Graph.h b/include/Graph.h index 71e6da60b..dc1d1fe16 100644 --- a/include/Graph.h +++ b/include/Graph.h @@ -55,7 +55,7 @@ public: int _width = 132, int _height = 104 ); - virtual ~Graph(); + virtual ~Graph() = default; void setForeground( const QPixmap & _pixmap ); @@ -122,7 +122,7 @@ public: bool _default_constructed = false, float _step = 0.0 ); - virtual ~graphModel(); + virtual ~graphModel() = default; // TODO: saveSettings, loadSettings? diff --git a/include/Instrument.h b/include/Instrument.h index 9dd68ef98..ec7245dce 100644 --- a/include/Instrument.h +++ b/include/Instrument.h @@ -57,7 +57,7 @@ public: Instrument( InstrumentTrack * _instrument_track, const Descriptor * _descriptor ); - virtual ~Instrument(); + virtual ~Instrument() = default; // -------------------------------------------------------------------- // functions that can/should be re-implemented: diff --git a/include/LcdSpinBox.h b/include/LcdSpinBox.h index 0bac3ddc0..d6896f52b 100644 --- a/include/LcdSpinBox.h +++ b/include/LcdSpinBox.h @@ -38,7 +38,7 @@ public: LcdSpinBox( int numDigits, const QString& style, QWidget* parent, const QString& name = QString::null ); - virtual ~LcdSpinBox(); + virtual ~LcdSpinBox() = default; virtual void modelChanged() { diff --git a/include/Pattern.h b/include/Pattern.h index 189631412..235f504c4 100644 --- a/include/Pattern.h +++ b/include/Pattern.h @@ -163,7 +163,7 @@ class PatternView : public TrackContentObjectView public: PatternView( Pattern* pattern, TrackView* parent ); - virtual ~PatternView(); + virtual ~PatternView() = default; Q_PROPERTY(QColor noteFillColor READ getNoteFillColor WRITE setNoteFillColor) Q_PROPERTY(QColor noteBorderColor READ getNoteBorderColor WRITE setNoteBorderColor) diff --git a/include/Piano.h b/include/Piano.h index 1515d267d..633236f4a 100644 --- a/include/Piano.h +++ b/include/Piano.h @@ -31,7 +31,7 @@ class InstrumentTrack; class MidiEventProcessor; -class Piano : public Model +class Piano final : public Model { public: enum KeyTypes @@ -41,7 +41,6 @@ public: } ; Piano( InstrumentTrack* track ); - virtual ~Piano(); void setKeyState( int key, bool state ); diff --git a/include/PianoView.h b/include/PianoView.h index 935279a98..2a362c584 100644 --- a/include/PianoView.h +++ b/include/PianoView.h @@ -38,7 +38,7 @@ class PianoView : public QWidget, public ModelView Q_OBJECT public: PianoView( QWidget * _parent ); - virtual ~PianoView(); + virtual ~PianoView() = default; static int getKeyFromKeyEvent( QKeyEvent * _ke ); diff --git a/include/SampleTrack.h b/include/SampleTrack.h index 6d39ed355..decf52f3f 100644 --- a/include/SampleTrack.h +++ b/include/SampleTrack.h @@ -98,8 +98,7 @@ class SampleTCOView : public TrackContentObjectView public: SampleTCOView( SampleTCO * _tco, TrackView * _tv ); - virtual ~SampleTCOView(); - + virtual ~SampleTCOView() = default; public slots: void updateSample(); diff --git a/include/SongEditor.h b/include/SongEditor.h index d6e904ace..e31d0f862 100644 --- a/include/SongEditor.h +++ b/include/SongEditor.h @@ -135,6 +135,7 @@ private: bool m_scrollBack; bool m_smoothScroll; + int m_widgetWidthTotal; EditMode m_mode; EditMode m_ctrlMode; // mode they were in before they hit ctrl diff --git a/include/TabBar.h b/include/TabBar.h index 56900fda4..4ef0b1ac7 100644 --- a/include/TabBar.h +++ b/include/TabBar.h @@ -42,7 +42,7 @@ class EXPORT TabBar : public QWidget public: TabBar( QWidget * _parent, QBoxLayout::Direction _dir = QBoxLayout::LeftToRight ); - virtual ~TabBar(); + virtual ~TabBar() = default; TabButton * addTab( QWidget * _w, const QString & _text, int _id, bool _add_stretch = false, diff --git a/include/TabWidget.h b/include/TabWidget.h index 402d7c9cc..dacd2648b 100644 --- a/include/TabWidget.h +++ b/include/TabWidget.h @@ -37,7 +37,7 @@ class TabWidget : public QWidget Q_OBJECT public: TabWidget( const QString & _caption, QWidget * _parent, bool usePixmap = false ); - virtual ~TabWidget(); + virtual ~TabWidget() = default; void addTab( QWidget * w, const QString & name, const char *pixmap = NULL, int idx = -1 ); diff --git a/include/TimeDisplayWidget.h b/include/TimeDisplayWidget.h index 67ae4d6ca..175f159c9 100644 --- a/include/TimeDisplayWidget.h +++ b/include/TimeDisplayWidget.h @@ -37,7 +37,7 @@ class TimeDisplayWidget : public QWidget Q_OBJECT public: TimeDisplayWidget(); - virtual ~TimeDisplayWidget(); + virtual ~TimeDisplayWidget() = default; protected: diff --git a/include/ToolButton.h b/include/ToolButton.h index 62901f590..196ec48f0 100644 --- a/include/ToolButton.h +++ b/include/ToolButton.h @@ -42,7 +42,7 @@ public: QToolButton(_parent) { } - virtual ~ToolButton(); + virtual ~ToolButton() = default; } ; diff --git a/include/Track.h b/include/Track.h index 8b1bf5e90..6ac6e390f 100644 --- a/include/Track.h +++ b/include/Track.h @@ -300,8 +300,6 @@ private: TextFloat * m_hint; - MidiTime m_oldTime;// used for undo/redo while mouse-button is pressed - // qproperty fields QColor m_mutedColor; QColor m_mutedBackgroundColor; diff --git a/plugins/Eq/EqEffect.cpp b/plugins/Eq/EqEffect.cpp index 4a10b672e..8d37b29ac 100644 --- a/plugins/Eq/EqEffect.cpp +++ b/plugins/Eq/EqEffect.cpp @@ -70,6 +70,8 @@ EqEffect::~EqEffect() bool EqEffect::processAudioBuffer( sampleFrame *buf, const fpp_t frames ) { + const int sampleRate = Engine::mixer()->processingSampleRate(); + //wet/dry controls const float dry = dryLevel(); const float wet = wetLevel(); @@ -93,59 +95,6 @@ bool EqEffect::processAudioBuffer( sampleFrame *buf, const fpp_t frames ) float highShelfFreq = m_eqControls.m_highShelfFreqModel.value(); float lpFreq = m_eqControls.m_lpFreqModel.value(); - ValueBuffer *hpResBuffer = m_eqControls.m_hpResModel.valueBuffer(); - ValueBuffer *lowShelfResBuffer = m_eqControls.m_lowShelfResModel.valueBuffer(); - ValueBuffer *para1BwBuffer = m_eqControls.m_para1BwModel.valueBuffer(); - ValueBuffer *para2BwBuffer = m_eqControls.m_para2BwModel.valueBuffer(); - ValueBuffer *para3BwBuffer = m_eqControls.m_para3BwModel.valueBuffer(); - ValueBuffer *para4BwBuffer = m_eqControls.m_para4BwModel.valueBuffer(); - ValueBuffer *highShelfResBuffer = m_eqControls.m_highShelfResModel.valueBuffer(); - ValueBuffer *lpResBuffer = m_eqControls.m_lpResModel.valueBuffer(); - - ValueBuffer *hpFreqBuffer = m_eqControls.m_hpFeqModel.valueBuffer(); - ValueBuffer *lowShelfFreqBuffer = m_eqControls.m_lowShelfFreqModel.valueBuffer(); - ValueBuffer *para1FreqBuffer = m_eqControls.m_para1FreqModel.valueBuffer(); - ValueBuffer *para2FreqBuffer = m_eqControls.m_para2FreqModel.valueBuffer(); - ValueBuffer *para3FreqBuffer = m_eqControls.m_para3FreqModel.valueBuffer(); - ValueBuffer *para4FreqBuffer = m_eqControls.m_para4FreqModel.valueBuffer(); - ValueBuffer *highShelfFreqBuffer = m_eqControls.m_highShelfFreqModel.valueBuffer(); - ValueBuffer *lpFreqBuffer = m_eqControls.m_lpFreqModel.valueBuffer(); - - int hpResInc = hpResBuffer ? 1 : 0; - int lowShelfResInc = lowShelfResBuffer ? 1 : 0; - int para1BwInc = para1BwBuffer ? 1 : 0; - int para2BwInc = para2BwBuffer ? 1 : 0; - int para3BwInc = para3BwBuffer ? 1 : 0; - int para4BwInc = para4BwBuffer ? 1 : 0; - int highShelfResInc = highShelfResBuffer ? 1 : 0; - int lpResInc = lpResBuffer ? 1 : 0; - - int hpFreqInc = hpFreqBuffer ? 1 : 0; - int lowShelfFreqInc = lowShelfFreqBuffer ? 1 : 0; - int para1FreqInc = para1FreqBuffer ? 1 : 0; - int para2FreqInc = para2FreqBuffer ? 1 : 0; - int para3FreqInc = para3FreqBuffer ? 1 : 0; - int para4FreqInc = para4FreqBuffer ? 1 : 0; - int highShelfFreqInc = highShelfFreqBuffer ? 1 : 0; - int lpFreqInc = lpFreqBuffer ? 1 : 0; - - float *hpResPtr = hpResBuffer ? &( hpResBuffer->values()[ 0 ] ) : &hpRes; - float *lowShelfResPtr = lowShelfResBuffer ? &( lowShelfResBuffer->values()[ 0 ] ) : &lowShelfRes; - float *para1BwPtr = para1BwBuffer ? &( para1BwBuffer->values()[ 0 ] ) : ¶1Bw; - float *para2BwPtr = para2BwBuffer ? &( para2BwBuffer->values()[ 0 ] ) : ¶2Bw; - float *para3BwPtr = para3BwBuffer ? &( para3BwBuffer->values()[ 0 ] ) : ¶3Bw; - float *para4BwPtr = para4BwBuffer ? &( para4BwBuffer->values()[ 0 ] ) : ¶4Bw; - float *highShelfResPtr = highShelfResBuffer ? &( highShelfResBuffer->values()[ 0 ] ) : &highShelfRes; - float *lpResPtr = lpResBuffer ? &( lpResBuffer->values()[ 0 ] ) : &lpRes; - - float *hpFreqPtr = hpFreqBuffer ? &( hpFreqBuffer->values()[ 0 ] ) : &hpFreq; - float *lowShelfFreqPtr = lowShelfFreqBuffer ? &( lowShelfFreqBuffer->values()[ 0 ] ) : &lowShelfFreq; - float *para1FreqPtr = para1FreqBuffer ? &(para1FreqBuffer->values()[ 0 ] ) : ¶1Freq; - float *para2FreqPtr = para2FreqBuffer ? &(para2FreqBuffer->values()[ 0 ] ) : ¶2Freq; - float *para3FreqPtr = para3FreqBuffer ? &(para3FreqBuffer->values()[ 0 ] ) : ¶3Freq; - float *para4FreqPtr = para4FreqBuffer ? &(para4FreqBuffer->values()[ 0 ] ) : ¶4Freq; - float *hightShelfFreqPtr = highShelfFreqBuffer ? &(highShelfFreqBuffer->values()[ 0 ] ) : &highShelfFreq; - float *lpFreqPtr = lpFreqBuffer ? &(lpFreqBuffer ->values()[ 0 ] ) : &lpFreq; bool hpActive = m_eqControls.m_hpActiveModel.value(); bool hp24Active = m_eqControls.m_hp24Model.value(); @@ -167,6 +116,29 @@ bool EqEffect::processAudioBuffer( sampleFrame *buf, const fpp_t frames ) float para4Gain = m_eqControls.m_para4GainModel.value(); float highShelfGain = m_eqControls.m_highShelfGainModel.value(); + //set all filter parameters once per frame, EqFilter handles + //smooth xfading, reducing pops clicks and dc bias offsets + + m_hp12.setParameters( sampleRate, hpFreq, hpRes, 1 ); + m_hp24.setParameters( sampleRate, hpFreq, hpRes, 1 ); + m_hp480.setParameters( sampleRate, hpFreq, hpRes, 1 ); + m_lp480.setParameters( sampleRate, lpFreq, lpRes, 1 ); + m_hp481.setParameters( sampleRate, hpFreq, hpRes, 1 ); + m_lp481.setParameters( sampleRate, hpFreq, hpRes, 1 ); + m_lowShelf.setParameters( sampleRate, lowShelfFreq, lowShelfRes, lowShelfGain ); + m_para1.setParameters( sampleRate, para1Freq, para1Bw, para1Gain ); + m_para2.setParameters( sampleRate, para2Freq, para2Bw, para2Gain ); + m_para3.setParameters( sampleRate, para3Freq, para3Bw, para3Gain ); + m_para4.setParameters( sampleRate, para4Freq, para4Bw, para4Gain ); + m_highShelf.setParameters( sampleRate, highShelfFreq, highShelfRes, highShelfGain ); + m_lp12.setParameters( sampleRate, lpFreq, lpRes, 1 ); + m_lp24.setParameters( sampleRate, lpFreq, lpRes, 1 ); + m_lp480.setParameters( sampleRate, lpFreq, lpRes, 1 ); + m_lp480.setParameters( sampleRate, lpFreq, lpRes, 1 ); + + + + if( !isEnabled() || !isRunning () ) { return( false ); @@ -191,7 +163,6 @@ bool EqEffect::processAudioBuffer( sampleFrame *buf, const fpp_t frames ) } const float outGain = m_outGain; - const int sampleRate = Engine::mixer()->processingSampleRate(); sampleFrame m_inPeak = { 0, 0 }; if(m_eqControls.m_analyseInModel.value( true ) && outSum > 0 ) @@ -207,99 +178,87 @@ bool EqEffect::processAudioBuffer( sampleFrame *buf, const fpp_t frames ) m_eqControls.m_inPeakL = m_eqControls.m_inPeakL < m_inPeak[0] ? m_inPeak[0] : m_eqControls.m_inPeakL; m_eqControls.m_inPeakR = m_eqControls.m_inPeakR < m_inPeak[1] ? m_inPeak[1] : m_eqControls.m_inPeakR; - for( fpp_t f = 0; f < frames; f++) + float periodProgress = 0.0f; // percentage of period processed + for( fpp_t f = 0; f < frames; ++f) { + periodProgress = (float)f / (float)(frames-1); //wet dry buffer dryS[0] = buf[f][0]; dryS[1] = buf[f][1]; if( hpActive ) { - m_hp12.setParameters( sampleRate, *hpFreqPtr, *hpResPtr, 1 ); - buf[f][0] = m_hp12.update( buf[f][0], 0 ); - buf[f][1] = m_hp12.update( buf[f][1], 1 ); + buf[f][0] = m_hp12.update( buf[f][0], 0, periodProgress ); + buf[f][1] = m_hp12.update( buf[f][1], 1, periodProgress ); if( hp24Active || hp48Active ) { - m_hp24.setParameters( sampleRate, *hpFreqPtr, *hpResPtr, 1 ); - buf[f][0] = m_hp24.update( buf[f][0], 0 ); - buf[f][1] = m_hp24.update( buf[f][1], 1 ); + buf[f][0] = m_hp24.update( buf[f][0], 0, periodProgress ); + buf[f][1] = m_hp24.update( buf[f][1], 1, periodProgress ); } if( hp48Active ) { - m_hp480.setParameters( sampleRate, *hpFreqPtr, *hpResPtr, 1 ); - buf[f][0] = m_hp480.update( buf[f][0], 0 ); - buf[f][1] = m_hp480.update( buf[f][1], 1 ); + buf[f][0] = m_hp480.update( buf[f][0], 0, periodProgress ); + buf[f][1] = m_hp480.update( buf[f][1], 1, periodProgress ); - m_hp481.setParameters( sampleRate, *hpFreqPtr, *hpResPtr, 1 ); - buf[f][0] = m_hp481.update( buf[f][0], 0 ); - buf[f][1] = m_hp481.update( buf[f][1], 1 ); + buf[f][0] = m_hp481.update( buf[f][0], 0, periodProgress ); + buf[f][1] = m_hp481.update( buf[f][1], 1, periodProgress ); } } if( lowShelfActive ) { - m_lowShelf.setParameters( sampleRate, *lowShelfFreqPtr, *lowShelfResPtr, lowShelfGain ); - buf[f][0] = m_lowShelf.update( buf[f][0], 0 ); - buf[f][1] = m_lowShelf.update( buf[f][1], 1 ); + buf[f][0] = m_lowShelf.update( buf[f][0], 0, periodProgress ); + buf[f][1] = m_lowShelf.update( buf[f][1], 1, periodProgress ); } if( para1Active ) { - m_para1.setParameters( sampleRate, *para1FreqPtr, *para1BwPtr, para1Gain ); - buf[f][0] = m_para1.update( buf[f][0], 0 ); - buf[f][1] = m_para1.update( buf[f][1], 1 ); + buf[f][0] = m_para1.update( buf[f][0], 0, periodProgress ); + buf[f][1] = m_para1.update( buf[f][1], 1, periodProgress ); } if( para2Active ) { - m_para2.setParameters( sampleRate, *para2FreqPtr, *para2BwPtr, para2Gain ); - buf[f][0] = m_para2.update( buf[f][0], 0 ); - buf[f][1] = m_para2.update( buf[f][1], 1 ); + buf[f][0] = m_para2.update( buf[f][0], 0, periodProgress ); + buf[f][1] = m_para2.update( buf[f][1], 1, periodProgress ); } if( para3Active ) { - m_para3.setParameters( sampleRate, *para3FreqPtr, *para3BwPtr, para3Gain ); - buf[f][0] = m_para3.update( buf[f][0], 0 ); - buf[f][1] = m_para3.update( buf[f][1], 1 ); + buf[f][0] = m_para3.update( buf[f][0], 0, periodProgress ); + buf[f][1] = m_para3.update( buf[f][1], 1, periodProgress ); } if( para4Active ) { - m_para4.setParameters( sampleRate, *para4FreqPtr, *para4BwPtr, para4Gain ); - buf[f][0] = m_para4.update( buf[f][0], 0 ); - buf[f][1] = m_para4.update( buf[f][1], 1 ); + buf[f][0] = m_para4.update( buf[f][0], 0, periodProgress ); + buf[f][1] = m_para4.update( buf[f][1], 1, periodProgress ); } if( highShelfActive ) { - m_highShelf.setParameters( sampleRate, *hightShelfFreqPtr, *highShelfResPtr, highShelfGain ); - buf[f][0] = m_highShelf.update( buf[f][0], 0 ); - buf[f][1] = m_highShelf.update( buf[f][1], 1 ); + buf[f][0] = m_highShelf.update( buf[f][0], 0, periodProgress ); + buf[f][1] = m_highShelf.update( buf[f][1], 1, periodProgress ); } if( lpActive ){ - m_lp12.setParameters( sampleRate, *lpFreqPtr, *lpResPtr, 1 ); - buf[f][0] = m_lp12.update( buf[f][0], 0 ); - buf[f][1] = m_lp12.update( buf[f][1], 1 ); + buf[f][0] = m_lp12.update( buf[f][0], 0, periodProgress ); + buf[f][1] = m_lp12.update( buf[f][1], 1, periodProgress ); if( lp24Active || lp48Active ) { - m_lp24.setParameters( sampleRate, *lpFreqPtr, *lpResPtr, 1 ); - buf[f][0] = m_lp24.update( buf[f][0], 0 ); - buf[f][1] = m_lp24.update( buf[f][1], 1 ); + buf[f][0] = m_lp24.update( buf[f][0], 0, periodProgress ); + buf[f][1] = m_lp24.update( buf[f][1], 1, periodProgress ); } if( lp48Active ) { - m_lp480.setParameters( sampleRate, *lpFreqPtr, *lpResPtr, 1 ); - buf[f][0] = m_lp480.update( buf[f][0], 0 ); - buf[f][1] = m_lp480.update( buf[f][1], 1 ); + buf[f][0] = m_lp480.update( buf[f][0], 0, periodProgress ); + buf[f][1] = m_lp480.update( buf[f][1], 1, periodProgress ); - m_lp481.setParameters( sampleRate, *lpFreqPtr, *lpResPtr, 1 ); - buf[f][0] = m_lp481.update( buf[f][0], 0 ); - buf[f][1] = m_lp481.update( buf[f][1], 1 ); + buf[f][0] = m_lp481.update( buf[f][0], 0, periodProgress ); + buf[f][1] = m_lp481.update( buf[f][1], 1, periodProgress ); } } @@ -307,24 +266,7 @@ bool EqEffect::processAudioBuffer( sampleFrame *buf, const fpp_t frames ) buf[f][1] = ( dry * dryS[1] ) + ( wet * buf[f][1] ); buf[f][0] = ( dry * dryS[0] ) + ( wet * buf[f][0] ); - //increment pointers if needed - hpResPtr += hpResInc; - lowShelfResPtr += lowShelfResInc; - para1BwPtr += para1BwInc; - para2BwPtr += para2BwInc; - para3BwPtr += para3BwInc; - para4BwPtr += para4BwInc; - highShelfResPtr += highShelfResInc; - lpResPtr += lpResInc; - hpFreqPtr += hpFreqInc; - lowShelfFreqPtr += lowShelfFreqInc; - para1FreqPtr += para1FreqInc; - para2FreqPtr += para2FreqInc; - para3FreqPtr += para3FreqInc; - para4FreqPtr += para4FreqInc; - hightShelfFreqPtr += highShelfFreqInc; - lpFreqPtr += lpFreqInc; } sampleFrame outPeak = { 0, 0 }; diff --git a/plugins/Eq/EqFilter.h b/plugins/Eq/EqFilter.h index 471152699..5223fdeda 100644 --- a/plugins/Eq/EqFilter.h +++ b/plugins/Eq/EqFilter.h @@ -31,11 +31,11 @@ /// /// \brief The EqFilter class. /// A wrapper for the StereoBiQuad class, giving it freq, res, and gain controls. -/// It is designed to process periods in one pass, with recalculation of coefficents +/// Used on a per channel per frame basis with recalculation of coefficents /// upon parameter changes. The intention is to use this as a bass class, children override /// the calcCoefficents() function, providing the coefficents a1, a2, b0, b1, b2. /// -class EqFilter : public StereoBiQuad +class EqFilter { public: EqFilter() : @@ -114,7 +114,28 @@ public: } + /// + /// \brief update + /// filters using two BiQuads, then crossfades, + /// depending on on percentage of period processes + /// \param in + /// \param ch + /// \param frameProgress percentage of frame processed + /// \return + /// + inline float update( float in, ch_cnt_t ch, float frameProgress) + { + float initailF = m_biQuadFrameInitial.update( in, ch ); + float targetF = m_biQuadFrameTarget.update( in, ch ); + if(frameProgress > 0.99999 ) + { + m_biQuadFrameInitial= m_biQuadFrameTarget; + } + + return (1.0f-frameProgress) * initailF + frameProgress * targetF; + + } protected: @@ -127,11 +148,23 @@ protected: } + inline void setCoeffs( float a1, float a2, float b0, float b1, float b2 ) + { + m_biQuadFrameTarget.setCoeffs( a1, a2, b0, b1, b2 ); + } + + + + + + float m_sampleRate; float m_freq; float m_res; float m_gain; float m_bw; + StereoBiQuad m_biQuadFrameInitial; + StereoBiQuad m_biQuadFrameTarget; }; diff --git a/plugins/LadspaEffect/CMakeLists.txt b/plugins/LadspaEffect/CMakeLists.txt index 90eb27dff..5bfbc3284 100644 --- a/plugins/LadspaEffect/CMakeLists.txt +++ b/plugins/LadspaEffect/CMakeLists.txt @@ -4,13 +4,7 @@ BUILD_PLUGIN(ladspaeffect LadspaEffect.cpp LadspaControls.cpp LadspaControlDialo SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/ladspa") -# Enable C++11 for all except mingw builds -# TODO: Validate against modern mingw compiler -IF(NOT MINGW_PREFIX) - SET(CMAKE_CXX_STANDARD 11) -ELSE() - SET(CMAKE_CXX_STANDARD 98) -ENDIF() +SET(CMAKE_CXX_STANDARD 11) IF(WANT_CAPS) ADD_SUBDIRECTORY(caps) diff --git a/plugins/LadspaEffect/calf/veal b/plugins/LadspaEffect/calf/veal index 2841b05a3..fe628885b 160000 --- a/plugins/LadspaEffect/calf/veal +++ b/plugins/LadspaEffect/calf/veal @@ -1 +1 @@ -Subproject commit 2841b05a36e53116508a8a862f052e14dad00d67 +Subproject commit fe628885b761372b37136a3f2b7c3d56e179e3ba diff --git a/plugins/LadspaEffect/caps/dsp/FPTruncateMode.h b/plugins/LadspaEffect/caps/dsp/FPTruncateMode.h index 354d062be..4fd1536ff 100644 --- a/plugins/LadspaEffect/caps/dsp/FPTruncateMode.h +++ b/plugins/LadspaEffect/caps/dsp/FPTruncateMode.h @@ -24,11 +24,9 @@ #define fistp(f,i) \ __asm__ ("fistpl %0" : "=m" (i) : "t" (f) : "st") #else /* ! __i386__ */ - #define fstcw(i) - #define fldcw(i) + #include - #define fistp(f,i) \ - i = (int) f + inline void fistp(float f, int32_t& i) { i = static_cast(f); } #endif namespace DSP { @@ -36,12 +34,13 @@ namespace DSP { class FPTruncateMode { public: - int cw0, cw1; /* fp control word */ +#ifdef __i386__ + int cw0; /* fp control word */ FPTruncateMode() { fstcw (cw0); - cw1 = cw0 | 0xC00; + const int cw1 = cw0 | 0xC00; fldcw (cw1); } @@ -49,6 +48,11 @@ class FPTruncateMode { fldcw (cw0); } +#else + // Avoid warnings about unused variables + FPTruncateMode() { (void)0; } + ~FPTruncateMode() { (void)0; } +#endif }; } /* namespace DSP */ diff --git a/plugins/peak_controller_effect/peak_controller_effect.cpp b/plugins/peak_controller_effect/peak_controller_effect.cpp index e08abcb24..f7dbb14f9 100644 --- a/plugins/peak_controller_effect/peak_controller_effect.cpp +++ b/plugins/peak_controller_effect/peak_controller_effect.cpp @@ -26,6 +26,7 @@ #include "Controller.h" #include "Song.h" +#include "PresetPreviewPlayHandle.h" #include "PeakController.h" #include "peak_controller_effect.h" #include "lmms_math.h" @@ -67,7 +68,7 @@ PeakControllerEffect::PeakControllerEffect( m_autoController( NULL ) { m_autoController = new PeakController( Engine::getSong(), this ); - if( !Engine::getSong()->isLoadingProject() ) + if( !Engine::getSong()->isLoadingProject() && !PresetPreviewPlayHandle::isPreviewing() ) { Engine::getSong()->addController( m_autoController ); } diff --git a/plugins/peak_controller_effect/peak_controller_effect_controls.cpp b/plugins/peak_controller_effect/peak_controller_effect_controls.cpp index 816c0d961..96282d29c 100644 --- a/plugins/peak_controller_effect/peak_controller_effect_controls.cpp +++ b/plugins/peak_controller_effect/peak_controller_effect_controls.cpp @@ -29,7 +29,6 @@ #include "PeakController.h" #include "peak_controller_effect_controls.h" #include "peak_controller_effect.h" -#include "PresetPreviewPlayHandle.h" #include "Song.h" @@ -81,12 +80,6 @@ void PeakControllerEffectControls::loadSettings( const QDomElement & _this ) // TODO: Fix possible collision m_effect->m_effectId = rand(); } - - if( m_effect->m_autoController && PresetPreviewPlayHandle::isPreviewing() == true ) - { - delete m_effect->m_autoController; - m_effect->m_autoController = 0; - } } diff --git a/plugins/sf2_player/sf2_player.cpp b/plugins/sf2_player/sf2_player.cpp index fb2412517..63253d4c0 100644 --- a/plugins/sf2_player/sf2_player.cpp +++ b/plugins/sf2_player/sf2_player.cpp @@ -114,6 +114,12 @@ sf2Instrument::sf2Instrument( InstrumentTrack * _instrument_track ) : m_notesRunning[i] = 0; } + +#if QT_VERSION_CHECK(FLUIDSYNTH_VERSION_MAJOR, FLUIDSYNTH_VERSION_MINOR, FLUIDSYNTH_VERSION_MICRO) >= QT_VERSION_CHECK(1,1,9) + // Deactivate all audio drivers in fluidsynth + const char *none[] = { NULL }; + fluid_audio_driver_register( none ); +#endif m_settings = new_fluid_settings(); //fluid_settings_setint( m_settings, (char *) "audio.period-size", engine::mixer()->framesPerPeriod() ); diff --git a/plugins/vst_base/CMakeLists.txt b/plugins/vst_base/CMakeLists.txt index b3dcc0e7e..b0a478232 100644 --- a/plugins/vst_base/CMakeLists.txt +++ b/plugins/vst_base/CMakeLists.txt @@ -49,6 +49,7 @@ SET(WINE_CXX_ARGS -I${CMAKE_BINARY_DIR} -I${CMAKE_SOURCE_DIR}/include -I${WINE_INCLUDE_BASE_DIR} + -I${WINE_INCLUDE_DIR}/windows -L${WINE_LIBRARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/RemoteVstPlugin.cpp -std=c++0x diff --git a/plugins/vst_base/RemoteVstPlugin.cpp b/plugins/vst_base/RemoteVstPlugin.cpp index 04ff97731..71ebf74c0 100644 --- a/plugins/vst_base/RemoteVstPlugin.cpp +++ b/plugins/vst_base/RemoteVstPlugin.cpp @@ -1450,7 +1450,6 @@ intptr_t RemoteVstPlugin::hostCallback( AEffect * _effect, int32_t _opcode, case audioMasterAutomate: SHOW_CALLBACK( "amc: audioMasterAutomate\n" ); // index, value, returns 0 - _effect->setParameter( _effect, _index, _opt ); return 0; case audioMasterVersion: diff --git a/src/3rdparty/rpmalloc/rpmalloc b/src/3rdparty/rpmalloc/rpmalloc index 2e0479192..36b1942fb 160000 --- a/src/3rdparty/rpmalloc/rpmalloc +++ b/src/3rdparty/rpmalloc/rpmalloc @@ -1 +1 @@ -Subproject commit 2e0479192b8dfb15e0084969fdf06208cffbfd09 +Subproject commit 36b1942fbc309b139e56a03166ba19a87f28f26c diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1453584ef..ff0ca8a8e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -45,7 +45,7 @@ INCLUDE(GenQrc) ADD_GEN_QRC(LMMS_RCC_OUT lmms.qrc "${CMAKE_SOURCE_DIR}/doc/AUTHORS" "${CMAKE_SOURCE_DIR}/LICENSE.txt" - "${CMAKE_SOURCE_DIR}/doc/CONTRIBUTORS" + "${CMAKE_BINARY_DIR}/CONTRIBUTORS" ) # Paths relative to lmms executable diff --git a/src/core/AutomationPattern.cpp b/src/core/AutomationPattern.cpp index 32b13f3f4..9345ad566 100644 --- a/src/core/AutomationPattern.cpp +++ b/src/core/AutomationPattern.cpp @@ -98,16 +98,6 @@ AutomationPattern::AutomationPattern( const AutomationPattern & _pat_to_copy ) : } } - - - -AutomationPattern::~AutomationPattern() -{ -} - - - - bool AutomationPattern::addObject( AutomatableModel * _obj, bool _search_dup ) { if( _search_dup && m_objects.contains(_obj) ) diff --git a/src/core/ConfigManager.cpp b/src/core/ConfigManager.cpp index a99223a9d..177a90437 100644 --- a/src/core/ConfigManager.cpp +++ b/src/core/ConfigManager.cpp @@ -26,6 +26,11 @@ #include #include #include +#if QT_VERSION >= 0x050000 +#include +#else +#include +#endif #include #include "ConfigManager.h" @@ -50,7 +55,11 @@ ConfigManager * ConfigManager::s_instanceOfMe = NULL; ConfigManager::ConfigManager() : m_lmmsRcFile( QDir::home().absolutePath() +"/.lmmsrc.xml" ), - m_workingDir( QDir::home().absolutePath() + "/lmms/"), + #if QT_VERSION >= 0x050000 + m_workingDir( QStandardPaths::writableLocation( QStandardPaths::DocumentsLocation ) + "/lmms/"), + #else + m_workingDir( QDesktopServices::storageLocation( QDesktopServices::DocumentsLocation ) + "/lmms/"), + #endif m_dataDir( "data:/" ), m_artworkDir( defaultArtworkDir() ), m_vstDir( m_workingDir + "vst/" ), @@ -58,6 +67,10 @@ ConfigManager::ConfigManager() : m_sf2Dir( m_workingDir + SF2_PATH ), m_version( defaultVersion() ) { + // Detect < 1.2.0 working directory as a courtesy + if ( QFileInfo( QDir::home().absolutePath() + "/lmms/projects/" ).exists() ) + m_workingDir = QDir::home().absolutePath() + "/lmms/"; + if (! qgetenv("LMMS_DATA_DIR").isEmpty()) QDir::addSearchPath("data", QString::fromLocal8Bit(qgetenv("LMMS_DATA_DIR"))); @@ -227,7 +240,7 @@ bool ConfigManager::hasWorkingDir() const void ConfigManager::setWorkingDir( const QString & wd ) { - m_workingDir = ensureTrailingSlash( QFileInfo( wd ).canonicalFilePath() ); + m_workingDir = ensureTrailingSlash( QDir::cleanPath( wd ) ); } diff --git a/src/core/EffectChain.cpp b/src/core/EffectChain.cpp index 4d0c5e8ae..886899c04 100644 --- a/src/core/EffectChain.cpp +++ b/src/core/EffectChain.cpp @@ -188,11 +188,8 @@ bool EffectChain::processAudioBuffer( sampleFrame * _buf, const fpp_t _frames, b { return false; } - const bool exporting = Engine::getSong()->isExporting(); - if( exporting ) // strip infs/nans if exporting - { - MixHelpers::sanitize( _buf, _frames ); - } + + MixHelpers::sanitize( _buf, _frames ); bool moreEffects = false; for( EffectList::Iterator it = m_effects.begin(); it != m_effects.end(); ++it ) @@ -200,10 +197,7 @@ bool EffectChain::processAudioBuffer( sampleFrame * _buf, const fpp_t _frames, b if( hasInputNoise || ( *it )->isRunning() ) { moreEffects |= ( *it )->processAudioBuffer( _buf, _frames ); - if( exporting ) // strip infs/nans if exporting - { - MixHelpers::sanitize( _buf, _frames ); - } + MixHelpers::sanitize( _buf, _frames ); } } diff --git a/src/core/EnvelopeAndLfoParameters.cpp b/src/core/EnvelopeAndLfoParameters.cpp index ef23654d3..cfa0e8dbb 100644 --- a/src/core/EnvelopeAndLfoParameters.cpp +++ b/src/core/EnvelopeAndLfoParameters.cpp @@ -380,22 +380,12 @@ void EnvelopeAndLfoParameters::loadSettings( const QDomElement & _this ) /* ### TODO: Old reversed sustain kept for backward compatibility with 4.15 file format*/ - if( _this.hasAttribute( "sus" ) ) { m_sustainModel.loadSettings( _this, "sus" ); m_sustainModel.setValue( 1.0 - m_sustainModel.value() ); } - // ### TODO: -/* // Keep compatibility with version 2.1 file format - if( _this.hasAttribute( "lfosyncmode" ) ) - { - m_lfoSpeedKnob->setSyncMode( - ( TempoSyncKnob::TtempoSyncMode ) _this.attribute( - "lfosyncmode" ).toInt() ); - }*/ - m_userWave.setAudioFile( _this.attribute( "userwavefile" ) ); updateSampleVars(); diff --git a/src/core/FxMixer.cpp b/src/core/FxMixer.cpp index ac50cab99..51e66939a 100644 --- a/src/core/FxMixer.cpp +++ b/src/core/FxMixer.cpp @@ -117,7 +117,6 @@ void FxChannel::unmuteForSolo() void FxChannel::doProcessing() { const fpp_t fpp = Engine::mixer()->framesPerPeriod(); - const bool exporting = Engine::getSong()->isExporting(); if( m_muted == false ) { @@ -140,25 +139,21 @@ void FxChannel::doProcessing() if( ! volBuf && ! sendBuf ) // neither volume nor send has sample-exact data... { const float v = sender->m_volumeModel.value() * sendModel->value(); - if( exporting ) { MixHelpers::addSanitizedMultiplied( m_buffer, ch_buf, v, fpp ); } - else { MixHelpers::addMultiplied( m_buffer, ch_buf, v, fpp ); } + MixHelpers::addSanitizedMultiplied( m_buffer, ch_buf, v, fpp ); } else if( volBuf && sendBuf ) // both volume and send have sample-exact data { - if( exporting ) { MixHelpers::addSanitizedMultipliedByBuffers( m_buffer, ch_buf, volBuf, sendBuf, fpp ); } - else { MixHelpers::addMultipliedByBuffers( m_buffer, ch_buf, volBuf, sendBuf, fpp ); } + MixHelpers::addSanitizedMultipliedByBuffers( m_buffer, ch_buf, volBuf, sendBuf, fpp ); } else if( volBuf ) // volume has sample-exact data but send does not { const float v = sendModel->value(); - if( exporting ) { MixHelpers::addSanitizedMultipliedByBuffer( m_buffer, ch_buf, v, volBuf, fpp ); } - else { MixHelpers::addMultipliedByBuffer( m_buffer, ch_buf, v, volBuf, fpp ); } + MixHelpers::addSanitizedMultipliedByBuffer( m_buffer, ch_buf, v, volBuf, fpp ); } else // vice versa { const float v = sender->m_volumeModel.value(); - if( exporting ) { MixHelpers::addSanitizedMultipliedByBuffer( m_buffer, ch_buf, v, sendBuf, fpp ); } - else { MixHelpers::addMultipliedByBuffer( m_buffer, ch_buf, v, sendBuf, fpp ); } + MixHelpers::addSanitizedMultipliedByBuffer( m_buffer, ch_buf, v, sendBuf, fpp ); } m_hasInput = true; } diff --git a/src/core/Instrument.cpp b/src/core/Instrument.cpp index 859882fd3..534bb783a 100644 --- a/src/core/Instrument.cpp +++ b/src/core/Instrument.cpp @@ -34,16 +34,6 @@ Instrument::Instrument( InstrumentTrack * _instrument_track, { } - - - -Instrument::~Instrument() -{ -} - - - - void Instrument::play( sampleFrame * ) { } diff --git a/src/core/InstrumentFunctions.cpp b/src/core/InstrumentFunctions.cpp index 4bcbbb9f4..5a87b54dd 100644 --- a/src/core/InstrumentFunctions.cpp +++ b/src/core/InstrumentFunctions.cpp @@ -547,7 +547,6 @@ void InstrumentFunctionArpeggio::saveSettings( QDomDocument & _doc, QDomElement m_arpTimeModel.saveSettings( _doc, _this, "arptime" ); m_arpGateModel.saveSettings( _doc, _this, "arpgate" ); m_arpDirectionModel.saveSettings( _doc, _this, "arpdir" ); - m_arpModeModel.saveSettings( _doc, _this, "arpmode" ); } @@ -565,14 +564,5 @@ void InstrumentFunctionArpeggio::loadSettings( const QDomElement & _this ) m_arpTimeModel.loadSettings( _this, "arptime" ); m_arpGateModel.loadSettings( _this, "arpgate" ); m_arpDirectionModel.loadSettings( _this, "arpdir" ); -/* - // Keep compatibility with version 0.2.1 file format - if( _this.hasAttribute( "arpsyncmode" ) ) - { - m_arpTimeKnob->setSyncMode( - ( tempoSyncKnob::tempoSyncMode ) _this.attribute( - "arpsyncmode" ).toInt() ); - }*/ - m_arpModeModel.loadSettings( _this, "arpmode" ); } diff --git a/src/core/MixHelpers.cpp b/src/core/MixHelpers.cpp index fac61649c..e1a2e092f 100644 --- a/src/core/MixHelpers.cpp +++ b/src/core/MixHelpers.cpp @@ -82,6 +82,10 @@ bool sanitize( sampleFrame * src, int frames ) src[f][c] = 0.0f; found = true; } + else + { + src[f][c] = qBound( -4.0f, src[f][c], 4.0f ); + } } } return found; diff --git a/src/core/PeakController.cpp b/src/core/PeakController.cpp index 976e3c96e..9e5e654a6 100644 --- a/src/core/PeakController.cpp +++ b/src/core/PeakController.cpp @@ -33,7 +33,6 @@ #include "Mixer.h" #include "EffectChain.h" #include "plugins/peak_controller_effect/peak_controller_effect.h" -#include "PresetPreviewPlayHandle.h" PeakControllerEffectVector PeakController::s_effects; int PeakController::m_getCount; @@ -64,11 +63,7 @@ PeakController::PeakController( Model * _parent, PeakController::~PeakController() { - //EffectChain::loadSettings() appends effect to EffectChain::m_effects - //When it's previewing, EffectChain::loadSettings() is not called - //Therefore, we shouldn't call removeEffect() as it is not even appended. - //NB: Most XML setting are loaded on preview, except controller fx. - if( m_peakEffect != NULL && m_peakEffect->effectChain() != NULL && PresetPreviewPlayHandle::isPreviewing() == false ) + if( m_peakEffect != NULL && m_peakEffect->effectChain() != NULL ) { m_peakEffect->effectChain()->removeEffect( m_peakEffect ); } diff --git a/src/core/Piano.cpp b/src/core/Piano.cpp index 7ea9cb2b0..565f1aa4f 100644 --- a/src/core/Piano.cpp +++ b/src/core/Piano.cpp @@ -70,19 +70,6 @@ Piano::Piano( InstrumentTrack* track ) : } - - - -/*! \brief Destroy this new keyboard display - * - */ -Piano::~Piano() -{ -} - - - - /*! \brief Turn a key on or off * * \param key the key number to change diff --git a/src/core/SampleBuffer.cpp b/src/core/SampleBuffer.cpp index 2a470f4fe..9cde88cf5 100644 --- a/src/core/SampleBuffer.cpp +++ b/src/core/SampleBuffer.cpp @@ -1404,7 +1404,7 @@ QString SampleBuffer::tryToMakeRelative( const QString & file ) if( QFileInfo( file ).isRelative() == false ) { // Normalize the path - QString f = QFileInfo( file ).canonicalFilePath().replace( QDir::separator(), '/' ); + QString f( QDir::cleanPath( file ) ); // First, look in factory samples // Isolate "samples/" from "data:/samples/" @@ -1413,7 +1413,7 @@ QString SampleBuffer::tryToMakeRelative( const QString & file ) // Iterate over all valid "data:/" searchPaths for ( const QString & path : QDir::searchPaths( "data" ) ) { - QString samplesPath = QString( path + samplesSuffix ).replace( QDir::separator(), '/' ); + QString samplesPath = QDir::cleanPath( path + samplesSuffix ) + "/"; if ( f.startsWith( samplesPath ) ) { return QString( f ).mid( samplesPath.length() ); diff --git a/src/core/Song.cpp b/src/core/Song.cpp index e26b812e8..c670ade66 100644 --- a/src/core/Song.cpp +++ b/src/core/Song.cpp @@ -605,7 +605,7 @@ void Song::setPlayPos( tick_t ticks, PlayModes playMode ) { tick_t ticksFromPlayMode = m_playPos[playMode].getTicks(); m_elapsedTicks += ticksFromPlayMode - ticks; - m_elapsedMilliSeconds[m_playMode] += MidiTime::ticksToMilliseconds( ticks - ticksFromPlayMode, getTempo() ); + m_elapsedMilliSeconds[playMode] += MidiTime::ticksToMilliseconds( ticks - ticksFromPlayMode, getTempo() ); m_playPos[playMode].setTicks( ticks ); m_playPos[playMode].setCurrentFrame( 0.0f ); diff --git a/src/core/Track.cpp b/src/core/Track.cpp index a67298105..348f4f96c 100644 --- a/src/core/Track.cpp +++ b/src/core/Track.cpp @@ -741,30 +741,47 @@ void TrackContentObjectView::mousePressEvent( QMouseEvent * me ) && !m_tco->getAutoResize() ) { m_action = ResizeLeft; - m_oldTime = m_tco->startPosition(); QCursor c( Qt::SizeHorCursor ); QApplication::setOverrideCursor( c ); - s_textFloat->setTitle( tr( "Current length" ) ); } else if( me->x() < width() - RESIZE_GRIP_WIDTH ) { m_action = Move; - m_oldTime = m_tco->startPosition(); QCursor c( Qt::SizeAllCursor ); QApplication::setOverrideCursor( c ); - s_textFloat->setTitle( tr( "Current position" ) ); } else if( !m_tco->getAutoResize() ) { m_action = Resize; - m_oldTime = m_tco->length(); QCursor c( Qt::SizeHorCursor ); QApplication::setOverrideCursor( c ); + } + + if( m_action == Move ) + { + s_textFloat->setTitle( tr( "Current position" ) ); + s_textFloat->setText( QString( "%1:%2" ). + arg( m_tco->startPosition().getTact() + 1 ). + arg( m_tco->startPosition().getTicks() % + MidiTime::ticksPerTact() ) ); + } + else if( m_action == Resize || m_action == ResizeLeft ) + { s_textFloat->setTitle( tr( "Current length" ) ); + s_textFloat->setText( tr( "%1:%2 (%3:%4 to %5:%6)" ). + arg( m_tco->length().getTact() ). + arg( m_tco->length().getTicks() % + MidiTime::ticksPerTact() ). + arg( m_tco->startPosition().getTact() + 1 ). + arg( m_tco->startPosition().getTicks() % + MidiTime::ticksPerTact() ). + arg( m_tco->endPosition().getTact() + 1 ). + arg( m_tco->endPosition().getTicks() % + MidiTime::ticksPerTact() ) ); } // s_textFloat->reparent( this ); // setup text-float as if TCO was already moved/resized - mouseMoveEvent( me ); + s_textFloat->moveGlobal( this, QPoint( width() + 2, height() + 2) ); s_textFloat->show(); } @@ -891,8 +908,7 @@ void TrackContentObjectView::mouseMoveEvent( QMouseEvent * me ) arg( m_tco->startPosition().getTact() + 1 ). arg( m_tco->startPosition().getTicks() % MidiTime::ticksPerTact() ) ); - s_textFloat->moveGlobal( this, QPoint( width() + 2, - height() + 2 ) ); + s_textFloat->moveGlobal( this, QPoint( width() + 2, height() + 2 ) ); } else if( m_action == MoveSelection ) { @@ -980,8 +996,7 @@ void TrackContentObjectView::mouseMoveEvent( QMouseEvent * me ) arg( m_tco->endPosition().getTact() + 1 ). arg( m_tco->endPosition().getTicks() % MidiTime::ticksPerTact() ) ); - s_textFloat->moveGlobal( this, QPoint( width() + 2, - height() + 2) ); + s_textFloat->moveGlobal( this, QPoint( width() + 2, height() + 2) ); } else { diff --git a/src/gui/AutomatableModelView.cpp b/src/gui/AutomatableModelView.cpp index 973e5c817..0597cf2f5 100644 --- a/src/gui/AutomatableModelView.cpp +++ b/src/gui/AutomatableModelView.cpp @@ -50,16 +50,6 @@ AutomatableModelView::AutomatableModelView( ::Model* model, QWidget* _this ) : widget()->setCursor( QCursor( embed::getIconPixmap( "hand" ), 3, 3 ) ); } - - - -AutomatableModelView::~AutomatableModelView() -{ -} - - - - void AutomatableModelView::addDefaultActions( QMenu* menu ) { AutomatableModel* model = modelUntyped(); diff --git a/src/gui/FileBrowser.cpp b/src/gui/FileBrowser.cpp index 4a0d22888..91804d136 100644 --- a/src/gui/FileBrowser.cpp +++ b/src/gui/FileBrowser.cpp @@ -112,16 +112,6 @@ FileBrowser::FileBrowser(const QString & directories, const QString & filter, show(); } - - - -FileBrowser::~FileBrowser() -{ -} - - - - bool FileBrowser::filterItems( const QString & filter, QTreeWidgetItem * item ) { // call with item=NULL to filter the entire tree @@ -338,16 +328,6 @@ FileBrowserTreeWidget::FileBrowserTreeWidget(QWidget * parent ) : } - - - -FileBrowserTreeWidget::~FileBrowserTreeWidget() -{ -} - - - - void FileBrowserTreeWidget::contextMenuEvent(QContextMenuEvent * e ) { FileItem * f = dynamic_cast( itemAt( e->pos() ) ); diff --git a/src/gui/FxMixerView.cpp b/src/gui/FxMixerView.cpp index 8da1cb4e0..cbcfd0a47 100644 --- a/src/gui/FxMixerView.cpp +++ b/src/gui/FxMixerView.cpp @@ -491,6 +491,12 @@ void FxMixerView::moveChannelRight(int index) } +void FxMixerView::renameChannel(int index) +{ + m_fxChannelViews[index]->m_fxLine->renameChannel(); +} + + void FxMixerView::keyPressEvent(QKeyEvent * e) { @@ -527,6 +533,11 @@ void FxMixerView::keyPressEvent(QKeyEvent * e) addNewChannel(); } break; + case Qt::Key_Enter: + case Qt::Key_Return: + case Qt::Key_F2: + renameChannel( m_currentFxLine->channelIndex() ); + break; } } diff --git a/src/gui/GuiApplication.cpp b/src/gui/GuiApplication.cpp index ce83d0712..2b3ac48de 100644 --- a/src/gui/GuiApplication.cpp +++ b/src/gui/GuiApplication.cpp @@ -61,7 +61,7 @@ GuiApplication::GuiApplication() QApplication::setAttribute(Qt::AA_EnableHighDpiScaling, true); #endif - // prompt the user to create the LMMS working directory (e.g. ~/lmms) if it doesn't exist + // prompt the user to create the LMMS working directory (e.g. ~/Documents/lmms) if it doesn't exist if ( !ConfigManager::inst()->hasWorkingDir() && QMessageBox::question( NULL, tr( "Working directory" ), diff --git a/src/gui/LmmsStyle.cpp b/src/gui/LmmsStyle.cpp index b883a2b2f..e57e29e47 100644 --- a/src/gui/LmmsStyle.cpp +++ b/src/gui/LmmsStyle.cpp @@ -177,6 +177,13 @@ void LmmsStyle::drawComplexControl( ComplexControl control, return; } } + else if (control == CC_MdiControls) + { + QStyleOptionComplex so(*option); + so.palette.setColor(QPalette::Button, QColor(223, 228, 236)); + QProxyStyle::drawComplexControl(control, &so, painter, widget); + return; + } /* else if( control == CC_ScrollBar ) { painter->fillRect( option->rect, QApplication::palette().color( QPalette::Active, @@ -365,4 +372,3 @@ void LmmsStyle::hoverColors( bool sunken, bool hover, bool active, QColor& color blend = QColor( 33, 33, 33 ); } } - diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index 92963d173..f1f8da42f 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -561,33 +561,33 @@ void MainWindow::finalize() "for managing effects for your song. You can insert " "effects into different effect-channels." ) ); + ToolButton * controllers_window = new ToolButton( + embed::getIconPixmap( "controller" ), + tr( "Show/hide controller rack" ) + + " (F10)", + this, SLOT( toggleControllerRack() ), + m_toolBar ); + controllers_window->setShortcut( Qt::Key_F10 ); + ToolButton * project_notes_window = new ToolButton( embed::getIconPixmap( "project_notes" ), tr( "Show/hide project notes" ) + - " (F10)", + " (F11)", this, SLOT( toggleProjectNotesWin() ), m_toolBar ); - project_notes_window->setShortcut( Qt::Key_F10 ); + project_notes_window->setShortcut( Qt::Key_F11 ); project_notes_window->setWhatsThis( tr( "Click here to show or hide the " "project notes window. In this window you can put " "down your project notes.") ); - ToolButton * controllers_window = new ToolButton( - embed::getIconPixmap( "controller" ), - tr( "Show/hide controller rack" ) + - " (F11)", - this, SLOT( toggleControllerRack() ), - m_toolBar ); - controllers_window->setShortcut( Qt::Key_F11 ); - m_toolBarLayout->addWidget( song_editor_window, 1, 1 ); m_toolBarLayout->addWidget( bb_editor_window, 1, 2 ); m_toolBarLayout->addWidget( piano_roll_window, 1, 3 ); m_toolBarLayout->addWidget( automation_editor_window, 1, 4 ); m_toolBarLayout->addWidget( fx_mixer_window, 1, 5 ); - m_toolBarLayout->addWidget( project_notes_window, 1, 6 ); - m_toolBarLayout->addWidget( controllers_window, 1, 7 ); + m_toolBarLayout->addWidget( controllers_window, 1, 6 ); + m_toolBarLayout->addWidget( project_notes_window, 1, 7 ); m_toolBarLayout->setColumnStretch( 100, 1 ); // setup-dialog opened before? @@ -1226,15 +1226,14 @@ void MainWindow::updateViewMenu() tr( "FX Mixer" ) + " (F9)", this, SLOT( toggleFxMixerWin() ) ); - m_viewMenu->addAction(embed::getIconPixmap( "project_notes" ), - tr( "Project Notes" ) + " (F10)", - this, SLOT( toggleProjectNotesWin() ) - ); m_viewMenu->addAction(embed::getIconPixmap( "controller" ), - tr( "Controller Rack" ) + - " (F11)", + tr( "Controller Rack" ) + " (F10)", this, SLOT( toggleControllerRack() ) ); + m_viewMenu->addAction(embed::getIconPixmap( "project_notes" ), + tr( "Project Notes" ) + " (F11)", + this, SLOT( toggleProjectNotesWin() ) + ); m_viewMenu->addSeparator(); diff --git a/src/gui/PianoView.cpp b/src/gui/PianoView.cpp index 351806936..6e8464dd4 100644 --- a/src/gui/PianoView.cpp +++ b/src/gui/PianoView.cpp @@ -130,19 +130,6 @@ PianoView::PianoView( QWidget * _parent ) : } - - - -/*! \brief Destroy this piano display view - * - */ -PianoView::~PianoView() -{ -} - - - - /*! \brief Map a keyboard key being pressed to a note in our keyboard view * * \param _k The keyboard scan code of the key being pressed. @@ -327,7 +314,9 @@ void PianoView::modelChanged() */ int PianoView::getKeyFromMouse( const QPoint & _p ) const { - int key_num = (int)( (float) _p.x() / (float) PW_WHITE_KEY_WIDTH ); + int offset = _p.x() % PW_WHITE_KEY_WIDTH; + if( offset < 0 ) offset += PW_WHITE_KEY_WIDTH; + int key_num = ( _p.x() - offset) / PW_WHITE_KEY_WIDTH; for( int i = 0; i <= key_num; ++i ) { @@ -336,6 +325,13 @@ int PianoView::getKeyFromMouse( const QPoint & _p ) const ++key_num; } } + for( int i = 0; i >= key_num; --i ) + { + if ( Piano::isBlackKey( m_startKey+i ) ) + { + --key_num; + } + } key_num += m_startKey; @@ -345,16 +341,14 @@ int PianoView::getKeyFromMouse( const QPoint & _p ) const // then do extra checking whether the mouse-cursor is over // a black key if( key_num > 0 && Piano::isBlackKey( key_num-1 ) && - _p.x() % PW_WHITE_KEY_WIDTH <= - ( PW_WHITE_KEY_WIDTH / 2 ) - - ( PW_BLACK_KEY_WIDTH / 2 ) ) + offset <= ( PW_WHITE_KEY_WIDTH / 2 ) - + ( PW_BLACK_KEY_WIDTH / 2 ) ) { --key_num; } if( key_num < NumKeys - 1 && Piano::isBlackKey( key_num+1 ) && - _p.x() % PW_WHITE_KEY_WIDTH >= - ( PW_WHITE_KEY_WIDTH - - PW_BLACK_KEY_WIDTH / 2 ) ) + offset >= ( PW_WHITE_KEY_WIDTH - + PW_BLACK_KEY_WIDTH / 2 ) ) { ++key_num; } diff --git a/src/gui/editors/AutomationEditor.cpp b/src/gui/editors/AutomationEditor.cpp index c47a58873..6743a7ca0 100644 --- a/src/gui/editors/AutomationEditor.cpp +++ b/src/gui/editors/AutomationEditor.cpp @@ -504,7 +504,7 @@ void AutomationEditor::mousePressEvent( QMouseEvent* mouseEvent ) int x = mouseEvent->x(); - if( x > VALUES_WIDTH ) + if( x >= VALUES_WIDTH ) { // set or move value @@ -1077,8 +1077,8 @@ void AutomationEditor::mouseMoveEvent(QMouseEvent * mouseEvent ) inline void AutomationEditor::drawCross( QPainter & p ) { QPoint mouse_pos = mapFromGlobal( QCursor::pos() ); - float level = getLevel( mouse_pos.y() ); int grid_bottom = height() - SCROLLBAR_SIZE - 1; + float level = getLevel( mouse_pos.y() ); float cross_y = m_y_auto ? grid_bottom - ( ( grid_bottom - TOP_MARGIN ) * ( level - m_minLevel ) @@ -1087,13 +1087,23 @@ inline void AutomationEditor::drawCross( QPainter & p ) p.setPen( crossColor() ); p.drawLine( VALUES_WIDTH, (int) cross_y, width(), (int) cross_y ); - p.drawLine( mouse_pos.x(), TOP_MARGIN, mouse_pos.x(), - height() - SCROLLBAR_SIZE ); + p.drawLine( mouse_pos.x(), TOP_MARGIN, mouse_pos.x(), height() - SCROLLBAR_SIZE ); + + QPoint tt_pos = QCursor::pos(); - tt_pos.ry() -= 64; - tt_pos.rx() += 32; + tt_pos.ry() -= 51; + tt_pos.rx() += 26; + float scaledLevel = m_pattern->firstObject()->scaledValue( level ); - QToolTip::showText( tt_pos, QString::number( scaledLevel ), this ); + + // Limit the scaled-level tooltip to the grid + if( mouse_pos.x() >= 0 && + mouse_pos.x() <= width() - SCROLLBAR_SIZE && + mouse_pos.y() >= 0 && + mouse_pos.y() <= height() - SCROLLBAR_SIZE ) + { + QToolTip::showText( tt_pos, QString::number( scaledLevel ), this ); + } } @@ -1670,6 +1680,17 @@ void AutomationEditor::wheelEvent(QWheelEvent * we ) x--; } x = qBound( 0, x, m_zoomingXModel.size() - 1 ); + + int mouseX = (we->x() - VALUES_WIDTH)* MidiTime::ticksPerTact(); + // ticks based on the mouse x-position where the scroll wheel was used + int ticks = mouseX / m_ppt; + // what would be the ticks in the new zoom level on the very same mouse x + int newTicks = mouseX / (DEFAULT_PPT * m_zoomXLevels[x]); + + // scroll so the tick "selected" by the mouse x doesn't move on the screen + m_leftRightScroll->setValue(m_leftRightScroll->value() + ticks - newTicks); + + m_zoomingXModel.setValue( x ); } else if( we->modifiers() & Qt::ShiftModifier diff --git a/src/gui/editors/PianoRoll.cpp b/src/gui/editors/PianoRoll.cpp index 4a044891e..983d2eb7b 100644 --- a/src/gui/editors/PianoRoll.cpp +++ b/src/gui/editors/PianoRoll.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -891,10 +892,6 @@ void PianoRoll::drawDetuningInfo( QPainter & _p, const Note * _n, int _x, for( timeMap::ConstIterator it = map.begin(); it != map.end(); ++it ) { int pos_ticks = it.key(); - if( pos_ticks > _n->length() ) - { - break; - } int pos_x = _x + pos_ticks * m_ppt / MidiTime::ticksPerTact(); const float level = it.value(); @@ -1340,8 +1337,8 @@ void PianoRoll::mousePressEvent(QMouseEvent * me ) if( m_editMode == ModeEditDetuning && noteUnderMouse() ) { - static AutomationPattern* detuningPattern = nullptr; - if (detuningPattern != nullptr) + static QPointer detuningPattern = nullptr; + if (detuningPattern.data() != nullptr) { detuningPattern->disconnect(this); } @@ -1351,7 +1348,7 @@ void PianoRoll::mousePressEvent(QMouseEvent * me ) n->createDetuning(); } detuningPattern = n->detuning()->automationPattern(); - connect(detuningPattern, SIGNAL(dataChanged()), this, SLOT(update())); + connect(detuningPattern.data(), SIGNAL(dataChanged()), this, SLOT(update())); gui->automationEditor()->open(detuningPattern); return; } @@ -2639,23 +2636,6 @@ void PianoRoll::paintEvent(QPaintEvent * pe ) int key = m_startKey; - // display note marks before drawing other lines - for( int i = 0; i < m_markedSemiTones.size(); i++ ) - { - const int key_num = m_markedSemiTones.at( i ); - const int y = keyAreaBottom() + 5 - - KEY_LINE_HEIGHT * ( key_num - m_startKey + 1 ); - - if( y > keyAreaBottom() ) - { - break; - } - - p.fillRect( WHITE_KEY_WIDTH + 1, y - KEY_LINE_HEIGHT / 2, width() - 10, KEY_LINE_HEIGHT, - markedSemitoneColor() ); - } - - // draw all white keys... for( int y = key_line_y + 1 + y_offset; y > PR_TOP_MARGIN; key_line_y -= KEY_LINE_HEIGHT, ++keys_processed ) @@ -2919,7 +2899,6 @@ void PianoRoll::paintEvent(QPaintEvent * pe ) } } - // Draw the vertical beat lines int ticksPerBeat = DefaultTicksPerTact / Engine::getSong()->getTimeSigModel().getDenominator(); @@ -2940,8 +2919,23 @@ void PianoRoll::paintEvent(QPaintEvent * pe ) p.setPen( barLineColor() ); p.drawLine( x, PR_TOP_MARGIN, x, height() - PR_BOTTOM_MARGIN ); } - } + // draw marked semitones after the grid + for( int i = 0; i < m_markedSemiTones.size(); i++ ) + { + const int key_num = m_markedSemiTones.at( i ); + const int y = keyAreaBottom() + 5 + - KEY_LINE_HEIGHT * ( key_num - m_startKey + 1 ); + + if( y > keyAreaBottom() ) + { + break; + } + + p.fillRect( WHITE_KEY_WIDTH + 1, y - KEY_LINE_HEIGHT / 2, width() - 10, KEY_LINE_HEIGHT + 1, + markedSemitoneColor() ); + } + } // following code draws all notes in visible area // and the note editing stuff (volume, panning, etc) @@ -3302,6 +3296,14 @@ void PianoRoll::wheelEvent(QWheelEvent * we ) z--; } z = qBound( 0, z, m_zoomingModel.size() - 1 ); + + int x = (we->x() - WHITE_KEY_WIDTH)* MidiTime::ticksPerTact(); + // ticks based on the mouse x-position where the scroll wheel was used + int ticks = x / m_ppt; + // what would be the ticks in the new zoom level on the very same mouse x + int newTicks = x / (DEFAULT_PR_PPT * m_zoomLevels[z]); + // scroll so the tick "selected" by the mouse x doesn't move on the screen + m_leftRightScroll->setValue(m_leftRightScroll->value() + ticks - newTicks); // update combobox with zooming-factor m_zoomingModel.setValue( z ); } @@ -4082,14 +4084,14 @@ PianoRollWindow::PianoRollWindow() : QAction* drawAction = editModeGroup->addAction( embed::getIconPixmap( "edit_draw" ), tr( "Draw mode (Shift+D)" ) ); QAction* eraseAction = editModeGroup->addAction( embed::getIconPixmap( "edit_erase" ), tr("Erase mode (Shift+E)" ) ); QAction* selectAction = editModeGroup->addAction( embed::getIconPixmap( "edit_select" ), tr( "Select mode (Shift+S)" ) ); - QAction* detuneAction = editModeGroup->addAction( embed::getIconPixmap( "automation" ), tr("Detune mode (Shift+T)" ) ); + QAction* pitchBendAction = editModeGroup->addAction( embed::getIconPixmap( "automation" ), tr("Pitch Bend mode (Shift+T)" ) ); drawAction->setChecked( true ); drawAction->setShortcut( Qt::SHIFT | Qt::Key_D ); eraseAction->setShortcut( Qt::SHIFT | Qt::Key_E ); selectAction->setShortcut( Qt::SHIFT | Qt::Key_S ); - detuneAction->setShortcut( Qt::SHIFT | Qt::Key_T ); + pitchBendAction->setShortcut( Qt::SHIFT | Qt::Key_T ); drawAction->setWhatsThis( tr( "Click here and draw mode will be activated. In this " @@ -4117,8 +4119,8 @@ PianoRollWindow::PianoRollWindow() : #else "Ctrl" ) ); #endif - detuneAction->setWhatsThis( - tr( "Click here and detune mode will be activated. " + pitchBendAction->setWhatsThis( + tr( "Click here and Pitch Bend mode will be activated. " "In this mode you can click a note to open its " "automation detuning. You can utilize this to slide " "notes from one to another. You can also press " @@ -4132,7 +4134,7 @@ PianoRollWindow::PianoRollWindow() : notesActionsToolBar->addAction( drawAction ); notesActionsToolBar->addAction( eraseAction ); notesActionsToolBar->addAction( selectAction ); - notesActionsToolBar->addAction( detuneAction ); + notesActionsToolBar->addAction( pitchBendAction ); notesActionsToolBar->addSeparator(); notesActionsToolBar->addAction( quantizeAction ); diff --git a/src/gui/editors/SongEditor.cpp b/src/gui/editors/SongEditor.cpp index b26b3bc86..d77a1a2f1 100644 --- a/src/gui/editors/SongEditor.cpp +++ b/src/gui/editors/SongEditor.cpp @@ -83,11 +83,11 @@ SongEditor::SongEditor( Song * song ) : { m_zoomingModel->setParent(this); // create time-line - int widgetTotal = ConfigManager::inst()->value( "ui", + m_widgetWidthTotal = ConfigManager::inst()->value( "ui", "compacttrackbuttons" ).toInt()==1 ? DEFAULT_SETTINGS_WIDGET_WIDTH_COMPACT + TRACK_OP_WIDTH_COMPACT : DEFAULT_SETTINGS_WIDGET_WIDTH + TRACK_OP_WIDTH; - m_timeLine = new TimeLineWidget( widgetTotal, 32, + m_timeLine = new TimeLineWidget( m_widgetWidthTotal, 32, pixelsPerTact(), m_song->m_playPos[Song::Mode_PlaySong], m_currentPosition, @@ -391,6 +391,16 @@ void SongEditor::wheelEvent( QWheelEvent * we ) z--; } z = qBound( 0, z, m_zoomingModel->size() - 1 ); + + + int x = (we->x() - m_widgetWidthTotal); + // tact based on the mouse x-position where the scroll wheel was used + int tact= x / pixelsPerTact(); + // what would be the tact in the new zoom level on the very same mouse x + int newTact = x / DEFAULT_PIXELS_PER_TACT / m_zoomLevels[z]; + // scroll so the tact "selected" by the mouse x doesn't move on the screen + m_leftRightScroll->setValue(m_leftRightScroll->value() + tact - newTact); + // update combobox with zooming-factor m_zoomingModel->setValue( z ); diff --git a/src/gui/widgets/EnvelopeAndLfoView.cpp b/src/gui/widgets/EnvelopeAndLfoView.cpp index 4d61e814c..4131a956e 100644 --- a/src/gui/widgets/EnvelopeAndLfoView.cpp +++ b/src/gui/widgets/EnvelopeAndLfoView.cpp @@ -393,14 +393,20 @@ void EnvelopeAndLfoView::dropEvent( QDropEvent * _de ) m_params->m_userWave.setAudioFile( StringPairDrag::decodeValue( _de ) ); m_userLfoBtn->model()->setValue( true ); + m_params->m_lfoWaveModel.setValue(EnvelopeAndLfoParameters::UserDefinedWave); _de->accept(); + update(); } else if( type == QString( "tco_%1" ).arg( Track::SampleTrack ) ) { DataFile dataFile( value.toUtf8() ); - m_params->m_userWave.setAudioFile( dataFile.content().firstChild().toElement(). attribute( "src" ) ); + m_params->m_userWave.setAudioFile( dataFile.content(). + firstChildElement().firstChildElement(). + firstChildElement().attribute( "src" ) ); m_userLfoBtn->model()->setValue( true ); + m_params->m_lfoWaveModel.setValue(EnvelopeAndLfoParameters::UserDefinedWave); _de->accept(); + update(); } } diff --git a/src/gui/widgets/Fader.cpp b/src/gui/widgets/Fader.cpp index b634ba819..4317066ab 100644 --- a/src/gui/widgets/Fader.cpp +++ b/src/gui/widgets/Fader.cpp @@ -133,12 +133,6 @@ Fader::Fader( FloatModel * model, const QString & name, QWidget * parent, QPixma init(model, name); } - -Fader::~Fader() -{ -} - - void Fader::init(FloatModel * model, QString const & name) { setWindowTitle( name ); diff --git a/src/gui/widgets/FxLine.cpp b/src/gui/widgets/FxLine.cpp index c6e6fd9ae..309ef6a1c 100644 --- a/src/gui/widgets/FxLine.cpp +++ b/src/gui/widgets/FxLine.cpp @@ -34,6 +34,24 @@ #include "GuiApplication.h" #include "Song.h" +bool FxLine::eventFilter( QObject *dist, QEvent *event ) +{ + // If we are in a rename, capture the enter/return events and handle them + if ( event->type() == QEvent::KeyPress ) + { + QKeyEvent * keyEvent = static_cast(event); + if( keyEvent->key() == Qt::Key_Enter || keyEvent->key() == Qt::Key_Return ) + { + if( m_inRename ) + { + renameFinished(); + event->accept(); // Stop the event from propagating + return true; + } + } + } + return false; +} const int FxLine::FxLineHeight = 287; QPixmap * FxLine::s_sendBgArrow = NULL; @@ -100,6 +118,7 @@ FxLine::FxLine( QWidget * _parent, FxMixerView * _mv, int _channelIndex ) : m_renameLineEdit->setFixedWidth( 65 ); m_renameLineEdit->setFont( pointSizeF( font(), 7.5f ) ); m_renameLineEdit->setReadOnly( true ); + m_renameLineEdit->installEventFilter( this ); QGraphicsScene * scene = new QGraphicsScene(); scene->setSceneRect( 0, 0, 33, FxLineHeight ); diff --git a/src/gui/widgets/Graph.cpp b/src/gui/widgets/Graph.cpp index 2cca2c424..ed57dcea6 100644 --- a/src/gui/widgets/Graph.cpp +++ b/src/gui/widgets/Graph.cpp @@ -56,13 +56,6 @@ Graph::Graph( QWidget * _parent, graphStyle _style, int _width, this, SLOT( updateGraph( ) ) ); } - -Graph::~Graph() -{ -} - - - void Graph::setForeground( const QPixmap &_pixmap ) { m_foreground = _pixmap; @@ -470,14 +463,6 @@ graphModel::graphModel( float _min, float _max, int _length, { } - - -graphModel::~graphModel() -{ -} - - - void graphModel::setRange( float _min, float _max ) { if( _min != m_minValue || _max != m_maxValue ) diff --git a/src/gui/widgets/LcdSpinBox.cpp b/src/gui/widgets/LcdSpinBox.cpp index 2dff70450..325c0171d 100644 --- a/src/gui/widgets/LcdSpinBox.cpp +++ b/src/gui/widgets/LcdSpinBox.cpp @@ -58,14 +58,6 @@ LcdSpinBox::LcdSpinBox( int numDigits, const QString& style, QWidget* parent, co { } - - -LcdSpinBox::~LcdSpinBox() -{ -} - - - void LcdSpinBox::update() { setValue( model()->value() + m_displayOffset ); diff --git a/src/gui/widgets/SideBar.cpp b/src/gui/widgets/SideBar.cpp index 2e6c2f048..01ea58919 100644 --- a/src/gui/widgets/SideBar.cpp +++ b/src/gui/widgets/SideBar.cpp @@ -41,9 +41,8 @@ public: m_orientation( _orientation ) { } - virtual ~SideBarButton() - { - } + + virtual ~SideBarButton() = default; Qt::Orientation orientation() const { diff --git a/src/gui/widgets/TabBar.cpp b/src/gui/widgets/TabBar.cpp index 115786be5..d40b41d98 100644 --- a/src/gui/widgets/TabBar.cpp +++ b/src/gui/widgets/TabBar.cpp @@ -41,16 +41,6 @@ TabBar::TabBar( QWidget * _parent, QBoxLayout::Direction _dir ) : setLayout( m_layout ); } - - - -TabBar::~TabBar() -{ -} - - - - TabButton * TabBar::addTab( QWidget * _w, const QString & _text, int _id, bool _add_stretch, bool _text_is_tooltip ) { diff --git a/src/gui/widgets/TabWidget.cpp b/src/gui/widgets/TabWidget.cpp index 6fde217c1..f06710098 100644 --- a/src/gui/widgets/TabWidget.cpp +++ b/src/gui/widgets/TabWidget.cpp @@ -61,12 +61,6 @@ TabWidget::TabWidget( const QString & caption, QWidget * parent, bool usePixmap } - -TabWidget::~TabWidget() -{ -} - - void TabWidget::addTab( QWidget * w, const QString & name, const char *pixmap, int idx ) { setFont( pointSize<8>( font() ) ); diff --git a/src/gui/widgets/TimeDisplayWidget.cpp b/src/gui/widgets/TimeDisplayWidget.cpp index 2805aa8f4..2ef764c34 100644 --- a/src/gui/widgets/TimeDisplayWidget.cpp +++ b/src/gui/widgets/TimeDisplayWidget.cpp @@ -58,17 +58,6 @@ TimeDisplayWidget::TimeDisplayWidget() : this, SLOT( updateTime() ) ); } - - - -TimeDisplayWidget::~TimeDisplayWidget() -{ -} - - - - - void TimeDisplayWidget::setDisplayMode( DisplayMode displayMode ) { m_displayMode = displayMode; diff --git a/src/gui/widgets/ToolButton.cpp b/src/gui/widgets/ToolButton.cpp index 2f89d8180..21363f66b 100644 --- a/src/gui/widgets/ToolButton.cpp +++ b/src/gui/widgets/ToolButton.cpp @@ -41,10 +41,3 @@ ToolButton::ToolButton( const QPixmap & _pixmap, const QString & _tooltip, ToolTip::add( this, _tooltip ); setIcon( _pixmap ); } - - - - -ToolButton::~ToolButton() -{ -} diff --git a/src/tracks/AutomationTrack.cpp b/src/tracks/AutomationTrack.cpp index 77693ace6..11c919f0e 100644 --- a/src/tracks/AutomationTrack.cpp +++ b/src/tracks/AutomationTrack.cpp @@ -40,16 +40,6 @@ AutomationTrack::AutomationTrack( TrackContainer* tc, bool _hidden ) : setName( tr( "Automation track" ) ); } - - - -AutomationTrack::~AutomationTrack() -{ -} - - - - bool AutomationTrack::play( const MidiTime & time_start, const fpp_t _frames, const f_cnt_t _frame_base, int _tco_num ) { @@ -108,16 +98,6 @@ AutomationTrackView::AutomationTrackView( AutomationTrack * _at, TrackContainerV setModel( _at ); } - - - -AutomationTrackView::~AutomationTrackView() -{ -} - - - - void AutomationTrackView::dragEnterEvent( QDragEnterEvent * _dee ) { StringPairDrag::processDragEnterEvent( _dee, "automatable_model" ); diff --git a/src/tracks/BBTrack.cpp b/src/tracks/BBTrack.cpp index 841050cc9..c37c1466f 100644 --- a/src/tracks/BBTrack.cpp +++ b/src/tracks/BBTrack.cpp @@ -61,16 +61,6 @@ BBTCO::BBTCO( Track * _track ) : setAutoResize( false ); } - - - -BBTCO::~BBTCO() -{ -} - - - - void BBTCO::saveSettings( QDomDocument & doc, QDomElement & element ) { element.setAttribute( "name", name() ); @@ -168,16 +158,6 @@ BBTCOView::BBTCOView( TrackContentObject * _tco, TrackView * _tv ) : setStyle( QApplication::style() ); } - - - -BBTCOView::~BBTCOView() -{ -} - - - - void BBTCOView::constructContextMenu( QMenu * _cm ) { QAction * a = new QAction( embed::getIconPixmap( "bb_track" ), diff --git a/src/tracks/Pattern.cpp b/src/tracks/Pattern.cpp index 372c0bb1b..8218d16f6 100644 --- a/src/tracks/Pattern.cpp +++ b/src/tracks/Pattern.cpp @@ -616,19 +616,6 @@ PatternView::PatternView( Pattern* pattern, TrackView* parent ) : setStyle( QApplication::style() ); } - - - - - -PatternView::~PatternView() -{ -} - - - - - void PatternView::update() { ToolTip::add(this, m_pat->name()); @@ -900,8 +887,9 @@ void PatternView::paintEvent( QPaintEvent * ) } // Compute pixels per tact - const int baseWidth = fixedTCOs() ? parentWidget()->width() : width(); - const float pixelsPerTact = ( baseWidth - 2 * TCO_BORDER_WIDTH ) / (float) m_pat->length().getTact(); + const int baseWidth = fixedTCOs() ? parentWidget()->width() - 2 * TCO_BORDER_WIDTH + : width() - TCO_BORDER_WIDTH; + const float pixelsPerTact = baseWidth / (float) m_pat->length().getTact(); // Length of one tact/beat in the [0,1] x [0,1] coordinate system const float tactLength = 1. / m_pat->length().getTact(); diff --git a/src/tracks/SampleTrack.cpp b/src/tracks/SampleTrack.cpp index 28cda3ffd..7fda6512e 100644 --- a/src/tracks/SampleTrack.cpp +++ b/src/tracks/SampleTrack.cpp @@ -302,16 +302,6 @@ SampleTCOView::SampleTCOView( SampleTCO * _tco, TrackView * _tv ) : setStyle( QApplication::style() ); } - - - -SampleTCOView::~SampleTCOView() -{ -} - - - - void SampleTCOView::updateSample() { update();