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