~ubuntu-branches/ubuntu/hardy/lmms/hardy

« back to all changes in this revision

Viewing changes to include/automatable_object.h

  • Committer: Bazaar Package Importer
  • Author(s): Tobias Doerffel
  • Date: 2007-09-17 15:00:24 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20070917150024-mo0zk4ks81jawqii
Tags: 0.3.0-1ubuntu1
* Resynchronized with Debian (LP: #139759, LP: #90806, LP: #102639,
  LP: #113447, LP: #121172, LP: #124890)
* reverted changes from 0.2.1-1.1ubuntu1 as upstream merged/included them

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 * automatable_object.h - declaration of class automatableObject
3
3
 *
4
 
 * Copyright (c) 2006 Tobias Doerffel <tobydox/at/users.sourceforge.net>
 
4
 * Copyright (c) 2006-2007 Tobias Doerffel <tobydox/at/users.sourceforge.net>
5
5
 * 
6
6
 * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
7
7
 *
17
17
 *
18
18
 * You should have received a copy of the GNU General Public
19
19
 * License along with this program (see COPYING); if not, write to the
20
 
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21
 
 * Boston, MA 02111-1307, USA.
 
20
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 
21
 * Boston, MA 02110-1301 USA.
22
22
 *
23
23
 */
24
24
 
29
29
#include <math.h>
30
30
 
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"
38
34
 
39
35
#ifndef QT3
40
36
 
41
 
#include <Qt/QtXml>
42
 
#include <QtCore/QVariant>
43
37
#include <QtCore/QPointer>
44
38
 
45
39
#else
46
40
 
47
 
#include <qdom.h>
48
 
#include <qvariant.h>
49
41
#include <qguardedptr.h>
50
42
 
51
43
#endif
52
44
 
53
45
 
 
46
class automationPattern;
 
47
class track;
 
48
 
 
49
 
54
50
template<typename T, typename EDIT_STEP_TYPE = T>
55
51
class automatableObject : public journallingObject, public levelObject
56
52
{
57
53
public:
58
54
        typedef automatableObject<T, EDIT_STEP_TYPE> autoObj;
59
55
 
60
 
        automatableObject( engine * _engine, track * _track = NULL,
61
 
                                        const T _val = 0, const T _min = 0,
62
 
                                        const T _max = 0,
63
 
                                        const T _step = defaultRelStep() ) :
64
 
                journallingObject( _engine ),
65
 
                m_oldValue( _val ),
66
 
                m_value( _val ),
67
 
                m_minValue( _min ),
68
 
                m_maxValue( _max ),
69
 
                m_step( _step ),
70
 
                m_automation_pattern( NULL ),
71
 
                m_track( _track )
72
 
        {
73
 
                m_curLevel = level( _val );
74
 
                m_minLevel = level( _min );
75
 
                m_maxLevel = level( _max );
76
 
        }
 
56
        automatableObject( track * _track = NULL, const T _val = 0,
 
57
                                        const T _min = 0, const T _max = 0,
 
58
                                        const T _step = defaultRelStep() );
77
59
 
78
 
        virtual ~automatableObject()
79
 
        {
80
 
                if( m_automation_pattern )
81
 
                {
82
 
                        delete m_automation_pattern;
83
 
                }
84
 
                while( m_linkedObjects.empty() == FALSE )
85
 
                {
86
 
                        m_linkedObjects.last()->unlinkObject( this );
87
 
                        m_linkedObjects.erase( m_linkedObjects.end() - 1 );
88
 
                }
89
 
        }
 
60
        virtual ~automatableObject();
90
61
 
91
62
        static inline T minRelStep( void )
92
63
        {
129
100
                return( m_curLevel );
130
101
        }
131
102
 
132
 
        inline T fittedValue( T _value )
133
 
        {
134
 
                _value = tLimit<T>( _value, minValue(), maxValue() );
135
 
 
136
 
                if( m_step != 0 )
137
 
                {
138
 
                        _value = static_cast<T>( roundf( _value
139
 
                                                / (float)step() ) * step() );
140
 
                }
141
 
                else
142
 
                {
143
 
                        _value = minValue();
144
 
                }
145
 
 
146
 
                // correct rounding error at the border
147
 
                if( tAbs<T>( _value - maxValue() ) < minEps() *
148
 
                                                        tAbs<T>( step() ) )
149
 
                {
150
 
                        _value = maxValue();
151
 
                }
152
 
 
153
 
                // correct rounding error if value = 0
154
 
                if( tAbs<T>( _value ) < minEps() * tAbs<T>( step() ) )
155
 
                {
156
 
                        _value = 0;
157
 
                }
158
 
 
159
 
                return( _value );
160
 
        }
161
 
 
162
 
        inline virtual void setInitValue( const T _value )
163
 
        {
164
 
                saveJournallingState( FALSE );
165
 
                setValue( _value );
166
 
                if( m_automation_pattern )
167
 
                {
168
 
                        setFirstValue();
169
 
                }
170
 
                restoreJournallingState();
171
 
        }
172
 
 
173
 
        inline virtual void setValue( const T _value )
174
 
        {
175
 
                const T old_val = m_value;
176
 
 
177
 
                m_value = fittedValue( _value );
178
 
                if( old_val != m_value )
179
 
                {
180
 
                        m_curLevel = level( m_value );
181
 
 
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 ) ) );
186
 
 
187
 
                        // notify linked objects
188
 
 
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 )
194
 
                        {
195
 
                                autoObj * it = m_linkedObjects[i];
196
 
                                if( value() != it->value() &&
197
 
                                        it->fittedValue( value() ) !=
198
 
                                                                it->value() )
199
 
                                {
200
 
                                        it->saveJournallingState(
201
 
                                                        isJournalling() );
202
 
                                        it->setValue( value() );
203
 
                                        it->restoreJournallingState();
204
 
                                }
205
 
                        }
206
 
                }
207
 
        }
 
103
        inline T fittedValue( T _value ) const;
 
104
 
 
105
        T value( int _level ) const
 
106
        {
 
107
                return( fittedValue( _level * m_step ) );
 
108
        }
 
109
 
 
110
        virtual void setInitValue( const T _value );
 
111
 
 
112
        inline virtual void setValue( const T _value );
208
113
 
209
114
        inline virtual void incValue( int _steps )
210
115
        {
211
116
                setValue( m_value + _steps * m_step );
212
117
        }
213
118
 
214
 
        inline virtual void setRange( const T _min, const T _max,
215
 
                                        const T _step = defaultRelStep() )
216
 
        {
217
 
                m_minValue = _min;
218
 
                m_maxValue = _max;
219
 
                if( m_minValue > m_maxValue )
220
 
                {
221
 
                        qSwap<T>( m_minValue, m_maxValue );
222
 
                }
223
 
                setStep( _step );
224
 
                // re-adjust value
225
 
                autoObj::setInitValue( value() );
226
 
        }
227
 
 
228
 
        inline virtual void setStep( const T _step )
229
 
        {
230
 
                /*
231
 
                const T intv = maxValue() - minValue();
232
 
 
233
 
                if( _step == 0 )
234
 
                {
235
 
                        m_step = intv * defaultRelStep();
236
 
                }
237
 
                else
238
 
                {
239
 
                        if( ( intv > 0 ) && ( _step < 0 ) || ( intv < 0 ) &&
240
 
                                                                ( _step > 0 ) )
241
 
                        {
242
 
                                m_step = -_step;
243
 
                        }
244
 
                        else
245
 
                        {
246
 
                                m_step = _step;
247
 
                        }
248
 
                        if( tAbs<T>( m_step ) <
249
 
                                        tAbs<T>( minRelStep() * intv ) )
250
 
                        {
251
 
                                m_step = minRelStep() * intv;
252
 
                        }
253
 
                }*/
254
 
                m_step = _step;
255
 
                m_curLevel = level( m_value );
256
 
                m_minLevel = level( m_minValue );
257
 
                m_maxLevel = level( m_maxValue );
258
 
        }
259
 
 
260
 
        static inline void linkObjects( autoObj * _object1,
261
 
                                        autoObj * _object2 )
262
 
        {
263
 
                _object1->linkObject( _object2 );
264
 
                _object2->linkObject( _object1 );
265
 
 
266
 
                if( _object1->m_automation_pattern
267
 
                                        != _object2->m_automation_pattern )
268
 
                {
269
 
                        if( _object2->m_automation_pattern )
270
 
                        {
271
 
                                delete _object2->m_automation_pattern;
272
 
                        }
273
 
                        _object2->m_automation_pattern
274
 
                                        = _object1->m_automation_pattern;
275
 
                }
276
 
        }
 
119
        virtual void setRange( const T _min, const T _max,
 
120
                                        const T _step = defaultRelStep() );
 
121
 
 
122
        inline virtual void setStep( const T _step );
 
123
 
 
124
        static void linkObjects( autoObj * _object1, autoObj * _object2 );
 
125
 
 
126
        static void unlinkObjects( autoObj * _object1, autoObj * _object2 );
277
127
 
278
128
        virtual void FASTCALL saveSettings( QDomDocument & _doc,
279
129
                                        QDomElement & _this,
280
 
                                        const QString & _name = "value" )
281
 
        {
282
 
                if( m_automation_pattern )
283
 
                {
284
 
                        QDomElement pattern_element;
285
 
                        QDomNode node = _this.namedItem(
286
 
                                        automationPattern::classNodeName() );
287
 
                        if( node.isElement() )
288
 
                        {
289
 
                                pattern_element = node.toElement();
290
 
                        }
291
 
                        else
292
 
                        {
293
 
                                pattern_element = _doc.createElement(
294
 
                                        automationPattern::classNodeName() );
295
 
                                _this.appendChild( pattern_element );
296
 
                        }
297
 
                        QDomElement element = _doc.createElement( _name );
298
 
                        m_automation_pattern->saveSettings( _doc, element );
299
 
                        pattern_element.appendChild( element );
300
 
                }
301
 
                else
302
 
                {
303
 
                        _this.setAttribute( _name, value() );
304
 
                }
305
 
        }
 
130
                                        const QString & _name = "value" );
306
131
 
307
132
        virtual void FASTCALL loadSettings( const QDomElement & _this,
308
 
                                        const QString & _name = "value" )
309
 
        {
310
 
                QDomNode node = _this.namedItem(
311
 
                                        automationPattern::classNodeName() );
312
 
                if( node.isElement() )
313
 
                {
314
 
                        node = node.namedItem( _name );
315
 
                        if( node.isElement() )
316
 
                        {
317
 
                                m_automation_pattern->loadSettings(
318
 
                                                        node.toElement() );
319
 
                                setLevel( m_automation_pattern->valueAt(
320
 
                                                        midiTime( 0 ) ) );
321
 
                                return;
322
 
                        }
323
 
                }
324
 
 
325
 
                setInitValue( attributeValue( _this.attribute( _name ) ) );
326
 
        }
 
133
                                        const QString & _name = "value" );
327
134
 
328
135
        virtual QString nodeName( void ) const
329
136
        {
330
137
                return( "automatableobject" );
331
138
        }
332
139
 
333
 
        inline const QVariant & data( void ) const
334
 
        {
335
 
                return( m_data );
336
 
        }
337
 
 
338
 
        void setData( const QVariant & _data )
339
 
        {
340
 
                m_data = _data;
341
 
        }
342
 
 
343
 
        inline automationPattern * getAutomationPattern( void )
344
 
        {
345
 
                if( !m_automation_pattern )
346
 
                {
347
 
                        m_automation_pattern = new automationPattern( m_track,
348
 
                                                                        this );
349
 
                        syncAutomationPattern();
350
 
                }
351
 
                return( m_automation_pattern );
352
 
        }
 
140
        inline automationPattern * getAutomationPattern( void );
353
141
 
354
142
        inline bool nullTrack( void )
355
143
        {
356
144
                return( m_track == NULL );
357
145
        }
358
146
 
359
 
        void initAutomationPattern( engine * _engine )
 
147
        void initAutomationPattern( void )
360
148
        {
361
 
                m_automation_pattern = new automationPattern( _engine, this );
 
149
                m_automation_pattern = new automationPattern( NULL, this );
362
150
        }
363
151
 
364
152
 
365
153
protected:
366
 
        virtual void redoStep( journalEntry & _je )
367
 
        {
368
 
                saveJournallingState( FALSE );
369
 
/*#ifndef QT3
370
 
                setValue( static_cast<T>( value() +
371
 
                                        _je.data().value<EDIT_STEP_TYPE>() ) );
372
 
#else*/
373
 
                setValue( static_cast<T>( value() + static_cast<EDIT_STEP_TYPE>(
374
 
                                                _je.data().toDouble() ) ) );
375
 
//#endif
376
 
                restoreJournallingState();
377
 
        }
378
 
 
379
 
        virtual void undoStep( journalEntry & _je )
380
 
        {
381
 
                journalEntry je( _je.actionID(),
382
 
/*#ifndef QT3
383
 
                                        -_je.data().value<EDIT_STEP_TYPE>()
384
 
#else*/
385
 
                        static_cast<EDIT_STEP_TYPE>( -_je.data().toDouble() )
386
 
//#endif
387
 
                                );
388
 
                redoStep( je );
389
 
        }
390
 
 
391
 
 
392
 
        // most objects will need this temporarily
393
 
        T m_oldValue;
394
 
 
395
 
        inline void addJournalEntryFromOldToCurVal( void )
396
 
        {
397
 
                addJournalEntry( journalEntry( 0, value() - m_oldValue ) );
398
 
        }
399
 
 
400
 
        inline void setFirstValue( void )
401
 
        {
402
 
                if( m_automation_pattern
403
 
                                        && m_automation_pattern->updateFirst() )
404
 
                {
405
 
                        m_automation_pattern->putValue( midiTime( 0 ),
406
 
                                                        m_curLevel, FALSE );
407
 
                        if( eng()->getAutomationEditor() &&
408
 
                                eng()->getAutomationEditor()->currentPattern()
409
 
                                                == m_automation_pattern )
410
 
                        {
411
 
                                eng()->getAutomationEditor()->update();
412
 
                        }
413
 
                }
414
 
        }
 
154
        virtual void redoStep( journalEntry & _je );
 
155
 
 
156
        virtual void undoStep( journalEntry & _je );
 
157
 
 
158
        void prepareJournalEntryFromOldVal( void );
 
159
 
 
160
        void addJournalEntryFromOldToCurVal( void );
 
161
 
 
162
        inline void setFirstValue( void );
415
163
 
416
164
 
417
165
private:
423
171
        QPointer<automationPattern> m_automation_pattern;
424
172
        track * m_track;
425
173
 
426
 
        QVariant m_data;
 
174
        // most objects will need this temporarily
 
175
        T m_oldValue;
 
176
        bool m_journalEntryReady;
427
177
 
428
178
        typedef vvector<autoObj *> autoObjVector;
429
179
        autoObjVector m_linkedObjects;
430
180
 
431
 
        inline void linkObject( autoObj * _object )
432
 
        {
433
 
                if( qFind( m_linkedObjects.begin(), m_linkedObjects.end(),
434
 
                                        _object ) == m_linkedObjects.end() )
435
 
                {
436
 
                        m_linkedObjects.push_back( _object );
437
 
                }
438
 
        }
439
 
 
440
 
        inline void unlinkObject( autoObj * _object )
441
 
        {
442
 
                m_linkedObjects.erase( qFind( m_linkedObjects.begin(),
443
 
                                                m_linkedObjects.end(),
444
 
                                                _object ) );
445
 
        }
446
 
 
447
 
        static T attributeValue( QString _value );
448
 
 
449
 
        inline void syncAutomationPattern( void )
450
 
        {
451
 
                for( csize i = 0; i < m_linkedObjects.size(); ++i )
452
 
                {
453
 
                        autoObj * it = m_linkedObjects[i];
454
 
                        if( m_automation_pattern != it->m_automation_pattern )
455
 
                        {
456
 
                                it->m_automation_pattern = m_automation_pattern;
457
 
                        }
458
 
                }
459
 
        }
460
 
 
461
 
        void setLevel( int _level )
462
 
        {
463
 
                if( m_curLevel == _level )
464
 
                {
465
 
                        return;
466
 
                }
467
 
                saveJournallingState( FALSE );
468
 
                m_automation_pattern->setUpdateFirst( FALSE );
469
 
                setValue( _level * m_step );
470
 
                m_automation_pattern->setUpdateFirst( TRUE );
471
 
                restoreJournallingState();
472
 
        }
 
181
        inline void linkObject( autoObj * _object );
 
182
 
 
183
        inline void unlinkObject( autoObj * _object );
 
184
 
 
185
        static inline T attributeValue( QString _value );
 
186
 
 
187
        inline void syncAutomationPattern( void );
 
188
 
 
189
        inline void setLevel( int _level );
473
190
 
474
191
        inline int level( T _value ) const
475
192
        {
476
193
                return( (int)roundf( _value / (float)m_step ) );
477
194
        }
478
195
 
479
 
        QString levelToLabel( int _level )
 
196
        QString levelToLabel( int _level ) const
480
197
        {
481
 
                return( QString::number( _level * m_step ) );
 
198
                return( QString::number( value( _level ) ) );
482
199
        }
483
200
 
484
201
        int labelToLevel( QString _label )
490
207
 
491
208
 
492
209
 
493
 
template<>
494
 
inline float automatableObject<float>::minRelStep( void )
495
 
{
496
 
        return( 1.0e-10 );
497
 
}
498
 
 
499
 
 
500
 
 
501
 
template<>
502
 
inline float automatableObject<float>::defaultRelStep( void )
503
 
{
504
 
        return( 1.0e-2 );
505
 
}
506
 
 
507
 
 
508
 
template<>
509
 
inline float automatableObject<float>::minEps( void )
510
 
{
511
 
        return( 1.0e-10 );
512
 
}
513
 
 
514
 
 
515
 
 
516
 
template<>
517
 
inline float automatableObject<float>::attributeValue( QString _value )
518
 
{
519
 
        return( _value.toFloat() );
520
 
}
521
 
 
522
 
 
523
 
 
524
 
template<>
525
 
inline int automatableObject<int>::attributeValue( QString _value )
526
 
{
527
 
        return( _value.toInt() );
528
 
}
529
 
 
530
 
 
531
 
 
532
 
template<>
533
 
inline bool automatableObject<bool, signed char>::attributeValue(
534
 
                                                                QString _value )
535
 
{
536
 
        return( static_cast<bool>( _value.toInt() ) );
537
 
}
538
 
 
539
 
 
540
 
 
541
210
 
542
211
#endif
543
212