1 /***************************************************************************
2          SignalManager.h -  manager class for multi channel signals
3 			     -------------------
4     begin                : Sun Oct 15 2000
5     copyright            : (C) 2000 by Thomas Eschenbacher
6     email                : Thomas.Eschenbacher@gmx.de
7  ***************************************************************************/
8 
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version.                                   *
15  *                                                                         *
16  ***************************************************************************/
17 
18 #ifndef SIGNAL_MANAGER_H
19 #define SIGNAL_MANAGER_H
20 
21 #include "config.h"
22 
23 #include <QtGlobal>
24 #include <QList>
25 #include <QMap>
26 #include <QObject>
27 #include <QRecursiveMutex>
28 #include <QString>
29 
30 #include "libkwave/FileInfo.h"
31 #include "libkwave/Label.h"
32 #include "libkwave/MetaData.h"
33 #include "libkwave/MetaDataList.h"
34 #include "libkwave/PlaybackController.h"
35 #include "libkwave/ReaderMode.h"
36 #include "libkwave/Selection.h"
37 #include "libkwave/Signal.h"
38 #include "libkwave/undo/UndoManager.h"
39 
40 class QBitmap;
41 class QFile;
42 class QUrl;
43 
44 #define NEW_FILENAME i18n("New File")
45 
46 namespace Kwave
47 {
48 
49     class UndoAction;
50     class UndoInsertAction;
51     class UndoTransaction;
52     class UndoTransactionGuard;
53     class MultiTrackWriter;
54     class SampleReader;
55     class SignalWidget;
56     class Track;
57     class Writer;
58 
59     /**
60      * The SignalManager class manages multi channel signals.
61      */
62     class Q_DECL_EXPORT SignalManager: public QObject
63     {
64 	Q_OBJECT
65 
66     public:
67 	/** Default constructor. */
68 	explicit SignalManager(QWidget *parent);
69 
70 	/** Default destructor */
71 	virtual ~SignalManager();
72 
73 	/**
74 	 * Closes the current signal and loads a new file.
75 	 * @param url URL of the file to be loaded
76 	 * @return 0 if succeeded or error code < 0
77 	 */
78 	int loadFile(const QUrl &url);
79 
80 	/**
81 	 * Closes the current signal and creates a new empty signal.
82 	 * @param samples number of samples per track
83 	 * @param rate sample rate
84 	 * @param bits number of bits per sample
85 	 * @param tracks number of tracks
86 	 */
87 	void newSignal(sample_index_t samples, double rate,
88 	               unsigned int bits, unsigned int tracks);
89 
90 	/**
91 	* Closes the current signal.
92 	*/
93 	void close();
94 
95 	/** Returns true if the signal is closed */
isClosed()96 	inline bool isClosed() { return m_closed; }
97 
98 	/** Returns true if the signal is empty. */
isEmpty()99 	inline bool isEmpty() { return m_empty; }
100 
101 	/** Returns true if the signal is modified */
isModified()102 	inline bool isModified() { return m_modified; }
103 
104 	/** Returns a reference to the playback controller. */
105 	Kwave::PlaybackController &playbackController();
106 
107 	/**
108 	* Execute a Kwave text command
109 	 * @param command a text command
110 	 * @return zero if succeeded or negative error code if failed
111 	 * @retval -ENOSYS is returned if the command is unknown in this component
112 	 */
113 	int executeCommand(const QString &command);
114 
115 	/**
116 	 * Returns a reference to the current name of the signal. If no signal is
117 	 * loaded the string is zero-length.
118 	 */
119 	QString signalName();
120 
121 	/**
122 	 * Returns the current sample resolution in bits per sample
123 	 */
bits()124 	inline unsigned int bits() const {
125 	    return Kwave::FileInfo(m_meta_data).bits();
126 	}
127 
128 	/** Returns the current sample rate in samples per second */
rate()129 	inline double rate() const {
130 	    return Kwave::FileInfo(m_meta_data).rate();
131 	}
132 
133 	/** Returns the current number of tracks */
tracks()134 	inline unsigned int tracks() { return m_signal.tracks(); }
135 
136 	/**
137 	 * Returns the number of samples in the current signal. Will be
138 	 * zero if no signal is loaded.
139 	 */
length()140 	inline sample_index_t length() { return m_signal.length(); }
141 
142 	/** Returns a reference to the current selection */
selection()143 	inline Kwave::Selection &selection() { return m_selection; }
144 
145 	/**
146 	 * Returns true if a given track is selected. If the track does
147 	 * not exist or is not selected the return value is false.
148 	 */
trackSelected(unsigned int track)149 	inline bool trackSelected(unsigned int track) {
150 	    return (m_signal.trackSelected(track));
151 	}
152 
153 	/**
154 	 * Returns an array of indices of currently selected tracks.
155 	 */
156 	const QVector<unsigned int> selectedTracks();
157 
158 	/**
159 	 * Returns an array of indices of all present tracks.
160 	 */
161 	const QVector<unsigned int> allTracks();
162 
163 	/**
164 	 * Saves the signal to a file with a given resolution. If the file
165 	 * already exists, it will be overwritten.
166 	 * @param url URL with the name of the file to be saved.
167 	 * @param selection if true, only the selected range will be saved
168 	 * @return zero if succeeded or negative error code
169 	 */
170 	int save(const QUrl &url, bool selection);
171 
172 	/**
173 	 * Deletes a range of samples and creates an undo action.
174 	 * @param offset index of the first sample
175 	 * @param length number of samples
176 	 * @param track_list a list of tracks to be affected
177 	 * @return true if successful or nothing to do, false if not enough
178 	 *         memory for undo
179 	 */
180 	bool deleteRange(sample_index_t offset, sample_index_t length,
181 			 const QVector<unsigned int> &track_list);
182 
183 	/**
184 	 * Deletes a range of samples and creates an undo action. Same as
185 	 * above, but affects all tracks.
186 	 * @param offset index of the first sample
187 	 * @param length number of samples
188 	 * @return true if successful or nothing to do, false if not enough
189 	 *         memory for undo
190 	 */
191 	bool deleteRange(sample_index_t offset, sample_index_t length);
192 
193 	/**
194 	 * Inserts space at a given position and creates an undo action.
195 	 * @param offset position of the first sample to insert
196 	 * @param length number of samples
197 	 * @param track_list a list of tracks to be affected
198 	 * @return true if successful or nothing to do, false if not enough
199 	 *         memory for undo
200 	 */
201 	bool insertSpace(sample_index_t offset, sample_index_t length,
202 			 const QVector<unsigned int> &track_list);
203 
204 	/**
205 	 * Sets the current start and length of the selection to new values.
206 	 * @param offset index of the first sample
207 	 * @param length number of samples
208 	 */
209 	void selectRange(sample_index_t offset, sample_index_t length);
210 
211 	/**
212 	 * Inserts a new track with the size of the current signal after
213 	 * the last track. The same as <c>insertTrack(tracks())</c>.
214 	 */
215 	void appendTrack();
216 
217 	/**
218 	 * Inserts a new track in the current signal.
219 	 * @param index position at which the new track will be
220 	 *              inserted [0...tracks()]
221 	 */
222 	void insertTrack(unsigned int index);
223 
224 	/**
225 	 * Deletes a track from the current signal, including generation
226 	 * of an undo action.
227 	 * @param index the index of the track to be deleted [0...tracks()-1]
228 	 */
229 	void deleteTrack(unsigned int index);
230 
231 	/**
232 	 * Selects multiple tracks, all other tracks will be disabled.
233 	 * @param track_list list of track indices
234 	 */
235 	void selectTracks(QVector<unsigned int> &track_list);
236 
237 	/**
238 	 * Sets the selection flag of a track.
239 	 * @param track index of the track [0..N-1]
240 	 * @param select if true, the track will be enabled,
241 	 *               if false it will be disabled
242 	 */
243 	void selectTrack(unsigned int track, bool select);
244 
245 	/**
246 	 * Opens an output stream for a track, starting at a specified sample
247 	 * position.
248 	 * @param mode specifies where and how to insert
249 	 * @param track index of the track. If the track does not exist, this
250 	 *        function will fail and return 0
251 	 * @param left start of the input (only useful in insert and
252 	 *             overwrite mode)
253 	 * @param right end of the input (only useful with overwrite mode)
254 	 * @see InsertMode
255 	 */
256 	inline Kwave::Writer *openWriter(Kwave::InsertMode mode,
257 	    unsigned int track,
258 	    sample_index_t left = 0, sample_index_t right = 0)
259 	{
260 	    return m_signal.openWriter(mode, track, left, right);
261 	}
262 
263 	/**
264 	 * Opens a stream for reading samples. If the last position
265 	 * is omitted, the value SAMPLE_INDEX_MAX will be used.
266 	 * @param mode a reader mode, see SampleReader::Mode
267 	 * @param track index of the track. If the track does not exist, this
268 	 *        function will fail and return 0
269 	 * @param left first offset to be read (default = 0)
270 	 * @param right last position to read (default = SAMPLE_INDEX_MAX)
271 	 */
272 	inline Kwave::SampleReader *openReader(Kwave::ReaderMode mode,
273 	    unsigned int track,
274 	    sample_index_t left = 0, sample_index_t right = SAMPLE_INDEX_MAX)
275 	{
276 	    return m_signal.openReader(mode, track, left, right);
277 	}
278 
279 
280 	/**
281 	 * Get a list of stripes that matches a given range of samples
282 	 * @param track_list list with indices of tracks for selecting
283 	 * @param left  offset of the first sample
284 	 * @param right offset of the last sample (default = SAMPLE_INDEX_MAX)
285 	 * @return a list with lists of stripes that cover the given range
286 	 *         between left and right
287 	 */
288 	QList<Kwave::Stripe::List> stripes(
289 	    const QVector<unsigned int> &track_list,
290 	    sample_index_t left = 0,
291 	    sample_index_t right = SAMPLE_INDEX_MAX);
292 
293 	/**
294 	 * Merge a list of stripes into the signal.
295 	 * @note this operation works without undo!
296 	 * @param stripes list of stripe list (multi track)
297 	 * @param track_list list with indices of tracks for selecting
298 	 * @return true if succeeded, false if failed
299 	 */
300 	bool mergeStripes(const QList<Kwave::Stripe::List> &stripes,
301 			  const QVector<unsigned int> &track_list);
302 
303 	/** Returns a reference to the undo manager */
undoManager()304 	inline Kwave::UndoManager &undoManager() { return m_undo_manager; }
305 
306 	/** Returns true if undo/redo is currently enabled */
undoEnabled()307 	inline bool undoEnabled() const { return m_undo_enabled; }
308 
309 	/** Return true if undo is possible */
canUndo()310 	inline bool canUndo() const {
311 	    return !m_undo_buffer.isEmpty() && undoEnabled();
312 	}
313 
314 	/** Return true if redo is possible */
canRedo()315 	inline bool canRedo() const {
316 	    return !m_redo_buffer.isEmpty() && undoEnabled();
317 	}
318 
319 	/**
320 	 * Enables undo and redo. If undo/redo is already enabled, nothing
321 	 * will be done.
322 	 */
323 	void enableUndo();
324 
325 	/**
326 	 * Disables undo and redo. If undo/redo was enabled, all undo data
327 	 * will be discarded in order to avoid trouble when modifications
328 	 * are done while undo is of.
329 	 * @note No modifications should be performed while undo is off!
330 	 */
331 	void disableUndo();
332 
333 	/**
334 	 * Sets a complete set of file info, including undo information
335 	 * @param new_info a new FileInfo
336 	 * @param with_undo if true, store undo information
337 	 */
338 	void setFileInfo(const Kwave::FileInfo &new_info, bool with_undo);
339 
340 	/**
341 	 * add a new label, without undo
342 	 * @param pos position of the label [samples]
343 	 * @param name the name of the label
344 	 * @return a newly created label instance
345 	 */
346 	Kwave::Label addLabel(sample_index_t pos, const QString &name);
347 
348 	/**
349 	 * delete an existing label
350 	 * @param index the index of the label [0...N-1]
351 	 * @param with_undo if true, create undo info
352 	 */
353 	void deleteLabel(int index, bool with_undo);
354 
355 	/**
356 	 * modify an existing label at a given index
357 	 * (always without undo)
358 	 * @param index the index of the label [0...N-1]
359 	 * @param pos position of the label [samples]
360 	 * @param name the name of the label
361 	 * @param with_undo if true, create undo info
362 	 * @return true if succeeded, false if the index is out of range or if
363 	 *         the new position is already occupied by an existing label
364 	 */
365 	bool modifyLabel(int index, sample_index_t pos, const QString &name,
366 	                 bool with_undo);
367 
368 	/**
369 	 * Returns the index of a label, counting from zero
370 	 * @param label reference to a Label
371 	 * @return index [0...N-1] or -1 if label is a null pointer or not found
372 	 */
373 	int labelIndex(const Kwave::Label &label) const;
374 
375 	/**
376 	 * returns the label at a given exact position
377 	 * @param pos position of the label [samples]
378 	 * @return valid label at the position or null label if not found
379 	 */
380 	Kwave::Label findLabel(sample_index_t pos);
381 
382 	/**
383 	 * Retrieves the list of meta data objects, mutable
384 	 * @return list with all MetaData objects
385 	 */
metaData()386 	Kwave::MetaDataList &metaData() { return m_meta_data; }
387 
388 	/**
389 	 * Retrieves the list of meta data objects, const
390 	 * @return reference to the list of all MetaData objects
391 	 */
metaData()392 	const Kwave::MetaDataList &metaData() const { return m_meta_data; }
393 
394 	/**
395 	 * Merges a list of meta data items
396 	 * @param meta_data the meta data to merge
397 	 */
398 	void mergeMetaData(const Kwave::MetaDataList &meta_data);
399 
400 	/**
401 	 * Returns the uuid of a track
402 	 * @param track index of the track [0...tracks-1]
403 	 * @return the QUuid of the track or a "null" uuid if the track
404 	 *         does not exist
405 	 */
uuidOfTrack(unsigned int track)406 	QUuid uuidOfTrack(unsigned int track) {
407 	    return m_signal.uuidOfTrack(track);
408 	}
409 
410 	/**
411 	 * assigns a new parent widget, to be used for messages
412 	 * @param new_parent pointer to a QWidget
413 	 */
setParentWidget(QWidget * new_parent)414 	inline void setParentWidget(QWidget *new_parent) {
415 	    m_parent_widget = new_parent;
416 	}
417 
418     signals:
419 
420 	/**
421 	 * Signals a change in the range of selected samples.
422 	 * @param offset index of the first selected sample
423 	 * @param length number of selected samples
424 	 */
425 	void sigSelectionChanged(sample_index_t offset, sample_index_t length);
426 
427 	/**
428 	 * Signals that a track has been inserted.
429 	 * @param index position of the new track [0...tracks()-1]
430 	 * @param track reference to the new track
431 	 */
432 	void sigTrackInserted(unsigned int index, Kwave::Track *track);
433 
434 	/**
435 	 * Signals that a track has been deleted.
436 	 * @param index position of the deleted track [0...tracks()-1]
437 	 * @param track reference to the new track
438 	 */
439 	void sigTrackDeleted(unsigned int index, Kwave::Track *track);
440 
441 	/**
442 	 * Signals that the selection of one of the tracks has changed
443 	 * @param enabled state of the track, true=selected
444 	 */
445 	void sigTrackSelectionChanged(bool enabled);
446 
447 	/**
448 	 * Emitted if samples have been inserted into a track. This implies
449 	 * a modification of the inserted data, so no extra sigSamplesModified
450 	 * is emitted.
451 	 * @param track index of the track
452 	 * @param offset position from which the data was inserted
453 	 * @param length number of samples inserted
454 	 * @see sigSamplesModified
455 	 */
456 	void sigSamplesInserted(unsigned int track, sample_index_t offset,
457 	                        sample_index_t length);
458 
459 	/**
460 	 * Emitted if samples have been removed from a track.
461 	 * @param track index of the track
462 	 * @param offset position from which the data was removed
463 	 * @param length number of samples deleted
464 	 */
465 	void sigSamplesDeleted(unsigned int track, sample_index_t offset,
466 	                       sample_index_t length);
467 
468 	/**
469 	 * Emitted if samples within a track have been modified.
470 	 * @param track index of the track
471 	 * @param offset position from which the data was modified
472 	 * @param length number of samples modified
473 	 */
474 	void sigSamplesModified(unsigned int track, sample_index_t offset,
475 	                        sample_index_t length);
476 
477 	/**
478 	* Emitted whenever meta data has changed, after some operation
479 	 * @param meta the current meta data
480 	 */
481 	void sigMetaDataChanged(Kwave::MetaDataList meta);
482 
483 	/**
484 	 * Emitted if the state or description of undo/redo has changed. If
485 	 * undo or redo is unavailable the description will be zero.
486 	 * @see emitUndoRedoInfo
487 	 */
488 	void sigUndoRedoInfo(const QString &undo, const QString &redo);
489 
490 	/**
491 	 * Emitted if the signal changes from non-modified to modified
492 	 * state or vice-versa.
493 	 */
494 	void sigModified();
495 
496     public slots:
497 
498 	/**
499 	 * Un-does the last action if possible.
500 	 */
501 	void undo();
502 
503 	/**
504 	 * re-does the last undone action.
505 	 */
506 	void redo();
507 
508     private slots:
509 
510 	/**
511 	 * Connected to the signal's sigTrackInserted.
512 	 * @param index numeric index of the inserted track
513 	 * @param track reference to the track that has been inserted
514 	 * @see Signal::sigTrackInserted
515 	 * @internal
516 	 */
517 	void slotTrackInserted(unsigned int index, Kwave::Track *track);
518 
519 	/**
520 	 * Connected to the signal's sigTrackInserted.
521 	 * @param index numeric index of the inserted track
522 	 * @param track reference to the track that has been deleted
523 	 * @see Signal::sigTrackDeleted
524 	 * @internal
525 	 */
526 	void slotTrackDeleted(unsigned int index, Kwave::Track *track);
527 
528 	/**
529 	 * Connected to the signal's sigSamplesInserted.
530 	 * @param track index of the source track [0...tracks-1]
531 	 * @param offset position from which the data was inserted
532 	 * @param length number of samples inserted
533 	 * @see Signal::sigSamplesInserted
534 	 * @internal
535 	 */
536 	void slotSamplesInserted(unsigned int track, sample_index_t offset,
537 	                         sample_index_t length);
538 
539 	/**
540 	 * Connected to the signal's sigSamplesDeleted.
541 	 * @param track index of the source track [0...tracks-1]
542 	 * @param offset position from which the data was removed
543 	 * @param length number of samples deleted
544 	 * @see Signal::sigSamplesDeleted
545 	 * @internal
546 	 */
547 	void slotSamplesDeleted(unsigned int track, sample_index_t offset,
548 	                        sample_index_t length);
549 
550 	/**
551 	 * Connected to the signal's sigSamplesModified
552 	 * @param track index of the source track [0...tracks-1]
553 	 * @param offset position from which the data was modified
554 	 * @param length number of samples modified
555 	 * @see Signal::sigSamplesModified
556 	 * @internal
557 	 */
558 	void slotSamplesModified(unsigned int track, sample_index_t offset,
559 	                         sample_index_t length);
560 
561 	/**
562 	 * Closes an undo transaction or recurses the current recursion level
563 	 * of nested undo transactions.
564 	 */
565 	void closeUndoTransaction();
566 
567 	/**
568 	 * Determines the description of undo and redo actions and emits
569 	 * a sigUndoRedoInfo. If undo or redo is currently not available,
570 	 * the descriptions will be zero-length. If an action is available
571 	 * but does not have a description, the description will be set
572 	 * to "last action".
573 	 * @see sigUndoRedoInfo
574 	 */
575 	void emitUndoRedoInfo();
576 
577     protected:
578 
579 	friend class Kwave::UndoInsertAction;
580 
581 	/**
582 	 * Deletes a range of samples.
583 	 * @note only for internal usage in the UndoInsertAction!
584 	 * @param track index of the track
585 	 * @param offset index of the first sample
586 	 * @param length number of samples
587 	 * @see Signal::deleteRange
588 	 */
deleteRange(unsigned int track,sample_index_t offset,sample_index_t length)589 	inline void deleteRange(unsigned int track, sample_index_t offset,
590 	                        sample_index_t length)
591 	{
592 	    m_signal.deleteRange(track, offset, length);
593 	}
594 
595     protected:
596 
597 	friend class MultiTrackWriter;
598 	friend class PlaybackController;
599 	friend class PluginManager;
600 	friend class MainWidget;
601 	friend class UndoTransactionGuard;
602 
603 	/**
604 	 * Tries to free memory for a new undo action and stores all needed
605 	 * data if successful.
606 	 * @param action UndoAction to that is to be registered
607 	 * @return true if the action is allowed, false if the user has
608 	 *         chosen to abort the operation if the memory limit of
609 	 *         the undo buffer would be exceeded. The return value
610 	 *         will also be false if the action is null.
611 	 * @note If undo is currently not enabled, the passed UndoAction
612 	 *       will be ignored and not freed, the return value will
613 	 *       be false. So it is safer not to call this function if
614 	 *       undo is not enabled.
615 	 */
616 	bool registerUndoAction(Kwave::UndoAction *action);
617 
618 	/**
619 	 * Saves undo data for deleting a range of samples from a list
620 	 * of tracks.
621 	 * @param track_list list of indices of tracks
622 	 * @param offset first sample position to delete
623 	 * @param length number of samples to delete
624 	 * @return true if successful, false if out of memory or aborted
625 	 */
626 	bool saveUndoDelete(QVector<unsigned int> &track_list,
627 	                    sample_index_t offset, sample_index_t length);
628 
629 	/**
630 	 * Aborts an undo transaction by deleting all of it's undo actions.
631 	 */
632 	void abortUndoTransaction();
633 
634 	/**
635 	 * Starts an undo transaction or enters a currently running transaction
636 	 * recursively.
637 	 * @param name the name of the transaction. Will be ignored if there
638 	 *        already is an active transaction (optional)
639 	 */
640 	void startUndoTransaction(const QString &name = QString());
641 
642 	/**
643 	 * Removes all undo and redo transactions.
644 	 * @note must not be called if an undo transaction is currently active!
645 	 */
646 	void flushUndoBuffers();
647 
648 	/**
649 	 * Removes all redo transactions.
650 	 */
651 	void flushRedoBuffer();
652 
653 	/**
654 	 * Sets the modified flag to a new value if m_modified_enabled is
655 	 * true, otherwise it will be ignored.
656 	 */
657 	void setModified(bool mod);
658 
659 	/** returns the associated parent widget, to be used for messages */
parentWidget()660 	QWidget *parentWidget() const { return m_parent_widget; }
661 
662     private:
663 
664 	/**
665 	 * Ask the user if he wants to continue without undo, maybe
666 	 * registering an undo action has failed due to out-of-memory.
667 	 * @return true if it is ok, false if the user doesn't want to.
668 	 */
669 	bool continueWithoutUndo();
670 
671 	/**
672 	 * Returns the amount of memory currently used for undo + redo.
673 	 */
674 	qint64 usedUndoRedoMemory();
675 
676 	/**
677 	 * Makes sure that enough memory for a following undo (or redo) action
678 	 * is available. If necessary, it deletes old undo transactions and if
679 	 * still no enough, it also removes old redo transactions.
680 	 * @param needed the amount of memory that should be free afterwards
681 	 */
682 	void freeUndoMemory(qint64 needed);
683 
684 	/**
685 	 * Enables changes of the modified flag.
686 	 * @param en new value for m_modified_enabled
687 	 */
688 	void enableModifiedChange(bool en);
689 
690 	/** saves the current sample and track selection */
691 	void rememberCurrentSelection();
692 
693 	/**
694 	 * Check whether the selection has changed since the start of
695 	 * the last undo and create a new undo action if the selection
696 	 * has been modified (e.g. manually)
697 	 */
698 	void checkSelectionChange();
699 
700     private:
701 
702 	/** Parent widget, used for showing messages */
703 	QWidget *m_parent_widget;
704 
705 	/** true if the signal is closed */
706 	bool m_closed;
707 
708 	/** true if the signal is completely empty */
709 	bool m_empty;
710 
711 	/** true if the signal has been modified */
712 	bool m_modified;
713 
714 	/**
715 	 * If set to true, prevents the modified flag from changes. Useful
716 	 * to prevent setting the modified flag during file load and creation,
717 	 * or if the change to the non-modified state through undo operations
718 	 * is no longer possible.
719 	 */
720 	bool m_modified_enabled;
721 
722 	/** signal with multiple tracks */
723 	Kwave::Signal m_signal;
724 
725 	/** the current selection */
726 	Kwave::Selection m_selection;
727 
728 	/** the last selection (stored in undo) */
729 	Kwave::Selection m_last_selection;
730 
731 	/** the last track selection (stored in undo) */
732 	QVector <unsigned int> m_last_track_selection;
733 
734 	/**
735 	 * Last known length of the signal. This will be used if a track is
736 	 * added to an empty signal and prevents from the creation of a
737 	 * completely empty new signal.
738 	 */
739 	sample_index_t m_last_length;
740 
741 	/** the controller for handling of playback */
742 	Kwave::PlaybackController m_playback_controller;
743 
744 	/** flag for "undo enabled" */
745 	bool m_undo_enabled;
746 
747 	/** fifo used for storing all undo transactions */
748 	QList<Kwave::UndoTransaction *> m_undo_buffer;
749 
750 	/** fifo for storing all redo transactions */
751 	QList<Kwave::UndoTransaction *> m_redo_buffer;
752 
753 	/** the current undo transaction */
754 	Kwave::UndoTransaction *m_undo_transaction;
755 
756 	/** level of nested undo transactions */
757 	unsigned int m_undo_transaction_level;
758 
759 	/** mutex for locking undo transactions */
760 	QRecursiveMutex m_undo_transaction_lock;
761 
762 	/** Manager for undo/redo actions */
763 	Kwave::UndoManager m_undo_manager;
764 
765 	/**
766 	 * meta data of the signal
767 	 * @see class MetaData
768 	 */
769 	Kwave::MetaDataList m_meta_data;
770 
771     };
772 }
773 
774 #endif  /* SIGNAL_MANAGER_H */
775 
776 //***************************************************************************
777 //***************************************************************************
778