diff --git a/.travis/debian_pkgs.sha256 b/.travis/debian_pkgs.sha256 index 96a4bd8aa..ed4e11737 100644 --- a/.travis/debian_pkgs.sha256 +++ b/.travis/debian_pkgs.sha256 @@ -1,2 +1,3 @@ 314ef4af137903dfb13e8c3ef1e6ea56cfdb23808d52ec4f5f50e288c73610c5 pbuilder_0.229.1_all.deb fa82aa8ed3055c6f6330104deedf080b26778295e589426d4c4dd0f2c2a5defa debootstrap_1.0.95_all.deb +2ef4c09f7841b72f93412803ddd142f72658536dbfabe00e449eb548f432f3f8 debian-archive-keyring_2017.7ubuntu1_all.deb diff --git a/.travis/linux.debian-sid.install.sh b/.travis/linux.debian-sid.install.sh index ecdcf6d91..ef8368822 100755 --- a/.travis/linux.debian-sid.install.sh +++ b/.travis/linux.debian-sid.install.sh @@ -2,15 +2,16 @@ set -e sudo apt-get install -y \ - debian-archive-keyring \ dpkg \ pbuilder # work around a pbuilder bug which breaks ccache # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=666525 +# and also missing signing keys in Trusty's debian-archive-keyring cd /tmp wget http://archive.ubuntu.com/ubuntu/pool/main/p/pbuilder/pbuilder_0.229.1_all.deb wget http://archive.ubuntu.com/ubuntu/pool/main/d/debootstrap/debootstrap_1.0.95_all.deb +wget http://archive.ubuntu.com/ubuntu/pool/universe/d/debian-archive-keyring/debian-archive-keyring_2017.7ubuntu1_all.deb sha256sum -c "$TRAVIS_BUILD_DIR/.travis/debian_pkgs.sha256" -sudo dpkg -i pbuilder_0.229.1_all.deb debootstrap_1.0.95_all.deb +sudo dpkg -i pbuilder_0.229.1_all.deb debootstrap_1.0.95_all.deb debian-archive-keyring_2017.7ubuntu1_all.deb cd "$OLDPWD" diff --git a/CMakeLists.txt b/CMakeLists.txt index 7a39d7d9f..0f9d66def 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -157,7 +157,7 @@ SET(QT_LIBRARIES Qt5::Xml ) -IF(LMMS_BUILD_LINUX) +IF(LMMS_BUILD_LINUX AND WANT_VST) FIND_PACKAGE(Qt5 COMPONENTS X11Extras REQUIRED) LIST(APPEND QT_LIBRARIES Qt5::X11Extras) ENDIF() diff --git a/cmake/linux/package_linux.sh.in b/cmake/linux/package_linux.sh.in index ba6c7279a..a517ee53e 100644 --- a/cmake/linux/package_linux.sh.in +++ b/cmake/linux/package_linux.sh.in @@ -74,8 +74,9 @@ else success "Downloaded $LINUXDEPLOYQT" # Extract AppImage and replace LINUXDEPLOYQT variable with extracted binary # to support systems without fuse - "$LINUXDEPLOYQT" --appimage-extract > /dev/null 2>&1 - LINUXDEPLOYQT="squashfs-root/AppRun" + # Also, we need to set LD_LIBRARY_PATH, but linuxdepoyqt's AppRun unsets it + # See https://github.com/probonopd/linuxdeployqt/pull/370/ + LINUXDEPLOYQT="squashfs-root/usr/bin/linuxdeployqt" success "Extracted $APPIMAGETOOL" fi diff --git a/include/NotePlayHandle.h b/include/NotePlayHandle.h index c94a69c2c..ae55c9ebb 100644 --- a/include/NotePlayHandle.h +++ b/include/NotePlayHandle.h @@ -303,6 +303,7 @@ private: NotePlayHandleList m_subNotes; // used for chords and arpeggios volatile bool m_released; // indicates whether note is released bool m_releaseStarted; + bool m_hasMidiNote; bool m_hasParent; // indicates whether note has parent NotePlayHandle * m_parent; // parent note bool m_hadChildren; diff --git a/plugins/Eq/EqControlsDialog.cpp b/plugins/Eq/EqControlsDialog.cpp index af2378a2c..00c8eaaa7 100644 --- a/plugins/Eq/EqControlsDialog.cpp +++ b/plugins/Eq/EqControlsDialog.cpp @@ -55,10 +55,10 @@ EqControlsDialog::EqControlsDialog( EqControls *controls ) : EqSpectrumView * inSpec = new EqSpectrumView( &controls->m_inFftBands, this ); inSpec->move( 26, 17 ); - inSpec->setColor( QColor( 54, 45, 142, 150 ) ); + inSpec->setColor( QColor( 77, 101, 242, 150 ) ); EqSpectrumView * outSpec = new EqSpectrumView( &controls->m_outFftBands, this ); - outSpec->setColor( QColor( 9, 166, 156, 150 ) ); + outSpec->setColor( QColor( 0, 255, 239, 150 ) ); outSpec->move( 26, 17 ); m_parameterWidget = new EqParameterWidget( this , controls ); diff --git a/plugins/LadspaEffect/LadspaControls.cpp b/plugins/LadspaEffect/LadspaControls.cpp index 8e65e0e93..028394d30 100644 --- a/plugins/LadspaEffect/LadspaControls.cpp +++ b/plugins/LadspaEffect/LadspaControls.cpp @@ -36,7 +36,8 @@ LadspaControls::LadspaControls( LadspaEffect * _eff ) : { connect( &m_stereoLinkModel, SIGNAL( dataChanged() ), - this, SLOT( updateLinkStatesFromGlobal() ) ); + this, SLOT( updateLinkStatesFromGlobal() ), + Qt::DirectConnection ); multi_proc_t controls = m_effect->getPortControls(); m_controlCount = controls.count(); @@ -59,7 +60,8 @@ LadspaControls::LadspaControls( LadspaEffect * _eff ) : if( linked_control ) { connect( (*it)->control, SIGNAL( linkChanged( int, bool ) ), - this, SLOT( linkPort( int, bool ) ) ); + this, SLOT( linkPort( int, bool ) ), + Qt::DirectConnection ); } } } diff --git a/plugins/VstEffect/VstEffect.cpp b/plugins/VstEffect/VstEffect.cpp index cbb30e2fe..80f209a7b 100644 --- a/plugins/VstEffect/VstEffect.cpp +++ b/plugins/VstEffect/VstEffect.cpp @@ -145,9 +145,6 @@ void VstEffect::openPlugin( const QString & _plugin ) return; } - VstPlugin::connect( Engine::getSong(), SIGNAL( tempoChanged( bpm_t ) ), m_plugin.data(), SLOT( setTempo( bpm_t ) ) ); - m_plugin->setTempo( Engine::getSong()->getTempo() ); - delete tf; m_key.attributes["file"] = _plugin; diff --git a/plugins/vst_base/RemoteVstPlugin.cpp b/plugins/vst_base/RemoteVstPlugin.cpp index 3526b27cc..48ab13743 100644 --- a/plugins/vst_base/RemoteVstPlugin.cpp +++ b/plugins/vst_base/RemoteVstPlugin.cpp @@ -1962,7 +1962,8 @@ DWORD WINAPI RemoteVstPlugin::processingThread( LPVOID _param ) { if( m.id == IdStartProcessing || m.id == IdMidiEvent - || m.id == IdVstSetParameter ) + || m.id == IdVstSetParameter + || m.id == IdVstSetTempo ) { _this->processMessage( m ); } diff --git a/plugins/vst_base/VstPlugin.cpp b/plugins/vst_base/VstPlugin.cpp index 9f468087c..f224f092d 100644 --- a/plugins/vst_base/VstPlugin.cpp +++ b/plugins/vst_base/VstPlugin.cpp @@ -162,7 +162,7 @@ VstPlugin::VstPlugin( const QString & _plugin ) : setTempo( Engine::getSong()->getTempo() ); connect( Engine::getSong(), SIGNAL( tempoChanged( bpm_t ) ), - this, SLOT( setTempo( bpm_t ) ) ); + this, SLOT( setTempo( bpm_t ) ), Qt::DirectConnection ); connect( Engine::mixer(), SIGNAL( sampleRateChanged() ), this, SLOT( updateSampleRate() ) ); diff --git a/src/3rdparty/CMakeLists.txt b/src/3rdparty/CMakeLists.txt index b40f7c3cd..473e7702f 100644 --- a/src/3rdparty/CMakeLists.txt +++ b/src/3rdparty/CMakeLists.txt @@ -3,7 +3,7 @@ set(CMAKE_CXX_FLAGS "") set(CMAKE_C_FLAGS_DEBUG "") set(CMAKE_CXX_FLAGS_DEBUG "") -IF(LMMS_BUILD_LINUX) +IF(LMMS_BUILD_LINUX AND WANT_VST) set(BUILD_SHARED_LIBS OFF) add_subdirectory(qt5-x11embed) ENDIF() diff --git a/src/core/ControllerConnection.cpp b/src/core/ControllerConnection.cpp index 45e36e12f..4d43a4366 100644 --- a/src/core/ControllerConnection.cpp +++ b/src/core/ControllerConnection.cpp @@ -205,7 +205,7 @@ void ControllerConnection::loadSettings( const QDomElement & _this ) else { m_controllerId = _this.attribute( "id", "-1" ).toInt(); - if( m_controllerId < 0 ) + if( m_controllerId < 0 || m_controllerId >= Engine::getSong()->controllers().size() ) { qWarning( "controller index invalid\n" ); m_controllerId = -1; diff --git a/src/core/EnvelopeAndLfoParameters.cpp b/src/core/EnvelopeAndLfoParameters.cpp index 9001cd796..27a73b2c1 100644 --- a/src/core/EnvelopeAndLfoParameters.cpp +++ b/src/core/EnvelopeAndLfoParameters.cpp @@ -131,32 +131,32 @@ EnvelopeAndLfoParameters::EnvelopeAndLfoParameters( instances()->add( this ); connect( &m_predelayModel, SIGNAL( dataChanged() ), - this, SLOT( updateSampleVars() ) ); + this, SLOT( updateSampleVars() ), Qt::DirectConnection ); connect( &m_attackModel, SIGNAL( dataChanged() ), - this, SLOT( updateSampleVars() ) ); + this, SLOT( updateSampleVars() ), Qt::DirectConnection ); connect( &m_holdModel, SIGNAL( dataChanged() ), - this, SLOT( updateSampleVars() ) ); + this, SLOT( updateSampleVars() ), Qt::DirectConnection ); connect( &m_decayModel, SIGNAL( dataChanged() ), - this, SLOT( updateSampleVars() ) ); + this, SLOT( updateSampleVars() ), Qt::DirectConnection ); connect( &m_sustainModel, SIGNAL( dataChanged() ), - this, SLOT( updateSampleVars() ) ); + this, SLOT( updateSampleVars() ), Qt::DirectConnection ); connect( &m_releaseModel, SIGNAL( dataChanged() ), - this, SLOT( updateSampleVars() ) ); + this, SLOT( updateSampleVars() ), Qt::DirectConnection ); connect( &m_amountModel, SIGNAL( dataChanged() ), - this, SLOT( updateSampleVars() ) ); + this, SLOT( updateSampleVars() ), Qt::DirectConnection ); connect( &m_lfoPredelayModel, SIGNAL( dataChanged() ), - this, SLOT( updateSampleVars() ) ); + this, SLOT( updateSampleVars() ), Qt::DirectConnection ); connect( &m_lfoAttackModel, SIGNAL( dataChanged() ), - this, SLOT( updateSampleVars() ) ); + this, SLOT( updateSampleVars() ), Qt::DirectConnection ); connect( &m_lfoSpeedModel, SIGNAL( dataChanged() ), - this, SLOT( updateSampleVars() ) ); + this, SLOT( updateSampleVars() ), Qt::DirectConnection ); connect( &m_lfoAmountModel, SIGNAL( dataChanged() ), - this, SLOT( updateSampleVars() ) ); + this, SLOT( updateSampleVars() ), Qt::DirectConnection ); connect( &m_lfoWaveModel, SIGNAL( dataChanged() ), - this, SLOT( updateSampleVars() ) ); + this, SLOT( updateSampleVars() ), Qt::DirectConnection ); connect( &m_x100Model, SIGNAL( dataChanged() ), - this, SLOT( updateSampleVars() ) ); + this, SLOT( updateSampleVars() ), Qt::DirectConnection ); connect( Engine::mixer(), SIGNAL( sampleRateChanged() ), this, SLOT( updateSampleVars() ) ); diff --git a/src/core/LadspaControl.cpp b/src/core/LadspaControl.cpp index cf8c6e468..731241b85 100644 --- a/src/core/LadspaControl.cpp +++ b/src/core/LadspaControl.cpp @@ -42,7 +42,8 @@ LadspaControl::LadspaControl( Model * _parent, port_desc_t * _port, if( m_link ) { connect( &m_linkEnabledModel, SIGNAL( dataChanged() ), - this, SLOT( linkStateChanged() ) ); + this, SLOT( linkStateChanged() ), + Qt::DirectConnection ); } switch( m_port->data_type ) diff --git a/src/core/LfoController.cpp b/src/core/LfoController.cpp index c1c81119f..2b2db2f14 100644 --- a/src/core/LfoController.cpp +++ b/src/core/LfoController.cpp @@ -49,12 +49,12 @@ LfoController::LfoController( Model * _parent ) : { setSampleExact( true ); connect( &m_waveModel, SIGNAL( dataChanged() ), - this, SLOT( updateSampleFunction() ) ); + this, SLOT( updateSampleFunction() ), Qt::DirectConnection ); connect( &m_speedModel, SIGNAL( dataChanged() ), - this, SLOT( updateDuration() ) ); + this, SLOT( updateDuration() ), Qt::DirectConnection ); connect( &m_multiplierModel, SIGNAL( dataChanged() ), - this, SLOT( updateDuration() ) ); + this, SLOT( updateDuration() ), Qt::DirectConnection ); connect( Engine::mixer(), SIGNAL( sampleRateChanged() ), this, SLOT( updateDuration() ) ); diff --git a/src/core/MeterModel.cpp b/src/core/MeterModel.cpp index 87b1b950a..30db26d9b 100644 --- a/src/core/MeterModel.cpp +++ b/src/core/MeterModel.cpp @@ -33,9 +33,9 @@ MeterModel::MeterModel( ::Model * _parent ) : m_denominatorModel( 4, 1, 32, this, tr( "Denominator" ) ) { connect( &m_numeratorModel, SIGNAL( dataChanged() ), - this, SIGNAL( dataChanged() ) ); + this, SIGNAL( dataChanged() ), Qt::DirectConnection ); connect( &m_denominatorModel, SIGNAL( dataChanged() ), - this, SIGNAL( dataChanged() ) ); + this, SIGNAL( dataChanged() ), Qt::DirectConnection ); } diff --git a/src/core/NotePlayHandle.cpp b/src/core/NotePlayHandle.cpp index 8c838f136..67b7b416a 100644 --- a/src/core/NotePlayHandle.cpp +++ b/src/core/NotePlayHandle.cpp @@ -62,6 +62,7 @@ NotePlayHandle::NotePlayHandle( InstrumentTrack* instrumentTrack, m_subNotes(), m_released( false ), m_releaseStarted( false ), + m_hasMidiNote( false ), m_hasParent( parent != NULL ), m_parent( parent ), m_hadChildren( false ), @@ -105,17 +106,6 @@ NotePlayHandle::NotePlayHandle( InstrumentTrack* instrumentTrack, m_instrumentTrack->midiNoteOn( *this ); } - if( hasParent() || ! m_instrumentTrack->isArpeggioEnabled() ) - { - const int baseVelocity = m_instrumentTrack->midiPort()->baseVelocity(); - - // send MidiNoteOn event - m_instrumentTrack->processOutEvent( - MidiEvent( MidiNoteOn, midiChannel(), midiKey(), midiVelocity( baseVelocity ) ), - MidiTime::fromFrames( offset(), Engine::framesPerTick() ), - offset() ); - } - if( m_instrumentTrack->instrument()->flags() & Instrument::IsSingleStreamed ) { setUsesBuffer( false ); @@ -205,6 +195,21 @@ void NotePlayHandle::play( sampleFrame * _working_buffer ) } lock(); + + if( m_totalFramesPlayed == 0 && !m_hasMidiNote + && ( hasParent() || ! m_instrumentTrack->isArpeggioEnabled() ) ) + { + m_hasMidiNote = true; + + const int baseVelocity = m_instrumentTrack->midiPort()->baseVelocity(); + + // send MidiNoteOn event + m_instrumentTrack->processOutEvent( + MidiEvent( MidiNoteOn, midiChannel(), midiKey(), midiVelocity( baseVelocity ) ), + MidiTime::fromFrames( offset(), Engine::framesPerTick() ), + offset() ); + } + if( m_frequencyNeedsUpdate ) { updateFrequency(); @@ -357,8 +362,10 @@ void NotePlayHandle::noteOff( const f_cnt_t _s ) m_framesBeforeRelease = _s; m_releaseFramesToDo = qMax( 0, actualReleaseFramesToDo() ); - if( hasParent() || ! m_instrumentTrack->isArpeggioEnabled() ) + if( m_hasMidiNote ) { + m_hasMidiNote = false; + // send MidiNoteOff event m_instrumentTrack->processOutEvent( MidiEvent( MidiNoteOff, midiChannel(), midiKey(), 0 ), diff --git a/src/core/PeakController.cpp b/src/core/PeakController.cpp index 9e5e654a6..b2e3bc921 100644 --- a/src/core/PeakController.cpp +++ b/src/core/PeakController.cpp @@ -53,8 +53,10 @@ PeakController::PeakController( Model * _parent, this, SLOT( handleDestroyedEffect( ) ) ); } connect( Engine::mixer(), SIGNAL( sampleRateChanged() ), this, SLOT( updateCoeffs() ) ); - connect( m_peakEffect->attackModel(), SIGNAL( dataChanged() ), this, SLOT( updateCoeffs() ) ); - connect( m_peakEffect->decayModel(), SIGNAL( dataChanged() ), this, SLOT( updateCoeffs() ) ); + connect( m_peakEffect->attackModel(), SIGNAL( dataChanged() ), + this, SLOT( updateCoeffs() ), Qt::DirectConnection ); + connect( m_peakEffect->decayModel(), SIGNAL( dataChanged() ), + this, SLOT( updateCoeffs() ), Qt::DirectConnection ); m_coeffNeedsUpdate = true; } diff --git a/src/core/Song.cpp b/src/core/Song.cpp index 2f57b51c3..2809c61ad 100644 --- a/src/core/Song.cpp +++ b/src/core/Song.cpp @@ -92,18 +92,18 @@ Song::Song() : { for(int i = 0; i < Mode_Count; ++i) m_elapsedMilliSeconds[i] = 0; connect( &m_tempoModel, SIGNAL( dataChanged() ), - this, SLOT( setTempo() ) ); + this, SLOT( setTempo() ), Qt::DirectConnection ); connect( &m_tempoModel, SIGNAL( dataUnchanged() ), - this, SLOT( setTempo() ) ); + this, SLOT( setTempo() ), Qt::DirectConnection ); connect( &m_timeSigModel, SIGNAL( dataChanged() ), - this, SLOT( setTimeSignature() ) ); + this, SLOT( setTimeSignature() ), Qt::DirectConnection ); connect( Engine::mixer(), SIGNAL( sampleRateChanged() ), this, SLOT( updateFramesPerTick() ) ); connect( &m_masterVolumeModel, SIGNAL( dataChanged() ), - this, SLOT( masterVolumeChanged() ) ); + this, SLOT( masterVolumeChanged() ), Qt::DirectConnection ); /* connect( &m_masterPitchModel, SIGNAL( dataChanged() ), this, SLOT( masterPitchChanged() ) );*/ diff --git a/src/core/TempoSyncKnobModel.cpp b/src/core/TempoSyncKnobModel.cpp index e94c6e424..a85ca2e9f 100644 --- a/src/core/TempoSyncKnobModel.cpp +++ b/src/core/TempoSyncKnobModel.cpp @@ -42,7 +42,8 @@ TempoSyncKnobModel::TempoSyncKnobModel( const float _val, const float _min, m_custom( _parent ) { connect( Engine::getSong(), SIGNAL( tempoChanged( bpm_t ) ), - this, SLOT( calculateTempoSyncTime( bpm_t ) ) ); + this, SLOT( calculateTempoSyncTime( bpm_t ) ), + Qt::DirectConnection ); } @@ -154,7 +155,8 @@ void TempoSyncKnobModel::setSyncMode( TempoSyncMode _new_mode ) if( _new_mode == SyncCustom ) { connect( &m_custom, SIGNAL( dataChanged() ), - this, SLOT( updateCustom() ) ); + this, SLOT( updateCustom() ), + Qt::DirectConnection ); } } calculateTempoSyncTime( Engine::getSong()->getTempo() ); diff --git a/src/core/Track.cpp b/src/core/Track.cpp index d08144e47..64c17c9e8 100644 --- a/src/core/Track.cpp +++ b/src/core/Track.cpp @@ -328,8 +328,8 @@ TrackContentObjectView::~TrackContentObjectView() /*! \brief Update a TrackContentObjectView * - * TCO's get drawn only when needed, - * and when a TCO is updated, + * TCO's get drawn only when needed, + * and when a TCO is updated, * it needs to be redrawn. * */ @@ -598,9 +598,9 @@ void TrackContentObjectView::dropEvent( QDropEvent * de ) */ void TrackContentObjectView::leaveEvent( QEvent * e ) { - while( QApplication::overrideCursor() != NULL ) + if( cursor().shape() != Qt::BitmapCursor ) { - QApplication::restoreOverrideCursor(); + setCursor( QCursor( embed::getIconPixmap( "hand" ), 3, 3 ) ); } if( e != NULL ) { @@ -746,20 +746,17 @@ void TrackContentObjectView::mousePressEvent( QMouseEvent * me ) && !m_tco->getAutoResize() ) { m_action = ResizeLeft; - QCursor c( Qt::SizeHorCursor ); - QApplication::setOverrideCursor( c ); + setCursor( Qt::SizeHorCursor ); } else if( me->x() < width() - RESIZE_GRIP_WIDTH ) { m_action = Move; - QCursor c( Qt::SizeAllCursor ); - QApplication::setOverrideCursor( c ); + setCursor( Qt::SizeAllCursor ); } else if( !m_tco->getAutoResize() ) { m_action = Resize; - QCursor c( Qt::SizeHorCursor ); - QApplication::setOverrideCursor( c ); + setCursor( Qt::SizeHorCursor ); } if( m_action == Move ) @@ -1007,17 +1004,7 @@ void TrackContentObjectView::mouseMoveEvent( QMouseEvent * me ) if( ( me->x() > width() - RESIZE_GRIP_WIDTH && !me->buttons() && !m_tco->getAutoResize() ) || ( me->x() < RESIZE_GRIP_WIDTH && !me->buttons() && sTco && !m_tco->getAutoResize() ) ) { - if( QApplication::overrideCursor() != NULL && - QApplication::overrideCursor()->shape() != - Qt::SizeHorCursor ) - { - while( QApplication::overrideCursor() != NULL ) - { - QApplication::restoreOverrideCursor(); - } - } - QCursor c( Qt::SizeHorCursor ); - QApplication::setOverrideCursor( c ); + setCursor( Qt::SizeHorCursor ); } else { @@ -1194,7 +1181,7 @@ void TrackContentWidget::updateBackground() // draw lines // vertical lines - pmp.setPen( QPen( gridColor(), 1 ) ); + pmp.setPen( QPen( gridColor(), 1 ) ); for( float x = 0; x < w * 2; x += ppt ) { pmp.drawLine( QLineF( x, 0.0, x, h ) ); @@ -1205,9 +1192,9 @@ void TrackContentWidget::updateBackground() { pmp.drawLine( QLineF( x, 0.0, x, h ) ); } - + // horizontal line - pmp.setPen( QPen( gridColor(), 1 ) ); + pmp.setPen( QPen( gridColor(), 1 ) ); pmp.drawLine( 0, h-1, w*2, h-1 ); pmp.end(); @@ -1390,7 +1377,7 @@ MidiTime TrackContentWidget::getPosition( int mouseX ) */ void TrackContentWidget::dragEnterEvent( QDragEnterEvent * dee ) { - MidiTime tcoPos = MidiTime( getPosition( dee->pos().x() ).getTact(), 0 ); + MidiTime tcoPos = getPosition( dee->pos().x() ); if( canPasteSelection( tcoPos, dee ) == false ) { dee->ignore(); @@ -1928,7 +1915,7 @@ void TrackOperationsWidget::updateMenu() toMenu->addAction( embed::getIconPixmap( "cancel", 16, 16 ), tr( "Remove this track" ), this, SLOT( removeTrack() ) ); - + if( ! m_trackView->trackContainerView()->fixedTCOs() ) { toMenu->addAction( tr( "Clear this track" ), this, SLOT( clearTrack() ) ); @@ -2624,7 +2611,7 @@ TrackView::TrackView( Track * track, TrackContainerView * tcv ) : &m_trackContentWidget, SLOT( update() ) ); connect( &m_track->m_soloModel, SIGNAL( dataChanged() ), - m_track, SLOT( toggleSolo() ) ); + m_track, SLOT( toggleSolo() ), Qt::DirectConnection ); // create views for already existing TCOs for( Track::tcoVector::iterator it = m_track->m_trackContentObjects.begin(); @@ -2871,12 +2858,12 @@ void TrackView::mouseMoveEvent( QMouseEvent * me ) else if( m_action == MoveTrack ) { // look which track-widget the mouse-cursor is over - const int yPos = + const int yPos = m_trackContainerView->contentWidget()->mapFromGlobal( me->globalPos() ).y(); const TrackView * trackAtY = m_trackContainerView->trackViewAt( yPos ); -// debug code -// qDebug( "y position %d", yPos ); + // debug code + // qDebug( "y position %d", yPos ); // a track-widget not equal to ourself? if( trackAtY != NULL && trackAtY != this ) diff --git a/src/core/midi/MidiAlsaSeq.cpp b/src/core/midi/MidiAlsaSeq.cpp index be1e623de..e420ebc08 100644 --- a/src/core/midi/MidiAlsaSeq.cpp +++ b/src/core/midi/MidiAlsaSeq.cpp @@ -100,7 +100,7 @@ MidiAlsaSeq::MidiAlsaSeq() : snd_seq_start_queue( m_seqHandle, m_queueID, NULL ); changeQueueTempo( Engine::getSong()->getTempo() ); connect( Engine::getSong(), SIGNAL( tempoChanged( bpm_t ) ), - this, SLOT( changeQueueTempo( bpm_t ) ) ); + this, SLOT( changeQueueTempo( bpm_t ) ), Qt::DirectConnection ); // initial list-update updatePortList(); diff --git a/src/core/midi/MidiPort.cpp b/src/core/midi/MidiPort.cpp index 9e3cdb13d..52e0a5223 100644 --- a/src/core/midi/MidiPort.cpp +++ b/src/core/midi/MidiPort.cpp @@ -63,9 +63,12 @@ MidiPort::MidiPort( const QString& name, m_readableModel.setValue( m_mode == Input || m_mode == Duplex ); m_writableModel.setValue( m_mode == Output || m_mode == Duplex ); - connect( &m_readableModel, SIGNAL( dataChanged() ), this, SLOT( updateMidiPortMode() ) ); - connect( &m_writableModel, SIGNAL( dataChanged() ), this, SLOT( updateMidiPortMode() ) ); - connect( &m_outputProgramModel, SIGNAL( dataChanged() ), this, SLOT( updateOutputProgram() ) ); + connect( &m_readableModel, SIGNAL( dataChanged() ), + this, SLOT( updateMidiPortMode() ), Qt::DirectConnection ); + connect( &m_writableModel, SIGNAL( dataChanged() ), + this, SLOT( updateMidiPortMode() ), Qt::DirectConnection ); + connect( &m_outputProgramModel, SIGNAL( dataChanged() ), + this, SLOT( updateOutputProgram() ), Qt::DirectConnection ); // when using with non-raw-clients we can provide buttons showing diff --git a/src/gui/FxMixerView.cpp b/src/gui/FxMixerView.cpp index 0a6a54866..90cd1dbf3 100644 --- a/src/gui/FxMixerView.cpp +++ b/src/gui/FxMixerView.cpp @@ -313,7 +313,7 @@ FxMixerView::FxChannelView::FxChannelView(QWidget * _parent, FxMixerView * _mv, m_soloBtn->setCheckable( true ); m_soloBtn->move( 9, m_fader->y()-21); connect(&fxChannel->m_soloModel, SIGNAL( dataChanged() ), - _mv, SLOT ( toggledSolo() ) ); + _mv, SLOT ( toggledSolo() ), Qt::DirectConnection ); ToolTip::add( m_soloBtn, tr( "Solo FX channel" ) ); // Create EffectRack for the channel diff --git a/src/gui/editors/PianoRoll.cpp b/src/gui/editors/PianoRoll.cpp index 76b2d04f1..03d7c14c7 100644 --- a/src/gui/editors/PianoRoll.cpp +++ b/src/gui/editors/PianoRoll.cpp @@ -1007,6 +1007,9 @@ void PianoRoll::drawDetuningInfo( QPainter & _p, const Note * _n, int _x, { int middle_y = _y + KEY_LINE_HEIGHT / 2; _p.setPen( noteColor() ); + _p.setClipRect(WHITE_KEY_WIDTH, PR_TOP_MARGIN, + width() - WHITE_KEY_WIDTH, + keyAreaBottom() - PR_TOP_MARGIN); int old_x = 0; int old_y = 0; @@ -3255,6 +3258,9 @@ void PianoRoll::paintEvent(QPaintEvent * pe ) drawDetuningInfo( p, note, x + WHITE_KEY_WIDTH, y_base - key * KEY_LINE_HEIGHT ); + p.setClipRect(WHITE_KEY_WIDTH, PR_TOP_MARGIN, + width() - WHITE_KEY_WIDTH, + height() - PR_TOP_MARGIN); } } @@ -3783,6 +3789,21 @@ void PianoRoll::finishRecordNote(const Note & n ) it->key(), it->getVolume(), it->getPanning() ); n1.quantizeLength( quantization() ); + + //Get selected chord + const InstrumentFunctionNoteStacking::Chord & chord = InstrumentFunctionNoteStacking::ChordTable::getInstance() + .getChordByName( m_chordModel.currentText() ); + + if( !chord.isEmpty() ) + { + for( int i = 1; i < chord.size(); i++ ) + { + Note new_note( n.length(), it->pos(), it->key() + chord[i] ); + new_note.setPanning( it->getPanning() ); + new_note.setVolume( it->getVolume() ); + m_pattern->addNote( new_note ); + } + } m_pattern->addNote( n1 ); update(); m_recordingNotes.erase( it ); diff --git a/src/tracks/SampleTrack.cpp b/src/tracks/SampleTrack.cpp index c965af140..959d6389e 100644 --- a/src/tracks/SampleTrack.cpp +++ b/src/tracks/SampleTrack.cpp @@ -65,7 +65,7 @@ SampleTCO::SampleTCO( Track * _track ) : // we need to receive bpm-change-events, because then we have to // change length of this TCO connect( Engine::getSong(), SIGNAL( tempoChanged( bpm_t ) ), - this, SLOT( updateLength() ) ); + this, SLOT( updateLength() ), Qt::DirectConnection ); connect( Engine::getSong(), SIGNAL( timeSignatureChanged( int,int ) ), this, SLOT( updateLength() ) ); @@ -110,7 +110,7 @@ SampleTCO::SampleTCO( Track * _track ) : SampleTCO::~SampleTCO() { SampleTrack * sampletrack = dynamic_cast( getTrack() ); - if( sampletrack) + if ( sampletrack ) { sampletrack->updateTcos(); } @@ -122,10 +122,7 @@ SampleTCO::~SampleTCO() void SampleTCO::changeLength( const MidiTime & _length ) { - float nom = Engine::getSong()->getTimeSigModel().getNumerator(); - float den = Engine::getSong()->getTimeSigModel().getDenominator(); - int ticksPerTact = DefaultTicksPerTact * ( nom / den ); - TrackContentObject::changeLength( qMax( static_cast( _length ), ticksPerTact ) ); + TrackContentObject::changeLength( qMax( static_cast( _length ), 1 ) ); } @@ -151,9 +148,21 @@ void SampleTCO::setSampleBuffer( SampleBuffer* sb ) void SampleTCO::setSampleFile( const QString & _sf ) { - m_sampleBuffer->setAudioFile( _sf ); + int length; + if ( _sf.isEmpty() ) + { //When creating an empty sample pattern make it a bar long + float nom = Engine::getSong()->getTimeSigModel().getNumerator(); + float den = Engine::getSong()->getTimeSigModel().getDenominator(); + length = DefaultTicksPerTact * ( nom / den ); + } + else + { //Otherwise set it to the sample's length + m_sampleBuffer->setAudioFile( _sf ); + length = sampleLength(); + } + changeLength(length); + setStartTimeOffset( 0 ); - changeLength( (int) ( m_sampleBuffer->frames() / Engine::framesPerTick() ) ); emit sampleChanged(); emit playbackPositionChanged(); @@ -440,8 +449,15 @@ void SampleTCOView::mouseReleaseEvent(QMouseEvent *_me) void SampleTCOView::mouseDoubleClickEvent( QMouseEvent * ) { QString af = m_tco->m_sampleBuffer->openAudioFile(); - if( af != "" && af != m_tco->m_sampleBuffer->audioFile() ) - { + + if ( af.isEmpty() ) {} //Don't do anything if no file is loaded + else if ( af == m_tco->m_sampleBuffer->audioFile() ) + { //Instead of reloading the existing file, just reset the size + int length = (int) ( m_tco->m_sampleBuffer->frames() / Engine::framesPerTick() ); + m_tco->changeLength(length); + } + else + { //Otherwise load the new file as ususal m_tco->setSampleFile( af ); Engine::getSong()->setModified(); }