Added track fetching timeouts to PlaybackService. This should skirt a

couple edge cases and possibly allow us to not immediately stop playback
when reconnecting.
This commit is contained in:
casey langen 2020-10-30 16:47:57 -07:00
parent 5e23a21aa6
commit a06d6f28d1
6 changed files with 42 additions and 25 deletions

View File

@ -60,6 +60,12 @@ using musik::core::ILibraryPtr;
using musik::core::audio::ITransport;
using Editor = PlaybackService::Editor;
/* internally PlaybackService leverages a message queue for synchronization;
tracks are a special in that they are heavy-weight so aggressively exjected
from caches... sometimes we may have to query for them. if they take more than
the specified timeout we consider it a failure and stop playback. */
static const size_t kTrackTimeoutMs = 3000;
#define NO_POSITION (size_t) -1
#define START_OVER (size_t) -2
@ -332,13 +338,17 @@ void PlaybackService::ProcessMessage(IMessage &message) {
}
if (this->index != NO_POSITION) {
track = this->playlist.Get(this->index);
track = this->playlist.GetWithTimeout(this->index, kTrackTimeoutMs);
}
}
if (track) {
this->OnTrackChanged(this->index, track);
}
else {
this->Stop();
return;
}
if (eventType == StreamPlaying) {
this->PrepareNextTrack();
@ -365,10 +375,13 @@ void PlaybackService::ProcessMessage(IMessage &message) {
/* notify track change as soon as we're prepared. if we wait until
we start playing, it may be a while until the UI knows to redraw! */
if (this->UriAtIndex(this->index) == transport->Uri()) {
auto track = this->playlist.Get(this->index);
auto track = this->playlist.GetWithTimeout(this->index, kTrackTimeoutMs);
if (track) {
this->OnTrackChanged(this->index, track);
}
else {
this->Stop();
}
}
}
@ -589,26 +602,18 @@ bool PlaybackService::HotSwap(const TrackList& tracks, size_t index) {
bool found = false;
auto playingTrack = this->GetPlaying();
if (playingTrack && tracks.Count() > index) {
auto supplantTrack = tracks.Get(index);
auto supplantLibrary = supplantTrack->Library();
auto supplantId = tracks.GetId(index);
auto playingId = playingTrack->GetId();
auto playingLibrary = playingTrack->Library();
const auto playingId = playingTrack->GetId();
/* look at the index hint, see if we can find a matching track without
iteration. */
if (supplantId == playingId && supplantLibrary == playingLibrary) {
if (supplantId == playingId) {
found = true;
}
/* otherwise search the input */
else {
for (size_t i = 0; i < tracks.Count(); i++) {
supplantTrack = tracks.Get(i);
auto supplantLibrary = supplantTrack->Library();
auto supplantId = supplantTrack->GetId();
if (supplantId == playingId && supplantLibrary == playingLibrary) {
if (tracks.GetId(i) == playingId) {
index = i;
found = true;
}
@ -828,7 +833,7 @@ double PlaybackService::GetDuration() {
size_t index = this->index;
if (index < this->playlist.Count()) {
track = this->playlist.Get(index);
track = this->playlist.GetWithTimeout(index, kTrackTimeoutMs);
}
}
@ -845,7 +850,7 @@ ITrack* PlaybackService::GetTrack(size_t index) {
const size_t count = this->playlist.Count();
if (count && index < this->playlist.Count()) {
auto track = this->playlist.Get(index);
auto track = this->playlist.GetWithTimeout(index, kTrackTimeoutMs * 10);
if (track) {
return track->GetSdkValue();
}
@ -876,7 +881,7 @@ TrackPtr PlaybackService::GetTrackAtIndex(size_t index) {
return TrackPtr();
}
return this->playlist.Get(index);
return this->playlist.GetWithTimeout(index, kTrackTimeoutMs);
}
Editor PlaybackService::Edit() {
@ -1101,7 +1106,7 @@ void PlaybackService::Editor::Release() {
std::string PlaybackService::UriAtIndex(size_t index) {
if (index < this->playlist.Count()) {
auto track = this->playlist.Get(index);
auto track = this->playlist.GetWithTimeout(index, kTrackTimeoutMs);
if (track) {
return this->library->GetResourceLocator().GetTrackUri(track.get());
}
@ -1128,7 +1133,7 @@ ITransport::Gain PlaybackService::GainAtIndex(size_t index) {
Mode mode = (Mode)playbackPrefs->GetInt(keys::ReplayGainMode.c_str(), (int) Mode::Disabled);
if (mode != Mode::Disabled && index < this->playlist.Count()) {
auto track = this->playlist.Get(index);
auto track = this->playlist.GetWithTimeout(index, kTrackTimeoutMs);
if (track) {
auto rg = track->GetReplayGain();
float gain = (mode == Mode::Album) ? rg.albumGain : rg.trackGain;

View File

@ -172,6 +172,22 @@ TrackPtr TrackList::Get(size_t index, bool async) const {
#endif
}
TrackPtr TrackList::GetWithTimeout(size_t index, size_t timeoutMs) const {
auto id = this->ids.at(index);
auto cached = this->GetFromCache(id);
if (cached) { return cached; }
auto target = std::make_shared<LibraryTrack>(id, this->library);
auto query = std::make_shared<TrackMetadataQuery>(target, this->library);
this->library->EnqueueAndWait(query, timeoutMs);
if (query->GetStatus() == IQuery::Finished) {
this->AddToCache(id, query->Result());
return query->Result();
}
return TrackPtr();
}
ITrack* TrackList::GetTrack(size_t index) const {
return this->Get(index)->GetSdkValue();
}

View File

@ -79,8 +79,7 @@ namespace musik { namespace core {
/* implementation specific */
TrackPtr Get(size_t index, bool async = false) const;
TrackPtr GetSync(size_t index) const { return this->Get(index, false); }
TrackPtr GetAsync(size_t index) const { return this->Get(index, true); }
TrackPtr GetWithTimeout(size_t index, size_t timeoutMs) const;
void ClearCache();
void Swap(TrackList& list);
void CopyFrom(const TrackList& from);

View File

@ -292,16 +292,11 @@ void MainLayout::SwitchToLibraryLayout() {
void MainLayout::OnLibraryConnectionStateChanged(ILibrary::ConnectionState state) {
auto currentLayout = this->GetLayout();
if (currentLayout == this->libraryLayout ||
currentLayout == this->libraryNotConnectedLayout)
{
this->SwitchToLibraryLayout();
}
if (state == ILibrary::ConnectionState::Disconnected) {
this->playback.Stop();
}
}
void MainLayout::OnLibraryChanged(musik::core::ILibraryPtr prev, musik::core::ILibraryPtr curr) {

View File

@ -93,6 +93,7 @@ TrackListView::TrackListView(
this->decorator = decorator;
this->trackNumType = TrackRowRenderers::TrackNumType::Metadata;
this->renderer = TrackRowRenderers::Get(TrackRowRenderers::Type::AlbumSort);
this->playing = playback.GetPlaying();
}
TrackListView::~TrackListView() {

View File

@ -373,6 +373,7 @@ TransportWindow::TransportWindow(
this->repeatPos.y = 1;
this->volumePos.y = 1;
this->timePos.y = 1;
this->currentTrack = playback.GetPlaying();
this->UpdateReplayGainState();
}