From 60e9b2f474100bce39acfb947af42ee9220e4efd Mon Sep 17 00:00:00 2001 From: Hyunjin Song Date: Sun, 29 Oct 2017 20:26:28 +0900 Subject: [PATCH 01/24] Fix crashes and deadlocks with previewing preset (#3905) * Fix crash when closing while previewing preset * Fix deadlock on previewing presets while playing arpeggio --- src/core/PresetPreviewPlayHandle.cpp | 43 +++++++++++++++++----------- src/tracks/InstrumentTrack.cpp | 13 +++++---- 2 files changed, 35 insertions(+), 21 deletions(-) diff --git a/src/core/PresetPreviewPlayHandle.cpp b/src/core/PresetPreviewPlayHandle.cpp index dd57e9f9c..b85d02474 100644 --- a/src/core/PresetPreviewPlayHandle.cpp +++ b/src/core/PresetPreviewPlayHandle.cpp @@ -22,6 +22,7 @@ * */ +#include #include #include "PresetPreviewPlayHandle.h" @@ -66,12 +67,25 @@ public: NotePlayHandle* previewNote() { + #if QT_VERSION >= 0x050000 + return m_previewNote.loadAcquire(); + #else return m_previewNote; + #endif } void setPreviewNote( NotePlayHandle * _note ) { + #if QT_VERSION >= 0x050000 + m_previewNote.storeRelease( _note ); + #else m_previewNote = _note; + #endif + } + + bool testAndSetPreviewNote( NotePlayHandle * expectedVal, NotePlayHandle * newVal ) + { + return m_previewNote.testAndSetOrdered( expectedVal, newVal ); } void lockData() @@ -97,7 +111,7 @@ public: private: InstrumentTrack* m_previewInstrumentTrack; - NotePlayHandle* m_previewNote; + QAtomicPointer m_previewNote; QMutex m_dataMutex; friend class PresetPreviewPlayHandle; @@ -113,15 +127,14 @@ PresetPreviewPlayHandle::PresetPreviewPlayHandle( const QString & _preset_file, PlayHandle( TypePresetPreviewHandle ), m_previewNote( NULL ) { - s_previewTC->lockData(); - setUsesBuffer( false ); - if( s_previewTC->previewNote() != NULL ) - { - s_previewTC->previewNote()->mute(); - } + s_previewTC->lockData(); + Engine::mixer()->requestChangeInModel(); + s_previewTC->setPreviewNote( nullptr ); + s_previewTC->previewInstrumentTrack()->silenceAllNotes(); + Engine::mixer()->doneChangeInModel(); const bool j = Engine::projectJournal()->isJournalling(); Engine::projectJournal()->setJournalling( false ); @@ -174,6 +187,7 @@ PresetPreviewPlayHandle::PresetPreviewPlayHandle( const QString & _preset_file, s_previewTC->previewInstrumentTrack()-> midiPort()->setMode( MidiPort::Disabled ); + Engine::mixer()->requestChangeInModel(); // create note-play-handle for it m_previewNote = NotePlayHandleManager::acquire( s_previewTC->previewInstrumentTrack(), 0, @@ -186,6 +200,7 @@ PresetPreviewPlayHandle::PresetPreviewPlayHandle( const QString & _preset_file, Engine::mixer()->addPlayHandle( m_previewNote ); + Engine::mixer()->doneChangeInModel(); s_previewTC->unlockData(); Engine::projectJournal()->setJournalling( j ); } @@ -195,15 +210,13 @@ PresetPreviewPlayHandle::PresetPreviewPlayHandle( const QString & _preset_file, PresetPreviewPlayHandle::~PresetPreviewPlayHandle() { - s_previewTC->lockData(); + Engine::mixer()->requestChangeInModel(); // not muted by other preset-preview-handle? - if( !m_previewNote->isMuted() ) + if (s_previewTC->testAndSetPreviewNote(m_previewNote, nullptr)) { - // then set according state - s_previewTC->setPreviewNote( NULL ); + m_previewNote->noteOff(); } - m_previewNote->noteOff(); - s_previewTC->unlockData(); + Engine::mixer()->doneChangeInModel(); } @@ -228,7 +241,7 @@ bool PresetPreviewPlayHandle::isFinished() const bool PresetPreviewPlayHandle::isFromTrack( const Track * _track ) const { - return s_previewTC->previewInstrumentTrack() == _track; + return s_previewTC && s_previewTC->previewInstrumentTrack() == _track; } @@ -258,13 +271,11 @@ ConstNotePlayHandleList PresetPreviewPlayHandle::nphsOfInstrumentTrack( const InstrumentTrack * _it ) { ConstNotePlayHandleList cnphv; - s_previewTC->lockData(); if( s_previewTC->previewNote() != NULL && s_previewTC->previewNote()->instrumentTrack() == _it ) { cnphv.push_back( s_previewTC->previewNote() ); } - s_previewTC->unlockData(); return cnphv; } diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index 6aaf3eb75..90dbf11a6 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -442,12 +442,15 @@ void InstrumentTrack::silenceAllNotes( bool removeIPH ) m_midiNotesMutex.unlock(); lock(); - // invalidate all NotePlayHandles linked to this track + // invalidate all NotePlayHandles and PresetPreviewHandles linked to this track m_processHandles.clear(); - Engine::mixer()->removePlayHandlesOfTypes( this, removeIPH - ? PlayHandle::TypeNotePlayHandle - | PlayHandle::TypeInstrumentPlayHandle - : PlayHandle::TypeNotePlayHandle ); + + quint8 flags = PlayHandle::TypeNotePlayHandle | PlayHandle::TypePresetPreviewHandle; + if( removeIPH ) + { + flags |= PlayHandle::TypeInstrumentPlayHandle; + } + Engine::mixer()->removePlayHandlesOfTypes( this, flags ); unlock(); } From 7e107f59142a915369dfce90c0d335067a869d65 Mon Sep 17 00:00:00 2001 From: Michael Gregorius Date: Sat, 30 Sep 2017 22:50:09 +0200 Subject: [PATCH 02/24] Fix #3842: Opening a project with LB302 produces a noise burst Fix the noise burst described in #3842 by removing the second initialization of vca_a to 9 in the constructor of lb302Synth. --- plugins/lb302/lb302.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/lb302/lb302.cpp b/plugins/lb302/lb302.cpp index 81cd46a47..ec21e8e8b 100644 --- a/plugins/lb302/lb302.cpp +++ b/plugins/lb302/lb302.cpp @@ -339,7 +339,6 @@ lb302Synth::lb302Synth( InstrumentTrack * _instrumentTrack ) : // Experimenting with a0 between original (0.5) and 1.0 vca_a0 = 0.5; - vca_a = 9; vca_mode = 3; vcfs[0] = new lb302FilterIIR2(&fs); From 88b940fa05fc39b0f4c8bf9fa7b24ef6bf2881b1 Mon Sep 17 00:00:00 2001 From: Oskar Wallgren Date: Tue, 31 Oct 2017 02:33:37 +0100 Subject: [PATCH 03/24] LADSPA - Fix various floating point errors (#3927) * swh - Dyson Compressor, fix NaN * swh - shaper_1187, division with 0 * Division with 0 in calf limiter --- plugins/LadspaEffect/calf/src/audio_fx.cpp | 1 + plugins/LadspaEffect/swh/dyson_compress_1403.c | 2 +- plugins/LadspaEffect/swh/shaper_1187.c | 8 ++++---- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/plugins/LadspaEffect/calf/src/audio_fx.cpp b/plugins/LadspaEffect/calf/src/audio_fx.cpp index f42ccc0a8..721a32ad5 100644 --- a/plugins/LadspaEffect/calf/src/audio_fx.cpp +++ b/plugins/LadspaEffect/calf/src/audio_fx.cpp @@ -731,6 +731,7 @@ void lookahead_limiter::process(float &left, float &right, float * multi_buffer) _peak = fabs(buffer[nextpos[j]]) > fabs(buffer[nextpos[j] + 1]) ? fabs(buffer[nextpos[j]]) : fabs(buffer[nextpos[j] + 1]); // calc a delta to use to reach our incoming peak from the // stored position + _peak = std::max( _peak, 0.000001f ); _delta = (_limit / peak - (limit * _multi_coeff * weight) / _peak) / (((buffer_size - nextpos[j] + pos) % buffer_size) / channels); if(_delta < nextdelta[j]) { // if the buffered delta is more important than the delta diff --git a/plugins/LadspaEffect/swh/dyson_compress_1403.c b/plugins/LadspaEffect/swh/dyson_compress_1403.c index 25e0b7d64..27062f051 100644 --- a/plugins/LadspaEffect/swh/dyson_compress_1403.c +++ b/plugins/LadspaEffect/swh/dyson_compress_1403.c @@ -836,7 +836,7 @@ static void __attribute__((constructor)) swh_init() { D_("Release time (s)"); port_range_hints[DYSONCOMPRESS_RELEASE_TIME].HintDescriptor = LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_LOW; - port_range_hints[DYSONCOMPRESS_RELEASE_TIME].LowerBound = 0; + port_range_hints[DYSONCOMPRESS_RELEASE_TIME].LowerBound = 0.0000001; port_range_hints[DYSONCOMPRESS_RELEASE_TIME].UpperBound = 1; /* Parameters for Fast compression ratio */ diff --git a/plugins/LadspaEffect/swh/shaper_1187.c b/plugins/LadspaEffect/swh/shaper_1187.c index c1a52906b..7adfb3abd 100644 --- a/plugins/LadspaEffect/swh/shaper_1187.c +++ b/plugins/LadspaEffect/swh/shaper_1187.c @@ -115,8 +115,8 @@ static void runShaper(LADSPA_Handle instance, unsigned long sample_count) { if (shapep < 1.0f && shapep > -1.0f) { shape = 1.0f; - } else if (shape < 0) { - shape = -1.0f / shape; + } else if (shapep < 0) { + shape = -1.0f / shapep; } else { shape = shapep; } @@ -160,8 +160,8 @@ static void runAddingShaper(LADSPA_Handle instance, unsigned long sample_count) if (shapep < 1.0f && shapep > -1.0f) { shape = 1.0f; - } else if (shape < 0) { - shape = -1.0f / shape; + } else if (shapep < 0) { + shape = -1.0f / shapep; } else { shape = shapep; } From f15acb8620c96bbe7e017be2d80f0b6d4f6580ab Mon Sep 17 00:00:00 2001 From: tresf Date: Wed, 1 Nov 2017 01:01:09 -0400 Subject: [PATCH 04/24] Specify architecture for AppImage --- cmake/linux/package_linux.sh.in | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmake/linux/package_linux.sh.in b/cmake/linux/package_linux.sh.in index 275baba35..b1f2b55fa 100644 --- a/cmake/linux/package_linux.sh.in +++ b/cmake/linux/package_linux.sh.in @@ -41,6 +41,9 @@ function skipped { echo -e " ${PLAIN}[${YELLOW}skipped${PLAIN}] ${1}" } +# Blindly assume system arch is appimage arch +ARCH=$(arch) +export ARCH # Check for problematic install locations INSTALL=$(echo "@CMAKE_INSTALL_PREFIX@" | sed 's/\/*$//g') From 0c31cf49c070110462f15791da161847f74a5245 Mon Sep 17 00:00:00 2001 From: Oskar Wallgren Date: Fri, 3 Nov 2017 09:41:28 +0100 Subject: [PATCH 05/24] linearToLogScale() - Input validation (#3932) --- include/lmms_math.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/lmms_math.h b/include/lmms_math.h index b1b01be27..ccf5fbf62 100644 --- a/include/lmms_math.h +++ b/include/lmms_math.h @@ -229,11 +229,12 @@ static inline float logToLinearScale( float min, float max, float value ) static inline float linearToLogScale( float min, float max, float value ) { static const float EXP = 1.0f / F_E; - const float val = ( value - min ) / ( max - min ); + const float valueLimited = qBound( min, value, max); + const float val = ( valueLimited - min ) / ( max - min ); if( min < 0 ) { const float mmax = qMax( qAbs( min ), qAbs( max ) ); - float result = signedPowf( value / mmax, EXP ) * mmax; + float result = signedPowf( valueLimited / mmax, EXP ) * mmax; return isnan( result ) ? 0 : result; } float result = powf( val, EXP ) * ( max - min ) + min; From a3c7328f9c59f500daf60c945b7a60695c609487 Mon Sep 17 00:00:00 2001 From: Hyunjin Song Date: Sat, 4 Nov 2017 08:54:33 +0900 Subject: [PATCH 06/24] Fix wrong value interpolation (#3929) --- src/core/AutomatableModel.cpp | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/core/AutomatableModel.cpp b/src/core/AutomatableModel.cpp index 0391061b6..e2a088e04 100644 --- a/src/core/AutomatableModel.cpp +++ b/src/core/AutomatableModel.cpp @@ -42,8 +42,6 @@ AutomatableModel::AutomatableModel( DataType type, Model( parent, displayName, defaultConstructed ), m_dataType( type ), m_scaleType( Linear ), - m_value( val ), - m_initValue( val ), m_minValue( min ), m_maxValue( max ), m_step( step ), @@ -59,6 +57,7 @@ AutomatableModel::AutomatableModel( DataType type, m_hasSampleExactData( false ) { + m_value = fittedValue( val ); setInitValue( val ); } @@ -523,14 +522,8 @@ float AutomatableModel::controllerValue( int frameOffset ) const ValueBuffer * AutomatableModel::valueBuffer() { - // if we've already calculated the valuebuffer this period, return the cached buffer - if( m_lastUpdatedPeriod == s_periodCounter ) - { - return m_hasSampleExactData - ? &m_valueBuffer - : NULL; - } QMutexLocker m( &m_valueBufferMutex ); + // if we've already calculated the valuebuffer this period, return the cached buffer if( m_lastUpdatedPeriod == s_periodCounter ) { return m_hasSampleExactData @@ -626,6 +619,7 @@ void AutomatableModel::setInitValue( const float value ) m_initValue = fittedValue( value ); bool journalling = testAndSetJournalling( false ); setValue( value ); + m_oldValue = m_value; setJournalling( journalling ); emit initValueChanged( value ); } From 298f1ec335e2982e05fd591e010dd5c12b4323b5 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sat, 4 Nov 2017 04:31:41 -0400 Subject: [PATCH 07/24] Fix recent files (#3872) * Fix templates and recent files on KDE. Workaround for https://bugs.kde.org/show_bug.cgi?id=337491 , Call into KDE stuff to stop it adding accelerators. * Fix & in recent files. Escape & as && when building the recent file lists, and reverse that when getting the file name. --- src/gui/MainWindow.cpp | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index b91fe3ef2..32d16546b 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -64,6 +65,21 @@ #include "lmmsversion.h" +#if !defined(LMMS_BUILD_WIN32) && !defined(LMMS_BULID_APPLE) && !defined(LMMS_BUILD_HAIKU) +//Work around an issue on KDE5 as per https://bugs.kde.org/show_bug.cgi?id=337491#c21 +void disableAutoKeyAccelerators(QWidget* mainWindow) +{ + using DisablerFunc = void(*)(QWidget*); + QLibrary kf5WidgetsAddon("KF5WidgetsAddons", 5); + DisablerFunc setNoAccelerators = + reinterpret_cast(kf5WidgetsAddon.resolve("_ZN19KAcceleratorManager10setNoAccelEP7QWidget")); + if(setNoAccelerators) + { + setNoAccelerators(mainWindow); + } + kf5WidgetsAddon.unload(); +} +#endif MainWindow::MainWindow() : @@ -76,6 +92,9 @@ MainWindow::MainWindow() : m_metronomeToggle( 0 ), m_session( Normal ) { +#if !defined(LMMS_BUILD_WIN32) && !defined(LMMS_BULID_APPLE) && !defined(LMMS_BUILD_HAIKU) + disableAutoKeyAccelerators(this); +#endif setAttribute( Qt::WA_DeleteOnClose ); QWidget * main_widget = new QWidget( this ); @@ -836,8 +855,8 @@ void MainWindow::createNewProjectFromTemplate( QAction * _idx ) ConfigManager::inst()->factoryTemplatesDir() : ConfigManager::inst()->userTemplateDir(); - Engine::getSong()->createNewProjectFromTemplate( - dirBase + _idx->text() + ".mpt" ); + const QString f = dirBase + _idx->text().replace("&&", "&") + ".mpt"; + Engine::getSong()->createNewProjectFromTemplate(f); } } @@ -888,7 +907,7 @@ void MainWindow::updateRecentlyOpenedProjectsMenu() } m_recentlyOpenedProjectsMenu->addAction( - embed::getIconPixmap( "project_file" ), *it ); + embed::getIconPixmap( "project_file" ), it->replace("&", "&&") ); #ifdef LMMS_BUILD_APPLE m_recentlyOpenedProjectsMenu->actions().last()->setIconVisibleInMenu(false); // QTBUG-44565 workaround m_recentlyOpenedProjectsMenu->actions().last()->setIconVisibleInMenu(true); @@ -904,12 +923,11 @@ void MainWindow::updateRecentlyOpenedProjectsMenu() - void MainWindow::openRecentlyOpenedProject( QAction * _action ) { if ( mayChangeProject(true) ) { - const QString & f = _action->text(); + const QString f = _action->text().replace("&&", "&"); setCursor( Qt::WaitCursor ); Engine::getSong()->loadProject( f ); setCursor( Qt::ArrowCursor ); @@ -1500,7 +1518,7 @@ void MainWindow::fillTemplatesMenu() { m_templatesMenu->addAction( embed::getIconPixmap( "project_file" ), - ( *it ).left( ( *it ).length() - 4 ) ); + ( *it ).left( ( *it ).length() - 4 ).replace("&", "&&") ); #ifdef LMMS_BUILD_APPLE m_templatesMenu->actions().last()->setIconVisibleInMenu(false); // QTBUG-44565 workaround m_templatesMenu->actions().last()->setIconVisibleInMenu(true); From eb09ff6f25931b10e1192bdec1d0d5600230b726 Mon Sep 17 00:00:00 2001 From: follower Date: Tue, 7 Nov 2017 22:23:34 +1300 Subject: [PATCH 08/24] Fix off-by-one/heap-buffer-overflow as reported by ASAN. It's probably not the best "solution" but it should hopefully be one less category of crash-on-close on Mac. ASAN a.k.a Clang "AddressSanitizer". --- src/core/midi/MidiApple.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/midi/MidiApple.cpp b/src/core/midi/MidiApple.cpp index 45f58e4bb..f4bc0d4dd 100644 --- a/src/core/midi/MidiApple.cpp +++ b/src/core/midi/MidiApple.cpp @@ -615,7 +615,7 @@ char * MidiApple::getFullName(MIDIEndpointRef &endpoint_ref) char * deviceName = getName(device); char * endPointName = getName(endpoint_ref); qDebug("device name='%s' endpoint name='%s'",deviceName,endPointName); - char * fullName = (char *)malloc(strlen(deviceName) + strlen(endPointName)+1); + char * fullName = (char *)malloc(strlen(deviceName) + strlen(":") + strlen(endPointName)+1); sprintf(fullName, "%s:%s", deviceName,endPointName); return fullName; } From 0dbdafc1f82ea0f6cb14a07bad4caab8e49643fc Mon Sep 17 00:00:00 2001 From: Lukas W Date: Tue, 7 Nov 2017 12:06:52 +0100 Subject: [PATCH 09/24] CMake: Fix non-existing target warnings --- CMakeLists.txt | 1 + src/CMakeLists.txt | 8 +++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8d9aa4ab0..7969d6810 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,6 +9,7 @@ IF(COMMAND CMAKE_POLICY) CMAKE_POLICY(SET CMP0003 NEW) IF (CMAKE_MAJOR_VERSION GREATER 2) CMAKE_POLICY(SET CMP0026 OLD) + CMAKE_POLICY(SET CMP0045 NEW) CMAKE_POLICY(SET CMP0050 OLD) ENDIF() ENDIF(COMMAND CMAKE_POLICY) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index bd29619b2..c98f304e1 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -160,9 +160,11 @@ TARGET_LINK_LIBRARIES(lmms ) FOREACH(LIB ${LMMS_REQUIRED_LIBS}) - GET_TARGET_PROPERTY(INCLUDE_DIRS ${LIB} INTERFACE_INCLUDE_DIRECTORIES) - if (INCLUDE_DIRS) - TARGET_INCLUDE_DIRECTORIES(lmmsobjs PRIVATE ${INCLUDE_DIRS}) + IF(TARGET ${LIB}) + GET_TARGET_PROPERTY(INCLUDE_DIRS ${LIB} INTERFACE_INCLUDE_DIRECTORIES) + if (INCLUDE_DIRS) + TARGET_INCLUDE_DIRECTORIES(lmmsobjs PRIVATE ${INCLUDE_DIRS}) + ENDIF() ENDIF() ENDFOREACH() From 8baf42fca045c2aa94e54b26b64f664d6716a5eb Mon Sep 17 00:00:00 2001 From: Hussam Eddin Alhomsi Date: Tue, 7 Nov 2017 22:21:12 +0300 Subject: [PATCH 10/24] Remove text from project notes of factory templates. (#3939) --- data/projects/templates/Empty.mpt | 6 +----- data/projects/templates/default.mpt | 6 +----- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/data/projects/templates/Empty.mpt b/data/projects/templates/Empty.mpt index cf5bfa150..4974213b7 100644 --- a/data/projects/templates/Empty.mpt +++ b/data/projects/templates/Empty.mpt @@ -30,11 +30,7 @@ - - -

Put down your project notes here.

]]>
+ diff --git a/data/projects/templates/default.mpt b/data/projects/templates/default.mpt index 18fcdd925..bebd41fe3 100644 --- a/data/projects/templates/default.mpt +++ b/data/projects/templates/default.mpt @@ -78,11 +78,7 @@ - - -

Enter project notes here

]]>
+ From 48b9b6508e684fbadd53e0ffb7e293f70260e6ea Mon Sep 17 00:00:00 2001 From: Hyunjin Song Date: Thu, 9 Nov 2017 06:58:51 +0900 Subject: [PATCH 11/24] Fix visual glitch with automation patterns (#3945) Fix off-by-one visual glitch in automation editor and automation pattern view --- src/gui/AutomationPatternView.cpp | 12 +++++++++++- src/gui/editors/AutomationEditor.cpp | 6 +++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/gui/AutomationPatternView.cpp b/src/gui/AutomationPatternView.cpp index 68bdb4bf2..448c233cb 100644 --- a/src/gui/AutomationPatternView.cpp +++ b/src/gui/AutomationPatternView.cpp @@ -319,6 +319,16 @@ void AutomationPatternView::paintEvent( QPaintEvent * ) float *values = m_pat->valuesAfter( it.key() ); + float nextValue; + if( m_pat->progressionType() == AutomationPattern::DiscreteProgression ) + { + nextValue = it.value(); + } + else + { + nextValue = ( it + 1 ).value(); + } + QPainterPath path; QPointF origin = QPointF( x_base + it.key() * ppTick, 0.0f ); path.moveTo( origin ); @@ -332,7 +342,7 @@ void AutomationPatternView::paintEvent( QPaintEvent * ) path.lineTo( QPointF( x, value ) ); } - path.lineTo( x_base + ( ( it + 1 ).key() ) * ppTick, values[ ( it + 1 ).key() - 1 - it.key() ] ); + path.lineTo( x_base + ( ( it + 1 ).key() ) * ppTick, nextValue ); path.lineTo( x_base + ( ( it + 1 ).key() ) * ppTick, 0.0f ); path.lineTo( origin ); diff --git a/src/gui/editors/AutomationEditor.cpp b/src/gui/editors/AutomationEditor.cpp index ca65b5275..965314087 100644 --- a/src/gui/editors/AutomationEditor.cpp +++ b/src/gui/editors/AutomationEditor.cpp @@ -1378,13 +1378,13 @@ void AutomationEditor::paintEvent(QPaintEvent * pe ) float *values = m_pattern->valuesAfter( it.key() ); float nextValue; - if ( m_pattern->valuesAfter( ( it + 1 ).key() ) != NULL ) + if( m_pattern->progressionType() == AutomationPattern::DiscreteProgression ) { - nextValue = *( m_pattern->valuesAfter( ( it + 1 ).key() ) ); + nextValue = it.value(); } else { - nextValue = values[ ( it + 1 ).key() - it.key() -1 ]; + nextValue = ( it + 1 ).value(); } p.setRenderHints( QPainter::Antialiasing, true ); From d4d909cd9e440f3eba923d748938df2064a29c4c Mon Sep 17 00:00:00 2001 From: Tres Finocchiaro Date: Thu, 9 Nov 2017 01:57:20 -0500 Subject: [PATCH 12/24] Add libjack.so.0 fallback logic for AppImages (#3958) Add libjack.so.0 fallback logic --- cmake/linux/package_linux.sh.in | 14 ++++++++++++++ src/core/CMakeLists.txt | 9 +++++++++ 2 files changed, 23 insertions(+) diff --git a/cmake/linux/package_linux.sh.in b/cmake/linux/package_linux.sh.in index b1f2b55fa..16a6297eb 100644 --- a/cmake/linux/package_linux.sh.in +++ b/cmake/linux/package_linux.sh.in @@ -109,6 +109,12 @@ if lsmod |grep vboxguest > /dev/null 2>&1; then echo "VirtualBox detected. Forcing libgl software rendering." export LIBGL_ALWAYS_SOFTWARE=1; fi +if ldconfig -p | grep libjack.so.0 > /dev/null 2>&1; then + echo "Jack appears to be installed on this system, so we'll use it." +else + echo "Jack does not appear to be installed. That's OK, we'll use a dummy version instead." + export LD_LIBRARY_PATH=\$DIR/usr/lib/lmms/optional:\$LD_LIBRARY_PATH +fi QT_X11_NO_NATIVE_MENUBAR=1 QT_AUTO_SCREEN_SCALE_FACTOR=1 \$DIR/usr/bin/lmms.real "\$@" EOL @@ -164,6 +170,14 @@ ln -sr "$VSTBIN" "$VSTLIB" # Remove wine library conflict rm -f "${APPDIR}/usr/lib/libwine.so.1" +# Remove problematic jack library, replace with weakjack +if [ -e "${APPDIR}/usr/lib/libjack.so.0" ]; then + rm -f "${APPDIR}/usr/lib/libjack.so.0" + mkdir -p "${APPDIR}usr/lib/lmms/optional/" + cp "@CMAKE_BINARY_DIR@/optional/weakjack.so" "${APPDIR}usr/lib/lmms/optional/weakjack.so" + ln -sr "${APPDIR}usr/lib/lmms/optional/weakjack.so" "${APPDIR}usr/lib/lmms/optional/libjack.so.0" +fi + # Create AppImage echo -e "\nFinishing the AppImage..." echo -e "\n\n>>>>> appimagetool" >> "$LOGFILE" diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index c8840997d..30566e5ae 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -1,5 +1,14 @@ IF(LMMS_HAVE_WEAKJACK) set(WEAKJACK core/audio/AudioWeakJack.c) + + # Build libjack.so.0 stub as weakjack.so for AppImages + IF(LMMS_BUILD_LINUX) + ADD_LIBRARY(weakjack MODULE ../../src/core/audio/AudioWeakJack.c) + INCLUDE_DIRECTORIES("${CMAKE_SOURCE_DIR}/include") + # We can't predict an AppImage build, so stash the build artifact for later + INSTALL(TARGETS weakjack LIBRARY DESTINATION "${CMAKE_BINARY_DIR}/optional") + SET_TARGET_PROPERTIES(weakjack PROPERTIES PREFIX "" SUFFIX ".so") + ENDIF() ENDIF() set(LMMS_SRCS From 43ae3c6376d30d313024f94cd225c465f0fb7561 Mon Sep 17 00:00:00 2001 From: Hussam Eddin Alhomsi Date: Thu, 9 Nov 2017 18:27:01 +0300 Subject: [PATCH 13/24] Update patterns in song editor after shifting their notes by semitones in piano roll. (#3961) After shifting notes up/down, call rearrangeAllNotes() to sort notes and dataChanged() to update the pattern the Song Editor. --- src/gui/editors/PianoRoll.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/gui/editors/PianoRoll.cpp b/src/gui/editors/PianoRoll.cpp index 9b65c6847..ae5c33c89 100644 --- a/src/gui/editors/PianoRoll.cpp +++ b/src/gui/editors/PianoRoll.cpp @@ -963,6 +963,9 @@ void PianoRoll::shiftSemiTone( int amount ) // shift notes by amount semitones } } + m_pattern->rearrangeAllNotes(); + m_pattern->dataChanged(); + // we modified the song update(); gui->songEditor()->update(); From 0dbbdd9f4c35d3227a8812c10c16081f37725895 Mon Sep 17 00:00:00 2001 From: Hussam Eddin Alhomsi Date: Mon, 2 Oct 2017 23:05:16 +0300 Subject: [PATCH 14/24] Update the grid after changing the quantization value in automation editor --- src/gui/editors/AutomationEditor.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/gui/editors/AutomationEditor.cpp b/src/gui/editors/AutomationEditor.cpp index 965314087..be3fb5248 100644 --- a/src/gui/editors/AutomationEditor.cpp +++ b/src/gui/editors/AutomationEditor.cpp @@ -2133,6 +2133,8 @@ void AutomationEditor::setQuantization() } quantization = DefaultTicksPerTact / quantization; AutomationPattern::setQuantization( quantization ); + + update(); } From 7ed9bea9fbded61b4ba2d32113e442c38f84a9b9 Mon Sep 17 00:00:00 2001 From: Dominic Clark Date: Sun, 12 Nov 2017 23:52:08 +0000 Subject: [PATCH 15/24] Disable plugin transparency on Qt5 (#3934) --- include/MainApplication.h | 11 +++++++++++ src/gui/MainApplication.cpp | 20 +++++++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/include/MainApplication.h b/include/MainApplication.h index 8d5df9f86..d3acb95ca 100644 --- a/include/MainApplication.h +++ b/include/MainApplication.h @@ -31,15 +31,26 @@ #ifdef LMMS_BUILD_WIN32 #include +#if QT_VERSION >= 0x050000 +#include +#endif #endif +#if defined(LMMS_BUILD_WIN32) && QT_VERSION >= 0x050000 +class MainApplication : public QApplication, public QAbstractNativeEventFilter +#else class MainApplication : public QApplication +#endif { public: MainApplication(int& argc, char** argv); bool event(QEvent* event); #ifdef LMMS_BUILD_WIN32 bool winEventFilter(MSG* msg, long* result); +#if QT_VERSION >= 0x050000 + bool nativeEventFilter(const QByteArray& eventType, void* message, + long* result); +#endif #endif inline QString& queuedFile() { diff --git a/src/gui/MainApplication.cpp b/src/gui/MainApplication.cpp index 767eaa8fe..5210dd76c 100644 --- a/src/gui/MainApplication.cpp +++ b/src/gui/MainApplication.cpp @@ -33,7 +33,12 @@ MainApplication::MainApplication(int& argc, char** argv) : QApplication(argc, argv), - m_queuedFile() {} + m_queuedFile() +{ +#if defined(LMMS_BUILD_WIN32) && QT_VERSION >= 0x050000 + installNativeEventFilter(this); +#endif +} bool MainApplication::event(QEvent* event) { @@ -64,6 +69,7 @@ bool MainApplication::event(QEvent* event) } #ifdef LMMS_BUILD_WIN32 +// This can be moved into nativeEventFilter once Qt4 support has been dropped bool MainApplication::winEventFilter(MSG* msg, long* result) { switch(msg->message) @@ -85,4 +91,16 @@ bool MainApplication::winEventFilter(MSG* msg, long* result) return false; } } + +#if QT_VERSION >= 0x050000 +bool MainApplication::nativeEventFilter(const QByteArray& eventType, + void* message, long* result) +{ + if(eventType == "windows_generic_MSG") + { + return winEventFilter(static_cast(message), result); + } + return false; +} +#endif #endif From de98781df4d5b66d1e273167aad05915c42ebcf1 Mon Sep 17 00:00:00 2001 From: Tres Finocchiaro Date: Tue, 14 Nov 2017 21:43:41 -0500 Subject: [PATCH 16/24] Use "soundfonts" folder, not "sf2" --- include/ConfigManager.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/ConfigManager.h b/include/ConfigManager.h index 4c0a73e05..2510283c0 100644 --- a/include/ConfigManager.h +++ b/include/ConfigManager.h @@ -44,7 +44,7 @@ const QString TEMPLATE_PATH = "templates/"; const QString PRESETS_PATH = "presets/"; const QString SAMPLES_PATH = "samples/"; const QString GIG_PATH = "samples/gig/"; -const QString SF2_PATH = "samples/sf2/"; +const QString SF2_PATH = "samples/soundfonts/"; const QString LADSPA_PATH ="plugins/ladspa/"; const QString DEFAULT_THEME_PATH = "themes/default/"; const QString TRACK_ICON_PATH = "track_icons/"; From 601046aa0335b1b3900ace6ec2cc3c824a480903 Mon Sep 17 00:00:00 2001 From: Hyunjin Song Date: Thu, 16 Nov 2017 00:18:03 +0900 Subject: [PATCH 17/24] Fix CAPS plugin build with some compilers (#3972) --- plugins/LadspaEffect/caps/SweepVF.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/LadspaEffect/caps/SweepVF.cc b/plugins/LadspaEffect/caps/SweepVF.cc index f97c220cf..3dab97d7e 100644 --- a/plugins/LadspaEffect/caps/SweepVF.cc +++ b/plugins/LadspaEffect/caps/SweepVF.cc @@ -28,10 +28,10 @@ 02111-1307, USA or point your web browser to http://www.gnu.org. */ -#include - #include "basics.h" +#include + #include "SweepVF.h" #include "Descriptor.h" From 01265ace66a360185d2581da7c9d27a974050c5f Mon Sep 17 00:00:00 2001 From: Oskar Wallgren Date: Fri, 17 Nov 2017 02:03:49 +0100 Subject: [PATCH 18/24] Default project when cancelling project loading (#3941) Default project when cancelling project loading If a user isn't aware that the loading of a project has been cancelled, it may be in an incomplete state. Saving such a project will overwrite the original file and result in data loss. This is solved by loading the default project on cancelling project loading. Add Mixer::clearNewPlayHandles() to prevent crash when cancelling loading of a single streamed instrument. --- include/Mixer.h | 1 + include/Song.h | 13 +++++++++++++ src/core/Mixer.cpp | 14 ++++++++++++++ src/core/Song.cpp | 12 ++++++++++-- src/core/TrackContainer.cpp | 10 ++++++++++ 5 files changed, 48 insertions(+), 2 deletions(-) diff --git a/include/Mixer.h b/include/Mixer.h index 8368e8434..1c3780b1b 100644 --- a/include/Mixer.h +++ b/include/Mixer.h @@ -155,6 +155,7 @@ public: void initDevices(); void clear(); + void clearNewPlayHandles(); // audio-device-stuff diff --git a/include/Song.h b/include/Song.h index b8879ad9b..0ba8a3503 100644 --- a/include/Song.h +++ b/include/Song.h @@ -33,6 +33,7 @@ #include "TrackContainer.h" #include "Controller.h" #include "MeterModel.h" +#include "Mixer.h" #include "VstSyncController.h" @@ -229,6 +230,17 @@ public: return m_loadingProject; } + void loadingCancelled() + { + m_isCancelled = true; + Engine::mixer()->clearNewPlayHandles(); + } + + bool isCancelled() + { + return m_isCancelled; + } + bool isModified() const { return m_modified; @@ -358,6 +370,7 @@ private: volatile bool m_paused; bool m_loadingProject; + bool m_isCancelled; QStringList m_errors; diff --git a/src/core/Mixer.cpp b/src/core/Mixer.cpp index c99d3ab8c..ed8d04a6c 100644 --- a/src/core/Mixer.cpp +++ b/src/core/Mixer.cpp @@ -501,6 +501,20 @@ void Mixer::clear() +void Mixer::clearNewPlayHandles() +{ + requestChangeInModel(); + for( LocklessListElement * e = m_newPlayHandles.popList(); e; ) + { + LocklessListElement * next = e->next; + m_newPlayHandles.free( e ); + e = next; + } + doneChangeInModel(); +} + + + // removes all play-handles. this is necessary, when the song is stopped -> // all remaining notes etc. would be played until their end void Mixer::clearInternal() diff --git a/src/core/Song.cpp b/src/core/Song.cpp index 01071668c..5f8e75320 100644 --- a/src/core/Song.cpp +++ b/src/core/Song.cpp @@ -86,6 +86,7 @@ Song::Song() : m_playing( false ), m_paused( false ), m_loadingProject( false ), + m_isCancelled( false ), m_playMode( Mode_None ), m_length( 0 ), m_patternToPlay( NULL ), @@ -1074,7 +1075,7 @@ void Song::loadProject( const QString & fileName ) } } - while( !node.isNull() ) + while( !node.isNull() && !isCancelled() ) { if( node.isElement() ) { @@ -1133,6 +1134,13 @@ void Song::loadProject( const QString & fileName ) emit projectLoaded(); + if( isCancelled() ) + { + m_isCancelled = false; + createNewProject(); + return; + } + if ( hasErrors()) { if ( gui ) @@ -1278,7 +1286,7 @@ void Song::saveControllerStates( QDomDocument & doc, QDomElement & element ) void Song::restoreControllerStates( const QDomElement & element ) { QDomNode node = element.firstChild(); - while( !node.isNull() ) + while( !node.isNull() && !isCancelled() ) { Controller * c = Controller::create( node.toElement(), this ); Q_ASSERT( c != NULL ); diff --git a/src/core/TrackContainer.cpp b/src/core/TrackContainer.cpp index 6e406b0a9..6877e6b1f 100644 --- a/src/core/TrackContainer.cpp +++ b/src/core/TrackContainer.cpp @@ -33,12 +33,14 @@ #include "AutomationTrack.h" #include "BBTrack.h" #include "BBTrackContainer.h" +#include "embed.h" #include "TrackContainer.h" #include "InstrumentTrack.h" #include "Song.h" #include "GuiApplication.h" #include "MainWindow.h" +#include "TextFloat.h" TrackContainer::TrackContainer() : Model( NULL ), @@ -110,6 +112,14 @@ void TrackContainer::loadSettings( const QDomElement & _this ) QEventLoop::AllEvents, 100 ); if( pd->wasCanceled() ) { + if ( gui ) + { + TextFloat::displayMessage( tr( "Loading cancelled" ), + tr( "Project loading was cancelled." ), + embed::getIconPixmap( "project_file", 24, 24 ), + 2000 ); + } + Engine::getSong()->loadingCancelled(); break; } } From b68dc572a3a58ad2187efe3ef5b4848ef7254abd Mon Sep 17 00:00:00 2001 From: Oskar Wallgren Date: Sat, 18 Nov 2017 15:03:37 +0100 Subject: [PATCH 19/24] Automtion Editor - left click response When you left click an existing value the automation point will only snap to the new value if it is higher. If it is lower the mouse click event will 'break'. Cleanup. Remove statement that will always evaluate as 'true'. --- src/3rdparty/rpmalloc/rpmalloc | 2 +- src/gui/editors/AutomationEditor.cpp | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/3rdparty/rpmalloc/rpmalloc b/src/3rdparty/rpmalloc/rpmalloc index 2e0479192..f3b2e6308 160000 --- a/src/3rdparty/rpmalloc/rpmalloc +++ b/src/3rdparty/rpmalloc/rpmalloc @@ -1 +1 @@ -Subproject commit 2e0479192b8dfb15e0084969fdf06208cffbfd09 +Subproject commit f3b2e630871c32288e7b501877c6d99d20171c20 diff --git a/src/gui/editors/AutomationEditor.cpp b/src/gui/editors/AutomationEditor.cpp index be3fb5248..f9124aaa8 100644 --- a/src/gui/editors/AutomationEditor.cpp +++ b/src/gui/editors/AutomationEditor.cpp @@ -517,16 +517,13 @@ void AutomationEditor::mousePressEvent( QMouseEvent* mouseEvent ) // loop through whole time-map... while( it != time_map.end() ) { - MidiTime len = 4; - // and check whether the user clicked on an // existing value if( pos_ticks >= it.key() && - len > 0 && ( it+1==time_map.end() || pos_ticks <= (it+1).key() ) && ( pos_ticks<= it.key() + MidiTime::ticksPerTact() *4 / m_ppt ) && - level <= it.value() ) + level == it.value() ) { break; } From 3de3ea6b16bb78a9559923c1b93dc7996535802b Mon Sep 17 00:00:00 2001 From: Oskar Wallgren Date: Sat, 18 Nov 2017 16:16:57 +0100 Subject: [PATCH 20/24] Revert accidental submodule changes --- src/3rdparty/rpmalloc/rpmalloc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/3rdparty/rpmalloc/rpmalloc b/src/3rdparty/rpmalloc/rpmalloc index f3b2e6308..2e0479192 160000 --- a/src/3rdparty/rpmalloc/rpmalloc +++ b/src/3rdparty/rpmalloc/rpmalloc @@ -1 +1 @@ -Subproject commit f3b2e630871c32288e7b501877c6d99d20171c20 +Subproject commit 2e0479192b8dfb15e0084969fdf06208cffbfd09 From 514ae34df3066698480d409d6f736870d686a4ee Mon Sep 17 00:00:00 2001 From: Hyunjin Song Date: Sun, 19 Nov 2017 10:50:22 +0900 Subject: [PATCH 21/24] Fix automation pattern regressions (#3977) Change the default value of ignoreSurroundingPoints in AutomationPattern::putValue to true, which was false in #3352. Fixes automation filpping bug and some potential issues. --- include/AutomationPattern.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/AutomationPattern.h b/include/AutomationPattern.h index 32b4bc286..0af7ea4fa 100644 --- a/include/AutomationPattern.h +++ b/include/AutomationPattern.h @@ -80,7 +80,7 @@ public: MidiTime putValue( const MidiTime & time, const float value, const bool quantPos = true, - const bool ignoreSurroundingPoints = false ); + const bool ignoreSurroundingPoints = true ); void removeValue( const MidiTime & time ); From 55076d0bb05be9144dc0ca2bef892c51621a8e39 Mon Sep 17 00:00:00 2001 From: Oskar Wallgren Date: Tue, 21 Nov 2017 20:56:54 +0100 Subject: [PATCH 22/24] Unsolo mixer channels on delete (#3982) If a mixer channel is soloed when it's deleted the other channels are left in the state their in which is, for the most part, muted. Solve this by clearing mixer channels on delete. --- src/gui/FxMixerView.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gui/FxMixerView.cpp b/src/gui/FxMixerView.cpp index 0e828c329..8da1cb4e0 100644 --- a/src/gui/FxMixerView.cpp +++ b/src/gui/FxMixerView.cpp @@ -382,6 +382,10 @@ void FxMixerView::deleteChannel(int index) // remember selected line int selLine = m_currentFxLine->channelIndex(); + // in case the deleted channel is soloed or the remaining + // channels will be left in a muted state + Engine::fxMixer()->clearChannel(index); + // delete the real channel Engine::fxMixer()->deleteChannel(index); From c6ae1dcba62ead5e7f97c3fb6d591fe543f9fa93 Mon Sep 17 00:00:00 2001 From: Oskar Wallgren Date: Fri, 24 Nov 2017 05:38:47 +0100 Subject: [PATCH 23/24] Automation Editor - delete automation point (#3986) Fix regression from b68dc572a3a58ad2187efe3ef5b4848ef7254abd Let the right mouse button delete the automation point like before and add the space above it too. --- src/gui/editors/AutomationEditor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/editors/AutomationEditor.cpp b/src/gui/editors/AutomationEditor.cpp index f9124aaa8..733cf2814 100644 --- a/src/gui/editors/AutomationEditor.cpp +++ b/src/gui/editors/AutomationEditor.cpp @@ -523,7 +523,7 @@ void AutomationEditor::mousePressEvent( QMouseEvent* mouseEvent ) ( it+1==time_map.end() || pos_ticks <= (it+1).key() ) && ( pos_ticks<= it.key() + MidiTime::ticksPerTact() *4 / m_ppt ) && - level == it.value() ) + ( level == it.value() || mouseEvent->button() == Qt::RightButton ) ) { break; } From 46ef3c6a11e9713c24aa3e9b01c658b2941a58d6 Mon Sep 17 00:00:00 2001 From: Lukas W Date: Sat, 25 Nov 2017 12:09:10 +0100 Subject: [PATCH 24/24] Fix rpmalloc debug build with GCC < 5 --- src/3rdparty/rpmalloc/CMakeLists.txt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/3rdparty/rpmalloc/CMakeLists.txt b/src/3rdparty/rpmalloc/CMakeLists.txt index b71af279b..23d1551c2 100644 --- a/src/3rdparty/rpmalloc/CMakeLists.txt +++ b/src/3rdparty/rpmalloc/CMakeLists.txt @@ -16,8 +16,15 @@ if (NOT LMMS_BUILD_WIN32) endif() if (CMAKE_BUILD_TYPE STREQUAL "Debug") + # rpmalloc uses GCC builtin "__builtin_umull_overflow" with ENABLE_VALIDATE_ARGS, + # which is only available starting with GCC 5 + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" AND CMAKE_C_COMPILER_VERSION VERSION_LESS 5) + set(ENABLE_VALIDATE_ARGS OFF) + else () + set(ENABLE_VALIDATE_ARGS ON) + endif() target_compile_definitions(rpmalloc - PRIVATE -DENABLE_ASSERTS=1 -DENABLE_VALIDATE_ARGS=1 + PRIVATE -DENABLE_ASSERTS=1 -DENABLE_VALIDATE_ARGS=${ENABLE_VALIDATE_ARGS} ) endif()