diff --git a/data/themes/default/pat_rec.png b/data/themes/default/pat_rec.png new file mode 100644 index 000000000..5c0ed9455 Binary files /dev/null and b/data/themes/default/pat_rec.png differ diff --git a/include/AutomatableModel.h b/include/AutomatableModel.h index 4a1e6d2b5..10ee252e9 100644 --- a/include/AutomatableModel.h +++ b/include/AutomatableModel.h @@ -133,7 +133,6 @@ public: float controllerValue( int frameOffset ) const; - template T initValue() const { diff --git a/include/AutomationPattern.h b/include/AutomationPattern.h index ca2ff2695..aea64947e 100644 --- a/include/AutomationPattern.h +++ b/include/AutomationPattern.h @@ -155,13 +155,21 @@ public: static AutomationPattern * globalAutomationPattern( AutomatableModel * _m ); static void resolveAllIDs(); + bool isRecording() const + { + return m_isRecording; + } + + void setRecording( const bool b ) + { + m_isRecording = b; + } public slots: void clear(); void openInAutomationEditor(); void objectDestroyed( jo_id_t ); - private: void cleanObjects(); void generateTangents(); @@ -179,6 +187,9 @@ private: ProgressionTypes m_progressionType; bool m_dragging; + + bool m_isRecording; + float m_lastRecordedValue; static const float DEFAULT_MIN_VALUE; static const float DEFAULT_MAX_VALUE; diff --git a/include/AutomationPatternView.h b/include/AutomationPatternView.h index 73b2a7d9e..382c28375 100644 --- a/include/AutomationPatternView.h +++ b/include/AutomationPatternView.h @@ -50,7 +50,7 @@ protected slots: void resetName(); void changeName(); void disconnectObject( QAction * _a ); - + void toggleRecording(); protected: virtual void constructContextMenu( QMenu * ); @@ -69,6 +69,8 @@ private: AutomationPattern * m_pat; QPixmap m_paintPixmap; bool m_needsUpdate; + + static QPixmap * s_pat_rec; void scaleTimemapToFit( float oldMin, float oldMax ); } ; diff --git a/src/core/AutomationPattern.cpp b/src/core/AutomationPattern.cpp index 0f38b34d9..37a6f7b27 100644 --- a/src/core/AutomationPattern.cpp +++ b/src/core/AutomationPattern.cpp @@ -47,7 +47,9 @@ AutomationPattern::AutomationPattern( AutomationTrack * _auto_track ) : m_objects(), m_tension( 1.0 ), m_progressionType( DiscreteProgression ), - m_dragging( false ) + m_dragging( false ), + m_isRecording( false ), + m_lastRecordedValue( 0 ) { changeLength( MidiTime( 1, 0 ) ); } @@ -469,27 +471,44 @@ const QString AutomationPattern::name() const -void AutomationPattern::processMidiTime( const MidiTime & _time ) +void AutomationPattern::processMidiTime( const MidiTime & time ) { - if( _time >= 0 && hasAutomation() ) + if( ! isRecording() ) { - const float val = valueAt( _time ); - for( objectVector::iterator it = m_objects.begin(); - it != m_objects.end(); ++it ) + if( time >= 0 && hasAutomation() ) { - if( *it ) + const float val = valueAt( time ); + for( objectVector::iterator it = m_objects.begin(); + it != m_objects.end(); ++it ) { - ( *it )->setAutomatedValue( val ); - } + if( *it ) + { + ( *it )->setAutomatedValue( val ); + } + } + } + } + else + { + if( time >= 0 && hasAutomation() && ! m_objects.isEmpty() ) + { + const float value = static_cast( firstObject()->value() ); + if( value != m_lastRecordedValue ) + { + putValue( time, value, true ); + m_lastRecordedValue = value; + } + else if( valueAt( time ) != value ) + { + removeValue( time, false ); + } } } } - - trackContentObjectView * AutomationPattern::createView( trackView * _tv ) { return new AutomationPatternView( this, _tv ); diff --git a/src/gui/AutomationPatternView.cpp b/src/gui/AutomationPatternView.cpp index baa19376c..7f0f22194 100644 --- a/src/gui/AutomationPatternView.cpp +++ b/src/gui/AutomationPatternView.cpp @@ -38,6 +38,7 @@ #include "tooltip.h" +QPixmap * AutomationPatternView::s_pat_rec = NULL; AutomationPatternView::AutomationPatternView( AutomationPattern * _pattern, trackView * _parent ) : @@ -58,6 +59,9 @@ AutomationPatternView::AutomationPatternView( AutomationPattern * _pattern, toolTip::add( this, tr( "double-click to open this pattern in " "automation editor" ) ); setStyle( QApplication::style() ); + + if( s_pat_rec == NULL ) { s_pat_rec = new QPixmap( embed::getIconPixmap( + "pat_rec" ) ); } } @@ -134,6 +138,11 @@ void AutomationPatternView::disconnectObject( QAction * _a ) } +void AutomationPatternView::toggleRecording() +{ + m_pat->setRecording( ! m_pat->isRecording() ); + update(); +} void AutomationPatternView::constructContextMenu( QMenu * _cm ) @@ -156,6 +165,9 @@ void AutomationPatternView::constructContextMenu( QMenu * _cm ) _cm->addAction( embed::getIconPixmap( "edit_rename" ), tr( "Change name" ), this, SLOT( changeName() ) ); + _cm->addAction( embed::getIconPixmap( "record" ), + tr( "Set/clear record" ), + this, SLOT( toggleRecording() ) ); if( !m_pat->m_objects.isEmpty() ) { _cm->addSeparator(); @@ -236,12 +248,6 @@ void AutomationPatternView::paintEvent( QPaintEvent * ) p.setPen( c.lighter( 130 ) ); p.drawRect( 1, 1, width()-3, height()-3 ); - p.setBrush( QBrush() ); - if( engine::automationEditor()->currentPattern() == m_pat ) - p.setPen( c.lighter( 130 ) ); - else - p.setPen( c.darker( 300 ) ); - p.drawRect( 0, 0, width()-1, height()-1 ); const float ppt = fixedTCOs() ? ( parentWidget()->width() - 2 * TCO_BORDER_WIDTH ) @@ -310,6 +316,22 @@ void AutomationPatternView::paintEvent( QPaintEvent * ) } p.resetMatrix(); + + // recording icon for when recording automation + if( m_pat->isRecording() ) + { + p.drawPixmap( 4, 14, *s_pat_rec ); + } + + // outer edge + p.setBrush( QBrush() ); + if( engine::automationEditor()->currentPattern() == m_pat ) + p.setPen( c.lighter( 130 ) ); + else + p.setPen( c.darker( 300 ) ); + p.drawRect( 0, 0, width()-1, height()-1 ); + + // pattern name p.setFont( pointSize<8>( p.font() ) ); QColor text_color = ( m_pat->isMuted() || m_pat->getTrack()->isMuted() ) @@ -327,6 +349,7 @@ void AutomationPatternView::paintEvent( QPaintEvent * ) embed::getIconPixmap( "muted", 16, 16 ) ); } + p.end(); _p.drawPixmap( 0, 0, m_paintPixmap );