31
31
#include "qt3support.h"
32
#include "automation_editor.h"
33
#include "automation_pattern.h"
34
32
#include "journalling_object.h"
35
#include "templates.h"
36
#include "midi_time.h"
37
33
#include "level_object.h"
42
#include <QtCore/QVariant>
43
37
#include <QtCore/QPointer>
49
41
#include <qguardedptr.h>
46
class automationPattern;
54
50
template<typename T, typename EDIT_STEP_TYPE = T>
55
51
class automatableObject : public journallingObject, public levelObject
58
54
typedef automatableObject<T, EDIT_STEP_TYPE> autoObj;
60
automatableObject( engine * _engine, track * _track = NULL,
61
const T _val = 0, const T _min = 0,
63
const T _step = defaultRelStep() ) :
64
journallingObject( _engine ),
70
m_automation_pattern( NULL ),
73
m_curLevel = level( _val );
74
m_minLevel = level( _min );
75
m_maxLevel = level( _max );
56
automatableObject( track * _track = NULL, const T _val = 0,
57
const T _min = 0, const T _max = 0,
58
const T _step = defaultRelStep() );
78
virtual ~automatableObject()
80
if( m_automation_pattern )
82
delete m_automation_pattern;
84
while( m_linkedObjects.empty() == FALSE )
86
m_linkedObjects.last()->unlinkObject( this );
87
m_linkedObjects.erase( m_linkedObjects.end() - 1 );
60
virtual ~automatableObject();
91
62
static inline T minRelStep( void )
129
100
return( m_curLevel );
132
inline T fittedValue( T _value )
134
_value = tLimit<T>( _value, minValue(), maxValue() );
138
_value = static_cast<T>( roundf( _value
139
/ (float)step() ) * step() );
146
// correct rounding error at the border
147
if( tAbs<T>( _value - maxValue() ) < minEps() *
153
// correct rounding error if value = 0
154
if( tAbs<T>( _value ) < minEps() * tAbs<T>( step() ) )
162
inline virtual void setInitValue( const T _value )
164
saveJournallingState( FALSE );
166
if( m_automation_pattern )
170
restoreJournallingState();
173
inline virtual void setValue( const T _value )
175
const T old_val = m_value;
177
m_value = fittedValue( _value );
178
if( old_val != m_value )
180
m_curLevel = level( m_value );
182
// add changes to history so user can undo it
183
addJournalEntry( journalEntry( 0,
184
static_cast<EDIT_STEP_TYPE>( m_value ) -
185
static_cast<EDIT_STEP_TYPE>( old_val ) ) );
187
// notify linked objects
189
// doesn't work because of implicit typename T
190
// for( autoObjVector::iterator it =
191
// m_linkedObjects.begin();
192
// it != m_linkedObjects.end(); ++it )
193
for( csize i = 0; i < m_linkedObjects.size(); ++i )
195
autoObj * it = m_linkedObjects[i];
196
if( value() != it->value() &&
197
it->fittedValue( value() ) !=
200
it->saveJournallingState(
202
it->setValue( value() );
203
it->restoreJournallingState();
103
inline T fittedValue( T _value ) const;
105
T value( int _level ) const
107
return( fittedValue( _level * m_step ) );
110
virtual void setInitValue( const T _value );
112
inline virtual void setValue( const T _value );
209
114
inline virtual void incValue( int _steps )
211
116
setValue( m_value + _steps * m_step );
214
inline virtual void setRange( const T _min, const T _max,
215
const T _step = defaultRelStep() )
219
if( m_minValue > m_maxValue )
221
qSwap<T>( m_minValue, m_maxValue );
225
autoObj::setInitValue( value() );
228
inline virtual void setStep( const T _step )
231
const T intv = maxValue() - minValue();
235
m_step = intv * defaultRelStep();
239
if( ( intv > 0 ) && ( _step < 0 ) || ( intv < 0 ) &&
248
if( tAbs<T>( m_step ) <
249
tAbs<T>( minRelStep() * intv ) )
251
m_step = minRelStep() * intv;
255
m_curLevel = level( m_value );
256
m_minLevel = level( m_minValue );
257
m_maxLevel = level( m_maxValue );
260
static inline void linkObjects( autoObj * _object1,
263
_object1->linkObject( _object2 );
264
_object2->linkObject( _object1 );
266
if( _object1->m_automation_pattern
267
!= _object2->m_automation_pattern )
269
if( _object2->m_automation_pattern )
271
delete _object2->m_automation_pattern;
273
_object2->m_automation_pattern
274
= _object1->m_automation_pattern;
119
virtual void setRange( const T _min, const T _max,
120
const T _step = defaultRelStep() );
122
inline virtual void setStep( const T _step );
124
static void linkObjects( autoObj * _object1, autoObj * _object2 );
126
static void unlinkObjects( autoObj * _object1, autoObj * _object2 );
278
128
virtual void FASTCALL saveSettings( QDomDocument & _doc,
279
129
QDomElement & _this,
280
const QString & _name = "value" )
282
if( m_automation_pattern )
284
QDomElement pattern_element;
285
QDomNode node = _this.namedItem(
286
automationPattern::classNodeName() );
287
if( node.isElement() )
289
pattern_element = node.toElement();
293
pattern_element = _doc.createElement(
294
automationPattern::classNodeName() );
295
_this.appendChild( pattern_element );
297
QDomElement element = _doc.createElement( _name );
298
m_automation_pattern->saveSettings( _doc, element );
299
pattern_element.appendChild( element );
303
_this.setAttribute( _name, value() );
130
const QString & _name = "value" );
307
132
virtual void FASTCALL loadSettings( const QDomElement & _this,
308
const QString & _name = "value" )
310
QDomNode node = _this.namedItem(
311
automationPattern::classNodeName() );
312
if( node.isElement() )
314
node = node.namedItem( _name );
315
if( node.isElement() )
317
m_automation_pattern->loadSettings(
319
setLevel( m_automation_pattern->valueAt(
325
setInitValue( attributeValue( _this.attribute( _name ) ) );
133
const QString & _name = "value" );
328
135
virtual QString nodeName( void ) const
330
137
return( "automatableobject" );
333
inline const QVariant & data( void ) const
338
void setData( const QVariant & _data )
343
inline automationPattern * getAutomationPattern( void )
345
if( !m_automation_pattern )
347
m_automation_pattern = new automationPattern( m_track,
349
syncAutomationPattern();
351
return( m_automation_pattern );
140
inline automationPattern * getAutomationPattern( void );
354
142
inline bool nullTrack( void )
356
144
return( m_track == NULL );
359
void initAutomationPattern( engine * _engine )
147
void initAutomationPattern( void )
361
m_automation_pattern = new automationPattern( _engine, this );
149
m_automation_pattern = new automationPattern( NULL, this );
366
virtual void redoStep( journalEntry & _je )
368
saveJournallingState( FALSE );
370
setValue( static_cast<T>( value() +
371
_je.data().value<EDIT_STEP_TYPE>() ) );
373
setValue( static_cast<T>( value() + static_cast<EDIT_STEP_TYPE>(
374
_je.data().toDouble() ) ) );
376
restoreJournallingState();
379
virtual void undoStep( journalEntry & _je )
381
journalEntry je( _je.actionID(),
383
-_je.data().value<EDIT_STEP_TYPE>()
385
static_cast<EDIT_STEP_TYPE>( -_je.data().toDouble() )
392
// most objects will need this temporarily
395
inline void addJournalEntryFromOldToCurVal( void )
397
addJournalEntry( journalEntry( 0, value() - m_oldValue ) );
400
inline void setFirstValue( void )
402
if( m_automation_pattern
403
&& m_automation_pattern->updateFirst() )
405
m_automation_pattern->putValue( midiTime( 0 ),
407
if( eng()->getAutomationEditor() &&
408
eng()->getAutomationEditor()->currentPattern()
409
== m_automation_pattern )
411
eng()->getAutomationEditor()->update();
154
virtual void redoStep( journalEntry & _je );
156
virtual void undoStep( journalEntry & _je );
158
void prepareJournalEntryFromOldVal( void );
160
void addJournalEntryFromOldToCurVal( void );
162
inline void setFirstValue( void );
423
171
QPointer<automationPattern> m_automation_pattern;
174
// most objects will need this temporarily
176
bool m_journalEntryReady;
428
178
typedef vvector<autoObj *> autoObjVector;
429
179
autoObjVector m_linkedObjects;
431
inline void linkObject( autoObj * _object )
433
if( qFind( m_linkedObjects.begin(), m_linkedObjects.end(),
434
_object ) == m_linkedObjects.end() )
436
m_linkedObjects.push_back( _object );
440
inline void unlinkObject( autoObj * _object )
442
m_linkedObjects.erase( qFind( m_linkedObjects.begin(),
443
m_linkedObjects.end(),
447
static T attributeValue( QString _value );
449
inline void syncAutomationPattern( void )
451
for( csize i = 0; i < m_linkedObjects.size(); ++i )
453
autoObj * it = m_linkedObjects[i];
454
if( m_automation_pattern != it->m_automation_pattern )
456
it->m_automation_pattern = m_automation_pattern;
461
void setLevel( int _level )
463
if( m_curLevel == _level )
467
saveJournallingState( FALSE );
468
m_automation_pattern->setUpdateFirst( FALSE );
469
setValue( _level * m_step );
470
m_automation_pattern->setUpdateFirst( TRUE );
471
restoreJournallingState();
181
inline void linkObject( autoObj * _object );
183
inline void unlinkObject( autoObj * _object );
185
static inline T attributeValue( QString _value );
187
inline void syncAutomationPattern( void );
189
inline void setLevel( int _level );
474
191
inline int level( T _value ) const
476
193
return( (int)roundf( _value / (float)m_step ) );
479
QString levelToLabel( int _level )
196
QString levelToLabel( int _level ) const
481
return( QString::number( _level * m_step ) );
198
return( QString::number( value( _level ) ) );
484
201
int labelToLevel( QString _label )