mirror of
https://github.com/librespot-org/librespot.git
synced 2024-12-18 17:11:53 +00:00
connect: fixes for context and transfer
- fix context_metadata and restriction incorrect reset - do some state updates earlier - add more logging
This commit is contained in:
parent
08624ddf36
commit
710e2fc7be
4 changed files with 41 additions and 39 deletions
|
@ -180,6 +180,11 @@ impl ContextResolver {
|
||||||
} else if self.queue.contains(&resolve) {
|
} else if self.queue.contains(&resolve) {
|
||||||
debug!("update for {resolve} is already added");
|
debug!("update for {resolve} is already added");
|
||||||
return;
|
return;
|
||||||
|
} else {
|
||||||
|
trace!(
|
||||||
|
"added {} to resolver queue",
|
||||||
|
resolve.resolve_uri().unwrap_or(resolve.context_uri())
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
self.queue.push_back(resolve)
|
self.queue.push_back(resolve)
|
||||||
|
@ -265,7 +270,7 @@ impl ContextResolver {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_next_context(
|
pub fn apply_next_context(
|
||||||
&self,
|
&self,
|
||||||
state: &mut ConnectState,
|
state: &mut ConnectState,
|
||||||
mut context: Context,
|
mut context: Context,
|
||||||
|
@ -319,15 +324,17 @@ impl ContextResolver {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!("last item of type <{:?}>, finishing state", next.update);
|
|
||||||
|
|
||||||
match (next.update, state.active_context) {
|
match (next.update, state.active_context) {
|
||||||
(UpdateContext::Default, ContextType::Default) => {}
|
(UpdateContext::Default, ContextType::Default) | (UpdateContext::Autoplay, _) => {
|
||||||
|
debug!(
|
||||||
|
"last item of type <{:?}>, finishing state setup",
|
||||||
|
next.update
|
||||||
|
);
|
||||||
|
}
|
||||||
(UpdateContext::Default, _) => {
|
(UpdateContext::Default, _) => {
|
||||||
debug!("skipped finishing default, because it isn't the active context");
|
debug!("skipped finishing default, because it isn't the active context");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
(UpdateContext::Autoplay, _) => {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(transfer_state) = transfer_state.take() {
|
if let Some(transfer_state) = transfer_state.take() {
|
||||||
|
@ -336,25 +343,6 @@ impl ContextResolver {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let res = if state.shuffling_context() {
|
|
||||||
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
|
|
||||||
.reset_playback_to_position(idx)
|
|
||||||
.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();
|
||||||
state.update_queue_revision();
|
state.update_queue_revision();
|
||||||
|
|
||||||
|
|
|
@ -139,7 +139,7 @@ const VOLUME_STEP_SIZE: u16 = 1024; // (u16::MAX + 1) / VOLUME_STEPS
|
||||||
// delay to update volume after a certain amount of time, instead on each update request
|
// delay to update volume after a certain amount of time, instead on each update request
|
||||||
const VOLUME_UPDATE_DELAY: Duration = Duration::from_secs(2);
|
const VOLUME_UPDATE_DELAY: Duration = Duration::from_secs(2);
|
||||||
// to reduce updates to remote, we group some request by waiting for a set amount of time
|
// to reduce updates to remote, we group some request by waiting for a set amount of time
|
||||||
const UPDATE_STATE_DELAY: Duration = Duration::from_millis(300);
|
const UPDATE_STATE_DELAY: Duration = Duration::from_millis(200);
|
||||||
|
|
||||||
pub struct Spirc {
|
pub struct Spirc {
|
||||||
commands: mpsc::UnboundedSender<SpircCommand>,
|
commands: mpsc::UnboundedSender<SpircCommand>,
|
||||||
|
@ -452,7 +452,12 @@ impl SpircTask {
|
||||||
self.connect_state.prev_autoplay_track_uris()
|
self.connect_state.prev_autoplay_track_uris()
|
||||||
}).await
|
}).await
|
||||||
}, if allow_context_resolving && self.context_resolver.has_next() => {
|
}, if allow_context_resolving && self.context_resolver.has_next() => {
|
||||||
self.handle_next_context(next_context)
|
let update_state = self.handle_next_context(next_context);
|
||||||
|
if update_state {
|
||||||
|
if let Err(why) = self.notify().await {
|
||||||
|
error!("update after context resolving failed: {why}")
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
else => break
|
else => break
|
||||||
}
|
}
|
||||||
|
@ -471,20 +476,22 @@ impl SpircTask {
|
||||||
self.session.dealer().close().await;
|
self.session.dealer().close().await;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_next_context(&mut self, next_context: Result<Context, Error>) {
|
fn handle_next_context(&mut self, next_context: Result<Context, Error>) -> bool {
|
||||||
let next_context = match next_context {
|
let next_context = match next_context {
|
||||||
Err(why) => {
|
Err(why) => {
|
||||||
self.context_resolver.mark_next_unavailable();
|
self.context_resolver.mark_next_unavailable();
|
||||||
self.context_resolver.remove_used_and_invalid();
|
self.context_resolver.remove_used_and_invalid();
|
||||||
error!("{why}");
|
error!("{why}");
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
Ok(ctx) => ctx,
|
Ok(ctx) => ctx,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
debug!("handling next context {}", next_context.uri);
|
||||||
|
|
||||||
match self
|
match self
|
||||||
.context_resolver
|
.context_resolver
|
||||||
.handle_next_context(&mut self.connect_state, next_context)
|
.apply_next_context(&mut self.connect_state, next_context)
|
||||||
{
|
{
|
||||||
Ok(remaining) => {
|
Ok(remaining) => {
|
||||||
if let Some(remaining) = remaining {
|
if let Some(remaining) = remaining {
|
||||||
|
@ -496,15 +503,18 @@ impl SpircTask {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if self
|
let update_state = if self
|
||||||
.context_resolver
|
.context_resolver
|
||||||
.try_finish(&mut self.connect_state, &mut self.transfer_state)
|
.try_finish(&mut self.connect_state, &mut self.transfer_state)
|
||||||
{
|
{
|
||||||
self.add_autoplay_resolving_when_required();
|
self.add_autoplay_resolving_when_required();
|
||||||
self.update_state = true;
|
true
|
||||||
}
|
} else {
|
||||||
|
false
|
||||||
|
};
|
||||||
|
|
||||||
self.context_resolver.remove_used_and_invalid();
|
self.context_resolver.remove_used_and_invalid();
|
||||||
|
update_state
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: is the time_delta still necessary?
|
// todo: is the time_delta still necessary?
|
||||||
|
@ -561,6 +571,7 @@ impl SpircTask {
|
||||||
fn handle_player_event(&mut self, event: PlayerEvent) -> Result<(), Error> {
|
fn handle_player_event(&mut self, event: PlayerEvent) -> Result<(), Error> {
|
||||||
if let PlayerEvent::TrackChanged { audio_item } = event {
|
if let PlayerEvent::TrackChanged { audio_item } = event {
|
||||||
self.connect_state.update_duration(audio_item.duration_ms);
|
self.connect_state.update_duration(audio_item.duration_ms);
|
||||||
|
self.update_state = true;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -574,6 +585,7 @@ impl SpircTask {
|
||||||
(event.get_play_request_id(), self.play_request_id),
|
(event.get_play_request_id(), self.play_request_id),
|
||||||
(Some(event_id), Some(current_id)) if event_id == current_id
|
(Some(event_id), Some(current_id)) if event_id == current_id
|
||||||
};
|
};
|
||||||
|
|
||||||
// we only process events if the play_request_id matches. If it doesn't, it is
|
// we only process events if the play_request_id matches. If it doesn't, it is
|
||||||
// an event that belongs to a previous track and only arrives now due to a race
|
// an event that belongs to a previous track and only arrives now due to a race
|
||||||
// condition. In this case we have updated the state already and don't want to
|
// condition. In this case we have updated the state already and don't want to
|
||||||
|
@ -878,7 +890,8 @@ impl SpircTask {
|
||||||
}
|
}
|
||||||
// modification and update of the connect_state
|
// modification and update of the connect_state
|
||||||
Transfer(transfer) => {
|
Transfer(transfer) => {
|
||||||
self.handle_transfer(transfer.data.expect("by condition checked"))?
|
self.handle_transfer(transfer.data.expect("by condition checked"))?;
|
||||||
|
return self.notify().await;
|
||||||
}
|
}
|
||||||
Play(play) => {
|
Play(play) => {
|
||||||
let shuffle = play
|
let shuffle = play
|
||||||
|
|
|
@ -104,9 +104,6 @@ impl ConnectState {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reset_context(&mut self, mut reset_as: ResetContext) {
|
pub fn reset_context(&mut self, mut reset_as: ResetContext) {
|
||||||
self.set_active_context(ContextType::Default);
|
|
||||||
self.fill_up_context = ContextType::Default;
|
|
||||||
|
|
||||||
if matches!(reset_as, ResetContext::WhenDifferent(ctx) if self.different_context_uri(ctx)) {
|
if matches!(reset_as, ResetContext::WhenDifferent(ctx) if self.different_context_uri(ctx)) {
|
||||||
reset_as = ResetContext::Completely
|
reset_as = ResetContext::Completely
|
||||||
}
|
}
|
||||||
|
@ -129,6 +126,8 @@ impl ConnectState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.fill_up_context = ContextType::Default;
|
||||||
|
self.set_active_context(ContextType::Default);
|
||||||
self.update_restrictions()
|
self.update_restrictions()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,6 +148,10 @@ impl ConnectState {
|
||||||
pub fn set_active_context(&mut self, new_context: ContextType) {
|
pub fn set_active_context(&mut self, new_context: ContextType) {
|
||||||
self.active_context = new_context;
|
self.active_context = new_context;
|
||||||
|
|
||||||
|
let player = self.player_mut();
|
||||||
|
player.context_metadata.clear();
|
||||||
|
player.restrictions.clear();
|
||||||
|
|
||||||
let ctx = match self.get_context(new_context) {
|
let ctx = match self.get_context(new_context) {
|
||||||
Err(why) => {
|
Err(why) => {
|
||||||
warn!("couldn't load context info because: {why}");
|
warn!("couldn't load context info because: {why}");
|
||||||
|
@ -162,9 +165,6 @@ impl ConnectState {
|
||||||
|
|
||||||
let player = self.player_mut();
|
let player = self.player_mut();
|
||||||
|
|
||||||
player.context_metadata.clear();
|
|
||||||
player.restrictions.clear();
|
|
||||||
|
|
||||||
if let Some(restrictions) = restrictions.take() {
|
if let Some(restrictions) = restrictions.take() {
|
||||||
player.restrictions = MessageField::some(restrictions);
|
player.restrictions = MessageField::some(restrictions);
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,6 +68,7 @@ impl ConnectState {
|
||||||
|
|
||||||
self.clear_prev_track();
|
self.clear_prev_track();
|
||||||
self.clear_next_tracks(false);
|
self.clear_next_tracks(false);
|
||||||
|
self.update_queue_revision()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// completes the transfer, loading the queue and updating metadata
|
/// completes the transfer, loading the queue and updating metadata
|
||||||
|
|
Loading…
Reference in a new issue