diff --git a/include/FadeButton.h b/include/FadeButton.h index 95753ecea..8f56a77b2 100644 --- a/include/FadeButton.h +++ b/include/FadeButton.h @@ -35,8 +35,10 @@ class FadeButton : public QAbstractButton { Q_OBJECT public: - FadeButton( const QColor & _normal_color, const QColor & - _activated_color, QWidget * _parent ); + FadeButton( const QColor & _normal_color, + const QColor & _activated_color, + const QColor & _hold_color, + QWidget * _parent ); virtual ~FadeButton(); void setActiveColor( const QColor & activated_color ); @@ -44,6 +46,7 @@ public: public slots: void activate(); + void noteEnd(); protected: @@ -53,13 +56,20 @@ protected: private: QTime m_stateTimer; + QTime m_releaseTimer; + + // the default color of the widget QColor m_normalColor; + // the color on note play QColor m_activatedColor; + // the color after the "play" fade is done but a note is still playing + QColor m_holdColor; + int activeNotes; void signalUpdate(); + QColor fadeToColor(QColor, QColor, QTime, float); } ; #endif - diff --git a/include/InstrumentTrack.h b/include/InstrumentTrack.h index c487438d0..72e0d04cc 100644 --- a/include/InstrumentTrack.h +++ b/include/InstrumentTrack.h @@ -221,6 +221,7 @@ signals: void midiNoteOff( const Note& ); void nameChanged(); void newNote(); + void endNote(); protected: diff --git a/src/gui/widgets/FadeButton.cpp b/src/gui/widgets/FadeButton.cpp index d4244701a..b633286b1 100644 --- a/src/gui/widgets/FadeButton.cpp +++ b/src/gui/widgets/FadeButton.cpp @@ -35,16 +35,21 @@ const float FadeDuration = 300; -FadeButton::FadeButton( const QColor & _normal_color, - const QColor & _activated_color, QWidget * _parent ) : +FadeButton::FadeButton(const QColor & _normal_color, + const QColor & _activated_color, + const QColor & holdColor, + QWidget * _parent) : QAbstractButton( _parent ), m_stateTimer(), + m_releaseTimer(), m_normalColor( _normal_color ), - m_activatedColor( _activated_color ) + m_activatedColor( _activated_color ), + m_holdColor( holdColor ) { - setAttribute( Qt::WA_OpaquePaintEvent, true ); - setCursor( QCursor( embed::getIconPixmap( "hand" ), 3, 3 ) ); - setFocusPolicy( Qt::NoFocus ); + setAttribute(Qt::WA_OpaquePaintEvent, true); + setCursor(QCursor(embed::getIconPixmap("hand"), 3, 3)); + setFocusPolicy(Qt::NoFocus); + activeNotes = 0; } @@ -54,7 +59,7 @@ FadeButton::~FadeButton() { } -void FadeButton::setActiveColor( const QColor & activated_color ) +void FadeButton::setActiveColor(const QColor & activated_color) { m_activatedColor = activated_color; } @@ -65,63 +70,104 @@ void FadeButton::setActiveColor( const QColor & activated_color ) void FadeButton::activate() { m_stateTimer.restart(); + activeNotes++; signalUpdate(); } -void FadeButton::customEvent( QEvent * ) +void FadeButton::noteEnd() +{ + if (activeNotes <= 0) + { + qWarning("noteEnd() triggered without a corresponding activate()!"); + activeNotes = 0; + } + else + { + activeNotes--; + } + + if (activeNotes == 0) + { + m_releaseTimer.restart(); + } + + signalUpdate(); +} + + + + +void FadeButton::customEvent(QEvent *) { update(); } - -void FadeButton::paintEvent( QPaintEvent * _pe ) +void FadeButton::paintEvent(QPaintEvent * _pe) { QColor col = m_normalColor; - if( ! m_stateTimer.isNull() && m_stateTimer.elapsed() < FadeDuration ) + + if(!m_stateTimer.isNull() && m_stateTimer.elapsed() < FadeDuration) { - const float state = 1 - m_stateTimer.elapsed() / FadeDuration; - const int r = (int)( m_normalColor.red() * - ( 1.0f - state ) + - m_activatedColor.red() * state ); - const int g = (int)( m_normalColor.green() * - ( 1.0f - state ) + - m_activatedColor.green() * state ); - const int b = (int)( m_normalColor.blue() * - ( 1.0f - state ) + - m_activatedColor.blue() * state ); - col.setRgb( r, g, b ); - QTimer::singleShot( 20, this, SLOT( update() ) ); + // The first part of the fade, when a note is triggered. + col = fadeToColor(m_activatedColor, m_holdColor, m_stateTimer, FadeDuration); + QTimer::singleShot(20, this, SLOT(update())); + } + else if (!m_stateTimer.isNull() + && m_stateTimer.elapsed() >= FadeDuration + && activeNotes > 0) + { + // The fade is done, but at least one note is still held. + col = m_holdColor; + } + else if (!m_releaseTimer.isNull() && m_releaseTimer.elapsed() < FadeDuration) + { + // Last note just ended. Fade to default color. + col = fadeToColor(m_holdColor, m_normalColor, m_releaseTimer, FadeDuration); + QTimer::singleShot(20, this, SLOT(update())); + } + else + { + // No fade, no notes. Set to default color. + col = m_normalColor; } - QPainter p( this ); - p.fillRect( rect(), col ); + QPainter p(this); + p.fillRect(rect(), col); int w = rect().right(); int h = rect().bottom(); - p.setPen( m_normalColor.darker(130) ); - p.drawLine( w, 1, w, h ); - p.drawLine( 1, h, w, h ); - p.setPen( m_normalColor.lighter(130) ); - p.drawLine( 0, 0, 0, h-1 ); - p.drawLine( 0, 0, w, 0 ); + p.setPen(m_normalColor.darker(130)); + p.drawLine(w, 1, w, h); + p.drawLine(1, h, w, h); + p.setPen(m_normalColor.lighter(130)); + p.drawLine(0, 0, 0, h-1); + p.drawLine(0, 0, w, 0); } +QColor FadeButton::fadeToColor(QColor startCol, QColor endCol, QTime timer, float duration) +{ + QColor col; + + const float state = 1 - timer.elapsed() / duration; + const int r = (int)(endCol.red() * (1.0f - state) + + startCol.red() * state); + const int g = (int)(endCol.green() * (1.0f - state) + + startCol.green() * state); + const int b = (int)(endCol.blue() * (1.0f - state) + + startCol.blue() * state); + col.setRgb(r, g, b); + + return col; +} void FadeButton::signalUpdate() { - QApplication::postEvent( this, new updateEvent() ); + QApplication::postEvent(this, new updateEvent()); } - - - - - - - diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index 093632831..607131be0 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -422,6 +422,7 @@ void InstrumentTrack::processOutEvent( const MidiEvent& event, const MidiTime& t m_instrument->handleMidiEvent( MidiEvent( MidiNoteOff, midiPort()->realOutputChannel(), key, 0 ), time, offset ); } m_midiNotesMutex.unlock(); + emit endNote(); break; default: @@ -976,6 +977,8 @@ InstrumentTrackView::InstrumentTrackView( InstrumentTrack * _it, TrackContainerV QPalette::Background), QApplication::palette().color( QPalette::Active, QPalette::BrightText ), + QApplication::palette().color( QPalette::Active, + QPalette::BrightText).darker(), getTrackSettingsWidget() ); m_activityIndicator->setGeometry( widgetWidth-2*24-11, 2, 8, 28 ); @@ -986,6 +989,8 @@ InstrumentTrackView::InstrumentTrackView( InstrumentTrack * _it, TrackContainerV this, SLOT( activityIndicatorReleased() ) ); connect( _it, SIGNAL( newNote() ), m_activityIndicator, SLOT( activate() ) ); + connect( _it, SIGNAL( endNote() ), + m_activityIndicator, SLOT( noteEnd() ) ); connect( &_it->m_mutedModel, SIGNAL( dataChanged() ), this, SLOT( muteChanged() ) ); setModel( _it );