mirror of
https://github.com/librespot-org/librespot.git
synced 2024-12-18 17:11:53 +00:00
connect: adjust finish of context resolving
This commit is contained in:
parent
dfbac73136
commit
0dfced80ba
2 changed files with 83 additions and 36 deletions
|
@ -337,29 +337,27 @@ impl ContextResolver {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(transfer_state) = transfer_state.take() {
|
let active_ctx = state.get_context(state.active_context);
|
||||||
if let Err(why) = state.finish_transfer(transfer_state) {
|
let res = if let Some(transfer_state) = transfer_state.take() {
|
||||||
error!("finishing setup of transfer failed: {why}")
|
state.finish_transfer(transfer_state)
|
||||||
}
|
} else if state.shuffling_context() {
|
||||||
|
state.shuffle()
|
||||||
|
} else if matches!(active_ctx, Ok(ctx) if ctx.index.track == 0) {
|
||||||
|
// has context, and context is not touched
|
||||||
|
// when the index is not zero, the next index was already evaluated elsewhere
|
||||||
|
let ctx = active_ctx.expect("checked by precondition");
|
||||||
|
let idx = ConnectState::find_index_in_context(ctx, |t| {
|
||||||
|
state.current_track(|c| t.uri == c.uri)
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
|
||||||
|
state.reset_playback_to_position(idx)
|
||||||
} else {
|
} else {
|
||||||
let res = if state.shuffling_context() {
|
state.fill_up_next_tracks()
|
||||||
state.shuffle()
|
};
|
||||||
} else if let Ok(ctx) = state.get_context(state.active_context) {
|
|
||||||
let idx = ConnectState::find_index_in_context(ctx, |t| {
|
|
||||||
state.current_track(|c| t.uri == c.uri)
|
|
||||||
})
|
|
||||||
.ok();
|
|
||||||
|
|
||||||
state
|
if let Err(why) = res {
|
||||||
.reset_playback_to_position(idx)
|
error!("setup of state failed: {why}, last used resolve {next:#?}")
|
||||||
.and_then(|_| state.fill_up_next_tracks())
|
|
||||||
} else {
|
|
||||||
state.fill_up_next_tracks()
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Err(why) = res {
|
|
||||||
error!("setting up state failed after updating contexts: {why}")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
state.update_restrictions();
|
state.update_restrictions();
|
||||||
|
|
|
@ -3,7 +3,11 @@ use crate::{
|
||||||
protocol::player::{
|
protocol::player::{
|
||||||
Context, ContextIndex, ContextPage, ContextTrack, ProvidedTrack, Restrictions,
|
Context, ContextIndex, ContextPage, ContextTrack, ProvidedTrack, Restrictions,
|
||||||
},
|
},
|
||||||
state::{metadata::Metadata, provider::Provider, ConnectState, StateError},
|
state::{
|
||||||
|
metadata::Metadata,
|
||||||
|
provider::{IsProvider, Provider},
|
||||||
|
ConnectState, StateError, SPOTIFY_MAX_NEXT_TRACKS_SIZE,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
use protobuf::MessageField;
|
use protobuf::MessageField;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
@ -222,22 +226,21 @@ impl ConnectState {
|
||||||
if !self.context_uri().starts_with(SEARCH_IDENTIFIER)
|
if !self.context_uri().starts_with(SEARCH_IDENTIFIER)
|
||||||
&& self.context_uri() == &context.uri
|
&& self.context_uri() == &context.uri
|
||||||
{
|
{
|
||||||
match Self::find_index_in_context(&new_context, |t| {
|
if let Some(new_index) = self.find_last_index_in_new_context(&new_context) {
|
||||||
self.current_track(|t| &t.uri) == &t.uri
|
new_context.index.track = match new_index {
|
||||||
}) {
|
Ok(i) => i,
|
||||||
Ok(new_pos) => {
|
Err(i) => {
|
||||||
debug!("found new index of current track, updating new_context index to {new_pos}");
|
self.player_mut().index = MessageField::none();
|
||||||
new_context.index.track = (new_pos + 1) as u32;
|
i
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// enforce reloading the context
|
||||||
|
if let Some(autoplay_ctx) = self.autoplay_context.as_mut() {
|
||||||
|
autoplay_ctx.index.track = 0
|
||||||
}
|
}
|
||||||
// the track isn't anymore in the context
|
self.clear_next_tracks();
|
||||||
Err(_) if matches!(self.active_context, ContextType::Default) => {
|
|
||||||
warn!("current track was removed, setting pos to last known index");
|
|
||||||
new_context.index.track = self.player().index.track
|
|
||||||
}
|
|
||||||
Err(_) => {}
|
|
||||||
}
|
}
|
||||||
// enforce reloading the context
|
|
||||||
self.clear_next_tracks();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.context = Some(new_context);
|
self.context = Some(new_context);
|
||||||
|
@ -283,6 +286,52 @@ impl ConnectState {
|
||||||
Ok(Some(next_contexts))
|
Ok(Some(next_contexts))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn find_first_prev_track_index(&self, ctx: &StateContext) -> Option<usize> {
|
||||||
|
let prev_tracks = self.prev_tracks();
|
||||||
|
for i in (0..prev_tracks.len()).rev() {
|
||||||
|
let prev_track = prev_tracks.get(i)?;
|
||||||
|
if let Ok(idx) = Self::find_index_in_context(ctx, |t| prev_track.uri == t.uri) {
|
||||||
|
return Some(idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_last_index_in_new_context(
|
||||||
|
&self,
|
||||||
|
new_context: &StateContext,
|
||||||
|
) -> Option<Result<u32, u32>> {
|
||||||
|
let ctx = self.context.as_ref()?;
|
||||||
|
|
||||||
|
let is_queued_item = self.current_track(|t| t.is_queue() || t.is_from_queue());
|
||||||
|
|
||||||
|
let new_index = if ctx.index.track as usize >= SPOTIFY_MAX_NEXT_TRACKS_SIZE {
|
||||||
|
Some(ctx.index.track as usize - SPOTIFY_MAX_NEXT_TRACKS_SIZE)
|
||||||
|
} else if is_queued_item {
|
||||||
|
self.find_first_prev_track_index(new_context)
|
||||||
|
} else {
|
||||||
|
Self::find_index_in_context(new_context, |current| {
|
||||||
|
self.current_track(|t| t.uri == current.uri)
|
||||||
|
})
|
||||||
|
.ok()
|
||||||
|
}
|
||||||
|
.map(|i| i as u32 + 1);
|
||||||
|
|
||||||
|
Some(new_index.ok_or_else(|| {
|
||||||
|
info!(
|
||||||
|
"couldn't distinguish index from current or previous tracks in the updated context"
|
||||||
|
);
|
||||||
|
let fallback_index = self
|
||||||
|
.player()
|
||||||
|
.index
|
||||||
|
.as_ref()
|
||||||
|
.map(|i| i.track)
|
||||||
|
.unwrap_or_default();
|
||||||
|
info!("falling back to index {fallback_index}");
|
||||||
|
fallback_index
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
fn state_context_from_page(
|
fn state_context_from_page(
|
||||||
&mut self,
|
&mut self,
|
||||||
page: ContextPage,
|
page: ContextPage,
|
||||||
|
|
Loading…
Reference in a new issue