CDNTrackStream.h 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. #pragma once
  2. #include <cstddef>
  3. #include <memory>
  4. #include "Crypto.h"
  5. #include "WrappedSemaphore.h"
  6. #include "Logger.h"
  7. #include "Utils.h"
  8. #include "CSpotContext.h"
  9. #include "AccessKeyFetcher.h"
  10. namespace cspot {
  11. class CDNTrackStream {
  12. public:
  13. CDNTrackStream(std::shared_ptr<cspot::AccessKeyFetcher>);
  14. ~CDNTrackStream();
  15. enum class Status { INITIALIZING, HAS_DATA, HAS_URL, FAILED };
  16. struct TrackInfo {
  17. std::string trackId;
  18. std::string name;
  19. std::string album;
  20. std::string artist;
  21. std::string imageUrl;
  22. int duration;
  23. };
  24. TrackInfo trackInfo;
  25. Status status;
  26. std::unique_ptr<bell::WrappedSemaphore> trackReady;
  27. void fetchFile(const std::vector<uint8_t>& trackId,
  28. const std::vector<uint8_t>& audioKey);
  29. void fail();
  30. void openStream();
  31. size_t readBytes(uint8_t* dst, size_t bytes);
  32. size_t getPosition();
  33. size_t getSize();
  34. void seek(size_t position);
  35. private:
  36. const int OPUS_HEADER_SIZE = 8 * 1024;
  37. const int OPUS_FOOTER_PREFFERED = 1024 * 12; // 12K should be safe
  38. const int SEEK_MARGIN_SIZE = 1024 * 4;
  39. const int HTTP_BUFFER_SIZE = 1024 * 14;
  40. const int SPOTIFY_OPUS_HEADER = 167;
  41. // Used to store opus metadata, speeds up read
  42. std::vector<uint8_t> header = std::vector<uint8_t>(OPUS_HEADER_SIZE);
  43. std::vector<uint8_t> footer;
  44. // General purpose buffer to read data
  45. std::vector<uint8_t> httpBuffer = std::vector<uint8_t>(HTTP_BUFFER_SIZE);
  46. // AES IV for decrypting the audio stream
  47. const std::vector<uint8_t> audioAESIV = {0x72, 0xe0, 0x67, 0xfb, 0xdd, 0xcb,
  48. 0xcf, 0x77, 0xeb, 0xe8, 0xbc, 0x64,
  49. 0x3f, 0x63, 0x0d, 0x93};
  50. std::unique_ptr<Crypto> crypto;
  51. std::shared_ptr<cspot::AccessKeyFetcher> accessKeyFetcher;
  52. std::unique_ptr<bell::HTTPClient::Response> httpConnection;
  53. bool isConnected = false;
  54. size_t position = 0; // Spotify header size
  55. size_t totalFileSize = 0;
  56. size_t lastRequestPosition = 0;
  57. size_t lastRequestCapacity = 0;
  58. bool enableRequestMargin = false;
  59. std::string cdnUrl;
  60. std::vector<uint8_t> trackId;
  61. std::vector<uint8_t> audioKey;
  62. void decrypt(uint8_t* dst, size_t nbytes, size_t pos);
  63. };
  64. } // namespace cspot