Skip to content

Commit

Permalink
added repeat and shuffle support, a context-resolver and a radio func…
Browse files Browse the repository at this point in the history
…tion
  • Loading branch information
tobiasguyer committed Jul 15, 2024
1 parent f744c9b commit e041d9a
Show file tree
Hide file tree
Showing 12 changed files with 317 additions and 69 deletions.
4 changes: 2 additions & 2 deletions cspot/include/TrackPlayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,15 @@ class TrackPlayer : bell::Task {
// Callback types
typedef std::function<void(std::shared_ptr<QueuedTrack>, bool)>
TrackLoadedCallback;
typedef std::function<size_t(uint8_t*, size_t, std::string_view
typedef std::function<size_t(uint8_t*, size_t, size_t

#ifdef CONFIG_BELL_NOCODEC
, bool
#endif
)>
DataCallback;
typedef std::function<void()> EOFCallback;
typedef std::function<size_t(std::string_view)> SeekableCallback;
typedef std::function<size_t(size_t)> SeekableCallback;


TrackPlayer(std::shared_ptr<cspot::Context> ctx,
Expand Down
23 changes: 22 additions & 1 deletion cspot/include/TrackQueue.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <deque>
#include <functional>
#include <mutex>
#include <random> //for random_device and default_random_engine

#include "BellTask.h"
#include "PlaybackState.h"
Expand All @@ -13,6 +14,11 @@

#include "protobuf/metadata.pb.h" // for Track, _Track, AudioFile, Episode

#define inner_tracks_treshhold 10
#define SEND_OLD_TRACKS 2
#define SEND_FUTURE_TRACKS 2
#define GET_RADIO_TRACKS 10

namespace bell {
class WrappedSemaphore;
};
Expand Down Expand Up @@ -96,11 +102,15 @@ class TrackQueue : public bell::Task {
enum class SkipDirection { NEXT, PREV };

std::shared_ptr<bell::WrappedSemaphore> playableSemaphore;
std::shared_ptr<PlaybackState> playbackState;
std::atomic<bool> notifyPending = false;

void runTask() override;
void stopTask();

void prepareRepeat();
void shuffle_tracks(bool shuffleTracks);
void update_ghost_tracks(int16_t offset = 0);
bool hasTracks();
bool isFinished();
bool skipTrack(SkipDirection dir, bool expectNotify = true);
Expand All @@ -113,25 +123,36 @@ class TrackQueue : public bell::Task {
static const int MAX_TRACKS_PRELOAD = 3;

std::shared_ptr<cspot::AccessKeyFetcher> accessKeyFetcher;
std::shared_ptr<PlaybackState> playbackState;
std::shared_ptr<cspot::Context> ctx;
std::shared_ptr<bell::WrappedSemaphore> processSemaphore;

std::deque<std::shared_ptr<QueuedTrack>> preloadedTracks;
std::vector<int32_t>alt_index;
std::vector<TrackReference> currentTracks;
std::vector<TrackReference> ghostTracks;
std::mutex tracksMutex, runningMutex;

// PB data
Track pbTrack;
Episode pbEpisode;

std::string accessKey;
uint32_t radio_offset = 0;

int16_t currentTracksIndex = -1;
int16_t currentTracksSize = 0;

bool isRunning = false;
bool context_resolved = false;
bool continue_with_radio = true;

std::random_device rd;
std::default_random_engine rng;

void resolveAutoplay();
void resolveContext();
void processTrack(std::shared_ptr<QueuedTrack> track);
bool queueNextTrack(int offset = 0, uint32_t positionMs = 0);
void loadRadio(std::string req);
};
} // namespace cspot
18 changes: 17 additions & 1 deletion cspot/include/TrackReference.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,28 @@
#include <string_view>
#include <vector>
#include "NanoPBHelper.h"
#include "Utils.h" //for base62decode
#include "pb_decode.h"
#include "protobuf/spirc.pb.h"

namespace cspot {
struct TrackReference {
TrackReference();
TrackReference();
TrackReference(std::string uri, std::string context) : type(Type::TRACK) {
this->gid = base62Decode(uri);
//this->uri=uri;
this->context=context;
}
TrackReference(std::string uri) : type(Type::TRACK) {
gid = base62Decode(uri);

if (uri.find("episode:") != std::string::npos) {
type = Type::EPISODE;
}
if (uri.find("track:") == std::string::npos) {
this->uri = uri;
}
}

// Resolved track GID
std::vector<uint8_t> gid;
Expand Down
8 changes: 8 additions & 0 deletions cspot/include/Utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,14 @@ std::vector<uint8_t> bigNumAdd(std::vector<uint8_t> num, int n);

unsigned char h2int(char c);

/**
* @brief Extracts the spotify id from a spotify uri and decodes its base62-format
*
* @param uri spotify uri/spotify id(base62) string
* @return std::vector<uint8_t> gid
*/
std::vector<uint8_t> base62Decode(std::string uri);

std::string urlDecode(std::string str);

/**
Expand Down
3 changes: 3 additions & 0 deletions cspot/src/PlaybackState.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,9 @@ std::vector<uint8_t> PlaybackState::encodeCurrentFrame(MessageType typ) {
innerFrame.has_device_state = true;
innerFrame.has_typ = true;
innerFrame.has_state_update_id = true;
innerFrame.state.playing_track_index = innerFrame.state.index;
innerFrame.state.has_playing_track_index = true;
innerFrame.state.has_index = true;

this->seqNum += 1;

Expand Down
20 changes: 8 additions & 12 deletions cspot/src/SpircHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,9 @@ void SpircHandler::loadTrackFromURI(const std::string& uri) {}
void SpircHandler::notifyAudioEnded() {
playbackState->updatePositionMs(0);
notify();
#ifndef CONFIG_BELL_NOCODEC
trackPlayer->resetState(true);
#endif
}

void SpircHandler::notifyAudioReachedPlayback() {
Expand All @@ -91,18 +93,8 @@ void SpircHandler::notifyAudioReachedPlayback() {
// get HEAD track
auto currentTrack = trackQueue->consumeTrack(nullptr, offset);

// Do not execute when meta is already updated
if (trackQueue->notifyPending) {
trackQueue->notifyPending = false;

playbackState->updatePositionMs(currentTrack->requestedPosition);

// Reset position in queued track
currentTrack->requestedPosition = 0;
} else {
trackQueue->skipTrack(TrackQueue::SkipDirection::NEXT, false);
playbackState->updatePositionMs(0);

if (!playbackState->innerFrame.state.repeat) {
trackQueue->skipTrack(TrackQueue::SkipDirection::NEXT);
// we moved to next track, re-acquire currentTrack again
currentTrack = trackQueue->consumeTrack(nullptr, offset);
}
Expand Down Expand Up @@ -227,11 +219,15 @@ void SpircHandler::handleFrame(std::vector<uint8_t>& data) {
}
case MessageType_kMessageTypeShuffle: {
CSPOT_LOG(debug, "Got shuffle frame");
playbackState->innerFrame.state.shuffle = playbackState->remoteFrame.state.shuffle;
trackQueue->shuffle_tracks(playbackState->remoteFrame.state.shuffle);
this->notify();
break;
}
case MessageType_kMessageTypeRepeat: {
CSPOT_LOG(debug, "Got repeat frame");
playbackState->innerFrame.state.repeat = playbackState->remoteFrame.state.repeat;
trackQueue->prepareRepeat();
this->notify();
break;
}
Expand Down
17 changes: 11 additions & 6 deletions cspot/src/TrackPlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ void TrackPlayer::runTask() {
std::shared_ptr<QueuedTrack> track= nullptr, newTrack = nullptr;

int trackOffset = 0;
size_t tracksPlayed = 0;
bool eof = false;
bool endOfQueueReached = false;

Expand Down Expand Up @@ -156,6 +157,7 @@ void TrackPlayer::runTask() {
}

newTrack = trackQueue->consumeTrack(track, trackOffset);
this->trackQueue->update_ghost_tracks(trackOffset);

if (newTrack == nullptr) {
if (trackOffset == -1) {
Expand Down Expand Up @@ -208,6 +210,7 @@ void TrackPlayer::runTask() {
startPaused = false;
}

track->trackMetrics->track_size = currentTrackStream->getSize();
int32_t r =
ov_open_callbacks(this, &vorbisFile, NULL, 0, vorbisCallbacks);
#else
Expand All @@ -219,21 +222,19 @@ void TrackPlayer::runTask() {
size_t toWrite = ret;
while (toWrite) {
written = dataCallback(pcmBuffer.data() + (ret - toWrite),
toWrite, track->identifier, 0);
toWrite, tracksPlayed, 0);
if (written == 0) {
BELL_SLEEP_MS(1000);
}
toWrite -= written;
}
track->written_bytes += ret;
start_offset = seekable_callback(track->identifier);
if(this->spaces_available(track->identifier)<pcmBuffer.size()){
start_offset = seekable_callback(tracksPlayed);
if(this->spaces_available(tracksPlayed)<pcmBuffer.size()){
BELL_SLEEP_MS(50);
continue;
}
if(ret == 0) printf("re == null");
}
track->trackMetrics->track_size = currentTrackStream->getSize();
float duration_lambda = 1.0 * (currentTrackStream->getSize() - start_offset) / track->trackInfo.duration;
#endif
if (pendingSeekPositionMs > 0) {
Expand All @@ -242,6 +243,7 @@ void TrackPlayer::runTask() {
pendingSeekPositionMs = 0;
#endif
}
ctx->playbackMetrics->end_reason = PlaybackMetrics::REMOTE;

if (track->requestedPosition > 0) {
#ifndef CONFIG_BELL_NOCODEC
Expand All @@ -256,6 +258,8 @@ void TrackPlayer::runTask() {
eof = false;
track->loading = true;
track->trackMetrics->startTrack(track->requestedPosition);
//in case of a repeatedtrack, set requested position to 0
track->requestedPosition = 0;

CSPOT_LOG(info, "Playing");

Expand Down Expand Up @@ -312,7 +316,7 @@ void TrackPlayer::runTask() {
}
#endif
written = dataCallback(pcmBuffer.data() + (ret - toWrite),
toWrite, track->identifier
toWrite, tracksPlayed
#ifdef CONFIG_BELL_NOCODEC
,skipped
#endif
Expand All @@ -327,6 +331,7 @@ void TrackPlayer::runTask() {
}
}
}
tracksPlayed++;
#ifndef CONFIG_BELL_NOCODEC
ov_clear(&vorbisFile);
#endif
Expand Down
Loading

0 comments on commit e041d9a

Please sign in to comment.