update cspot

This commit is contained in:
philippe44
2023-10-02 19:06:59 -07:00
parent eb7df4a5e9
commit 719b289659
26 changed files with 156 additions and 146 deletions

View File

@@ -1,3 +1,6 @@
2023-10-02
- update cspot
2023-09-29 2023-09-29
- sleep mechanism - sleep mechanism
- spotify can store credentials so that zeroconf is optional and players are always registered - spotify can store credentials so that zeroconf is optional and players are always registered

View File

@@ -1,8 +1,8 @@
#include "AACDecoder.h" #include "AACDecoder.h"
#include <assert.h>
#include <stdlib.h> // for free, malloc #include <stdlib.h> // for free, malloc
#include <string.h> #include <string.h>
#include <assert.h>
#include "e_tmp4audioobjecttype.h" #include "e_tmp4audioobjecttype.h"
#include "pvmp4audiodecoder_api.h" #include "pvmp4audiodecoder_api.h"

View File

@@ -24,7 +24,7 @@ class DecodersInstance {
void ensureAAC() { void ensureAAC() {
// if (aacDecoder == NULL) { // if (aacDecoder == NULL) {
// aacDecoder = AACInitDecoder(); // aacDecoder = AACInitDecoder();
// } // }
} }

View File

@@ -7,7 +7,8 @@
using namespace bell; using namespace bell;
MP3Container::MP3Container(std::istream& istr, const std::byte* headingBytes) : bell::AudioContainer(istr) { MP3Container::MP3Container(std::istream& istr, const std::byte* headingBytes)
: bell::AudioContainer(istr) {
if (headingBytes != nullptr) { if (headingBytes != nullptr) {
memcpy(buffer.data(), headingBytes, 7); memcpy(buffer.data(), headingBytes, 7);
bytesInBuffer = 7; bytesInBuffer = 7;
@@ -38,7 +39,6 @@ std::byte* MP3Container::readSample(uint32_t& len) {
bytesInBuffer -= toConsume; bytesInBuffer -= toConsume;
} }
if (!this->fillBuffer()) { if (!this->fillBuffer()) {
len = 0; len = 0;
return nullptr; return nullptr;

View File

@@ -2,76 +2,77 @@
#include "MGStreamAdapter.h" #include "MGStreamAdapter.h"
mg_buf::mg_buf(struct mg_connection* _conn) : conn(_conn) { mg_buf::mg_buf(struct mg_connection* _conn) : conn(_conn) {
setp(buffer, buffer + BUF_SIZE - 1); // -1 to leave space for overflow '\0' setp(buffer, buffer + BUF_SIZE - 1); // -1 to leave space for overflow '\0'
} }
mg_buf::int_type mg_buf::overflow(int_type c) { mg_buf::int_type mg_buf::overflow(int_type c) {
if (c != EOF) { if (c != EOF) {
*pptr() = c; *pptr() = c;
pbump(1); pbump(1);
} }
if (flush_buffer() == EOF) { if (flush_buffer() == EOF) {
return EOF; return EOF;
} }
return c; return c;
} }
int mg_buf::flush_buffer() { int mg_buf::flush_buffer() {
int len = int(pptr() - pbase()); int len = int(pptr() - pbase());
if (mg_write(conn, buffer, len) != len) { if (mg_write(conn, buffer, len) != len) {
return EOF; return EOF;
} }
pbump(-len); // reset put pointer accordingly pbump(-len); // reset put pointer accordingly
return len; return len;
} }
int mg_buf::sync() { int mg_buf::sync() {
if (flush_buffer() == EOF) { if (flush_buffer() == EOF) {
return -1; // return -1 on error return -1; // return -1 on error
} }
return 0; return 0;
} }
MGStreamAdapter::MGStreamAdapter(struct mg_connection* _conn) : std::ostream(&buf), buf(_conn) { MGStreamAdapter::MGStreamAdapter(struct mg_connection* _conn)
rdbuf(&buf); // set the custom streambuf : std::ostream(&buf), buf(_conn) {
rdbuf(&buf); // set the custom streambuf
} }
mg_read_buf::mg_read_buf(struct mg_connection* _conn) : conn(_conn) { mg_read_buf::mg_read_buf(struct mg_connection* _conn) : conn(_conn) {
setg(buffer + BUF_SIZE, // beginning of putback area setg(buffer + BUF_SIZE, // beginning of putback area
buffer + BUF_SIZE, // read position buffer + BUF_SIZE, // read position
buffer + BUF_SIZE); // end position buffer + BUF_SIZE); // end position
} }
mg_read_buf::int_type mg_read_buf::underflow() { mg_read_buf::int_type mg_read_buf::underflow() {
if (gptr() < egptr()) { // buffer not exhausted if (gptr() < egptr()) { // buffer not exhausted
return traits_type::to_int_type(*gptr());
}
char* base = buffer;
char* start = base;
if (eback() == base) { // true when this isn't the first fill
// Make arrangements for putback characters
std::memmove(base, egptr() - 2, 2);
start += 2;
}
// Read new characters
int n = mg_read(conn, start, buffer + BUF_SIZE - start);
if (n == 0) {
return traits_type::eof();
}
// Set buffer pointers
setg(base, start, start + n);
// Return next character
return traits_type::to_int_type(*gptr()); return traits_type::to_int_type(*gptr());
}
char* base = buffer;
char* start = base;
if (eback() == base) { // true when this isn't the first fill
// Make arrangements for putback characters
std::memmove(base, egptr() - 2, 2);
start += 2;
}
// Read new characters
int n = mg_read(conn, start, buffer + BUF_SIZE - start);
if (n == 0) {
return traits_type::eof();
}
// Set buffer pointers
setg(base, start, start + n);
// Return next character
return traits_type::to_int_type(*gptr());
} }
MGInputStreamAdapter::MGInputStreamAdapter(struct mg_connection* _conn) : std::istream(&buf), buf(_conn) { MGInputStreamAdapter::MGInputStreamAdapter(struct mg_connection* _conn)
rdbuf(&buf); // set the custom streambuf : std::istream(&buf), buf(_conn) {
rdbuf(&buf); // set the custom streambuf
} }

View File

@@ -1,12 +1,12 @@
#include "X509Bundle.h" #include "X509Bundle.h"
#include <mbedtls/md.h> // for mbedtls_md, mbedtls_md_get_size #include <mbedtls/md.h> // for mbedtls_md, mbedtls_md_get_size
#include <mbedtls/pk.h> // for mbedtls_pk_can_do, mbedtls_pk_pa... #include <mbedtls/pk.h> // for mbedtls_pk_can_do, mbedtls_pk_pa...
#include <mbedtls/ssl.h> // for mbedtls_ssl_conf_ca_chain, mbedt... #include <mbedtls/ssl.h> // for mbedtls_ssl_conf_ca_chain, mbedt...
#include <mbedtls/x509.h> // for mbedtls_x509_buf, MBEDTLS_ERR_X5... #include <mbedtls/x509.h> // for mbedtls_x509_buf, MBEDTLS_ERR_X5...
#include <stdlib.h> // for free, calloc #include <stdlib.h> // for free, calloc
#include <string.h> // for memcmp, memcpy #include <string.h> // for memcmp, memcpy
#include <stdexcept> // for runtime_error #include <stdexcept> // for runtime_error
#include "BellLogger.h" // for AbstractLogger, BELL_LOG #include "BellLogger.h" // for AbstractLogger, BELL_LOG

View File

@@ -1,8 +1,8 @@
#pragma once #pragma once
#include <cstring>
#include <iostream> #include <iostream>
#include <ostream> #include <ostream>
#include <cstring>
#include "civetweb.h" #include "civetweb.h"
const size_t BUF_SIZE = 1024; const size_t BUF_SIZE = 1024;
@@ -36,25 +36,24 @@ class MGStreamAdapter : public std::ostream {
// Custom streambuf // Custom streambuf
class mg_read_buf : public std::streambuf { class mg_read_buf : public std::streambuf {
private: private:
struct mg_connection* conn; struct mg_connection* conn;
char buffer[BUF_SIZE]; char buffer[BUF_SIZE];
public: public:
mg_read_buf(struct mg_connection* _conn); mg_read_buf(struct mg_connection* _conn);
protected: protected:
virtual int_type underflow(); virtual int_type underflow();
}; };
/** /**
* @brief Adapts istream to mg_read * @brief Adapts istream to mg_read
*/ */
class MGInputStreamAdapter : public std::istream { class MGInputStreamAdapter : public std::istream {
private: private:
mg_read_buf buf; mg_read_buf buf;
public: public:
MGInputStreamAdapter(struct mg_connection* _conn); MGInputStreamAdapter(struct mg_connection* _conn);
}; };

View File

@@ -145,9 +145,9 @@ std::vector<uint8_t> CryptoMbedTLS::pbkdf2HmacSha1(
// Free sha context // Free sha context
mbedtls_md_free(&sha1Context); mbedtls_md_free(&sha1Context);
#else #else
mbedtls_pkcs5_pbkdf2_hmac_ext(MBEDTLS_MD_SHA1, password.data(), password.size(), mbedtls_pkcs5_pbkdf2_hmac_ext(MBEDTLS_MD_SHA1, password.data(),
salt.data(), salt.size(), iterations, digestSize, password.size(), salt.data(), salt.size(),
digest.data()); iterations, digestSize, digest.data());
#endif #endif
return digest; return digest;

View File

@@ -3,12 +3,12 @@
#include <stdint.h> #include <stdint.h>
#include <memory> #include <memory>
#include "Crypto.h"
#include "LoginBlob.h" #include "LoginBlob.h"
#include "MercurySession.h" #include "MercurySession.h"
#include "TimeProvider.h" #include "TimeProvider.h"
#include "Crypto.h" #include "protobuf/authentication.pb.h" // for AuthenticationType_AUTHE...
#include "protobuf/metadata.pb.h" #include "protobuf/metadata.pb.h"
#include "protobuf/authentication.pb.h" // for AuthenticationType_AUTHE...
#ifdef BELL_ONLY_CJSON #ifdef BELL_ONLY_CJSON
#include "cJSON.h" #include "cJSON.h"
#else #else
@@ -37,24 +37,28 @@ struct Context {
std::shared_ptr<cspot::MercurySession> session; std::shared_ptr<cspot::MercurySession> session;
std::string getCredentialsJson() { std::string getCredentialsJson() {
#ifdef BELL_ONLY_CJSON #ifdef BELL_ONLY_CJSON
cJSON* json_obj = cJSON_CreateObject(); cJSON* json_obj = cJSON_CreateObject();
cJSON_AddStringToObject(json_obj, "authData", Crypto::base64Encode(config.authData).c_str()); cJSON_AddStringToObject(json_obj, "authData",
cJSON_AddNumberToObject(json_obj, "authType", AuthenticationType_AUTHENTICATION_STORED_SPOTIFY_CREDENTIALS); Crypto::base64Encode(config.authData).c_str());
cJSON_AddStringToObject(json_obj, "username", config.username.c_str()); cJSON_AddNumberToObject(
json_obj, "authType",
AuthenticationType_AUTHENTICATION_STORED_SPOTIFY_CREDENTIALS);
cJSON_AddStringToObject(json_obj, "username", config.username.c_str());
char* str = cJSON_PrintUnformatted(json_obj); char* str = cJSON_PrintUnformatted(json_obj);
cJSON_Delete(json_obj); cJSON_Delete(json_obj);
std::string json_objStr(str); std::string json_objStr(str);
free(str); free(str);
return json_objStr; return json_objStr;
#else #else
nlohmann::json obj; nlohmann::json obj;
obj["authData"] = Crypto::base64Encode(config.authData); obj["authData"] = Crypto::base64Encode(config.authData);
obj["authType"] = AuthenticationType_AUTHENTICATION_STORED_SPOTIFY_CREDENTIALS; obj["authType"] =
obj["username"] = config.username; AuthenticationType_AUTHENTICATION_STORED_SPOTIFY_CREDENTIALS;
obj["username"] = config.username;
return obj.dump(); return obj.dump();
#endif #endif
} }

View File

@@ -88,8 +88,8 @@ class MercurySession : public bell::Task, public cspot::Session {
void unregisterAudioKey(uint32_t sequenceId); void unregisterAudioKey(uint32_t sequenceId);
uint32_t requestAudioKey(const std::vector<uint8_t>& trackId, uint32_t requestAudioKey(const std::vector<uint8_t>& trackId,
const std::vector<uint8_t>& fileId, const std::vector<uint8_t>& fileId,
AudioKeyCallback audioCallback); AudioKeyCallback audioCallback);
std::string getCountryCode(); std::string getCountryCode();

View File

@@ -7,7 +7,7 @@
#include <variant> // for variant #include <variant> // for variant
#include <vector> // for vector #include <vector> // for vector
#include "CDNAudioFile.h" // for CDNTrackStream, CDNTrackStream::Track... #include "CDNAudioFile.h" // for CDNTrackStream, CDNTrackStream::Track...
#include "TrackQueue.h" #include "TrackQueue.h"
#include "protobuf/spirc.pb.h" // for MessageType #include "protobuf/spirc.pb.h" // for MessageType

View File

@@ -33,7 +33,8 @@ class TrackPlayer : bell::Task {
public: public:
// Callback types // Callback types
typedef std::function<void(std::shared_ptr<QueuedTrack>)> TrackLoadedCallback; typedef std::function<void(std::shared_ptr<QueuedTrack>)> TrackLoadedCallback;
typedef std::function<size_t(uint8_t*, size_t, std::string_view)> DataCallback; typedef std::function<size_t(uint8_t*, size_t, std::string_view)>
DataCallback;
typedef std::function<void()> EOFCallback; typedef std::function<void()> EOFCallback;
typedef std::function<bool()> isAiringCallback; typedef std::function<bool()> isAiringCallback;

View File

@@ -3,8 +3,8 @@
#include <stddef.h> // for size_t #include <stddef.h> // for size_t
#include <atomic> #include <atomic>
#include <deque> #include <deque>
#include <mutex>
#include <functional> #include <functional>
#include <mutex>
#include "BellTask.h" #include "BellTask.h"
#include "PlaybackState.h" #include "PlaybackState.h"
@@ -94,7 +94,6 @@ class TrackQueue : public bell::Task {
std::shared_ptr<bell::WrappedSemaphore> playableSemaphore; std::shared_ptr<bell::WrappedSemaphore> playableSemaphore;
std::atomic<bool> notifyPending = false; std::atomic<bool> notifyPending = false;
void runTask() override; void runTask() override;
void stopTask(); void stopTask();

View File

@@ -1,9 +1,9 @@
#pragma once #pragma once
#include <pb_encode.h> #include <pb_encode.h>
#include <optional>
#include <string_view> #include <string_view>
#include <vector> #include <vector>
#include <optional>
#include "NanoPBHelper.h" #include "NanoPBHelper.h"
#include "pb_decode.h" #include "pb_decode.h"
#include "protobuf/spirc.pb.h" #include "protobuf/spirc.pb.h"

View File

@@ -6,7 +6,7 @@
#include <string_view> // for string_view #include <string_view> // for string_view
#include <vector> // for vector #include <vector> // for vector
#include "HTTPClient.h" // for HTTPClient, HTTPClient::Response #include "HTTPClient.h" // for HTTPClient, HTTPClient::Response
#ifdef BELL_ONLY_CJSON #ifdef BELL_ONLY_CJSON
#include "cJSON.h" #include "cJSON.h"
#else #else

View File

@@ -10,11 +10,11 @@
#include "AccessKeyFetcher.h" // for AccessKeyFetcher #include "AccessKeyFetcher.h" // for AccessKeyFetcher
#include "BellLogger.h" // for AbstractLogger #include "BellLogger.h" // for AbstractLogger
#include "Crypto.h" #include "Crypto.h"
#include "Logger.h" // for CSPOT_LOG #include "Logger.h" // for CSPOT_LOG
#include "Packet.h" // for cspot #include "Packet.h" // for cspot
#include "SocketStream.h" // for SocketStream #include "SocketStream.h" // for SocketStream
#include "Utils.h" // for bigNumAdd, bytesToHexString, string... #include "Utils.h" // for bigNumAdd, bytesToHexString, string...
#include "WrappedSemaphore.h" // for WrappedSemaphore #include "WrappedSemaphore.h" // for WrappedSemaphore
#ifdef BELL_ONLY_CJSON #ifdef BELL_ONLY_CJSON
#include "cJSON.h" #include "cJSON.h"
#else #else

View File

@@ -3,10 +3,10 @@
#include <stdio.h> // for sprintf #include <stdio.h> // for sprintf
#include <initializer_list> // for initializer_list #include <initializer_list> // for initializer_list
#include "BellLogger.h" // for AbstractLogger #include "BellLogger.h" // for AbstractLogger
#include "ConstantParameters.h" // for brandName, cspot, protoc... #include "ConstantParameters.h" // for brandName, cspot, protoc...
#include "Logger.h" // for CSPOT_LOG #include "Logger.h" // for CSPOT_LOG
#include "protobuf/authentication.pb.h" // for AuthenticationType_AUTHE... #include "protobuf/authentication.pb.h" // for AuthenticationType_AUTHE...
#ifdef BELL_ONLY_CJSON #ifdef BELL_ONLY_CJSON
#include "cJSON.h" #include "cJSON.h"
#else #else
@@ -142,7 +142,8 @@ void LoginBlob::loadJson(const std::string& json) {
cJSON* root = cJSON_Parse(json.c_str()); cJSON* root = cJSON_Parse(json.c_str());
this->authType = cJSON_GetObjectItem(root, "authType")->valueint; this->authType = cJSON_GetObjectItem(root, "authType")->valueint;
this->username = cJSON_GetObjectItem(root, "username")->valuestring; this->username = cJSON_GetObjectItem(root, "username")->valuestring;
std::string authDataObject = cJSON_GetObjectItem(root, "authData")->valuestring; std::string authDataObject =
cJSON_GetObjectItem(root, "authData")->valuestring;
this->authData = crypto->base64Decode(authDataObject); this->authData = crypto->base64Decode(authDataObject);
cJSON_Delete(root); cJSON_Delete(root);
#else #else

View File

@@ -7,7 +7,7 @@
#include <type_traits> // for remove_extent_t, __underlying_type_impl<>:... #include <type_traits> // for remove_extent_t, __underlying_type_impl<>:...
#include <utility> // for pair #include <utility> // for pair
#ifndef _WIN32 #ifndef _WIN32
#include <arpa/inet.h> // for htons, ntohs, htonl, ntohl #include <arpa/inet.h> // for htons, ntohs, htonl, ntohl
#endif #endif
#include "BellLogger.h" // for AbstractLogger #include "BellLogger.h" // for AbstractLogger
#include "BellTask.h" // for Task #include "BellTask.h" // for Task

View File

@@ -1,22 +1,22 @@
#include "PlainConnection.h" #include "PlainConnection.h"
#ifndef _WIN32 #ifndef _WIN32
#include <netdb.h> // for addrinfo, freeaddrinfo, getaddrinfo #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
#include <cstring> // for memset
#include <stdexcept> // for runtime_error
#include <netinet/tcp.h> // for TCP_NODELAY
#include <netdb.h> #include <netdb.h>
#include <netinet/in.h> // for IPPROTO_IP, IPPROTO_TCP
#include <netinet/tcp.h> // for TCP_NODELAY
#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
#include <cstring> // for memset
#include <stdexcept> // for runtime_error
#else #else
#include <ws2tcpip.h> #include <ws2tcpip.h>
#endif #endif
#include "BellLogger.h" // for AbstractLogger #include "BellLogger.h" // for AbstractLogger
#include "Logger.h" // for CSPOT_LOG #include "Logger.h" // for CSPOT_LOG
#include "Packet.h" // for cspot #include "Packet.h" // for cspot
#include "Utils.h" // for extract, pack #include "Utils.h" // for extract, pack
using namespace cspot; using namespace cspot;

View File

@@ -17,8 +17,8 @@
#include "PlainConnection.h" // for PlainConnection, timeoutCallback #include "PlainConnection.h" // for PlainConnection, timeoutCallback
#include "ShannonConnection.h" // for ShannonConnection #include "ShannonConnection.h" // for ShannonConnection
#include "pb_decode.h"
#include "NanoPBHelper.h" // for pbPutString, pbEncode, pbDecode #include "NanoPBHelper.h" // for pbPutString, pbEncode, pbDecode
#include "pb_decode.h"
#include "protobuf/authentication.pb.h" #include "protobuf/authentication.pb.h"
using random_bytes_engine = using random_bytes_engine =
@@ -86,10 +86,9 @@ std::vector<uint8_t> Session::authenticate(std::shared_ptr<LoginBlob> blob) {
APWelcome welcome; APWelcome welcome;
CSPOT_LOG(debug, "Authorization successful"); CSPOT_LOG(debug, "Authorization successful");
pbDecode(welcome, APWelcome_fields, packet.data); pbDecode(welcome, APWelcome_fields, packet.data);
return std::vector<uint8_t>( return std::vector<uint8_t>(welcome.reusable_auth_credentials.bytes,
welcome.reusable_auth_credentials.bytes, welcome.reusable_auth_credentials.bytes +
welcome.reusable_auth_credentials.bytes + welcome.reusable_auth_credentials.size welcome.reusable_auth_credentials.size);
);
break; break;
} }
case AUTH_DECLINED_COMMAND: { case AUTH_DECLINED_COMMAND: {

View File

@@ -38,7 +38,7 @@ SpircHandler::SpircHandler(std::shared_ptr<cspot::Context> ctx) {
this->notify(); this->notify();
// Send playback start event, unpause // Send playback start event, unpause
sendEvent(EventType::PLAYBACK_START, (int) track->requestedPosition); sendEvent(EventType::PLAYBACK_START, (int)track->requestedPosition);
sendEvent(EventType::PLAY_PAUSE, false); sendEvent(EventType::PLAY_PAUSE, false);
}; };
@@ -111,7 +111,7 @@ void SpircHandler::updatePositionMs(uint32_t position) {
void SpircHandler::disconnect() { void SpircHandler::disconnect() {
this->trackQueue->stopTask(); this->trackQueue->stopTask();
this->trackPlayer->resetState(); this->trackPlayer->stop();
this->ctx->session->disconnect(); this->ctx->session->disconnect();
} }

View File

@@ -1,8 +1,8 @@
#include "TimeProvider.h" #include "TimeProvider.h"
#include "BellLogger.h" // for AbstractLogger #include "BellLogger.h" // for AbstractLogger
#include "Logger.h" // for CSPOT_LOG #include "Logger.h" // for CSPOT_LOG
#include "Utils.h" // for extract, getCurrentTimestamp #include "Utils.h" // for extract, getCurrentTimestamp
#ifndef _WIN32 #ifndef _WIN32
#include <arpa/inet.h> #include <arpa/inet.h>
#endif #endif

View File

@@ -13,8 +13,10 @@
#include "WrappedSemaphore.h" // for WrappedSemaphore #include "WrappedSemaphore.h" // for WrappedSemaphore
#ifdef BELL_VORBIS_FLOAT #ifdef BELL_VORBIS_FLOAT
#define VORBIS_SEEK(file, position) (ov_time_seek(file, (double)position / 1000)) #define VORBIS_SEEK(file, position) \
#define VORBIS_READ(file, buffer, bufferSize, section) (ov_read(file, buffer, bufferSize, 0, 2, 1, section)) (ov_time_seek(file, (double)position / 1000))
#define VORBIS_READ(file, buffer, bufferSize, section) \
(ov_read(file, buffer, bufferSize, 0, 2, 1, section))
#else #else
#define VORBIS_SEEK(file, position) (ov_time_seek(file, position)) #define VORBIS_SEEK(file, position) (ov_time_seek(file, position))
#define VORBIS_READ(file, buffer, bufferSize, section) \ #define VORBIS_READ(file, buffer, bufferSize, section) \
@@ -68,6 +70,7 @@ TrackPlayer::TrackPlayer(std::shared_ptr<cspot::Context> ctx,
TrackPlayer::~TrackPlayer() { TrackPlayer::~TrackPlayer() {
isRunning = false; isRunning = false;
resetState();
std::scoped_lock lock(runningMutex); std::scoped_lock lock(runningMutex);
} }
@@ -233,8 +236,8 @@ void TrackPlayer::runTask() {
if (!currentSongPlaying || pendingReset) if (!currentSongPlaying || pendingReset)
break; break;
written = written = dataCallback(pcmBuffer.data() + (ret - toWrite),
dataCallback(pcmBuffer.data() + (ret - toWrite), toWrite, track->identifier); toWrite, track->identifier);
} }
if (written == 0) { if (written == 0) {
BELL_SLEEP_MS(50); BELL_SLEEP_MS(50);

View File

@@ -1,12 +1,12 @@
#include "Utils.h" #include "Utils.h"
#include <stdlib.h> // for strtol #include <stdlib.h> // for strtol
#include <chrono>
#include <iomanip> // for operator<<, setfill, setw #include <iomanip> // for operator<<, setfill, setw
#include <iostream> // for basic_ostream, hex #include <iostream> // for basic_ostream, hex
#include <sstream> // for stringstream #include <sstream> // for stringstream
#include <string> // for string #include <string> // for string
#include <type_traits> // for enable_if<>::type #include <type_traits> // for enable_if<>::type
#include <chrono>
#ifndef _WIN32 #ifndef _WIN32
#include <arpa/inet.h> #include <arpa/inet.h>
#endif #endif