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
|
/***************************************************************************
Track.h - collects one or more stripes in one track
-------------------
begin : Feb 09 2001
copyright : (C) 2001 by Thomas Eschenbacher
email : Thomas Eschenbacher <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 TRACK_H
#define TRACK_H
#include "config.h"
#include "libkwave_export.h"
#include <vector>
#include <QtGlobal>
#include <QObject>
#include <QReadWriteLock>
#include <QRecursiveMutex>
#include <QUuid>
#include "libkwave/InsertMode.h"
#include "libkwave/ReaderMode.h"
#include "libkwave/SampleArray.h"
#include "libkwave/Stripe.h"
//***************************************************************************
namespace Kwave
{
class SampleReader;
class TrackWriter;
class Writer;
class LIBKWAVE_EXPORT Track: public QObject
{
Q_OBJECT
public:
/**
* Default constructor. Creates a new and empty track with
* zero-length, no stripes and new uuid
*/
Track();
/**
* Constructor. Creates an empty track with a specified length.
* @param length the length in samples
* @param uuid unique ID of the track, can be null
*/
Track(sample_index_t length, QUuid *uuid);
/**
* Destructor.
*/
virtual ~Track() override;
/**
* Returns the length of the track. This is equivalent
* to the position of the last sample of the last Stripe.
*/
sample_index_t length();
/**
* Opens a stream for writing samples, starting at a
* sample position.
* @param mode specifies where and how to insert
* @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
* @note destruction of the writer triggers defragmentation
*/
Kwave::Writer *openWriter(Kwave::InsertMode mode,
sample_index_t left = 0,
sample_index_t right = 0);
/**
* Opens a stream for reading samples. If the last position
* is omitted, the value SAMPLE_INDEX_MAX will be used.
* @param mode read mode, see Kwave::ReaderMode
* @param left first offset to be read (default = 0)
* @param right last position to read (default = SAMPLE_INDEX_MAX)
*/
Kwave::SampleReader *openReader(Kwave::ReaderMode mode,
sample_index_t left = 0,
sample_index_t right = SAMPLE_INDEX_MAX);
/**
* Get a list of stripes that matches a given range of samples
* @param left offset of the first sample
* @param right offset of the last sample
* @return a list of stripes that cover the given range
* between left and right
*/
Kwave::Stripe::List stripes(sample_index_t left,
sample_index_t right);
/**
* Merge a list of stripes into the track.
* @param stripes list of stripes
* @return true if succeeded, false if failed
* @note triggers a defragmentation
*/
bool mergeStripes(const Kwave::Stripe::List &stripes);
/**
* Deletes a range of samples
* @param offset index of the first sample
* @param length number of samples
* @param make_gap if true, make a gap into the list of stripes
* instead of moving the stuff from right to left
* @note triggers a defragmentation if make_gap is false
*/
void deleteRange(sample_index_t offset, sample_index_t length,
bool make_gap = false);
/**
* Inserts space at a given offset by moving all stripes that are
* are starting at or after the given offset right.
*
* @param offset position after which everything is moved right
* @param shift distance of the shift [samples]
* @return true if succeeded, false if failed (OOM?)
*/
bool insertSpace(sample_index_t offset, sample_index_t shift);
/** Returns the "selected" flag. */
inline bool selected() const { return m_selected; }
/** Sets the "selected" flag. */
void select(bool select);
/** returns the unique ID of this track instance */
const QUuid &uuid() const { return m_uuid; }
public slots:
/** toggles the selection of the slot on/off */
void toggleSelection();
/** do some defragmentation of stripes */
void defragment();
signals:
/**
* Emitted if the track has grown. This implies a modification of
* the inserted data, so no extra sigSamplesModified is emitted.
* @param src source track of the signal (*this)
* @param offset position from which the data was inserted
* @param length number of samples inserted
* @see sigSamplesModified
*/
void sigSamplesInserted(Kwave::Track *src, sample_index_t offset,
sample_index_t length);
/**
* Emitted if data has been removed from the track.
* @param src source track of the signal (*this)
* @param offset position from which the data was removed
* @param length number of samples deleted
*/
void sigSamplesDeleted(Kwave::Track *src, sample_index_t offset,
sample_index_t length);
/**
* Emitted if some data within the track has been modified.
* @param src source track of the signal (*this)
* @param offset position from which the data was modified
* @param length number of samples modified
*/
void sigSamplesModified(Kwave::Track *src, sample_index_t offset,
sample_index_t length);
/**
* Emitted whenever the selection of the track has changed.
* @param selected true if selected, false if unselected
*/
void sigSelectionChanged(bool selected);
private:
/**
* Returns the current length of the stripe in samples. This
* function uses no locks and is therefore reserved for internal
* usage from within locked functions.
* @note this must be private, it does no locking !
*/
sample_index_t unlockedLength();
/**
* Deletes a range of samples, used internally by deleteRange()
* @param offset index of the first sample
* @param length number of samples
* @param make_gap if true, make a gap into the list of stripes
* instead of moving the stuff from right to left
*/
void unlockedDelete(sample_index_t offset, sample_index_t length,
bool make_gap = false);
/**
* Append samples after a given stripe.
*
* @param stripe the stripe after which to instert. Null pointer is
* allowed, in this case a new stripe is created
* @param offset position where the new data should start
* @param buffer array with samples
* @param buf_offset offset within the buffer
* @param length number of samples to write
* @return true if successful, false if failed (e.g. out of memory)
*/
bool appendAfter(Stripe *stripe, sample_index_t offset,
const Kwave::SampleArray &buffer,
unsigned int buf_offset, unsigned int length);
/**
* Move all stripes after an offset to the right. Only looks at the
* start position of the stripes, comparing with ">=", if the start
* of a stripe is at the given offset, it will not be moved!
*
* @param offset position after which everything is moved right
* @param shift distance of the shift [samples]
*/
void moveRight(sample_index_t offset, sample_index_t shift);
/**
* Append a new stripe with a given length.
*
* @param length number of samples, zero is allowed
*/
void appendStripe(sample_index_t length);
/**
* Split a stripe into two stripes. The new stripe will be created
* from the right portion of the given stripe and the original
* stripe will be shrinked to it's new size. The newly created stripe
* will be inserted into m_stripes after the old one.
*
* @param stripe the stripe to be split
* @param offset the offset within the stripe, which becomes the first
* sample in the new stripe
* @return the new created stripe
*/
Stripe splitStripe(Stripe &stripe, unsigned int offset);
/**
* Merge a single stripe into the track.
*
* @param stripe the stripe to merge
* @return true if succeeded, false if failed
*/
bool mergeStripe(Kwave::Stripe &stripe);
/**
* dump the list of stripes, for debugging
* @internal for debugging only
*/
void dump();
protected:
friend class Kwave::TrackWriter;
/**
* Write a block of samples. If necessary it starts, appends to,
* or splits a stripe.
*
* @param mode a InsertMode (append/overwrite/insert)
* @param offset position where to start the write operation
* @param buffer array with samples
* @param buf_offset offset within the buffer
* @param length number of samples to write
* @return true if successful, false if failed (e.g. out of memory)
*/
bool writeSamples(Kwave::InsertMode mode,
sample_index_t offset,
const Kwave::SampleArray &buffer,
unsigned int buf_offset,
unsigned int length);
/** increments the usage counter (read lock to m_lock_usage) */
void use();
/** decrements the usage counter (read lock to m_lock_usage) */
void release();
private:
/**
* Creates a new stripe with a start position and a length.
* @param start offset of the first sample
* @param length number of samples, zero is allowed
* @note this must be private, it does no locking !
*/
Stripe *newStripe(sample_index_t start, unsigned int length);
private:
/** lock for access to the whole track */
QRecursiveMutex m_lock;
/** lock to protect against deletion while the track is in use */
QReadWriteLock m_lock_usage;
/** list of stripes (a track actually is a container for stripes) */
std::vector<Stripe> m_stripes;
/** True if the track is selected */
bool m_selected;
/** unique ID */
QUuid m_uuid;
};
}
#endif /* TRACK_H */
//***************************************************************************
//***************************************************************************
|