mirror of
https://github.com/sle118/squeezelite-esp32.git
synced 2025-12-07 03:57:07 +03:00
trying to follow cspot...
This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
#include "CSpotContext.h"
|
||||
#include "Utils.h"
|
||||
#include <functional> // for function
|
||||
#include <memory> // for shared_ptr
|
||||
#include <string> // for string
|
||||
|
||||
namespace cspot {
|
||||
struct Context;
|
||||
|
||||
class AccessKeyFetcher {
|
||||
public:
|
||||
AccessKeyFetcher(std::shared_ptr<cspot::Context> ctx);
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "HTTPClient.h"
|
||||
#include <string> // for string
|
||||
#ifdef BELL_ONLY_CJSON
|
||||
#include "cJSON.h"
|
||||
#else
|
||||
#include "nlohmann/json.hpp"
|
||||
#endif
|
||||
|
||||
namespace cspot {
|
||||
|
||||
@@ -1,20 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <algorithm>
|
||||
#include <climits>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <random>
|
||||
#include <vector>
|
||||
#include <cstdint> // for uint8_t
|
||||
#include <memory> // for unique_ptr
|
||||
#include <string> // for string
|
||||
#include <vector> // for vector
|
||||
|
||||
#include "Crypto.h"
|
||||
#include "Logger.h"
|
||||
#include "NanoPBHelper.h"
|
||||
#include "Utils.h"
|
||||
|
||||
#include "protobuf/authentication.pb.h"
|
||||
#include "protobuf/keyexchange.pb.h"
|
||||
#include "Crypto.h" // for Crypto
|
||||
#include "protobuf/authentication.pb.h" // for ClientResponseEncrypted
|
||||
#include "protobuf/keyexchange.pb.h" // for APResponseMessage, ClientHello
|
||||
|
||||
namespace cspot {
|
||||
class AuthChallenges {
|
||||
|
||||
@@ -1,16 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include "Crypto.h"
|
||||
#include "WrappedSemaphore.h"
|
||||
#include <cstddef> // for size_t
|
||||
#include <cstdint> // for uint8_t
|
||||
#include <memory> // for shared_ptr, unique_ptr
|
||||
#include <string> // for string
|
||||
#include <vector> // for vector
|
||||
|
||||
#include "Logger.h"
|
||||
#include "Utils.h"
|
||||
#include "CSpotContext.h"
|
||||
#include "AccessKeyFetcher.h"
|
||||
#include "Crypto.h" // for Crypto
|
||||
#include "HTTPClient.h" // for HTTPClient
|
||||
|
||||
namespace bell {
|
||||
class WrappedSemaphore;
|
||||
} // namespace bell
|
||||
|
||||
namespace cspot {
|
||||
class AccessKeyFetcher;
|
||||
|
||||
class CDNTrackStream {
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "MercurySession.h"
|
||||
#include "TimeProvider.h"
|
||||
#include "protobuf/metadata.pb.h"
|
||||
#include "LoginBlob.h"
|
||||
|
||||
namespace cspot {
|
||||
struct Context {
|
||||
|
||||
@@ -1,17 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#ifndef BELL_ONLY_CJSON
|
||||
#include <nlohmann/json.hpp>
|
||||
#endif
|
||||
#include <vector>
|
||||
#include <cstdint> // for uint8_t, uint32_t
|
||||
#include <map> // for map
|
||||
#include <memory> // for unique_ptr
|
||||
#include <string> // for string
|
||||
#include <vector> // for vector
|
||||
|
||||
#include "ConstantParameters.h"
|
||||
#include "Crypto.h"
|
||||
|
||||
#include "protobuf/authentication.pb.h"
|
||||
#include "Crypto.h" // for CryptoMbedTLS, Crypto
|
||||
|
||||
namespace cspot {
|
||||
class LoginBlob {
|
||||
|
||||
@@ -1,22 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include "BellTask.h"
|
||||
#include "Logger.h"
|
||||
#include "NanoPBHelper.h"
|
||||
#include "Packet.h"
|
||||
#include "Queue.h"
|
||||
#include "Session.h"
|
||||
#include "TimeProvider.h"
|
||||
#include "Utils.h"
|
||||
#include "protobuf/mercury.pb.h"
|
||||
#include <atomic> // for atomic
|
||||
#include <cstdint> // for uint8_t, uint64_t, uint32_t
|
||||
#include <functional> // for function
|
||||
#include <memory> // for shared_ptr
|
||||
#include <mutex> // for mutex
|
||||
#include <string> // for string
|
||||
#include <unordered_map> // for unordered_map
|
||||
#include <vector> // for vector
|
||||
|
||||
#include "BellTask.h" // for Task
|
||||
#include "Packet.h" // for Packet
|
||||
#include "Queue.h" // for Queue
|
||||
#include "Session.h" // for Session
|
||||
#include "protobuf/mercury.pb.h" // for Header
|
||||
|
||||
namespace cspot {
|
||||
class TimeProvider;
|
||||
|
||||
class MercurySession : public bell::Task, public cspot::Session {
|
||||
public:
|
||||
MercurySession(std::shared_ptr<cspot::TimeProvider> timeProvider);
|
||||
|
||||
@@ -3,19 +3,15 @@
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
|
||||
#include "win32shim.h"
|
||||
#else
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
#include "sys/socket.h"
|
||||
#include <netinet/in.h>
|
||||
#include <unistd.h> // for size_t
|
||||
#endif
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "Packet.h"
|
||||
#include "Utils.h"
|
||||
#include <cstdint> // for uint8_t
|
||||
#include <functional> // for function
|
||||
#include <string> // for string
|
||||
#include <vector> // for vector
|
||||
|
||||
typedef std::function<bool()> timeoutCallback;
|
||||
|
||||
|
||||
@@ -1,18 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <NanoPBHelper.h>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "CSpotContext.h"
|
||||
#include "ConstantParameters.h"
|
||||
#include "CspotAssert.h"
|
||||
#include "TimeProvider.h"
|
||||
#include "Utils.h"
|
||||
#include <stdint.h> // for uint8_t, uint32_t
|
||||
#include <memory> // for shared_ptr
|
||||
#include <string> // for string
|
||||
#include <vector> // for vector
|
||||
|
||||
#include "protobuf/spirc.pb.h"
|
||||
#include "protobuf/spirc.pb.h" // for Frame, TrackRef, CapabilityType, Mess...
|
||||
|
||||
namespace cspot {
|
||||
struct Context;
|
||||
|
||||
class PlaybackState {
|
||||
private:
|
||||
|
||||
@@ -1,20 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <stdint.h> // for uint8_t
|
||||
#include <memory> // for shared_ptr, unique_ptr
|
||||
#include <string> // for string
|
||||
#include <vector> // for vector
|
||||
|
||||
#include "ApResolve.h"
|
||||
#include "AuthChallenges.h"
|
||||
#include "ConstantParameters.h"
|
||||
#include "Logger.h"
|
||||
#include "LoginBlob.h"
|
||||
#include "Packet.h"
|
||||
#include "PlainConnection.h"
|
||||
#include "ShannonConnection.h"
|
||||
#include "Utils.h"
|
||||
#include "protobuf/mercury.pb.h"
|
||||
namespace cspot {
|
||||
class AuthChallenges;
|
||||
class LoginBlob;
|
||||
class PlainConnection;
|
||||
class ShannonConnection;
|
||||
} // namespace cspot
|
||||
|
||||
#define LOGIN_REQUEST_COMMAND 0xAB
|
||||
#define AUTH_SUCCESSFUL_COMMAND 0xAC
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
#ifndef SHANNON_H
|
||||
#define SHANNON_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include <cstdint> // for uint32_t, uint8_t
|
||||
#include <vector> // for vector
|
||||
|
||||
class Shannon
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
#ifndef SHANNONCONNECTION_H
|
||||
#define SHANNONCONNECTION_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cstdint> // for uint8_t, uint32_t
|
||||
#include <memory> // for shared_ptr, unique_ptr
|
||||
#include <mutex> // for mutex
|
||||
#include <vector> // for vector
|
||||
|
||||
#include "Packet.h"
|
||||
#include "PlainConnection.h"
|
||||
#include "Shannon.h"
|
||||
#include <mutex>
|
||||
#include "Utils.h"
|
||||
#include "Logger.h"
|
||||
#include "Packet.h" // for Packet
|
||||
|
||||
class Shannon;
|
||||
namespace cspot {
|
||||
|
||||
class PlainConnection;
|
||||
} // namespace cspot
|
||||
|
||||
#define MAC_SIZE 4
|
||||
namespace cspot {
|
||||
|
||||
@@ -1,16 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include "BellTask.h"
|
||||
#include <stdint.h> // for uint32_t, uint8_t
|
||||
#include <functional> // for function
|
||||
#include <memory> // for shared_ptr, unique_ptr
|
||||
#include <string> // for string
|
||||
#include <variant> // for variant
|
||||
#include <vector> // for vector
|
||||
|
||||
#include "CDNTrackStream.h"
|
||||
#include "CSpotContext.h"
|
||||
#include "PlaybackState.h"
|
||||
#include "TrackPlayer.h"
|
||||
#include "TrackProvider.h"
|
||||
#include "protobuf/spirc.pb.h"
|
||||
#include "CDNTrackStream.h" // for CDNTrackStream, CDNTrackStream::Track...
|
||||
#include "PlaybackState.h" // for PlaybackState
|
||||
#include "protobuf/spirc.pb.h" // for MessageType
|
||||
|
||||
namespace cspot {
|
||||
class TrackPlayer;
|
||||
struct Context;
|
||||
|
||||
class SpircHandler {
|
||||
public:
|
||||
SpircHandler(std::shared_ptr<cspot::Context> ctx);
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
|
||||
#include "Utils.h"
|
||||
#include <stdint.h> // for uint8_t
|
||||
#include <vector> // for vector
|
||||
|
||||
namespace cspot {
|
||||
class TimeProvider {
|
||||
|
||||
@@ -1,22 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <atomic>
|
||||
#include <BellUtils.h>
|
||||
#include <WrappedSemaphore.h>
|
||||
#include "CDNTrackStream.h"
|
||||
#include "CSpotContext.h"
|
||||
#include "TrackProvider.h"
|
||||
#include "TrackReference.h"
|
||||
#include <atomic> // for atomic
|
||||
#include <cstdint> // for uint8_t, int64_t
|
||||
#include <ctime> // for size_t, time
|
||||
#include <functional> // for function
|
||||
#include <memory> // for shared_ptr, unique_ptr
|
||||
#include <mutex> // for mutex
|
||||
#include <string_view> // for string_view
|
||||
#include <vector> // for vector
|
||||
|
||||
#include "BellTask.h" // for Task
|
||||
#include "CDNTrackStream.h" // for CDNTrackStream, CDNTrackStream::TrackInfo
|
||||
|
||||
namespace bell {
|
||||
class WrappedSemaphore;
|
||||
} // namespace bell
|
||||
#ifdef BELL_VORBIS_FLOAT
|
||||
#include "vorbis/vorbisfile.h"
|
||||
#else
|
||||
#include "ivorbisfile.h"
|
||||
#include "ivorbisfile.h" // for OggVorbis_File, ov_callbacks
|
||||
#endif
|
||||
|
||||
namespace cspot {
|
||||
class TrackProvider;
|
||||
struct Context;
|
||||
struct TrackReference;
|
||||
|
||||
class TrackPlayer : bell::Task {
|
||||
public:
|
||||
typedef std::function<void()> TrackLoadedCallback;
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <stdint.h> // for uint8_t
|
||||
#include <memory> // for shared_ptr, unique_ptr, weak_ptr
|
||||
#include <vector> // for vector
|
||||
|
||||
#include "AccessKeyFetcher.h"
|
||||
#include "CDNTrackStream.h"
|
||||
#include "CSpotContext.h"
|
||||
#include "TrackReference.h"
|
||||
#include "protobuf/metadata.pb.h"
|
||||
#include "protobuf/spirc.pb.h"
|
||||
#include "MercurySession.h" // for MercurySession
|
||||
#include "TrackReference.h" // for TrackReference
|
||||
#include "protobuf/metadata.pb.h" // for Episode, Restriction, Track
|
||||
|
||||
namespace cspot {
|
||||
class AccessKeyFetcher;
|
||||
class CDNTrackStream;
|
||||
struct Context;
|
||||
|
||||
class TrackProvider {
|
||||
public:
|
||||
TrackProvider(std::shared_ptr<cspot::Context> ctx);
|
||||
@@ -23,11 +26,13 @@ class TrackProvider {
|
||||
std::unique_ptr<cspot::CDNTrackStream> cdnStream;
|
||||
|
||||
Track trackInfo;
|
||||
Episode episodeInfo;
|
||||
std::weak_ptr<CDNTrackStream> currentTrackReference;
|
||||
TrackReference trackIdInfo;
|
||||
|
||||
void queryMetadata();
|
||||
void onMetadataResponse(MercurySession::Response& res);
|
||||
bool doRestrictionsApply(Restriction* restrictions, int count);
|
||||
void fetchFile(const std::vector<uint8_t>& fileId,
|
||||
const std::vector<uint8_t>& trackId);
|
||||
bool canPlayTrack(int index);
|
||||
|
||||
@@ -28,12 +28,11 @@ struct TrackReference {
|
||||
// Episode GID is being fetched via base62 encoded URI
|
||||
auto uri = std::string(ref->uri);
|
||||
auto idString = uri.substr(uri.find_last_of(":") + 1, uri.size());
|
||||
|
||||
trackRef.gid = {0};
|
||||
|
||||
std::string_view alphabet(base62Alphabet);
|
||||
for (int x = 0; x < uri.size(); x++) {
|
||||
size_t d = alphabet.find(uri[x]);
|
||||
for (int x = 0; x < idString.size(); x++) {
|
||||
size_t d = alphabet.find(idString[x]);
|
||||
trackRef.gid = bigNumMultiply(trackRef.gid, 62);
|
||||
trackRef.gid = bigNumAdd(trackRef.gid, d);
|
||||
}
|
||||
|
||||
@@ -1,27 +1,20 @@
|
||||
#ifndef UTILS_H
|
||||
#define UTILS_H
|
||||
#include <vector>
|
||||
#include <cstdio> // for snprintf, size_t
|
||||
#include <vector> // for vector
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
|
||||
#include "win32shim.h"
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#include "sys/socket.h"
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#endif
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <chrono>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <cstdint> // for uint8_t, uint64_t
|
||||
#include <cstring> // for memcpy
|
||||
#include <memory> // for unique_ptr
|
||||
#include <stdexcept> // for runtime_error
|
||||
#include <string> // for string
|
||||
|
||||
#define HMAC_SHA1_BLOCKSIZE 64
|
||||
|
||||
|
||||
@@ -12,7 +12,8 @@ Album.name type: FT_POINTER
|
||||
Episode.gid type: FT_POINTER
|
||||
Episode.name type: FT_POINTER
|
||||
ImageGroup.image type: FT_POINTER
|
||||
Episode.audio type: FT_POINTER
|
||||
Episode.file type: FT_POINTER
|
||||
Episode.restriction type: FT_POINTER
|
||||
Episode.covers type: FT_POINTER
|
||||
Restriction.countries_allowed type: FT_POINTER
|
||||
Restriction.countries_forbidden type: FT_POINTER
|
||||
@@ -44,7 +44,8 @@ message Episode {
|
||||
optional bytes gid = 1;
|
||||
optional string name = 2;
|
||||
optional sint32 duration = 7;
|
||||
repeated AudioFile audio = 12;
|
||||
repeated AudioFile file = 12;
|
||||
repeated Restriction restriction = 0x4B;
|
||||
optional ImageGroup covers = 0x44;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,24 @@
|
||||
#include "AccessKeyFetcher.h"
|
||||
#include <cstring>
|
||||
#include "Logger.h"
|
||||
#include "Utils.h"
|
||||
|
||||
#include <cstring> // for strrchr
|
||||
#include <initializer_list> // for initializer_list
|
||||
#include <map> // for operator!=, operator==
|
||||
#include <type_traits> // for remove_extent_t
|
||||
#include <vector> // for vector
|
||||
|
||||
#include "BellLogger.h" // for AbstractLogger
|
||||
#include "CSpotContext.h" // for Context
|
||||
#include "Logger.h" // for CSPOT_LOG
|
||||
#include "MercurySession.h" // for MercurySession, MercurySession::Res...
|
||||
#include "Packet.h" // for cspot
|
||||
#include "TimeProvider.h" // for TimeProvider
|
||||
#include "Utils.h" // for string_format
|
||||
#ifdef BELL_ONLY_CJSON
|
||||
#include "cJSON.h"
|
||||
#else
|
||||
#include "nlohmann/json.hpp" // for basic_json<>::object_t, basic_json
|
||||
#include "nlohmann/json_fwd.hpp" // for json
|
||||
#endif
|
||||
|
||||
using namespace cspot;
|
||||
|
||||
@@ -38,18 +55,21 @@ void AccessKeyFetcher::getAccessKey(AccessKeyFetcher::Callback callback) {
|
||||
ctx->session->execute(
|
||||
MercurySession::RequestType::GET, url,
|
||||
[this, timeProvider, callback](MercurySession::Response& res) {
|
||||
if (res.fail) return;
|
||||
if (res.fail)
|
||||
return;
|
||||
char* accessKeyJson = (char*)res.parts[0].data();
|
||||
auto accessJSON = std::string(accessKeyJson, strrchr(accessKeyJson, '}') - accessKeyJson + 1);
|
||||
auto accessJSON = std::string(
|
||||
accessKeyJson, strrchr(accessKeyJson, '}') - accessKeyJson + 1);
|
||||
#ifdef BELL_ONLY_CJSON
|
||||
cJSON* jsonBody = cJSON_Parse(accessJSON.c_str());
|
||||
this->accessKey = cJSON_GetObjectItem(jsonBody, "accessToken")->valuestring;
|
||||
this->accessKey =
|
||||
cJSON_GetObjectItem(jsonBody, "accessToken")->valuestring;
|
||||
int expiresIn = cJSON_GetObjectItem(jsonBody, "expiresIn")->valueint;
|
||||
#else
|
||||
auto jsonBody = nlohmann::json::parse(accessJSON);
|
||||
this->accessKey = jsonBody["accessToken"];
|
||||
int expiresIn = jsonBody["expiresIn"];
|
||||
#endif
|
||||
#endif
|
||||
expiresIn = expiresIn / 2; // Refresh token before it expires
|
||||
|
||||
this->expiresAt =
|
||||
@@ -57,8 +77,8 @@ void AccessKeyFetcher::getAccessKey(AccessKeyFetcher::Callback callback) {
|
||||
#ifdef BELL_ONLY_CJSON
|
||||
callback(cJSON_GetObjectItem(jsonBody, "accessToken")->valuestring);
|
||||
cJSON_Delete(jsonBody);
|
||||
#else
|
||||
#else
|
||||
callback(jsonBody["accessToken"]);
|
||||
#endif
|
||||
#endif
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,5 +1,19 @@
|
||||
#include "ApResolve.h"
|
||||
|
||||
#include <initializer_list> // for initializer_list
|
||||
#include <map> // for operator!=, operator==
|
||||
#include <memory> // for allocator, unique_ptr
|
||||
#include <string_view> // for string_view
|
||||
#include <vector> // for vector
|
||||
|
||||
#include "HTTPClient.h" // for HTTPClient, HTTPClient::Response
|
||||
#ifdef BELL_ONLY_CJSON
|
||||
#include "cJSON.h"
|
||||
#else
|
||||
#include "nlohmann/json.hpp" // for basic_json<>::object_t, basic_json
|
||||
#include "nlohmann/json_fwd.hpp" // for json
|
||||
#endif
|
||||
|
||||
using namespace cspot;
|
||||
|
||||
ApResolve::ApResolve(std::string apOverride)
|
||||
@@ -18,7 +32,7 @@ std::string ApResolve::fetchFirstApAddress()
|
||||
std::string_view responseStr = request->body();
|
||||
|
||||
// parse json with nlohmann
|
||||
#if BELL_ONLY_CJSON
|
||||
#ifdef BELL_ONLY_CJSON
|
||||
cJSON* json = cJSON_Parse(responseStr.data());
|
||||
auto ap_string = std::string(cJSON_GetArrayItem(cJSON_GetObjectItem(json, "ap_list"), 0)->valuestring);
|
||||
cJSON_Delete(json);
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
#include "AuthChallenges.h"
|
||||
|
||||
#include <algorithm> // for copy
|
||||
#include <climits> // for CHAR_BIT
|
||||
#include <random> // for default_random_engine, independent_bits_en...
|
||||
|
||||
#include "NanoPBHelper.h" // for pbPutString, pbEncode, pbDecode
|
||||
#include "pb.h" // for pb_byte_t
|
||||
#include "pb_decode.h" // for pb_release
|
||||
|
||||
using namespace cspot;
|
||||
using random_bytes_engine =
|
||||
std::independent_bits_engine<std::default_random_engine, CHAR_BIT, uint8_t>;
|
||||
|
||||
@@ -1,5 +1,26 @@
|
||||
#include "CDNTrackStream.h"
|
||||
|
||||
#include <string.h> // for memcpy
|
||||
#include <functional> // for __base
|
||||
#include <initializer_list> // for initializer_list
|
||||
#include <map> // for operator!=, operator==
|
||||
#include <string_view> // for string_view
|
||||
#include <type_traits> // for remove_extent_t
|
||||
|
||||
#include "AccessKeyFetcher.h" // for AccessKeyFetcher
|
||||
#include "BellLogger.h" // for AbstractLogger
|
||||
#include "Logger.h" // for CSPOT_LOG
|
||||
#include "Packet.h" // for cspot
|
||||
#include "SocketStream.h" // for SocketStream
|
||||
#include "Utils.h" // for bigNumAdd, bytesToHexString, string...
|
||||
#include "WrappedSemaphore.h" // for WrappedSemaphore
|
||||
#ifdef BELL_ONLY_CJSON
|
||||
#include "cJSON.h"
|
||||
#else
|
||||
#include "nlohmann/json.hpp" // for basic_json<>::object_t, basic_json
|
||||
#include "nlohmann/json_fwd.hpp" // for json
|
||||
#endif
|
||||
|
||||
using namespace cspot;
|
||||
|
||||
CDNTrackStream::CDNTrackStream(
|
||||
@@ -10,8 +31,7 @@ CDNTrackStream::CDNTrackStream(
|
||||
this->crypto = std::make_unique<Crypto>();
|
||||
}
|
||||
|
||||
CDNTrackStream::~CDNTrackStream() {
|
||||
}
|
||||
CDNTrackStream::~CDNTrackStream() {}
|
||||
|
||||
void CDNTrackStream::fail() {
|
||||
this->status = Status::FAILED;
|
||||
@@ -40,7 +60,9 @@ void CDNTrackStream::fetchFile(const std::vector<uint8_t>& trackId,
|
||||
|
||||
#ifdef BELL_ONLY_CJSON
|
||||
cJSON* jsonResult = cJSON_Parse(result.data());
|
||||
std::string cdnUrl = cJSON_GetArrayItem(cJSON_GetObjectItem(jsonResult, "cdnurl"), 0)->valuestring;
|
||||
std::string cdnUrl =
|
||||
cJSON_GetArrayItem(cJSON_GetObjectItem(jsonResult, "cdnurl"), 0)
|
||||
->valuestring;
|
||||
cJSON_Delete(jsonResult);
|
||||
#else
|
||||
auto jsonResult = nlohmann::json::parse(result);
|
||||
|
||||
@@ -1,8 +1,18 @@
|
||||
#include "LoginBlob.h"
|
||||
#include "ConstantParameters.h"
|
||||
#include "Logger.h"
|
||||
|
||||
#include <stdio.h> // for sprintf
|
||||
#include <initializer_list> // for initializer_list
|
||||
|
||||
#include "BellLogger.h" // for AbstractLogger
|
||||
#include "ConstantParameters.h" // for brandName, cspot, protoc...
|
||||
#include "Logger.h" // for CSPOT_LOG
|
||||
#include "protobuf/authentication.pb.h" // for AuthenticationType_AUTHE...
|
||||
#ifdef BELL_ONLY_CJSON
|
||||
#include "cJSON.h"
|
||||
#else
|
||||
#include "nlohmann/detail/json_pointer.hpp" // for json_pointer<>::string_t
|
||||
#include "nlohmann/json.hpp" // for basic_json<>::object_t
|
||||
#include "nlohmann/json_fwd.hpp" // for json
|
||||
#endif
|
||||
|
||||
using namespace cspot;
|
||||
|
||||
@@ -1,11 +1,25 @@
|
||||
#include "MercurySession.h"
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include "BellLogger.h"
|
||||
#include "BellTask.h"
|
||||
#include "BellUtils.h"
|
||||
#include "CSpotContext.h"
|
||||
#include "Logger.h"
|
||||
|
||||
#include <string.h> // for memcpy
|
||||
#include <memory> // for shared_ptr
|
||||
#include <mutex> // for scoped_lock
|
||||
#include <stdexcept> // for runtime_error
|
||||
#include <type_traits> // for remove_extent_t, __underlying_type_impl<>:...
|
||||
#include <utility> // for pair
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#include "BellLogger.h" // for AbstractLogger
|
||||
#include "BellTask.h" // for Task
|
||||
#include "BellUtils.h" // for BELL_SLEEP_MS
|
||||
#include "Logger.h" // for CSPOT_LOG
|
||||
#include "NanoPBHelper.h" // for pbPutString, pbDecode, pbEncode
|
||||
#include "PlainConnection.h" // for PlainConnection
|
||||
#include "ShannonConnection.h" // for ShannonConnection
|
||||
#include "TimeProvider.h" // for TimeProvider
|
||||
#include "Utils.h" // for extract, pack, hton64
|
||||
|
||||
using namespace cspot;
|
||||
|
||||
@@ -167,7 +181,7 @@ void MercurySession::handlePacket() {
|
||||
}
|
||||
|
||||
void MercurySession::failAllPending() {
|
||||
Response response = { };
|
||||
Response response = {};
|
||||
response.fail = true;
|
||||
|
||||
// Fail all callbacks
|
||||
|
||||
@@ -1,12 +1,24 @@
|
||||
#include "PlainConnection.h"
|
||||
#include <cstring>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <netdb.h> // for addrinfo, freeaddrinfo, getaddrinfo
|
||||
#include <netinet/in.h> // for IPPROTO_IP, IPPROTO_TCP
|
||||
#include <sys/errno.h> // for EAGAIN, EINTR, ETIMEDOUT, errno
|
||||
#include <sys/socket.h> // for setsockopt, connect, recv, send, shutdown
|
||||
#include <sys/time.h> // for timeval
|
||||
#endif
|
||||
#include <cstring> // for memset
|
||||
#include <stdexcept> // for runtime_error
|
||||
#ifdef _WIN32
|
||||
#include <ws2tcpip.h>
|
||||
#else
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/tcp.h> // for TCP_NODELAY
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#include "Logger.h"
|
||||
#include "BellLogger.h" // for AbstractLogger
|
||||
#include "Logger.h" // for CSPOT_LOG
|
||||
#include "Packet.h" // for cspot
|
||||
#include "Utils.h" // for extract, pack
|
||||
|
||||
using namespace cspot;
|
||||
|
||||
|
||||
@@ -1,7 +1,20 @@
|
||||
#include "PlaybackState.h"
|
||||
#include <memory>
|
||||
#include "CSpotContext.h"
|
||||
#include "Logger.h"
|
||||
|
||||
#include <string.h> // for strdup, memcpy, strcpy, strlen
|
||||
#include <cstdint> // for uint8_t
|
||||
#include <cstdlib> // for free, NULL, realloc, rand
|
||||
#include <memory> // for shared_ptr
|
||||
#include <type_traits> // for remove_extent_t
|
||||
#include <utility> // for swap
|
||||
|
||||
#include "BellLogger.h" // for AbstractLogger
|
||||
#include "CSpotContext.h" // for Context::ConfigState, Context (ptr o...
|
||||
#include "ConstantParameters.h" // for protocolVersion, swVersion
|
||||
#include "Logger.h" // for CSPOT_LOG
|
||||
#include "NanoPBHelper.h" // for pbEncode, pbPutString
|
||||
#include "Packet.h" // for cspot
|
||||
#include "pb.h" // for pb_bytes_array_t, PB_BYTES_ARRAY_T_A...
|
||||
#include "pb_decode.h" // for pb_release
|
||||
|
||||
using namespace cspot;
|
||||
|
||||
|
||||
@@ -1,6 +1,21 @@
|
||||
#include "Session.h"
|
||||
#include <memory>
|
||||
#include "AuthChallenges.h"
|
||||
|
||||
#include <limits.h> // for CHAR_BIT
|
||||
#include <cstdint> // for uint8_t
|
||||
#include <functional> // for __base
|
||||
#include <memory> // for shared_ptr, unique_ptr, make_unique
|
||||
#include <random> // for default_random_engine, independent_bi...
|
||||
#include <type_traits> // for remove_extent_t
|
||||
#include <utility> // for move
|
||||
|
||||
#include "ApResolve.h" // for ApResolve, cspot
|
||||
#include "AuthChallenges.h" // for AuthChallenges
|
||||
#include "BellLogger.h" // for AbstractLogger
|
||||
#include "Logger.h" // for CSPOT_LOG
|
||||
#include "LoginBlob.h" // for LoginBlob
|
||||
#include "Packet.h" // for Packet
|
||||
#include "PlainConnection.h" // for PlainConnection, timeoutCallback
|
||||
#include "ShannonConnection.h" // for ShannonConnection
|
||||
|
||||
using random_bytes_engine =
|
||||
std::independent_bits_engine<std::default_random_engine, CHAR_BIT, uint8_t>;
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
#include "Shannon.h"
|
||||
// #include <bit>
|
||||
#include <stdint.h> // for uint32_t
|
||||
#include <limits.h> // for CHAR_BIT
|
||||
// #define NDEBUG
|
||||
#include <assert.h>
|
||||
|
||||
#include <limits.h> // for CHAR_BIT
|
||||
#include <stddef.h> // for size_t
|
||||
|
||||
using std::size_t;
|
||||
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
#include "ShannonConnection.h"
|
||||
#include "Packet.h"
|
||||
|
||||
#include <type_traits> // for remove_extent_t
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#include "BellLogger.h" // for AbstractLogger
|
||||
#include "Logger.h" // for CSPOT_LOG
|
||||
#include "Packet.h" // for Packet, cspot
|
||||
#include "PlainConnection.h" // for PlainConnection
|
||||
#include "Shannon.h" // for Shannon
|
||||
#include "Utils.h" // for pack, extract
|
||||
|
||||
using namespace cspot;
|
||||
|
||||
|
||||
@@ -1,14 +1,22 @@
|
||||
#include "SpircHandler.h"
|
||||
#include <memory>
|
||||
#include "AccessKeyFetcher.h"
|
||||
#include "BellUtils.h"
|
||||
#include "CSpotContext.h"
|
||||
#include "Logger.h"
|
||||
#include "MercurySession.h"
|
||||
#include "PlaybackState.h"
|
||||
#include "TrackPlayer.h"
|
||||
#include "TrackReference.h"
|
||||
#include "protobuf/spirc.pb.h"
|
||||
|
||||
#include <cstdint> // for uint8_t
|
||||
#include <memory> // for shared_ptr, make_unique, unique_ptr
|
||||
#include <type_traits> // for remove_extent_t
|
||||
#include <utility> // for move
|
||||
|
||||
#include "BellLogger.h" // for AbstractLogger
|
||||
#include "CSpotContext.h" // for Context::ConfigState, Context (ptr only)
|
||||
#include "Logger.h" // for CSPOT_LOG
|
||||
#include "MercurySession.h" // for MercurySession, MercurySession::Response
|
||||
#include "NanoPBHelper.h" // for pbDecode
|
||||
#include "Packet.h" // for cspot
|
||||
#include "PlaybackState.h" // for PlaybackState, PlaybackState::State
|
||||
#include "TrackPlayer.h" // for TrackPlayer
|
||||
#include "TrackReference.h" // for TrackReference
|
||||
#include "Utils.h" // for stringHexToBytes
|
||||
#include "pb_decode.h" // for pb_release
|
||||
#include "protobuf/spirc.pb.h" // for Frame, State, Frame_fields, MessageTy...
|
||||
|
||||
using namespace cspot;
|
||||
|
||||
@@ -155,9 +163,9 @@ void SpircHandler::handleFrame(std::vector<uint8_t>& data) {
|
||||
* when last track has been reached, we has to restart as we can't tell the difference */
|
||||
if ((!isNextTrackPreloaded && this->playbackState.getNextTrackRef()) || isRequestedFromLoad) {
|
||||
CSPOT_LOG(debug, "Seek command while streaming current");
|
||||
sendEvent(EventType::SEEK, (int)playbackState.remoteFrame.position);
|
||||
playbackState.updatePositionMs(playbackState.remoteFrame.position);
|
||||
trackPlayer->seekMs(playbackState.remoteFrame.position);
|
||||
sendEvent(EventType::SEEK, (int)playbackState.remoteFrame.position);
|
||||
} else {
|
||||
CSPOT_LOG(debug, "Seek command while streaming next or before started");
|
||||
isRequestedFromLoad = true;
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
#include "TimeProvider.h"
|
||||
#include "Logger.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#include "BellLogger.h" // for AbstractLogger
|
||||
#include "Logger.h" // for CSPOT_LOG
|
||||
#include "Utils.h" // for extract, getCurrentTimestamp
|
||||
|
||||
using namespace cspot;
|
||||
|
||||
|
||||
@@ -1,12 +1,22 @@
|
||||
#include "TrackPlayer.h"
|
||||
#include <cstddef>
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
#include "CDNTrackStream.h"
|
||||
#include "Logger.h"
|
||||
#include "TrackReference.h"
|
||||
|
||||
#include <mutex> // for mutex, scoped_lock
|
||||
#include <string> // for string
|
||||
#include <type_traits> // for remove_extent_t
|
||||
#include <vector> // for vector, vector<>::value_type
|
||||
|
||||
#include "BellLogger.h" // for AbstractLogger
|
||||
#include "BellUtils.h" // for BELL_SLEEP_MS
|
||||
#include "CDNTrackStream.h" // for CDNTrackStream, CDNTrackStream::TrackInfo
|
||||
#include "Logger.h" // for CSPOT_LOG
|
||||
#include "Packet.h" // for cspot
|
||||
#include "TrackProvider.h" // for TrackProvider
|
||||
#include "WrappedSemaphore.h" // for WrappedSemaphore
|
||||
|
||||
namespace cspot {
|
||||
struct Context;
|
||||
struct TrackReference;
|
||||
} // namespace cspot
|
||||
|
||||
using namespace cspot;
|
||||
|
||||
|
||||
@@ -1,12 +1,26 @@
|
||||
#include "TrackProvider.h"
|
||||
#include <memory>
|
||||
#include "AccessKeyFetcher.h"
|
||||
#include "CDNTrackStream.h"
|
||||
#include "Logger.h"
|
||||
#include "MercurySession.h"
|
||||
#include "TrackReference.h"
|
||||
#include "Utils.h"
|
||||
#include "protobuf/metadata.pb.h"
|
||||
|
||||
#include <assert.h> // for assert
|
||||
#include <string.h> // for strlen
|
||||
#include <cstdint> // for uint8_t
|
||||
#include <functional> // for __base
|
||||
#include <memory> // for shared_ptr, weak_ptr, make_shared
|
||||
#include <string> // for string, operator+
|
||||
#include <type_traits> // for remove_extent_t
|
||||
|
||||
#include "AccessKeyFetcher.h" // for AccessKeyFetcher
|
||||
#include "BellLogger.h" // for AbstractLogger
|
||||
#include "CDNTrackStream.h" // for CDNTrackStream, CDNTrackStream::Tr...
|
||||
#include "CSpotContext.h" // for Context::ConfigState, Context (ptr...
|
||||
#include "Logger.h" // for CSPOT_LOG
|
||||
#include "MercurySession.h" // for MercurySession, MercurySession::Da...
|
||||
#include "NanoPBHelper.h" // for pbArrayToVector, pbDecode
|
||||
#include "Packet.h" // for cspot
|
||||
#include "TrackReference.h" // for TrackReference, TrackReference::Type
|
||||
#include "Utils.h" // for bytesToHexString, string_format
|
||||
#include "WrappedSemaphore.h" // for WrappedSemaphore
|
||||
#include "pb_decode.h" // for pb_release
|
||||
#include "protobuf/metadata.pb.h" // for Track, _Track, AudioFile, Episode
|
||||
|
||||
using namespace cspot;
|
||||
|
||||
@@ -21,9 +35,11 @@ TrackProvider::TrackProvider(std::shared_ptr<cspot::Context> ctx) {
|
||||
|
||||
TrackProvider::~TrackProvider() {
|
||||
pb_release(Track_fields, &trackInfo);
|
||||
pb_release(Episode_fields, &trackInfo);
|
||||
}
|
||||
|
||||
std::shared_ptr<cspot::CDNTrackStream> TrackProvider::loadFromTrackRef(TrackReference& trackRef) {
|
||||
std::shared_ptr<cspot::CDNTrackStream> TrackProvider::loadFromTrackRef(
|
||||
TrackReference& trackRef) {
|
||||
auto track = std::make_shared<cspot::CDNTrackStream>(this->accessKeyFetcher);
|
||||
this->currentTrackReference = track;
|
||||
this->trackIdInfo = trackRef;
|
||||
@@ -34,7 +50,8 @@ std::shared_ptr<cspot::CDNTrackStream> TrackProvider::loadFromTrackRef(TrackRefe
|
||||
|
||||
void TrackProvider::queryMetadata() {
|
||||
std::string requestUrl = string_format(
|
||||
"hm://metadata/3/%s/%s", trackIdInfo.type == TrackReference::Type::TRACK ? "track" : "episode",
|
||||
"hm://metadata/3/%s/%s",
|
||||
trackIdInfo.type == TrackReference::Type::TRACK ? "track" : "episode",
|
||||
bytesToHexString(trackIdInfo.gid).c_str());
|
||||
CSPOT_LOG(debug, "Requesting track metadata from %s", requestUrl.c_str());
|
||||
|
||||
@@ -50,54 +67,40 @@ void TrackProvider::queryMetadata() {
|
||||
void TrackProvider::onMetadataResponse(MercurySession::Response& res) {
|
||||
CSPOT_LOG(debug, "Got track metadata response");
|
||||
|
||||
pb_release(Track_fields, &trackInfo);
|
||||
pbDecode(trackInfo, Track_fields, res.parts[0]);
|
||||
int alternativeCount, filesCount = 0;
|
||||
bool canPlay = false;
|
||||
AudioFile* selectedFiles;
|
||||
std::vector<uint8_t> trackId, fileId;
|
||||
|
||||
CSPOT_LOG(info, "Track name: %s", trackInfo.name);
|
||||
CSPOT_LOG(info, "Track duration: %d", trackInfo.duration);
|
||||
if (trackIdInfo.type == TrackReference::Type::TRACK) {
|
||||
pb_release(Track_fields, &trackInfo);
|
||||
assert(res.parts.size() > 0);
|
||||
pbDecode(trackInfo, Track_fields, res.parts[0]);
|
||||
CSPOT_LOG(info, "Track name: %s", trackInfo.name);
|
||||
CSPOT_LOG(info, "Track duration: %d", trackInfo.duration);
|
||||
|
||||
CSPOT_LOG(debug, "trackInfo.restriction.size() = %d",
|
||||
trackInfo.restriction_count);
|
||||
CSPOT_LOG(debug, "trackInfo.restriction.size() = %d",
|
||||
trackInfo.restriction_count);
|
||||
|
||||
int altIndex = -1;
|
||||
while (!canPlayTrack(altIndex)) {
|
||||
altIndex++;
|
||||
CSPOT_LOG(info, "Trying alternative %d", altIndex);
|
||||
|
||||
if (altIndex >= trackInfo.alternative_count) {
|
||||
// no alternatives for song
|
||||
if (!this->currentTrackReference.expired()) {
|
||||
auto trackRef = this->currentTrackReference.lock();
|
||||
trackRef->status = CDNTrackStream::Status::FAILED;
|
||||
trackRef->trackReady->give();
|
||||
if (doRestrictionsApply(trackInfo.restriction,
|
||||
trackInfo.restriction_count)) {
|
||||
// Go through alternatives
|
||||
for (int x = 0; x < trackInfo.alternative_count; x++) {
|
||||
if (!doRestrictionsApply(trackInfo.alternative[x].restriction,
|
||||
trackInfo.alternative[x].restriction_count)) {
|
||||
selectedFiles = trackInfo.alternative[x].file;
|
||||
filesCount = trackInfo.alternative[x].file_count;
|
||||
trackId = pbArrayToVector(trackInfo.alternative[x].gid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
selectedFiles = trackInfo.file;
|
||||
filesCount = trackInfo.file_count;
|
||||
trackId = pbArrayToVector(trackInfo.gid);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<uint8_t> trackId;
|
||||
std::vector<uint8_t> fileId;
|
||||
|
||||
if (altIndex < 0) {
|
||||
trackId = pbArrayToVector(trackInfo.gid);
|
||||
for (int x = 0; x < trackInfo.file_count; x++) {
|
||||
if (trackInfo.file[x].format == ctx->config.audioFormat) {
|
||||
fileId = pbArrayToVector(trackInfo.file[x].file_id);
|
||||
break; // If file found stop searching
|
||||
}
|
||||
}
|
||||
} else {
|
||||
trackId = pbArrayToVector(trackInfo.alternative[altIndex].gid);
|
||||
for (int x = 0; x < trackInfo.alternative[altIndex].file_count; x++) {
|
||||
if (trackInfo.alternative[altIndex].file[x].format == ctx->config.audioFormat) {
|
||||
fileId =
|
||||
pbArrayToVector(trackInfo.alternative[altIndex].file[x].file_id);
|
||||
break; // If file found stop searching
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!this->currentTrackReference.expired()) {
|
||||
// Set track's metadata
|
||||
auto trackRef = this->currentTrackReference.lock();
|
||||
|
||||
auto imageId =
|
||||
@@ -110,6 +113,60 @@ void TrackProvider::onMetadataResponse(MercurySession::Response& res) {
|
||||
trackRef->trackInfo.imageUrl =
|
||||
"https://i.scdn.co/image/" + bytesToHexString(imageId);
|
||||
trackRef->trackInfo.duration = trackInfo.duration;
|
||||
} else {
|
||||
pb_release(Episode_fields, &episodeInfo);
|
||||
assert(res.parts.size() > 0);
|
||||
pbDecode(episodeInfo, Episode_fields, res.parts[0]);
|
||||
|
||||
CSPOT_LOG(info, "Episode name: %s", episodeInfo.name);
|
||||
CSPOT_LOG(info, "Episode duration: %d", episodeInfo.duration);
|
||||
|
||||
CSPOT_LOG(debug, "episodeInfo.restriction.size() = %d",
|
||||
episodeInfo.restriction_count);
|
||||
if (!doRestrictionsApply(episodeInfo.restriction,
|
||||
episodeInfo.restriction_count)) {
|
||||
selectedFiles = episodeInfo.file;
|
||||
filesCount = episodeInfo.file_count;
|
||||
trackId = pbArrayToVector(episodeInfo.gid);
|
||||
}
|
||||
|
||||
auto trackRef = this->currentTrackReference.lock();
|
||||
|
||||
auto imageId = pbArrayToVector(episodeInfo.covers->image[0].file_id);
|
||||
|
||||
trackRef->trackInfo.trackId = bytesToHexString(trackIdInfo.gid);
|
||||
trackRef->trackInfo.name = std::string(episodeInfo.name);
|
||||
trackRef->trackInfo.album = "";
|
||||
trackRef->trackInfo.artist = "",
|
||||
trackRef->trackInfo.imageUrl =
|
||||
"https://i.scdn.co/image/" + bytesToHexString(imageId);
|
||||
trackRef->trackInfo.duration = episodeInfo.duration;
|
||||
}
|
||||
|
||||
for (int x = 0; x < filesCount; x++) {
|
||||
CSPOT_LOG(debug, "File format: %d", selectedFiles[x].format);
|
||||
if (selectedFiles[x].format == ctx->config.audioFormat) {
|
||||
fileId = pbArrayToVector(selectedFiles[x].file_id);
|
||||
break; // If file found stop searching
|
||||
}
|
||||
|
||||
// Fallback to OGG Vorbis 96kbps
|
||||
if (fileId.size() == 0 &&
|
||||
selectedFiles[x].format == AudioFormat_OGG_VORBIS_96) {
|
||||
fileId = pbArrayToVector(selectedFiles[x].file_id);
|
||||
}
|
||||
}
|
||||
|
||||
// No viable files found for playback
|
||||
if (fileId.size() == 0) {
|
||||
CSPOT_LOG(info, "File not available for playback");
|
||||
// no alternatives for song
|
||||
if (!this->currentTrackReference.expired()) {
|
||||
auto trackRef = this->currentTrackReference.lock();
|
||||
trackRef->status = CDNTrackStream::Status::FAILED;
|
||||
trackRef->trackReady->give();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
this->fetchFile(fileId, trackId);
|
||||
@@ -147,20 +204,25 @@ bool countryListContains(char* countryList, char* country) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TrackProvider::doRestrictionsApply(Restriction* restrictions, int count) {
|
||||
for (int x = 0; x < count; x++) {
|
||||
if (restrictions[x].countries_allowed != nullptr) {
|
||||
return !countryListContains(restrictions[x].countries_allowed,
|
||||
(char*)ctx->config.countryCode.c_str());
|
||||
}
|
||||
|
||||
if (restrictions[x].countries_forbidden != nullptr) {
|
||||
return countryListContains(restrictions[x].countries_forbidden,
|
||||
(char*)ctx->config.countryCode.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TrackProvider::canPlayTrack(int altIndex) {
|
||||
if (altIndex < 0) {
|
||||
for (int x = 0; x < trackInfo.restriction_count; x++) {
|
||||
if (trackInfo.restriction[x].countries_allowed != nullptr) {
|
||||
return countryListContains(trackInfo.restriction[x].countries_allowed,
|
||||
(char*)ctx->config.countryCode.c_str());
|
||||
}
|
||||
|
||||
if (trackInfo.restriction[x].countries_forbidden != nullptr) {
|
||||
return !countryListContains(
|
||||
trackInfo.restriction[x].countries_forbidden,
|
||||
(char*)ctx->config.countryCode.c_str());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int x = 0; x < trackInfo.alternative[altIndex].restriction_count;
|
||||
x++) {
|
||||
|
||||
@@ -1,168 +1,154 @@
|
||||
#include "Utils.h"
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <chrono>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
|
||||
unsigned long long getCurrentTimestamp()
|
||||
{
|
||||
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
|
||||
#include <stdlib.h> // for strtol
|
||||
#include <iomanip> // for operator<<, setfill, setw
|
||||
#include <iostream> // for basic_ostream, hex
|
||||
#include <sstream> // for stringstream
|
||||
#include <string> // for string
|
||||
#include <type_traits> // for enable_if<>::type
|
||||
#include <chrono>
|
||||
#ifndef _WIN32
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
unsigned long long getCurrentTimestamp() {
|
||||
return std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
std::chrono::system_clock::now().time_since_epoch())
|
||||
.count();
|
||||
}
|
||||
|
||||
uint64_t hton64(uint64_t value) {
|
||||
int num = 42;
|
||||
if (*(char *)&num == 42) {
|
||||
uint32_t high_part = htonl((uint32_t)(value >> 32));
|
||||
uint32_t low_part = htonl((uint32_t)(value & 0xFFFFFFFFLL));
|
||||
return (((uint64_t)low_part) << 32) | high_part;
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
int num = 42;
|
||||
if (*(char*)&num == 42) {
|
||||
uint32_t high_part = htonl((uint32_t)(value >> 32));
|
||||
uint32_t low_part = htonl((uint32_t)(value & 0xFFFFFFFFLL));
|
||||
return (((uint64_t)low_part) << 32) | high_part;
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<uint8_t> stringHexToBytes(const std::string & s) {
|
||||
std::vector<uint8_t> v;
|
||||
v.reserve(s.length() / 2);
|
||||
std::vector<uint8_t> stringHexToBytes(const std::string& s) {
|
||||
std::vector<uint8_t> v;
|
||||
v.reserve(s.length() / 2);
|
||||
|
||||
for (std::string::size_type i = 0; i < s.length(); i += 2) {
|
||||
std::string byteString = s.substr(i, 2);
|
||||
uint8_t byte = (uint8_t) strtol(byteString.c_str(), NULL, 16);
|
||||
v.push_back(byte);
|
||||
}
|
||||
for (std::string::size_type i = 0; i < s.length(); i += 2) {
|
||||
std::string byteString = s.substr(i, 2);
|
||||
uint8_t byte = (uint8_t)strtol(byteString.c_str(), NULL, 16);
|
||||
v.push_back(byte);
|
||||
}
|
||||
|
||||
return v;
|
||||
return v;
|
||||
}
|
||||
|
||||
std::string bytesToHexString(const std::vector<uint8_t>& v) {
|
||||
std::stringstream ss;
|
||||
ss << std::hex << std::setfill('0');
|
||||
std::vector<uint8_t>::const_iterator it;
|
||||
std::stringstream ss;
|
||||
ss << std::hex << std::setfill('0');
|
||||
std::vector<uint8_t>::const_iterator it;
|
||||
|
||||
for (it = v.begin(); it != v.end(); it++) {
|
||||
ss << std::setw(2) << static_cast<unsigned>(*it);
|
||||
}
|
||||
for (it = v.begin(); it != v.end(); it++) {
|
||||
ss << std::setw(2) << static_cast<unsigned>(*it);
|
||||
}
|
||||
|
||||
return ss.str();
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::vector<uint8_t> bigNumAdd(std::vector<uint8_t> num, int n)
|
||||
{
|
||||
auto carry = n;
|
||||
for (int x = num.size() - 1; x >= 0; x--)
|
||||
{
|
||||
int res = num[x] + carry;
|
||||
if (res < 256)
|
||||
{
|
||||
carry = 0;
|
||||
num[x] = res;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Carry the rest of the division
|
||||
carry = res / 256;
|
||||
num[x] = res % 256;
|
||||
std::vector<uint8_t> bigNumAdd(std::vector<uint8_t> num, int n) {
|
||||
auto carry = n;
|
||||
for (int x = num.size() - 1; x >= 0; x--) {
|
||||
int res = num[x] + carry;
|
||||
if (res < 256) {
|
||||
carry = 0;
|
||||
num[x] = res;
|
||||
} else {
|
||||
// Carry the rest of the division
|
||||
carry = res / 256;
|
||||
num[x] = res % 256;
|
||||
|
||||
// extend the vector at the last index
|
||||
if (x == 0)
|
||||
{
|
||||
num.insert(num.begin(), carry);
|
||||
return num;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> bigNumDivide(std::vector<uint8_t> num, int n)
|
||||
{
|
||||
auto carry = 0;
|
||||
for (int x = 0; x < num.size(); x++)
|
||||
{
|
||||
int res = num[x] + carry * 256;
|
||||
if (res < n)
|
||||
{
|
||||
carry = res;
|
||||
num[x] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Carry the rest of the division
|
||||
carry = res % n;
|
||||
num[x] = res / n;
|
||||
}
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> bigNumMultiply(std::vector<uint8_t> num, int n)
|
||||
{
|
||||
auto carry = 0;
|
||||
for (int x = num.size() - 1; x >= 0; x--)
|
||||
{
|
||||
int res = num[x] * n + carry;
|
||||
if (res < 256)
|
||||
{
|
||||
carry = 0;
|
||||
num[x] = res;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Carry the rest of the division
|
||||
carry = res / 256;
|
||||
num[x] = res % 256;
|
||||
|
||||
// extend the vector at the last index
|
||||
if (x == 0)
|
||||
{
|
||||
num.insert(num.begin(), carry);
|
||||
return num;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
unsigned char h2int(char c)
|
||||
{
|
||||
if (c >= '0' && c <='9'){
|
||||
return((unsigned char)c - '0');
|
||||
}
|
||||
if (c >= 'a' && c <='f'){
|
||||
return((unsigned char)c - 'a' + 10);
|
||||
}
|
||||
if (c >= 'A' && c <='F'){
|
||||
return((unsigned char)c - 'A' + 10);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
std::string urlDecode(std::string str)
|
||||
{
|
||||
std::string encodedString="";
|
||||
char c;
|
||||
char code0;
|
||||
char code1;
|
||||
for (int i =0; i < str.length(); i++){
|
||||
c=str[i];
|
||||
if (c == '+'){
|
||||
encodedString+=' ';
|
||||
}else if (c == '%') {
|
||||
i++;
|
||||
code0=str[i];
|
||||
i++;
|
||||
code1=str[i];
|
||||
c = (h2int(code0) << 4) | h2int(code1);
|
||||
encodedString+=c;
|
||||
} else{
|
||||
|
||||
encodedString+=c;
|
||||
// extend the vector at the last index
|
||||
if (x == 0) {
|
||||
num.insert(num.begin(), carry);
|
||||
return num;
|
||||
}
|
||||
}
|
||||
|
||||
return encodedString;
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> bigNumDivide(std::vector<uint8_t> num, int n) {
|
||||
auto carry = 0;
|
||||
for (int x = 0; x < num.size(); x++) {
|
||||
int res = num[x] + carry * 256;
|
||||
if (res < n) {
|
||||
carry = res;
|
||||
num[x] = 0;
|
||||
} else {
|
||||
// Carry the rest of the division
|
||||
carry = res % n;
|
||||
num[x] = res / n;
|
||||
}
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> bigNumMultiply(std::vector<uint8_t> num, int n) {
|
||||
auto carry = 0;
|
||||
for (int x = num.size() - 1; x >= 0; x--) {
|
||||
int res = num[x] * n + carry;
|
||||
if (res < 256) {
|
||||
carry = 0;
|
||||
num[x] = res;
|
||||
} else {
|
||||
// Carry the rest of the division
|
||||
carry = res / 256;
|
||||
num[x] = res % 256;
|
||||
|
||||
// extend the vector at the last index
|
||||
if (x == 0) {
|
||||
num.insert(num.begin(), carry);
|
||||
return num;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
unsigned char h2int(char c) {
|
||||
if (c >= '0' && c <= '9') {
|
||||
return ((unsigned char)c - '0');
|
||||
}
|
||||
if (c >= 'a' && c <= 'f') {
|
||||
return ((unsigned char)c - 'a' + 10);
|
||||
}
|
||||
if (c >= 'A' && c <= 'F') {
|
||||
return ((unsigned char)c - 'A' + 10);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
std::string urlDecode(std::string str) {
|
||||
std::string encodedString = "";
|
||||
char c;
|
||||
char code0;
|
||||
char code1;
|
||||
for (int i = 0; i < str.length(); i++) {
|
||||
c = str[i];
|
||||
if (c == '+') {
|
||||
encodedString += ' ';
|
||||
} else if (c == '%') {
|
||||
i++;
|
||||
code0 = str[i];
|
||||
i++;
|
||||
code1 = str[i];
|
||||
c = (h2int(code0) << 4) | h2int(code1);
|
||||
encodedString += c;
|
||||
} else {
|
||||
|
||||
encodedString += c;
|
||||
}
|
||||
}
|
||||
|
||||
return encodedString;
|
||||
}
|
||||
Reference in New Issue
Block a user