CachingReader::CachingReader(const char* group, ConfigObject<ConfigValue>* config) : m_pConfig(config), m_chunkReadRequestFIFO(1024), m_readerStatusFIFO(1024), m_readerStatus(INVALID), m_mruChunk(NULL), m_lruChunk(NULL), m_pRawMemoryBuffer(NULL), m_iTrackNumSamplesCallbackSafe(0) { int rawMemoryBufferLength = CachingReaderWorker::kSamplesPerChunk * maximumChunksInMemory; m_pRawMemoryBuffer = new CSAMPLE[rawMemoryBufferLength]; m_allocatedChunks.reserve(maximumChunksInMemory); CSAMPLE* bufferStart = m_pRawMemoryBuffer; // Divide up the allocated raw memory buffer into total_chunks // chunks. Initialize each chunk to hold nothing and add it to the free // list. for (int i=0; i < maximumChunksInMemory; i++) { Chunk* c = new Chunk; c->chunk_number = -1; c->length = 0; c->data = bufferStart; c->next_lru = NULL; c->prev_lru = NULL; m_chunks.push_back(c); m_freeChunks.push_back(c); bufferStart += CachingReaderWorker::kSamplesPerChunk; } m_pWorker = new CachingReaderWorker(group, &m_chunkReadRequestFIFO, &m_readerStatusFIFO); // Forward signals from worker connect(m_pWorker, SIGNAL(trackLoading()), this, SIGNAL(trackLoading()), Qt::DirectConnection); connect(m_pWorker, SIGNAL(trackLoaded(TrackPointer, int, int)), this, SIGNAL(trackLoaded(TrackPointer, int, int)), Qt::DirectConnection); connect(m_pWorker, SIGNAL(trackLoadFailed(TrackPointer, QString)), this, SIGNAL(trackLoadFailed(TrackPointer, QString)), Qt::DirectConnection); m_pWorker->start(QThread::HighPriority); }
void CachingReaderWorker::loadTrack(const TrackPointer& pTrack) { //qDebug() << m_group << "CachingReaderWorker::loadTrack() lock acquired for load."; // Emit that a new track is loading, stops the current track emit(trackLoading()); ReaderStatusUpdate status; status.status = TRACK_NOT_LOADED; QString filename = pTrack->getLocation(); if (filename.isEmpty() || !pTrack->exists()) { // Must unlock before emitting to avoid deadlock qDebug() << m_group << "CachingReaderWorker::loadTrack() load failed for\"" << filename << "\", unlocked reader lock"; m_pReaderStatusFIFO->writeBlocking(&status, 1); emit(trackLoadFailed( pTrack, QString("The file '%1' could not be found.").arg(filename))); return; } Mixxx::AudioSourceConfig audioSrcCfg; audioSrcCfg.setChannelCount(CachingReaderChunk::kChannels); m_pAudioSource = openAudioSourceForReading(pTrack, audioSrcCfg); if (m_pAudioSource.isNull()) { m_maxReadableFrameIndex = Mixxx::AudioSource::getMinFrameIndex(); // Must unlock before emitting to avoid deadlock qDebug() << m_group << "CachingReaderWorker::loadTrack() load failed for\"" << filename << "\", file invalid, unlocked reader lock"; m_pReaderStatusFIFO->writeBlocking(&status, 1); emit(trackLoadFailed( pTrack, QString("The file '%1' could not be loaded.").arg(filename))); return; } // Initially assume that the complete content offered by audio source // is available for reading. Later if read errors occur this value will // be decreased to avoid repeated reading of corrupt audio data. m_maxReadableFrameIndex = m_pAudioSource->getMaxFrameIndex(); status.maxReadableFrameIndex = m_maxReadableFrameIndex; status.status = TRACK_LOADED; m_pReaderStatusFIFO->writeBlocking(&status, 1); // Clear the chunks to read list. CachingReaderChunkReadRequest request; while (m_pChunkReadRequestFIFO->read(&request, 1) == 1) { qDebug() << "Skipping read request for " << request.chunk->getIndex(); status.status = CHUNK_READ_INVALID; status.chunk = request.chunk; m_pReaderStatusFIFO->writeBlocking(&status, 1); } // Emit that the track is loaded. const SINT sampleCount = CachingReaderChunk::frames2samples( m_pAudioSource->getFrameCount()); emit(trackLoaded(pTrack, m_pAudioSource->getSamplingRate(), sampleCount)); }
void CachingReaderWorker::loadTrack(const TrackPointer& pTrack) { //qDebug() << m_group << "CachingReaderWorker::loadTrack() lock acquired for load."; // Emit that a new track is loading, stops the current track emit(trackLoading()); ReaderStatusUpdate status; status.status = TRACK_NOT_LOADED; status.chunk = NULL; status.trackFrameCount = 0; QString filename = pTrack->getLocation(); if (filename.isEmpty() || !pTrack->exists()) { // Must unlock before emitting to avoid deadlock qDebug() << m_group << "CachingReaderWorker::loadTrack() load failed for\"" << filename << "\", unlocked reader lock"; m_pReaderStatusFIFO->writeBlocking(&status, 1); emit(trackLoadFailed( pTrack, QString("The file '%1' could not be found.").arg(filename))); return; } Mixxx::AudioSourceConfig audioSrcCfg; audioSrcCfg.channelCountHint = kChunkChannels; m_pAudioSource = openAudioSourceForReading(pTrack, audioSrcCfg); if (m_pAudioSource.isNull()) { // Must unlock before emitting to avoid deadlock qDebug() << m_group << "CachingReaderWorker::loadTrack() load failed for\"" << filename << "\", file invalid, unlocked reader lock"; m_pReaderStatusFIFO->writeBlocking(&status, 1); emit(trackLoadFailed( pTrack, QString("The file '%1' could not be loaded.").arg(filename))); return; } status.trackFrameCount = m_pAudioSource->getFrameCount(); status.status = TRACK_LOADED; m_pReaderStatusFIFO->writeBlocking(&status, 1); // Clear the chunks to read list. ChunkReadRequest request; while (m_pChunkReadRequestFIFO->read(&request, 1) == 1) { qDebug() << "Skipping read request for " << request.chunk->chunk_number; status.status = CHUNK_READ_INVALID; status.chunk = request.chunk; m_pReaderStatusFIFO->writeBlocking(&status, 1); } // Emit that the track is loaded. const SINT sampleCount = m_pAudioSource->getFrameCount() * kChunkChannels; emit(trackLoaded(pTrack, m_pAudioSource->getFrameRate(), sampleCount)); }
CachingReader::CachingReader(QString group, UserSettingsPointer config) : m_pConfig(config), m_chunkReadRequestFIFO(1024), m_readerStatusFIFO(1024), m_readerStatus(INVALID), m_mruCachingReaderChunk(nullptr), m_lruCachingReaderChunk(nullptr), m_sampleBuffer(CachingReaderChunk::kSamples * maximumCachingReaderChunksInMemory), m_maxReadableFrameIndex(Mixxx::AudioSource::getMinFrameIndex()), m_worker(group, &m_chunkReadRequestFIFO, &m_readerStatusFIFO) { m_allocatedCachingReaderChunks.reserve(m_sampleBuffer.size()); CSAMPLE* bufferStart = m_sampleBuffer.data(); // Divide up the allocated raw memory buffer into total_chunks // chunks. Initialize each chunk to hold nothing and add it to the free // list. for (int i = 0; i < maximumCachingReaderChunksInMemory; ++i) { CachingReaderChunkForOwner* c = new CachingReaderChunkForOwner(bufferStart); m_chunks.push_back(c); m_freeChunks.push_back(c); bufferStart += CachingReaderChunk::kSamples; } // Forward signals from worker connect(&m_worker, SIGNAL(trackLoading()), this, SIGNAL(trackLoading()), Qt::DirectConnection); connect(&m_worker, SIGNAL(trackLoaded(TrackPointer, int, int)), this, SIGNAL(trackLoaded(TrackPointer, int, int)), Qt::DirectConnection); connect(&m_worker, SIGNAL(trackLoadFailed(TrackPointer, QString)), this, SIGNAL(trackLoadFailed(TrackPointer, QString)), Qt::DirectConnection); m_worker.start(QThread::HighPriority); }
void CachingReaderWorker::loadTrack(TrackPointer pTrack) { //qDebug() << m_pGroup << "CachingReaderWorker::loadTrack() lock acquired for load."; // Emit that a new track is loading, stops the current track emit(trackLoading()); ReaderStatusUpdate status; status.status = TRACK_LOADED; status.chunk = NULL; status.trackNumSamples = 0; if (m_pCurrentSoundSource != NULL) { delete m_pCurrentSoundSource; m_pCurrentSoundSource = NULL; } m_iTrackNumSamples = 0; QString filename = pTrack->getLocation(); if (filename.isEmpty() || !pTrack->exists()) { // Must unlock before emitting to avoid deadlock qDebug() << m_pGroup << "CachingReaderWorker::loadTrack() load failed for\"" << filename << "\", unlocked reader lock"; status.status = TRACK_NOT_LOADED; m_pReaderStatusFIFO->writeBlocking(&status, 1); emit(trackLoadFailed( pTrack, QString("The file '%1' could not be found.").arg(filename))); return; } m_pCurrentSoundSource = new SoundSourceProxy(pTrack); bool openSucceeded = (m_pCurrentSoundSource->open() == OK); //Open the song for reading unsigned int trackSampleRate = m_pCurrentSoundSource->getSampleRate(); m_iTrackNumSamples = status.trackNumSamples = m_pCurrentSoundSource->length(); if (!openSucceeded || m_iTrackNumSamples == 0 || trackSampleRate == 0) { // Must unlock before emitting to avoid deadlock qDebug() << m_pGroup << "CachingReaderWorker::loadTrack() load failed for\"" << filename << "\", file invalid, unlocked reader lock"; status.status = TRACK_NOT_LOADED; m_pReaderStatusFIFO->writeBlocking(&status, 1); emit(trackLoadFailed( pTrack, QString("The file '%1' could not be loaded.").arg(filename))); return; } m_pReaderStatusFIFO->writeBlocking(&status, 1); // Clear the chunks to read list. ChunkReadRequest request; while (m_pChunkReadRequestFIFO->read(&request, 1) == 1) { qDebug() << "Skipping read request for " << request.chunk->chunk_number; status.status = CHUNK_READ_INVALID; status.chunk = request.chunk; m_pReaderStatusFIFO->writeBlocking(&status, 1); } // Emit that the track is loaded. emit(trackLoaded(pTrack, trackSampleRate, m_iTrackNumSamples)); }