mirror of
https://github.com/clangen/musikcube.git
synced 2025-02-06 03:39:50 +00:00
Added the ability for remote clients to request playback of a previously
snapshotted queue. Also fixed a bug in TrackList where the wrong type of wrapped ITrack was getting returned, potentially leading to read-after-free bugs.
This commit is contained in:
parent
2b8d40126a
commit
0b3e1b2f19
@ -150,9 +150,7 @@ TrackPtr TrackList::Get(size_t index) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ITrack* TrackList::GetTrack(size_t index) const {
|
ITrack* TrackList::GetTrack(size_t index) const {
|
||||||
auto track = this->Get(index).get();
|
return this->Get(index)->GetSdkValue();
|
||||||
track->Retain();
|
|
||||||
return track;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t TrackList::GetId(size_t index) const {
|
int64_t TrackList::GetId(size_t index) const {
|
||||||
|
@ -179,6 +179,7 @@ namespace request {
|
|||||||
static const std::string query_albums = "query_albums";
|
static const std::string query_albums = "query_albums";
|
||||||
static const std::string query_tracks_by_category = "query_tracks_by_category";
|
static const std::string query_tracks_by_category = "query_tracks_by_category";
|
||||||
static const std::string play_all_tracks = "play_all_tracks";
|
static const std::string play_all_tracks = "play_all_tracks";
|
||||||
|
static const std::string play_snapshot_tracks = "play_snapshot_tracks";
|
||||||
static const std::string play_tracks = "play_tracks";
|
static const std::string play_tracks = "play_tracks";
|
||||||
static const std::string play_tracks_by_category = "play_tracks_by_category";
|
static const std::string play_tracks_by_category = "play_tracks_by_category";
|
||||||
static const std::string query_play_queue_tracks = "query_play_queue_tracks";
|
static const std::string query_play_queue_tracks = "query_play_queue_tracks";
|
||||||
|
@ -410,6 +410,10 @@ void WebSocketServer::HandleRequest(connection_hdl connection, json& request) {
|
|||||||
this->RespondWithPlayAllTracks(connection, request);
|
this->RespondWithPlayAllTracks(connection, request);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
else if (name == request::play_snapshot_tracks) {
|
||||||
|
this->RespondWithPlaySnapshotTracks(connection, request);
|
||||||
|
return;
|
||||||
|
}
|
||||||
else if (name == request::play_tracks) {
|
else if (name == request::play_tracks) {
|
||||||
this->RespondWithPlayTracks(connection, request);
|
this->RespondWithPlayTracks(connection, request);
|
||||||
return;
|
return;
|
||||||
@ -702,6 +706,7 @@ void WebSocketServer::RespondWithQueryTracksByExternalIds(connection_hdl connect
|
|||||||
track = trackList->GetTrack(i);
|
track = trackList->GetTrack(i);
|
||||||
externalId = GetMetadataString(track, track::ExternalId);
|
externalId = GetMetadataString(track, track::ExternalId);
|
||||||
tracks[externalId] = this->ReadTrackMetadata(track);
|
tracks[externalId] = this->ReadTrackMetadata(track);
|
||||||
|
track->Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
trackList->Release();
|
trackList->Release();
|
||||||
@ -752,53 +757,48 @@ void WebSocketServer::RespondWithPlayQueueTracks(connection_hdl connection, json
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
bool idsOnly = request[message::options].value(key::ids_only, false);
|
||||||
|
|
||||||
static auto releaseDeleter = [](ITrack* track) { track->Release(); };
|
static auto releaseDeleter = [](ITrack* track) { track->Release(); };
|
||||||
static auto nullDeleter = [](ITrack* track) { };
|
static auto nullDeleter = [](ITrack* track) { };
|
||||||
|
|
||||||
std::vector<std::shared_ptr<ITrack>> tracks;
|
|
||||||
|
|
||||||
/* edit the playlist so it can be changed while we're getting the tracks
|
|
||||||
out of it. only applicable for the "live" type. */
|
|
||||||
ITrackListEditor* editor = nullptr;
|
|
||||||
|
|
||||||
if (type == value::live) {
|
|
||||||
editor = context.playback->EditPlaylist();
|
|
||||||
}
|
|
||||||
|
|
||||||
int trackCount = (int)context.playback->Count();
|
|
||||||
int to = trackCount;
|
|
||||||
|
|
||||||
if (offset >= 0 && limit >= 0) {
|
|
||||||
to = std::min(trackCount, offset + limit);
|
|
||||||
}
|
|
||||||
|
|
||||||
ITrack* track;
|
|
||||||
std::function<void(ITrack*)> deleter;
|
|
||||||
|
|
||||||
if (editor) { deleter = releaseDeleter; }
|
|
||||||
else { deleter = nullDeleter; }
|
|
||||||
|
|
||||||
for (int i = offset; i < to; i++) {
|
|
||||||
track = editor ? context.playback->GetTrack(i) : playQueueSnapshot->GetTrack(i);
|
|
||||||
tracks.push_back(std::shared_ptr<ITrack>(track, deleter));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (editor) {
|
|
||||||
editor->Release();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* now add the tracks to the output. they will be Release()'d automatically
|
/* now add the tracks to the output. they will be Release()'d automatically
|
||||||
as soon as this scope ends. */
|
as soon as this scope ends. */
|
||||||
json data = json::array();
|
json data = json::array();
|
||||||
|
|
||||||
bool idsOnly = request[message::options].value(key::ids_only, false);
|
if (type == value::live) {
|
||||||
|
/* edit the playlist so it can be changed while we're getting the tracks
|
||||||
|
out of it. only applicable for the "live" type. */
|
||||||
|
ITrackListEditor* editor = context.playback->EditPlaylist();
|
||||||
|
int to = (int)context.playback->Count();
|
||||||
|
|
||||||
for (auto track : tracks) {
|
if (offset >= 0 && limit >= 0) {
|
||||||
if (idsOnly) {
|
to = std::min(to, offset + limit);
|
||||||
data.push_back(GetMetadataString(track.get(), key::external_id));
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
data.push_back(this->ReadTrackMetadata(track.get()));
|
for (int i = offset; i < to; i++) {
|
||||||
|
ITrack* track = context.playback->GetTrack(i);
|
||||||
|
if (idsOnly) { data.push_back(GetMetadataString(track, key::external_id)); }
|
||||||
|
else { data.push_back(this->ReadTrackMetadata(track)); }
|
||||||
|
track->Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
editor->Release();
|
||||||
|
}
|
||||||
|
else if (type == value::snapshot) {
|
||||||
|
if (this->playQueueSnapshot) {
|
||||||
|
int to = (int)this->playQueueSnapshot->Count();
|
||||||
|
|
||||||
|
if (offset >= 0 && limit >= 0) {
|
||||||
|
to = std::min(to, offset + limit);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = offset; i < to; i++) {
|
||||||
|
ITrack* track = playQueueSnapshot->GetTrack(i);
|
||||||
|
if (idsOnly) { data.push_back(GetMetadataString(track, key::external_id)); }
|
||||||
|
else { data.push_back(this->ReadTrackMetadata(track)); }
|
||||||
|
track->Release();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1064,6 +1064,32 @@ void WebSocketServer::RespondWithPlayAllTracks(connection_hdl connection, json&
|
|||||||
RespondWithSuccess(connection, request);
|
RespondWithSuccess(connection, request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WebSocketServer::RespondWithPlaySnapshotTracks(connection_hdl connection, json& request) {
|
||||||
|
if (this->playQueueSnapshot) {
|
||||||
|
size_t index = 0;
|
||||||
|
double time = 0.0;
|
||||||
|
|
||||||
|
if (request.find(message::options) != request.end()) {
|
||||||
|
index = request[message::options].value(key::index, 0);
|
||||||
|
time = request[message::options].value(key::time, 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
context.playback->Play(this->playQueueSnapshot, index);
|
||||||
|
|
||||||
|
if (time > 0.0) {
|
||||||
|
context.playback->SetPosition(time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
context.playback->Stop();
|
||||||
|
auto editor = context.playback->EditPlaylist();
|
||||||
|
editor->Clear();
|
||||||
|
editor->Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
RespondWithSuccess(connection, request);
|
||||||
|
}
|
||||||
|
|
||||||
void WebSocketServer::RespondWithPlayTracksByCategory(connection_hdl connection, json& request) {
|
void WebSocketServer::RespondWithPlayTracksByCategory(connection_hdl connection, json& request) {
|
||||||
int limit, offset;
|
int limit, offset;
|
||||||
ITrackList* tracks = this->QueryTracksByCategory(request, limit, offset);
|
ITrackList* tracks = this->QueryTracksByCategory(request, limit, offset);
|
||||||
|
@ -146,6 +146,7 @@ class WebSocketServer {
|
|||||||
void RespondWithListCategories(connection_hdl connection, json& request);
|
void RespondWithListCategories(connection_hdl connection, json& request);
|
||||||
void RespondWithQueryCategory(connection_hdl connection, json& request);
|
void RespondWithQueryCategory(connection_hdl connection, json& request);
|
||||||
void RespondWithPlayAllTracks(connection_hdl connection, json& request);
|
void RespondWithPlayAllTracks(connection_hdl connection, json& request);
|
||||||
|
void RespondWithPlaySnapshotTracks(connection_hdl connection, json& request);
|
||||||
void RespondWithPlayTracksByCategory(connection_hdl connection, json& request);
|
void RespondWithPlayTracksByCategory(connection_hdl connection, json& request);
|
||||||
void RespondWithEnvironment(connection_hdl connection, json& request);
|
void RespondWithEnvironment(connection_hdl connection, json& request);
|
||||||
void RespondWithCurrentTime(connection_hdl connection, json& request);
|
void RespondWithCurrentTime(connection_hdl connection, json& request);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user