kwave  18.07.70
Track.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  Track.cpp - collects one or more stripes in one track
3  -------------------
4  begin : Feb 10 2001
5  copyright : (C) 2001 by Thomas Eschenbacher
6  email : Thomas Eschenbacher <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 #include "config.h"
19 
20 #include <new>
21 
22 #include <QMutexLocker>
23 #include <QReadLocker>
24 #include <QWriteLocker>
25 
26 #include "libkwave/SampleReader.h"
27 #include "libkwave/Stripe.h"
28 #include "libkwave/Track.h"
29 #include "libkwave/TrackWriter.h"
30 #include "libkwave/Utils.h"
31 #include "libkwave/Writer.h"
32 
37 #define STRIPE_LENGTH_OPTIMAL (4UL * 1024UL * 1024UL) /* 16MB */
38 
46 #define STRIPE_LENGTH_MAXIMUM (STRIPE_LENGTH_OPTIMAL * 2)
47 
55 #define STRIPE_LENGTH_MINIMUM (STRIPE_LENGTH_OPTIMAL / 2)
56 
57 //***************************************************************************
59  :m_lock(QMutex::Recursive), m_lock_usage(), m_stripes(), m_selected(true),
60  m_uuid(QUuid::createUuid())
61 {
62 }
63 
64 //***************************************************************************
66  :m_lock(QMutex::Recursive), m_lock_usage(), m_stripes(), m_selected(true),
67  m_uuid((uuid) ? *uuid : QUuid::createUuid())
68 {
69  if (length < STRIPE_LENGTH_MAXIMUM) {
70  if (length) appendStripe(length);
71  } else {
72  Stripe s(length - STRIPE_LENGTH_OPTIMAL);
74  if (s.length()) m_stripes.append(s);
75  }
76 }
77 
78 //***************************************************************************
80 {
81  // wait until all readers are finished
82  QWriteLocker lock_usage(&m_lock_usage);
83 
84  // don't allow any further operation
85  QMutexLocker lock(&m_lock);
86 
87  // delete all stripes
88  m_stripes.clear();
89 }
90 
91 //***************************************************************************
93 {
95  do {
96  unsigned int len = Kwave::toUint(
97  qMin<sample_index_t>(STRIPE_LENGTH_MAXIMUM, length));
98 
99  Stripe s(start);
100  s.resize(len);
101  if (len) emit sigSamplesInserted(this, start, len);
102 
103  length -= len;
104  start += len;
105  m_stripes.append(s);
106  } while (length);
107 
108 }
109 
110 //***************************************************************************
112  unsigned int offset)
113 {
114  Q_ASSERT(offset < stripe.length());
115  Q_ASSERT(offset);
116  if (offset >= stripe.length()) return Stripe();
117  if (!offset) return 0;
118 
119  // create a new stripe with the data that has been split off
120  Stripe s(stripe.start() + offset, stripe, offset);
121  if (!s.length()) return Stripe();
122 
123  // shrink the old stripe
124  stripe.resize(offset);
125 
126 // qDebug("Kwave::Track::splitStripe(%p, %u): new stripe at [%u ... %u] (%u)",
127 // stripe, offset, s->start(), s->end(), s->length());
128 
129  return s;
130 }
131 
132 //***************************************************************************
134 {
135  sample_index_t left = stripe.start();
136  sample_index_t right = stripe.end();
137  int index_before = -1;
138 
139 // qDebug("Track::mergeStripe() [%llu - %llu]", left, right);
140 // dump();
141 
142  // remove all stripes that are overlapped completely by
143  // this stripe and crop stripes that overlap partially
144  unlockedDelete(left, right - left + 1, true);
145 
146 // qDebug("Track::mergeStripe() [%llu - %llu] - after delete", left, right);
147 // dump();
148 
149  // find the stripe after which we have to insert
150  QListIterator<Stripe> it(m_stripes);
151  while (it.hasNext()) {
152  const Stripe &s = it.next();
153  if (left > s.end()) index_before = m_stripes.indexOf(s);
154  }
155 
156  if (index_before >= 0) {
157  // insert after some existing stripe
158 // qDebug("Kwave::Track::mergeStripe: insert after index %d",
159 // index_before);
160  m_stripes.insert(index_before + 1, stripe);
161  } else {
162  // the one and only or insert before all others
163 // qDebug("Kwave::Track::mergeStripe: prepending");
164  m_stripes.prepend(stripe);
165  }
166 
167 // qDebug("Track::mergeStripe() - done");
168 // dump();
169  return true;
170 }
171 
172 //***************************************************************************
174 {
175  QMutexLocker lock(&m_lock);
176  return unlockedLength();
177 }
178 
179 //***************************************************************************
181 {
182  if (m_stripes.isEmpty()) return 0;
183  const Stripe &s = m_stripes.last();
184  return s.start() + s.length();
185 }
186 
187 //***************************************************************************
189  sample_index_t left,
190  sample_index_t right)
191 {
192  // create the input stream
193  Kwave::Writer *stream =
194  new(std::nothrow) Kwave::TrackWriter(*this, mode, left, right);
195  Q_ASSERT(stream);
196 
197  if (stream) {
198  // at the point of time when the writer gets closed we can take
199  // care of fragmentation
200  connect(stream, SIGNAL(destroyed(QObject*)),
201  this, SLOT(defragment()),
202  Qt::DirectConnection);
203  }
204 
205  return stream;
206 }
207 
208 //***************************************************************************
210  sample_index_t right)
211 {
212  QMutexLocker lock(&m_lock);
213 
214  // collect all stripes that are in the requested range
215  Kwave::Stripe::List stripes(left, right);
216  foreach (const Stripe &stripe, m_stripes) {
217  if (!stripe.length()) continue;
218  sample_index_t start = stripe.start();
219  sample_index_t end = stripe.end();
220 
221  if (end < left) continue; // not yet in range
222  if (start > right) break; // done
223 
224  if ((end <= right) && (start >= left)) {
225  // append the stripe as it is, unmodified
226  stripes.append(stripe);
227  continue;
228  }
229 
230  // there is only some overlap, no 100% match
231  // -> make a cropped copy
232  Stripe cropped(stripe);
233 
234  // remove data after the end of the selection
235  if (end > right)
236  cropped.resize(Kwave::toUint(cropped.length() - (end - right)));
237 
238  // remove data before the start of the selection
239  if (start < left) {
240  cropped.deleteRange(0, Kwave::toUint(left - start));
241  cropped.setStart(left);
242  }
243 
244  stripes.append(cropped);
245  }
246 
247  return stripes;
248 }
249 
250 //***************************************************************************
252 {
253  bool succeeded = true;
254  {
255  QMutexLocker lock(&m_lock);
256  foreach (Stripe stripe, stripes) {
257  if (!mergeStripe(stripe)) {
258  succeeded = false;
259  break;
260  }
261  }
262  }
263 
264  // do some defragmentation, to combine the ends of the inserted stripes
265  defragment();
266 
267  const sample_index_t left = stripes.left();
268  const sample_index_t right = stripes.right();
269  emit sigSamplesModified(this, left, right - left + 1);
270  return succeeded;
271 }
272 
273 //***************************************************************************
275  sample_index_t left, sample_index_t right)
276 {
277  QMutexLocker lock(&m_lock);
278 
280  if (right >= length) right = (length) ? (length - 1) : 0;
281 
282  // collect all stripes that are in the requested range
283  Kwave::Stripe::List stripe_list = stripes(left, right);
284 
285  // create the input stream
286  Kwave::SampleReader *stream =
287  new(std::nothrow) Kwave::SampleReader(mode, stripe_list);
288  Q_ASSERT(stream);
289  return stream;
290 }
291 
292 //***************************************************************************
294  bool make_gap)
295 {
296  if (!length) return;
297 
298 // qDebug("Kwave::Track::deleteRange() [%u ... %u] (%u)",
299 // offset, offset + length - 1, length);
300 
301  {
302  QMutexLocker lock(&m_lock);
303  unlockedDelete(offset, length, make_gap);
304  }
305 
306  // deletion without gap might have left some fragments
307  if (!make_gap)
308  defragment();
309 
310  emit sigSamplesDeleted(this, offset, length);
311 }
312 
313 //***************************************************************************
315 {
316 // qDebug("Kwave::Track::insertSpace(offset=%u,shift=%u)",offset, shift);
317  if (!shift) return true;
318 
319  {
320  QMutexLocker lock(&m_lock);
322  if (offset < len) {
323  // find out whether the offset is within a stripe and
324  // split that one if necessary
325  QMutableListIterator<Stripe> it(m_stripes);
326  while (it.hasNext()) {
327  Stripe &s = it.next();
328  sample_index_t end = s.end();
329  if (end < offset) continue; // skip, stripe is at left
330 
331  sample_index_t start = s.start();
332  if (start >= offset) break; // not "within" the stripe
333 
334 // qDebug("Kwave::Track::insertSpace => splitting [%u...%u]",start,end);
335  Stripe new_stripe = splitStripe(s,
336  Kwave::toUint(offset - start)
337  );
338  if (!new_stripe.length()) return false; // OOM ?
339  it.insert(new_stripe);
340  break;
341  }
342 
343  // move all stripes that are after the offset right
344 // qDebug("Kwave::Track::insertSpace => moving right");
345  moveRight(offset, shift);
346  } else {
347 // qDebug("Kwave::Track::insertSpace => appending stripe at %u", offset + shift - 1);
348  Stripe s(offset + shift - 1);
349  s.resize(1);
350  if (s.length()) m_stripes.append(s);
351  }
352  }
353 
354 // dump();
355  emit sigSamplesInserted(this, offset, shift);
356  return true;
357 }
358 
359 //***************************************************************************
361  bool make_gap)
362 {
363  if (!length) return;
364 
365  // add all stripes within the specified range to the list
366  sample_index_t left = offset;
367  sample_index_t right = offset + length - 1;
368 
369  QMutableListIterator<Stripe> it(m_stripes);
370  it.toBack();
371  while (it.hasPrevious()) {
372  Stripe &s = it.previous();
373  sample_index_t start = s.start();
374  sample_index_t end = s.end();
375 
376  if (end < left) break; // done, stripe is at left
377  if (start > right) continue; // skip, stripe is at right
378 
379  if ((left <= start) && (right >= end)) {
380  // case #1: total overlap -> delete whole stripe
381 // qDebug("deleting stripe [%u ... %u]", start, end);
382  it.remove(); // decrements the iterator !!!
383  if (m_stripes.isEmpty()) break;
384  continue;
385  } else /* if ((end >= left) && (start <= right)) */ {
386  // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
387  // already checked above
388  // partial stripe overlap
389  sample_index_t ofs = (start < left) ? left : start;
390  if (end > right) end = right;
391 // qDebug("deleting [%u ... %u] (start=%u, ofs-start=%u, len=%u)",
392 // ofs, end, start, ofs-start, end - ofs + 1);
393 
394  if (!make_gap ||
395  ((left <= s.start()) && (right < s.end())) ||
396  ((left > s.start()) && (right >= s.end())))
397  {
398  // case #2: delete without creating a gap
399  // case #3: delete from the left only
400  // case #4: delete from the right only
401 // qDebug(" deleting within the stripe");
402  s.deleteRange(
403  Kwave::toUint(ofs - start),
404  Kwave::toUint(end - ofs + 1)
405  );
406  if (!s.length()) break; // OOM ?
407 
408  // if deleted from start
409  if (left <= s.start()) {
410  // move right, producing a (temporary) gap
411 // qDebug("shifting [%u ... %u] to %u",
412 // start, s.end(), end + 1);
413  s.setStart(end + 1);
414  }
415  } else {
416  // case #5: delete from the middle and produce a gap
417  // by splitting off a new stripe
418 // qDebug(" splitting off to new stripe @ %u (ofs=%u)",
419 // right + 1, right + 1 - start);
420  Stripe new_stripe = splitStripe(s,
421  Kwave::toUint(right + 1 - start));
422  if (!new_stripe.length()) break; // OOM ?
423  it.next(); // right after "s"
424  it.insert(new_stripe);
425  it.previous(); // before new_stripe == after s
426  it.previous(); // before s, like
427 
428  // erase to the end (reduce size)
429  const unsigned int todel = Kwave::toUint(s.end() - ofs + 1);
430 // qDebug("ofs-start=%u, s->end()-ofs+1=%u [%u...%u] (%u)",
431 // ofs-start, todel, s.start(), s.end(), s.length());
432  s.deleteRange(Kwave::toUint(ofs - start), todel);
433 // qDebug("length now: %u [%u ... %u]", s.length(),
434 // s.start(), s.end());
435 // Q_ASSERT(s.length());
436  }
437 // Q_ASSERT(s.length());
438  }
439  }
440 
441  // loop over all remaining stripes and move them left
442  // (maybe we start the search one stripe too left,
443  // but this doesn't matter, we don't care...)
444  if (!make_gap) {
445  if (!it.hasNext()) it.toFront();
446 
447  while (it.hasNext()) {
448  Stripe &s = it.next();
449 // qDebug("checking for shift [%u ... %u]",
450 // s.start(), s.end());
451  Q_ASSERT(s.start() != right);
452  if (s.start() > right) {
453  // move left
454 // qDebug("moving stripe %p [%u...%u] %u samples left",
455 // s, s.start(), s.end(), length);
456  Q_ASSERT(s.start() >= length);
457  s.setStart(s.start() - length);
458  }
459  }
460  }
461 }
462 
463 //***************************************************************************
465 {
466  if (m_selected == selected) return;
469 }
470 
471 //***************************************************************************
473 {
474  select(!selected());
475 }
476 
477 //***************************************************************************
479  const Kwave::SampleArray &buffer,
480  unsigned int buf_offset, unsigned int length)
481 {
482  Q_ASSERT(buf_offset + length <= buffer.size());
483  if (buf_offset + length > buffer.size()) return false;
484 
485  // append to the last stripe if one exists and it's not full
486  // and the offset is immediately after the last stripe
487  if ((stripe) && (stripe->end()+1 == offset) &&
488  (stripe->length() < STRIPE_LENGTH_MAXIMUM))
489  {
490  unsigned int len = length;
491  if (len + stripe->length() > STRIPE_LENGTH_MAXIMUM)
492  len = STRIPE_LENGTH_MAXIMUM - stripe->length();
493 
494 // qDebug("Kwave::Track::appendAfter(): appending %u samples to %p",
495 // len, stripe);
496  if (!stripe->append(buffer, buf_offset, len))
497  return false; // out of memory
498 
499  offset += len;
500  length -= len;
501  buf_offset += len;
502  }
503 
504  int index_before = (stripe) ? (m_stripes.indexOf(*stripe)) : -1;
505 
506  // append new stripes as long as there is something remaining
507  while (length) {
508  unsigned int len = Kwave::toUint(qMin<sample_index_t>(
509  length, STRIPE_LENGTH_MAXIMUM));
510 
511 // qDebug("Kwave::Track::appendAfter: new stripe, ofs=%u, len=%u",
512 // offset, len);
513  Stripe new_stripe(offset);
514 
515  // append to the new stripe
516  if (!new_stripe.append(buffer, buf_offset, len)) {
517  qWarning("Kwave::Track::appendAfter FAILED / OOM");
518  return false; /* out of memory */
519  }
520  Q_ASSERT(new_stripe.length() == len);
521 
522 // qDebug("new stripe: [%u ... %u] (%u)", new_stripe->start(),
523 // new_stripe->end(), new_stripe->length());
524 
525  if (index_before >= 0) {
526  // insert after the last one
527  index_before++;
528 // qDebug("Kwave::Track::appendAfter: insert after %p [%10u - %10u]",
529 // stripe, stripe->start(), stripe->end());
530  m_stripes.insert(index_before, new_stripe);
531  } else {
532  // the one and only or insert before all others
533 // qDebug("Kwave::Track::appendAfter: prepending");
534  m_stripes.prepend(new_stripe);
535  index_before = 0;
536  }
537  offset += len;
538  length -= len;
539  buf_offset += len;
540  }
541 
542  return true;
543 }
544 
545 //***************************************************************************
547 {
548  if (m_stripes.isEmpty()) return;
549  QMutableListIterator<Stripe> it(m_stripes);
550  it.toBack();
551  while (it.hasPrevious()) {
552  Stripe &s = it.previous();
553  sample_index_t start = s.start();
554  if (start < offset) break;
555 
556  s.setStart(start + shift);
557  }
558 }
559 
560 //***************************************************************************
562  sample_index_t offset,
563  const Kwave::SampleArray &buffer,
564  unsigned int buf_offset,
565  unsigned int length)
566 {
567  Q_ASSERT(length);
568  if (!length) return true; // nothing to do !?
569 
570  switch (mode) {
571  case Kwave::Append: {
572 // qDebug("writeSamples() - Append");
573  bool appended;
574  {
575  QMutexLocker _lock(&m_lock);
576  appended = appendAfter(
577  m_stripes.isEmpty() ? Q_NULLPTR : &(m_stripes.last()),
578  offset, buffer,
579  buf_offset, length);
580  }
581  if (appended)
582  emit sigSamplesInserted(this, offset, length);
583  else
584  return false; /* out of memory */
585  break;
586  }
587  case Kwave::Insert: {
588  m_lock.lock();
589 
590 // qDebug("Kwave::Track::writeSamples() - Insert @ %u, length=%u",
591 // offset, length);
592 
593  // find the stripe into which we insert
594  Stripe *target_stripe = Q_NULLPTR;
595  Stripe *stripe_before = Q_NULLPTR;
596  QMutableListIterator<Stripe> it(m_stripes);
597  while (it.hasNext()) {
598  Stripe &s = it.next();
599  sample_index_t st = s.start();
600  sample_index_t len = s.length();
601  if (!len) continue; // skip zero-length tracks
602 
603  if (offset >= st + len) stripe_before = &s;
604 
605  if ((offset >= st) && (offset < st+len)) {
606  // match found
607  target_stripe = &s;
608  break;
609  }
610  }
611 
612 // qDebug("stripe_before = %p [%u...%u]", stripe_before,
613 // stripe_before ? stripe_before->start() : 0,
614 // stripe_before ? (stripe_before->start() +
615 // stripe_before->length() - 1) : 0);
616 // qDebug("target_stripe = %p [%u...%u]", target_stripe,
617 // target_stripe ? target_stripe->start() : 0,
618 // target_stripe ? (target_stripe->start() +
619 // target_stripe->length() - 1) : 0);
620 
621  // if insert is requested immediately after the last
622  // sample of the stripe before
623  if (stripe_before && (offset == stripe_before->start()+
624  stripe_before->length()))
625  {
626  // append to the existing stripe
627  moveRight(offset, length);
628  appendAfter(stripe_before, offset, buffer,
629  buf_offset, length);
630  m_lock.unlock();
631  emit sigSamplesInserted(this, offset, length);
632  break;
633  }
634 
635  // if no stripe was found, create a new one and
636  // insert it between the existing ones
637  if (!target_stripe || (offset == target_stripe->start())) {
638  // insert somewhere before, between or after stripes
639  moveRight(offset, length);
640  appendAfter(stripe_before, offset, buffer,
641  buf_offset, length);
642  } else {
643  // split the target stripe and insert the samples
644  // between the two new ones
645  Stripe new_stripe = splitStripe(*target_stripe,
646  Kwave::toUint(offset - target_stripe->start())
647  );
648  if (!new_stripe.length()) {
649  m_lock.unlock();
650  break;
651  }
652  m_stripes.insert(m_stripes.indexOf(*target_stripe) + 1,
653  new_stripe);
654 
655  moveRight(offset, length);
656  appendAfter(target_stripe, offset, buffer,
657  buf_offset, length);
658  }
659 
660  m_lock.unlock();
661  emit sigSamplesInserted(this, offset, length);
662 
663  break;
664  }
665  case Kwave::Overwrite: {
666 // const sample_index_t left = offset;
667 // const sample_index_t right = offset + length - 1;
668 // qDebug("writeSamples() - Overwrite [%u - %u]", left, right);
669 
670  {
671  QMutexLocker _lock(&m_lock);
672 
673  // delete old content, producing a gap
674  unlockedDelete(offset, length, true);
675 
676  // fill in the content of the buffer, append to the stripe
677  // before the gap if possible
678  Stripe *stripe_before = Q_NULLPTR;
679  QMutableListIterator<Stripe> it(m_stripes);
680  while (it.hasNext()) {
681  Stripe &s = it.next();
682  if (s.start() >= offset) break;
683  if (s.end() < offset) stripe_before = &s;
684  }
685  appendAfter(stripe_before, offset, buffer, buf_offset, length);
686  }
687  emit sigSamplesModified(this, offset, length);
688  break;
689  }
690  }
691 
692  return true;
693 }
694 
695 //***************************************************************************
697 {
698 
699  if (!m_lock.tryLock()) {
700  // this could happen when there are two or more writers
701 // qDebug("Track::defragment() - busy");
702  return;
703  }
704 
705  if (m_stripes.count() > 1)
706  {
707 // qDebug("Track::defragment(), state before:");
708 // dump();
709 
710 // unsigned int index = 0;
711  Kwave::Stripe *before = Q_NULLPTR;
712  Kwave::Stripe *stripe = Q_NULLPTR;
713 
714  // use a quick and simple algorithm:
715  // iterate over all stripes and analyze pairwise
716  QMutableListIterator<Kwave::Stripe> it(m_stripes);
717  while (it.hasNext()) {
718  before = stripe;
719  stripe = &(it.next());
720  if (!before) continue; // skip the first entry
721 // index++;
722 
723 // qDebug("Track::defragment(), checking #%u [%llu..%llu] (%u)",
724 // index, stripe->start(), stripe->end(), stripe->length());
725 
726  const sample_index_t before_start = before->start();
727  const sample_index_t stripe_end = stripe->end();
728  const sample_index_t combined_len = stripe_end - before_start + 1;
729 
730  if (combined_len > STRIPE_LENGTH_MAXIMUM)
731  continue; // would be too large
732 
733  if ((before->length() < STRIPE_LENGTH_MINIMUM) ||
734  (stripe->length() < STRIPE_LENGTH_MINIMUM)) {
735 // qDebug("Track::defragment(), combine #%u [%llu..%llu] & "
736 // "#%u [%llu..%llu] => [%llu..%llu] (%llu)",
737 // index - 1, before->start(), before->end(),
738 // index, stripe->start(), stripe->end(),
739 // before->start(), stripe->end(), combined_len);
740 
741  // try to resize the stripe before to contain the
742  // combined length
743  const unsigned int offset = Kwave::toUint(
744  stripe->start() - before_start);
745  if (!before->combine(offset, *stripe))
746  continue; // not possible, maybe OOM ?
747 
748  // remove the current stripe, to avoid an overlap
749  it.remove();
750  stripe = before;
751 // index--;
752  }
753  }
754 
755 // qDebug("Track::defragment(), state after:");
756 // dump();
757  }
758 
759  m_lock.unlock();
760 }
761 
762 //***************************************************************************
764 {
765  m_lock_usage.lockForRead();
766 }
767 
768 //***************************************************************************
770 {
771  m_lock_usage.unlock();
772 }
773 
774 //***************************************************************************
776 {
777  qDebug("------------------------------------");
778  unsigned int index = 0;
779  sample_index_t last_end = 0;
780  foreach (const Stripe &s, m_stripes) {
781  sample_index_t start = s.start();
782  if (index && (start <= last_end))
783  qDebug("--- OVERLAP ---");
784  if (start > last_end+1)
785  qDebug(" : GAP [%10lu - %10lu] (%10lu)",
786  static_cast<unsigned long int>(last_end + ((index) ? 1 : 0)),
787  static_cast<unsigned long int>(start - 1),
788  static_cast<unsigned long int>(start - last_end -
789  ((index) ? 1 : 0)));
790  qDebug("#%6d: %p - [%10lu - %10lu] (%10lu)",
791  index++, static_cast<const void *>(&s),
792  static_cast<unsigned long int>(s.start()),
793  static_cast<unsigned long int>(s.end()),
794  static_cast<unsigned long int>(s.length()));
795  last_end = s.end();
796  }
797  qDebug("------------------------------------");
798 }
799 
800 //***************************************************************************
801 //***************************************************************************
bool combine(unsigned int offset, Kwave::Stripe &other)
Definition: Stripe.cpp:457
bool selected() const
Definition: Track.h:137
unsigned int append(const Kwave::SampleArray &samples, unsigned int offset, unsigned int count)
Definition: Stripe.cpp:381
QMutex m_lock
Definition: Track.h:308
QUuid m_uuid
Definition: Track.h:320
unsigned int length() const
Definition: Stripe.cpp:276
void deleteRange(sample_index_t offset, sample_index_t length, bool make_gap=false)
Definition: Track.cpp:293
ReaderMode
Definition: ReaderMode.h:27
sample_index_t left() const
Definition: Stripe.h:214
void sigSamplesInserted(Kwave::Track *src, sample_index_t offset, sample_index_t length)
void defragment()
Definition: Track.cpp:696
QList< Stripe > m_stripes
Definition: Track.h:314
const QUuid & uuid() const
Definition: Track.h:143
bool appendAfter(Stripe *stripe, sample_index_t offset, const Kwave::SampleArray &buffer, unsigned int buf_offset, unsigned int length)
Definition: Track.cpp:478
sample_index_t right() const
Definition: Stripe.h:217
void use()
Definition: Track.cpp:763
Stripe splitStripe(Stripe &stripe, unsigned int offset)
Definition: Track.cpp:111
Kwave::SampleReader * openReader(Kwave::ReaderMode mode, sample_index_t left=0, sample_index_t right=SAMPLE_INDEX_MAX)
Definition: Track.cpp:274
quint64 sample_index_t
Definition: Sample.h:28
bool mergeStripes(const Kwave::Stripe::List &stripes)
Definition: Track.cpp:251
void toggleSelection()
Definition: Track.cpp:472
sample_index_t unlockedLength()
Definition: Track.cpp:180
bool insertSpace(sample_index_t offset, sample_index_t shift)
Definition: Track.cpp:314
bool connect(Kwave::StreamObject &source, const char *output, Kwave::StreamObject &sink, const char *input)
Definition: Connect.cpp:48
void deleteRange(unsigned int offset, unsigned int length)
Definition: Stripe.cpp:414
unsigned int resize(unsigned int length, bool initialize=true)
Definition: Stripe.cpp:339
sample_index_t start() const
Definition: Stripe.cpp:262
#define STRIPE_LENGTH_MAXIMUM
Definition: Track.cpp:46
void sigSamplesDeleted(Kwave::Track *src, sample_index_t offset, sample_index_t length)
sample_index_t end() const
Definition: Stripe.cpp:282
void select(bool select)
Definition: Track.cpp:464
bool mergeStripe(Kwave::Stripe &stripe)
Definition: Track.cpp:133
#define STRIPE_LENGTH_OPTIMAL
Definition: Track.cpp:37
void release()
Definition: Track.cpp:769
#define STRIPE_LENGTH_MINIMUM
Definition: Track.cpp:55
void sigSelectionChanged(bool selected)
bool writeSamples(Kwave::InsertMode mode, sample_index_t offset, const Kwave::SampleArray &buffer, unsigned int buf_offset, unsigned int length)
Definition: Track.cpp:561
void setStart(sample_index_t start)
Definition: Stripe.cpp:268
unsigned int size() const
Kwave::Writer * openWriter(Kwave::InsertMode mode, sample_index_t left=0, sample_index_t right=0)
Definition: Track.cpp:188
void sigSamplesModified(Kwave::Track *src, sample_index_t offset, sample_index_t length)
unsigned int toUint(T x)
Definition: Utils.h:109
QReadWriteLock m_lock_usage
Definition: Track.h:311
InsertMode
Definition: InsertMode.h:26
Kwave::Stripe::List stripes(sample_index_t left, sample_index_t right)
Definition: Track.cpp:209
bool m_selected
Definition: Track.h:317
void unlockedDelete(sample_index_t offset, sample_index_t length, bool make_gap=false)
Definition: Track.cpp:360
sample_index_t length()
Definition: Track.cpp:173
virtual ~Track()
Definition: Track.cpp:79
void appendStripe(sample_index_t length)
Definition: Track.cpp:92
void moveRight(sample_index_t offset, sample_index_t shift)
Definition: Track.cpp:546
void dump()
Definition: Track.cpp:775