154
158
// We'll tolerate not being in allocatedChunks because sometime you free a
155
159
// chunk right after you allocated it.
156
Q_ASSERT(removed <= 1);
161
qDebug() << "ERROR: freeChunk free'd a chunk that was multiply-allocated.";
158
164
// If this is the LRU chunk then set its previous LRU chunk to the LRU
159
165
if (m_lruChunk == pChunk) {
197
203
Chunk* CachingReader::allocateChunkExpireLRU() {
198
204
Chunk* chunk = allocateChunk();
199
205
if (chunk == NULL) {
200
Q_ASSERT(m_lruChunk);
206
if (m_lruChunk == NULL) {
207
qDebug() << "ERROR: No LRU chunk to free in allocateChunkExpireLRU.";
201
210
//qDebug() << "Expiring LRU" << m_lruChunk << m_lruChunk->chunk_number;
202
211
freeChunk(m_lruChunk);
203
212
chunk = allocateChunk();
206
214
//qDebug() << "allocateChunkExpireLRU" << chunk;
215
223
chunk = m_allocatedChunks.value(chunk_number);
217
225
// Make sure we're all in agreement here.
218
Q_ASSERT(chunk_number == chunk->chunk_number);
226
if (chunk_number != chunk->chunk_number) {
227
qDebug() << "ERROR: Inconsistent chunk has chunk_number that doesn't match allocated-chunks key.";
221
230
// If this is the LRU chunk then set the previous LRU to the new LRU
222
231
if (chunk == m_lruChunk && chunk->prev_lru != NULL) {
293
302
m_iTrackNumSamplesCallbackSafe = status.trackNumSamples;
294
303
} else if (status.status == CHUNK_READ_SUCCESS) {
295
304
Chunk* pChunk = status.chunk;
296
Q_ASSERT(pChunk != NULL);
305
if (pChunk == NULL) {
306
qDebug() << "ERROR: status.chunk is NULL in CHUNK_READ_SUCCESS ReaderStatusUpdate. Ignoring update.";
297
309
Chunk* pChunk2 = m_chunksBeingRead.take(pChunk->chunk_number);
298
310
if (pChunk2 != pChunk) {
299
311
qDebug() << "Mismatch in requested chunk to read!";
321
333
} else if (status.status == CHUNK_READ_EOF) {
322
334
Chunk* pChunk = status.chunk;
323
Q_ASSERT(pChunk != NULL);
335
if (pChunk == NULL) {
336
qDebug() << "ERROR: status.chunk is NULL in CHUNK_READ_EOF ReaderStatusUpdate. Ignoring update.";
324
339
Chunk* pChunk2 = m_chunksBeingRead.take(pChunk->chunk_number);
325
340
if (pChunk2 != pChunk) {
326
341
qDebug() << "Mismatch in requested chunk to read!";
329
344
} else if (status.status == CHUNK_READ_INVALID) {
330
345
qDebug() << "WARNING: READER THREAD RECEIVED INVALID CHUNK READ";
331
346
Chunk* pChunk = status.chunk;
332
Q_ASSERT(pChunk != NULL);
347
if (pChunk == NULL) {
348
qDebug() << "ERROR: status.chunk is NULL in CHUNK_READ_INVALID ReaderStatusUpdate. Ignoring update.";
333
351
Chunk* pChunk2 = m_chunksBeingRead.take(pChunk->chunk_number);
334
352
if (pChunk2 != pChunk) {
335
353
qDebug() << "Mismatch in requested chunk to read!";
342
360
int CachingReader::read(int sample, int num_samples, CSAMPLE* buffer) {
343
int zerosWritten = 0;
344
// Check for bogus sample numbers
345
//Q_ASSERT(sample >= 0);
346
QString temp = QString("Sample = %1").arg(sample);
347
QByteArray tempBA = QString(temp).toUtf8();
348
Q_ASSERT_X(sample % 2 == 0,"CachingReader::read",tempBA);
349
Q_ASSERT(num_samples >= 0);
361
// Check for bad inputs
362
if (sample % 2 != 0 || num_samples < 0 || !buffer) {
363
QString temp = QString("Sample = %1").arg(sample);
364
QByteArray tempBA = QString(temp).toUtf8();
365
qDebug() << "CachingReader::read() invalid arguments sample:" << sample
366
<< "num_samples:" << num_samples << "buffer:" << buffer;
351
370
// If asked to read 0 samples, don't do anything. (this is a perfectly
352
371
// reasonable request that happens sometimes. If no track is loaded, don't
390
410
int current_sample = sample;
393
Q_ASSERT(start_chunk <= end_chunk);
413
if (start_chunk > end_chunk) {
414
qDebug() << "CachingReader::read() bad chunk range to read ["
415
<< start_chunk << end_chunk << "]";
395
419
for (int chunk_num = start_chunk; chunk_num <= end_chunk; chunk_num++) {
396
420
Chunk* current = lookupChunk(chunk_num);
411
435
int chunk_remaining_samples = current->length - chunk_offset;
413
437
// More sanity checks
414
Q_ASSERT(current_sample >= chunk_start_sample);
415
Q_ASSERT(current_sample % 2 == 0);
417
if (start_chunk != chunk_num) {
418
Q_ASSERT(chunk_start_sample == current_sample);
421
Q_ASSERT(samples_remaining >= 0);
438
if (current_sample < chunk_start_sample || current_sample % 2 != 0) {
439
qDebug() << "CachingReader::read() bad chunk parameters"
440
<< "chunk_start_sample" << chunk_start_sample
441
<< "current_sample" << current_sample;
445
// If we're past the start_chunk then current_sample should be
446
// chunk_start_sample.
447
if (start_chunk != chunk_num && chunk_start_sample != current_sample) {
448
qDebug() << "CachingReader::read() bad chunk parameters"
449
<< "chunk_num" << chunk_num
450
<< "start_chunk" << start_chunk
451
<< "chunk_start_sample" << chunk_start_sample
452
<< "current_sample" << current_sample;
456
if (samples_remaining < 0) {
457
qDebug() << "CachingReader::read() bad samples remaining"
458
<< samples_remaining;
422
462
// It is completely possible that chunk_remaining_samples is less than
423
463
// zero. If the caller is trying to read from beyond the end of the
424
464
// file, then this can happen. We should tolerate it.
426
465
int samples_to_read = math_max(0, math_min(samples_remaining,
427
466
chunk_remaining_samples));
429
// samples_to_read should be non-negative and even
430
Q_ASSERT(samples_to_read >= 0);
431
Q_ASSERT(samples_to_read % 2 == 0);
433
CSAMPLE *data = current->data + chunk_offset;
435
468
// If we did not decide to read any samples from this chunk then that
436
469
// means we have exhausted all the samples in the song.
437
470
if (samples_to_read == 0) {
474
// samples_to_read should be non-negative and even
475
if (samples_to_read < 0 || samples_to_read % 2 != 0) {
476
qDebug() << "CachingReader::read() samples_to_read invalid"
441
481
// TODO(rryan) do a test and see if using memcpy is faster than gcc
442
482
// optimizing the for loop
483
CSAMPLE *data = current->data + chunk_offset;
443
484
memcpy(buffer, data, sizeof(*buffer) * samples_to_read);
444
485
// for (int i=0; i < samples_to_read; i++) {
445
486
// buffer[i] = data[i];
499
Q_ASSERT(hint.length >= 0);
542
if (hint.length < 0) {
543
qDebug() << "ERROR: Negative hint length. Ignoring.";
500
546
int start_sample = math_max(0, math_min(
501
547
m_iTrackNumSamplesCallbackSafe, hint.sample));
502
548
int start_chunk = chunkForSample(start_sample);
521
567
if (!m_chunksBeingRead.contains(chunk) && lookupChunk(chunk) == NULL) {
522
568
shouldWake = true;
523
569
Chunk* pChunk = allocateChunkExpireLRU();
524
Q_ASSERT(pChunk != NULL);
570
if (pChunk == NULL) {
571
qDebug() << "ERROR: Couldn't allocate spare Chunk to make ChunkReadRequest.";
526
574
m_chunksBeingRead.insert(chunk, pChunk);
527
575
ChunkReadRequest request;
528
576
pChunk->chunk_number = chunk;