File: Track.h

package info (click to toggle)
kwave 25.04.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 23,272 kB
  • sloc: cpp: 56,173; xml: 817; perl: 688; sh: 57; makefile: 11
file content (328 lines) | stat: -rw-r--r-- 12,204 bytes parent folder | download
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 */

//***************************************************************************
//***************************************************************************