#ifndef CHUNKEDAUDIOSTREAM_H #define CHUNKEDAUDIOSTREAM_H #include #include #include #include #include #include #include "ivorbisfile.h" #include "MercuryManager.h" #include "AudioSink.h" #include "AudioChunk.h" #include "platform/WrappedMutex.h" #define SPOTIFY_HEADER_SIZE 167 #define BUFFER_SIZE 0x20000 * 1.5 typedef std::function&)> pcmDataCallback; enum class Whence { START, CURRENT, END }; class ChunkedAudioStream { private: // Vorbis related OggVorbis_File vorbisFile; ov_callbacks vorbisCallbacks; int currentSection; // Audio chunking std::vector audioKey; std::vector> chunks; // Audio data uint32_t duration; bool loadingChunks = false; uint16_t lastSequenceId = 0; std::shared_ptr manager; std::vector fileId; uint32_t startPositionMs; std::shared_ptr requestChunk(size_t chunkIndex); void fetchTraillingPacket(); std::shared_ptr findChunkForPosition(size_t position); public: ChunkedAudioStream(std::vector fileId, std::vector audioKey, uint32_t duration, std::shared_ptr manager, uint32_t startPositionMs, bool isPaused); ~ChunkedAudioStream(); int requestedChunkIndex = 0; std::function streamFinishedCallback; size_t pos = SPOTIFY_HEADER_SIZE; // size of some spotify header uint32_t fileSize; uint32_t readBeforeSeek = 0; bool loadingMeta = true; std::atomic isPaused = false; std::atomic isRunning = false; std::atomic finished = false; pcmDataCallback pcmCallback; std::shared_ptr audioSink; WrappedMutex seekMutex; std::vector read(size_t bytes); void seekMs(uint32_t positionMs); void seek(size_t pos, Whence whence); void startPlaybackLoop(); }; #endif