#ifndef CACHINGREADERWORKER_H #define CACHINGREADERWORKER_H #include #include #include #include #include #include #include "soundsource.h" #include "trackinfoobject.h" #include "engine/engineworker.h" #include "util/fifo.h" #include "util/types.h" // A Chunk is a section of audio that is being cached. The chunk_number can be // used to figure out the sample number of the first sample in data by using // sampleForChunk() typedef struct Chunk { int chunk_number; int length; CSAMPLE* data; Chunk* prev_lru; Chunk* next_lru; enum State { FREE, ALLOCATED, READ_IN_PROGRESS, READ }; State state; } Chunk; typedef struct ChunkReadRequest { Chunk* chunk; ChunkReadRequest() { chunk = NULL; } } ChunkReadRequest; enum ReaderStatus { INVALID, TRACK_NOT_LOADED, TRACK_LOADED, CHUNK_READ_SUCCESS, CHUNK_READ_EOF, CHUNK_READ_INVALID }; typedef struct ReaderStatusUpdate { ReaderStatus status; Chunk* chunk; int trackNumSamples; ReaderStatusUpdate() { status = INVALID; chunk = NULL; trackNumSamples = 0; } } ReaderStatusUpdate; class CachingReaderWorker : public EngineWorker { Q_OBJECT public: // Construct a CachingReader with the given group. CachingReaderWorker(QString group, FIFO* pChunkReadRequestFIFO, FIFO* pReaderStatusFIFO); virtual ~CachingReaderWorker(); // Request to load a new track. wake() must be called afterwards. virtual void newTrack(TrackPointer pTrack); // Run upkeep operations like loading tracks and reading from file. Run by a // thread pool via the EngineWorkerScheduler. virtual void run(); void quitWait(); // A Chunk is a memory-resident section of audio that has been cached. Each // chunk holds a fixed number of samples given by kSamplesPerChunk. const static int kChunkLength, kSamplesPerChunk; // Given a chunk number, return the start sample number for the chunk. inline static int sampleForChunk(int chunk_number) { return chunk_number * kSamplesPerChunk; } signals: // Emitted once a new track is loaded and ready to be read from. void trackLoading(); void trackLoaded(TrackPointer pTrack, int iSampleRate, int iNumSamples); void trackLoadFailed(TrackPointer pTrack, QString reason); private: QString m_group; QString m_tag; // Thread-safe FIFOs for communication between the engine callback and // reader thread. FIFO* m_pChunkReadRequestFIFO; FIFO* m_pReaderStatusFIFO; // Queue of Tracks to load, and the corresponding lock. Must acquire the // lock to touch. QMutex m_newTrackMutex; TrackPointer m_newTrack; // Internal method to load a track. Emits trackLoaded when finished. void loadTrack(const TrackPointer& pTrack); // Read the given chunk_number from the file into pChunk's data // buffer. Fills length/sample information about Chunk* as well. void processChunkReadRequest(ChunkReadRequest* request, ReaderStatusUpdate* update); // The current sound source of the track loaded Mixxx::SoundSourcePointer m_pCurrentSoundSource; int m_iTrackNumSamples; // Temporary buffer for reading from SoundSources SAMPLE* m_pSample; QAtomicInt m_stop; }; #endif /* CACHINGREADERWORKER_H */