AutomationPattern: removed magic value at position zero

In automation patterns there always had to be a value at position zero
which also had a special semantic concerning the initial values of
connected objects. However that logic was buggy and confusing.
I therefore completely removed the neccessity for a value at position
zero (automated value will be 0 until the first set point).
This commit is contained in:
Tobias Doerffel
2013-01-07 00:29:25 +01:00
parent 99091e9ce3
commit 80106138c8
2 changed files with 54 additions and 95 deletions

View File

@@ -2,7 +2,7 @@
* AutomationPattern.h - declaration of class AutomationPattern, which contains
* all information about an automation pattern
*
* Copyright (c) 2008-2010 Tobias Doerffel <tobydox/at/users.sourceforge.net>
* Copyright (c) 2008-2013 Tobias Doerffel <tobydox/at/users.sourceforge.net>
* Copyright (c) 2006-2008 Javier Serrano Polo <jasp00/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
@@ -109,6 +109,8 @@ public slots:
private:
void cleanObjects();
AutomationTrack * m_autoTrack;
QVector<jo_id_t> m_idsToResolve;
objectVector m_objects;

View File

@@ -2,7 +2,7 @@
* AutomationPattern.cpp - implementation of class AutomationPattern which
* holds dynamic values
*
* Copyright (c) 2008-2010 Tobias Doerffel <tobydox/at/users.sourceforge.net>
* Copyright (c) 2008-2013 Tobias Doerffel <tobydox/at/users.sourceforge.net>
* Copyright (c) 2006-2008 Javier Serrano Polo <jasp00/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
@@ -45,7 +45,6 @@ AutomationPattern::AutomationPattern( AutomationTrack * _auto_track ) :
m_hasAutomation( false )
{
changeLength( midiTime( 1, 0 ) );
m_timeMap[0] = 0;
}
@@ -101,12 +100,6 @@ void AutomationPattern::addObject( AutomatableModel * _obj, bool _search_dup )
if( addIt )
{
m_objects += _obj;
// been empty before?
if( m_objects.size() == 1 && !hasAutomation() )
{
// then initialize default-value
putValue( 0, _obj->value<float>(), false );
}
connect( _obj, SIGNAL( destroyed( jo_id_t ) ),
this, SLOT( objectDestroyed( jo_id_t ) ),
Qt::DirectConnection );
@@ -152,6 +145,8 @@ midiTime AutomationPattern::putValue( const midiTime & _time,
const float _value,
const bool _quant_pos )
{
cleanObjects();
midiTime newTime = _quant_pos && engine::automationEditor() ?
note::quantized( _time,
engine::automationEditor()->quantization() ) :
@@ -159,43 +154,7 @@ midiTime AutomationPattern::putValue( const midiTime & _time,
m_timeMap[newTime] = _value;
if( newTime == 0 )
{
for( objectVector::iterator it = m_objects.begin();
it != m_objects.end(); )
{
if( *it )
{
( *it )->setValue( _value );
++it;
}
else
{
it = m_objects.erase( it );
}
}
}
// just one automation value?
if( m_timeMap.size() == 1 )
{
m_hasAutomation = m_objects.isEmpty(); // usually false
for( objectVector::iterator it = m_objects.begin();
it != m_objects.end(); ++it )
{
// default value differs from current value?
if( *it && _value != ( *it )->initValue<float>() )
{
// then enable automating this object
m_hasAutomation = true;
}
}
}
else
{
// in all other cases assume we have automation
m_hasAutomation = true;
}
m_hasAutomation = true;
// we need to maximize our length in case we're part of a hidden
// automation track as the user can't resize this pattern
@@ -214,41 +173,22 @@ midiTime AutomationPattern::putValue( const midiTime & _time,
void AutomationPattern::removeValue( const midiTime & _time )
{
if( _time != 0 )
cleanObjects();
m_timeMap.remove( _time );
if( getTrack() &&
getTrack()->type() == track::HiddenAutomationTrack )
{
m_timeMap.remove( _time );
if( m_timeMap.size() == 1 )
{
const float val = m_timeMap[0];
m_hasAutomation = false;
for( objectVector::iterator it = m_objects.begin();
it != m_objects.end(); )
{
if( *it )
{
( *it )->setValue( val );
if( ( *it )->initValue<float>() != val )
{
m_hasAutomation = true;
}
++it;
}
else
{
it = m_objects.erase( it );
}
}
}
if( getTrack() &&
getTrack()->type() == track::HiddenAutomationTrack )
{
changeLength( length() );
}
emit dataChanged();
changeLength( length() );
}
if( m_timeMap.isEmpty() )
{
m_hasAutomation = false;
}
emit dataChanged();
}
@@ -260,10 +200,22 @@ float AutomationPattern::valueAt( const midiTime & _time ) const
{
return 0;
}
timeMap::const_iterator v = m_timeMap.lowerBound( _time );
if( m_timeMap.contains( _time ) )
{
return m_timeMap[_time];
}
// lowerBound returns next value with greater key, therefore we take
// the previous element to get the current value
return ( v != m_timeMap.begin() ) ? (v-1).value() : v.value();
timeMap::ConstIterator v = m_timeMap.lowerBound( _time );
if( v == m_timeMap.begin() )
{
return 0;
}
return (v-1).value();
}
@@ -326,17 +278,7 @@ void AutomationPattern::loadSettings( const QDomElement & _this )
}
m_hasAutomation = m_timeMap.size() > 0;
if( m_hasAutomation == false )
{
for( objectVector::iterator it = m_objects.begin();
it != m_objects.end(); ++it )
{
if( *it )
{
( *it )->setValue( m_timeMap[0] );
}
}
}
int len = _this.attribute( "len" ).toInt();
if( len <= 0 )
{
@@ -366,7 +308,7 @@ const QString AutomationPattern::name() const
void AutomationPattern::processMidiTime( const midiTime & _time )
{
if( _time >= 0 && m_hasAutomation )
if( _time >= 0 && hasAutomation() )
{
const float val = valueAt( _time );
for( objectVector::iterator it = m_objects.begin();
@@ -502,9 +444,9 @@ void AutomationPattern::resolveAllIDs()
void AutomationPattern::clear()
{
const float val = firstObject()->value<float>();
m_timeMap.clear();
putValue( 0, val );
emit dataChanged();
if( engine::automationEditor() &&
engine::automationEditor()->currentPattern() == this )
@@ -537,6 +479,21 @@ void AutomationPattern::objectDestroyed( jo_id_t _id )
void AutomationPattern::cleanObjects()
{
for( objectVector::iterator it = m_objects.begin(); it != m_objects.end(); )
{
if( *it )
{
++it;
}
else
{
it = m_objects.erase( it );
}
}
}
#include "moc_AutomationPattern.cxx"