mirror of
https://github.com/sle118/squeezelite-esp32.git
synced 2025-12-11 22:17:17 +03:00
Merge branch 'master-v4.3' of https://github.com/wizmo2/squeezelite-esp32 into led_visu-v4.3
This commit is contained in:
@@ -66,7 +66,7 @@ static void squeezelite_thread(void *arg){
|
||||
|
||||
cmd_send_messaging("cfg-audio-tmpl",ret > 1 ? MESSAGING_ERROR : MESSAGING_WARNING,"squeezelite exited with error code %d\n", ret);
|
||||
|
||||
if (ret == 1) {
|
||||
if (ret <= 1) {
|
||||
int wait = 60;
|
||||
wait_for_commit();
|
||||
cmd_send_messaging("cfg-audio-tmpl",MESSAGING_ERROR,"Rebooting in %d sec\n", wait);
|
||||
|
||||
@@ -16,7 +16,10 @@
|
||||
#include <stdarg.h>
|
||||
#include <ApResolve.h>
|
||||
|
||||
#include "BellTask.h"
|
||||
#include "MDNSService.h"
|
||||
#include "TrackPlayer.h"
|
||||
#include "CSpotContext.h"
|
||||
#include "SpircHandler.h"
|
||||
#include "LoginBlob.h"
|
||||
#include "CentralAudioBuffer.h"
|
||||
@@ -39,13 +42,13 @@ class chunkManager : public bell::Task {
|
||||
public:
|
||||
std::atomic<bool> isRunning = true;
|
||||
std::atomic<bool> isPaused = true;
|
||||
std::atomic<bool> discard = true;
|
||||
chunkManager(std::shared_ptr<bell::CentralAudioBuffer> centralAudioBuffer, std::function<void()> trackHandler,
|
||||
std::function<void(const uint8_t*, size_t)> dataHandler);
|
||||
chunkManager(std::function<void()> trackHandler, std::function<void(const uint8_t*, size_t)> dataHandler);
|
||||
size_t writePCM(uint8_t* data, size_t bytes, std::string_view trackId, size_t sequence);
|
||||
void flush();
|
||||
void teardown();
|
||||
|
||||
private:
|
||||
std::shared_ptr<bell::CentralAudioBuffer> centralAudioBuffer;
|
||||
std::unique_ptr<bell::CentralAudioBuffer> centralAudioBuffer;
|
||||
std::function<void()> trackHandler;
|
||||
std::function<void(const uint8_t*, size_t)> dataHandler;
|
||||
std::mutex runningMutex;
|
||||
@@ -53,20 +56,27 @@ private:
|
||||
void runTask() override;
|
||||
};
|
||||
|
||||
chunkManager::chunkManager(std::shared_ptr<bell::CentralAudioBuffer> centralAudioBuffer,
|
||||
std::function<void()> trackHandler, std::function<void(const uint8_t*, size_t)> dataHandler)
|
||||
chunkManager::chunkManager(std::function<void()> trackHandler, std::function<void(const uint8_t*, size_t)> dataHandler)
|
||||
: bell::Task("chunker", 4 * 1024, 0, 0) {
|
||||
this->centralAudioBuffer = centralAudioBuffer;
|
||||
this->centralAudioBuffer = std::make_unique<bell::CentralAudioBuffer>(32);
|
||||
this->trackHandler = trackHandler;
|
||||
this->dataHandler = dataHandler;
|
||||
startTask();
|
||||
}
|
||||
|
||||
size_t chunkManager::writePCM(uint8_t* data, size_t bytes, std::string_view trackId, size_t sequence) {
|
||||
return centralAudioBuffer->writePCM(data, bytes, sequence);
|
||||
}
|
||||
|
||||
void chunkManager::teardown() {
|
||||
isRunning = false;
|
||||
std::scoped_lock lock(runningMutex);
|
||||
}
|
||||
|
||||
void chunkManager::flush() {
|
||||
centralAudioBuffer->clearBuffer();
|
||||
}
|
||||
|
||||
void chunkManager::runTask() {
|
||||
std::scoped_lock lock(runningMutex);
|
||||
size_t lastHash = 0;
|
||||
@@ -89,11 +99,10 @@ void chunkManager::runTask() {
|
||||
if (lastHash != chunk->trackHash) {
|
||||
CSPOT_LOG(info, "hash update %x => %x", lastHash, chunk->trackHash);
|
||||
lastHash = chunk->trackHash;
|
||||
discard = false;
|
||||
trackHandler();
|
||||
}
|
||||
|
||||
if (!discard) dataHandler(chunk->pcmData, chunk->pcmSize);
|
||||
dataHandler(chunk->pcmData, chunk->pcmSize);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,7 +114,6 @@ class cspotPlayer : public bell::Task {
|
||||
private:
|
||||
std::string name;
|
||||
bell::WrappedSemaphore clientConnected;
|
||||
std::shared_ptr<bell::CentralAudioBuffer> centralAudioBuffer;
|
||||
|
||||
int startOffset, volume = 0, bitrate = 160;
|
||||
httpd_handle_t serverHandle;
|
||||
@@ -225,8 +233,7 @@ esp_err_t cspotPlayer::handlePOST(httpd_req_t *request) {
|
||||
void cspotPlayer::eventHandler(std::unique_ptr<cspot::SpircHandler::Event> event) {
|
||||
switch (event->eventType) {
|
||||
case cspot::SpircHandler::EventType::PLAYBACK_START: {
|
||||
chunker->discard = true;
|
||||
centralAudioBuffer->clearBuffer();
|
||||
chunker->flush();
|
||||
|
||||
// we are not playing anymore
|
||||
trackStatus = TRACK_INIT;
|
||||
@@ -257,17 +264,17 @@ void cspotPlayer::eventHandler(std::unique_ptr<cspot::SpircHandler::Event> event
|
||||
case cspot::SpircHandler::EventType::PREV:
|
||||
case cspot::SpircHandler::EventType::FLUSH: {
|
||||
// FLUSH is sent when there is no next, just clean everything
|
||||
centralAudioBuffer->clearBuffer();
|
||||
chunker->flush();
|
||||
cmdHandler(CSPOT_FLUSH);
|
||||
break;
|
||||
}
|
||||
case cspot::SpircHandler::EventType::DISC:
|
||||
centralAudioBuffer->clearBuffer();
|
||||
chunker->flush();
|
||||
cmdHandler(CSPOT_DISC);
|
||||
chunker->teardown();
|
||||
break;
|
||||
case cspot::SpircHandler::EventType::SEEK: {
|
||||
centralAudioBuffer->clearBuffer();
|
||||
chunker->flush();
|
||||
cmdHandler(CSPOT_SEEK, std::get<int>(event->data));
|
||||
break;
|
||||
}
|
||||
@@ -372,7 +379,6 @@ void cspotPlayer::runTask() {
|
||||
|
||||
CSPOT_LOG(info, "Spotify client connected for %s", name.c_str());
|
||||
|
||||
centralAudioBuffer = std::make_shared<bell::CentralAudioBuffer>(32);
|
||||
auto ctx = cspot::Context::createFromBlob(blob);
|
||||
|
||||
if (bitrate == 320) ctx->config.audioFormat = AudioFormat_OGG_VORBIS_320;
|
||||
@@ -385,11 +391,20 @@ void cspotPlayer::runTask() {
|
||||
// Auth successful
|
||||
if (token.size() > 0) {
|
||||
spirc = std::make_unique<cspot::SpircHandler>(ctx);
|
||||
|
||||
// Create a player, pass the track handler
|
||||
chunker = std::make_unique<chunkManager>(
|
||||
[this](void) {
|
||||
return trackHandler();
|
||||
},
|
||||
[this](const uint8_t* data, size_t bytes) {
|
||||
return dataHandler(data, bytes);
|
||||
});
|
||||
|
||||
// set call back to calculate a hash on trackId
|
||||
spirc->getTrackPlayer()->setDataCallback(
|
||||
[this](uint8_t* data, size_t bytes, std::string_view trackId, size_t sequence) {
|
||||
return centralAudioBuffer->writePCM(data, bytes, sequence);
|
||||
return chunker->writePCM(data, bytes, trackId, sequence);
|
||||
});
|
||||
|
||||
// set event (PLAY, VOLUME...) handler
|
||||
@@ -401,15 +416,6 @@ void cspotPlayer::runTask() {
|
||||
// Start handling mercury messages
|
||||
ctx->session->startTask();
|
||||
|
||||
// Create a player, pass the tack handler
|
||||
chunker = std::make_unique<chunkManager>(centralAudioBuffer,
|
||||
[this](void) {
|
||||
return trackHandler();
|
||||
},
|
||||
[this](const uint8_t* data, size_t bytes) {
|
||||
return dataHandler(data, bytes);
|
||||
});
|
||||
|
||||
// set volume at connection
|
||||
cmdHandler(CSPOT_VOLUME, volume);
|
||||
|
||||
@@ -447,7 +453,6 @@ void cspotPlayer::runTask() {
|
||||
}
|
||||
|
||||
// we want to release memory ASAP and for sure
|
||||
centralAudioBuffer.reset();
|
||||
ctx.reset();
|
||||
token.clear();
|
||||
|
||||
|
||||
@@ -71,6 +71,7 @@ class CentralAudioBuffer {
|
||||
void clearBuffer() {
|
||||
std::scoped_lock lock(this->dataAccessMutex);
|
||||
//size_t exceptSize = currentSampleRate + (sizeof(AudioChunk) - (currentSampleRate % sizeof(AudioChunk)));
|
||||
hasChunk = false;
|
||||
audioBuffer->emptyBuffer();
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -54,7 +54,6 @@ struct opus {
|
||||
size_t overframes;
|
||||
u8_t *overbuf;
|
||||
int channels;
|
||||
bool eos;
|
||||
};
|
||||
|
||||
#if !LINKALL
|
||||
@@ -133,7 +132,7 @@ static opus_uint32 parse_uint32(const unsigned char* _data) {
|
||||
}
|
||||
|
||||
static int get_opus_packet(void) {
|
||||
int status = 0;
|
||||
int status, packet = -1;
|
||||
|
||||
LOCK_S;
|
||||
size_t bytes = min(_buf_used(streambuf), _buf_cont_read(streambuf));
|
||||
@@ -152,9 +151,13 @@ static int get_opus_packet(void) {
|
||||
// if we have a new page, put it in
|
||||
if (status) OG(&go, stream_pagein, &u->state, &u->page);
|
||||
}
|
||||
|
||||
// only return a negative value when end of streaming is reached
|
||||
if (status > 0) packet = status;
|
||||
else if (stream.state > DISCONNECT) packet = 0;
|
||||
|
||||
UNLOCK_S;
|
||||
return status;
|
||||
return packet;
|
||||
}
|
||||
|
||||
static int read_opus_header(void) {
|
||||
@@ -219,7 +222,6 @@ static int read_opus_header(void) {
|
||||
|
||||
static decode_state opus_decompress(void) {
|
||||
frames_t frames;
|
||||
int n;
|
||||
u8_t *write_buf;
|
||||
|
||||
if (decode.new_stream) {
|
||||
@@ -257,6 +259,8 @@ static decode_state opus_decompress(void) {
|
||||
frames = process.max_in_frames;
|
||||
write_buf = process.inbuf;
|
||||
);
|
||||
|
||||
int packet, n = 0;
|
||||
|
||||
// get some packets and decode them, or use the leftover from previous pass
|
||||
if (u->overframes) {
|
||||
@@ -265,7 +269,7 @@ static decode_state opus_decompress(void) {
|
||||
memcpy(write_buf, u->overbuf, u->overframes * BYTES_PER_FRAME);
|
||||
n = u->overframes;
|
||||
u->overframes = 0;
|
||||
} else if (get_opus_packet() > 0) {
|
||||
} else if ((packet = get_opus_packet()) > 0) {
|
||||
if (frames < MAX_OPUS_FRAMES) {
|
||||
// don't have enough contiguous space, use the overflow buffer
|
||||
n = OP(&gu, decode, u->decoder, u->packet.packet, u->packet.bytes, (opus_int16*) u->overbuf, MAX_OPUS_FRAMES, 0);
|
||||
@@ -280,10 +284,10 @@ static decode_state opus_decompress(void) {
|
||||
* outputbuf and streambuf for maybe a long time while we process it all, so don't do that */
|
||||
n = OP(&gu, decode, u->decoder, u->packet.packet, u->packet.bytes, (opus_int16*) write_buf, frames, 0);
|
||||
}
|
||||
} else if (!OG(&go, page_eos, &u->page)) {
|
||||
} else if (!packet && !OG(&go, page_eos, &u->page)) {
|
||||
UNLOCK_O_direct;
|
||||
return DECODE_RUNNING;
|
||||
} else u->eos = true;
|
||||
}
|
||||
|
||||
if (n > 0) {
|
||||
frames_t count;
|
||||
@@ -326,7 +330,7 @@ static decode_state opus_decompress(void) {
|
||||
|
||||
} else if (n == 0) {
|
||||
|
||||
if (stream.state <= DISCONNECT && u->eos) {
|
||||
if (packet < 0) {
|
||||
LOG_INFO("end of decode");
|
||||
UNLOCK_O_direct;
|
||||
return DECODE_COMPLETE;
|
||||
@@ -351,7 +355,6 @@ static void opus_open(u8_t size, u8_t rate, u8_t chan, u8_t endianness) {
|
||||
|
||||
if (!u->overbuf) u->overbuf = malloc(MAX_OPUS_FRAMES * BYTES_PER_FRAME);
|
||||
|
||||
u->eos = false;
|
||||
u->status = OGG_SYNC;
|
||||
u->overframes = 0;
|
||||
|
||||
|
||||
@@ -65,7 +65,6 @@ struct vorbis {
|
||||
};
|
||||
int rate, channels;
|
||||
uint32_t overflow;
|
||||
bool eos;
|
||||
};
|
||||
|
||||
#if !LINKALL
|
||||
@@ -133,7 +132,7 @@ extern struct processstate process;
|
||||
#endif
|
||||
|
||||
static int get_ogg_packet(void) {
|
||||
int status = 0;
|
||||
int status, packet = -1;
|
||||
|
||||
LOCK_S;
|
||||
size_t bytes = min(_buf_used(streambuf), _buf_cont_read(streambuf));
|
||||
@@ -152,9 +151,13 @@ static int get_ogg_packet(void) {
|
||||
// if we have a new page, put it in
|
||||
if (status) OG(&go, stream_pagein, &v->state, &v->page);
|
||||
}
|
||||
|
||||
// only return a negative value when end of streaming is reached
|
||||
if (status > 0) packet = status;
|
||||
else if (stream.state > DISCONNECT) packet = 0;
|
||||
|
||||
UNLOCK_S;
|
||||
return status;
|
||||
return packet;
|
||||
}
|
||||
|
||||
static int read_vorbis_header(void) {
|
||||
@@ -261,10 +264,8 @@ inline int pcm_out(vorbis_dsp_state* decoder, void*** pcm) {
|
||||
|
||||
static decode_state vorbis_decode(void) {
|
||||
frames_t frames;
|
||||
int n = 0;
|
||||
u8_t *write_buf;
|
||||
void** pcm = NULL;
|
||||
|
||||
|
||||
if (decode.new_stream) {
|
||||
int status = read_vorbis_header();
|
||||
|
||||
@@ -300,19 +301,22 @@ static decode_state vorbis_decode(void) {
|
||||
frames = process.max_in_frames;
|
||||
write_buf = process.inbuf;
|
||||
);
|
||||
|
||||
void** pcm = NULL;
|
||||
int packet, n = 0;
|
||||
|
||||
if (v->overflow) {
|
||||
n = pcm_out(&v->decoder, &pcm);
|
||||
v->overflow = n - min(n, frames);
|
||||
} else if (get_ogg_packet() > 0) {
|
||||
} else if ((packet = get_ogg_packet()) > 0) {
|
||||
n = OV(&gv, synthesis, &v->block, &v->packet);
|
||||
if (n == 0) n = OV(&gv, synthesis_blockin, &v->decoder, &v->block);
|
||||
if (n == 0) n = pcm_out(&v->decoder, &pcm);
|
||||
v->overflow = n - min(n, frames);
|
||||
} else if (!OG(&go, page_eos, &v->page)) {
|
||||
} else if (!packet && !OG(&go, page_eos, &v->page)) {
|
||||
UNLOCK_O_direct;
|
||||
return DECODE_RUNNING;
|
||||
} else v->eos = true;
|
||||
}
|
||||
|
||||
if (n > 0) {
|
||||
ISAMPLE_T *optr = (ISAMPLE_T*) write_buf;
|
||||
@@ -370,7 +374,7 @@ static decode_state vorbis_decode(void) {
|
||||
|
||||
} else if (n == 0) {
|
||||
|
||||
if (stream.state <= DISCONNECT && v->eos) {
|
||||
if (packet < 0) {
|
||||
LOG_INFO("end of decode");
|
||||
UNLOCK_O_direct;
|
||||
return DECODE_COMPLETE;
|
||||
@@ -397,7 +401,6 @@ static void vorbis_open(u8_t size, u8_t rate, u8_t chan, u8_t endianness) {
|
||||
OV(&go, dsp_clear, &v->decoder);
|
||||
}
|
||||
|
||||
v->eos = false;
|
||||
v->opened = false;
|
||||
v->status = OGG_SYNC;
|
||||
v->overflow = 0;
|
||||
|
||||
File diff suppressed because one or more lines are too long
BIN
components/wifi-manager/webapp/dist/index.html.gz
vendored
BIN
components/wifi-manager/webapp/dist/index.html.gz
vendored
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
@@ -43,6 +43,9 @@ declare function getStatus(): {};
|
||||
declare function getStatus(): {};
|
||||
declare function getStatus(): {};
|
||||
declare function getStatus(): {};
|
||||
declare function getStatus(): {};
|
||||
declare function getStatus(): {};
|
||||
declare function getStatus(): {};
|
||||
declare function getRadioButton(entry: any): string;
|
||||
declare function getRadioButton(entry: any): string;
|
||||
declare function getRadioButton(entry: any): string;
|
||||
@@ -88,6 +91,12 @@ declare function getRadioButton(entry: any): string;
|
||||
declare function getRadioButton(entry: any): string;
|
||||
declare function getRadioButton(entry: any): string;
|
||||
declare function getRadioButton(entry: any): string;
|
||||
declare function getRadioButton(entry: any): string;
|
||||
declare function getRadioButton(entry: any): string;
|
||||
declare function getRadioButton(entry: any): string;
|
||||
declare function pushStatus(): void;
|
||||
declare function pushStatus(): void;
|
||||
declare function pushStatus(): void;
|
||||
declare function pushStatus(): void;
|
||||
declare function pushStatus(): void;
|
||||
declare function pushStatus(): void;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
target_add_binary_data( __idf_wifi-manager webapp/dist/css/index.cd56ff129e3113d8cd3a.css.gz BINARY)
|
||||
target_add_binary_data( __idf_wifi-manager webapp/dist/favicon-32x32.png BINARY)
|
||||
target_add_binary_data( __idf_wifi-manager webapp/dist/index.html.gz BINARY)
|
||||
target_add_binary_data( __idf_wifi-manager webapp/dist/js/index.b79c88.bundle.js.gz BINARY)
|
||||
target_add_binary_data( __idf_wifi-manager webapp/dist/js/node_vendors.b79c88.bundle.js.gz BINARY)
|
||||
target_add_binary_data( __idf_wifi-manager webapp/dist/js/index.997af2.bundle.js.gz BINARY)
|
||||
target_add_binary_data( __idf_wifi-manager webapp/dist/js/node_vendors.997af2.bundle.js.gz BINARY)
|
||||
|
||||
@@ -6,29 +6,29 @@ extern const uint8_t _favicon_32x32_png_start[] asm("_binary_favicon_32x32_png_s
|
||||
extern const uint8_t _favicon_32x32_png_end[] asm("_binary_favicon_32x32_png_end");
|
||||
extern const uint8_t _index_html_gz_start[] asm("_binary_index_html_gz_start");
|
||||
extern const uint8_t _index_html_gz_end[] asm("_binary_index_html_gz_end");
|
||||
extern const uint8_t _index_b79c88_bundle_js_gz_start[] asm("_binary_index_b79c88_bundle_js_gz_start");
|
||||
extern const uint8_t _index_b79c88_bundle_js_gz_end[] asm("_binary_index_b79c88_bundle_js_gz_end");
|
||||
extern const uint8_t _node_vendors_b79c88_bundle_js_gz_start[] asm("_binary_node_vendors_b79c88_bundle_js_gz_start");
|
||||
extern const uint8_t _node_vendors_b79c88_bundle_js_gz_end[] asm("_binary_node_vendors_b79c88_bundle_js_gz_end");
|
||||
extern const uint8_t _index_997af2_bundle_js_gz_start[] asm("_binary_index_997af2_bundle_js_gz_start");
|
||||
extern const uint8_t _index_997af2_bundle_js_gz_end[] asm("_binary_index_997af2_bundle_js_gz_end");
|
||||
extern const uint8_t _node_vendors_997af2_bundle_js_gz_start[] asm("_binary_node_vendors_997af2_bundle_js_gz_start");
|
||||
extern const uint8_t _node_vendors_997af2_bundle_js_gz_end[] asm("_binary_node_vendors_997af2_bundle_js_gz_end");
|
||||
const char * resource_lookups[] = {
|
||||
"/css/index.cd56ff129e3113d8cd3a.css.gz",
|
||||
"/favicon-32x32.png",
|
||||
"/index.html.gz",
|
||||
"/js/index.b79c88.bundle.js.gz",
|
||||
"/js/node_vendors.b79c88.bundle.js.gz",
|
||||
"/js/index.997af2.bundle.js.gz",
|
||||
"/js/node_vendors.997af2.bundle.js.gz",
|
||||
""
|
||||
};
|
||||
const uint8_t * resource_map_start[] = {
|
||||
_index_cd56ff129e3113d8cd3a_css_gz_start,
|
||||
_favicon_32x32_png_start,
|
||||
_index_html_gz_start,
|
||||
_index_b79c88_bundle_js_gz_start,
|
||||
_node_vendors_b79c88_bundle_js_gz_start
|
||||
_index_997af2_bundle_js_gz_start,
|
||||
_node_vendors_997af2_bundle_js_gz_start
|
||||
};
|
||||
const uint8_t * resource_map_end[] = {
|
||||
_index_cd56ff129e3113d8cd3a_css_gz_end,
|
||||
_favicon_32x32_png_end,
|
||||
_index_html_gz_end,
|
||||
_index_b79c88_bundle_js_gz_end,
|
||||
_node_vendors_b79c88_bundle_js_gz_end
|
||||
_index_997af2_bundle_js_gz_end,
|
||||
_node_vendors_997af2_bundle_js_gz_end
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/***********************************
|
||||
webpack_headers
|
||||
dist/css/index.cd56ff129e3113d8cd3a.css.gz,dist/favicon-32x32.png,dist/index.html.gz,dist/js/index.b79c88.bundle.js.gz,dist/js/node_vendors.b79c88.bundle.js.gz
|
||||
dist/css/index.cd56ff129e3113d8cd3a.css.gz,dist/favicon-32x32.png,dist/index.html.gz,dist/js/index.997af2.bundle.js.gz,dist/js/node_vendors.997af2.bundle.js.gz
|
||||
***********************************/
|
||||
#pragma once
|
||||
#include <inttypes.h>
|
||||
|
||||
Reference in New Issue
Block a user