Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 55 additions & 47 deletions connect/src/spirc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1057,12 +1057,16 @@ impl SpircTask {
let mut ctx_uri = match transfer.current_session.context.uri {
None => Err(SpircError::NoUri("transfer context"))?,
// can apparently happen when a state is transferred and was started with "uris" via the api
Some(ref uri) if uri == "-" => String::new(),
Some(ref uri) => uri.clone(),
Some(ref uri) if uri == "-" || uri.is_empty() => None,
Some(ref uri) => Some(uri.clone()),
};

self.connect_state
.reset_context(ResetContext::WhenDifferent(&ctx_uri));
self.connect_state.reset_context(
ctx_uri
.as_deref()
.map(ResetContext::WhenDifferent)
.unwrap_or(ResetContext::Completely),
);

match self.connect_state.current_track_from_transfer(&transfer) {
Err(why) => warn!("didn't find initial track: {why}"),
Expand All @@ -1074,43 +1078,41 @@ impl SpircTask {

let autoplay = self.connect_state.current_track(|t| t.is_autoplay());
if autoplay {
ctx_uri = ctx_uri.replace("station:", "");
ctx_uri = ctx_uri.map(|c| c.replace("station:", ""));
}

let fallback = self.connect_state.current_track(|t| &t.uri).clone();
let load_from_context_uri = !ctx_uri.is_empty();

if load_from_context_uri {
self.context_resolver.add(ResolveContext::from_uri(
ctx_uri.clone(),
&fallback,
ContextType::Default,
ContextAction::Replace,
));
} else {
let all_tracks = transfer
.current_session
.context
.pages
.iter()
.cloned()
.flat_map(|p| p.tracks)
.collect::<Vec<_>>();

if !all_tracks.is_empty() {
self.load_context_from_tracks(all_tracks)?
} else {
warn!("tried to transfer with an invalid state, using fallback ({fallback})");
ctx_uri = fallback.clone();
let load_from_context_uri = ctx_uri.is_some();

match ctx_uri {
Some(ref uri) => {
self.context_resolver.add(ResolveContext::from_uri(
uri.clone(),
&fallback,
ContextType::Default,
ContextAction::Replace,
));
}
}

self.context_resolver.add(ResolveContext::from_uri(
ctx_uri.clone(),
&fallback,
ContextType::Default,
ContextAction::Replace,
));
None => {
let all_tracks = transfer
.current_session
.context
.pages
.iter()
.cloned()
.flat_map(|p| p.tracks)
.collect::<Vec<_>>();

if !all_tracks.is_empty() {
self.load_context_from_tracks(all_tracks)?;
} else {
warn!(
"tried to transfer with an invalid state, using fallback as ctx_uri ({fallback})"
);
ctx_uri = Some(fallback.clone())
}
}
};

self.handle_activate();

Expand Down Expand Up @@ -1140,23 +1142,26 @@ impl SpircTask {
let is_playing = !transfer.playback.is_paused();

if self.connect_state.current_track(|t| t.is_autoplay()) || autoplay {
debug!("currently in autoplay context, async resolving autoplay for {ctx_uri}");

self.context_resolver.add(ResolveContext::from_uri(
ctx_uri,
fallback,
ContextType::Autoplay,
ContextAction::Replace,
))
if let Some(ctx_uri) = ctx_uri {
debug!("currently in autoplay context, async resolving autoplay for {ctx_uri}");
self.context_resolver.add(ResolveContext::from_uri(
ctx_uri,
fallback,
ContextType::Autoplay,
ContextAction::Replace,
))
} else {
warn!("couldn't resolve autoplay context without a context uri");
}
}

if load_from_context_uri {
self.transfer_state = Some(transfer);
} else {
match self.connect_state.get_context(ContextType::Default) {
Err(_) => {
Err(why) => {
warn!("continuing transfer in an unknown state. {why}");
self.transfer_state = Some(transfer);
warn!("no context to reset with, continuing transfer after context resolved");
}
Ok(ctx) => {
let idx = ConnectState::find_index_in_context(ctx, |pt| {
Expand Down Expand Up @@ -1369,6 +1374,9 @@ impl SpircTask {

fn load_context_from_tracks(&mut self, tracks: impl Into<ContextPage>) -> Result<(), Error> {
let ctx = Context {
// by providing values for uri/url the player in the official client's isn't frozen
uri: Some(String::from("spotify:web-api")),
url: Some(String::from("context://spotify:web-api")),
pages: vec![tracks.into()],
..Default::default()
};
Expand Down
16 changes: 13 additions & 3 deletions connect/src/state/transfer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,11 @@ impl ConnectState {
}

/// handles the initially transferable data
pub fn handle_initial_transfer(&mut self, transfer: &mut TransferState, ctx_uri: String) {
pub fn handle_initial_transfer(
&mut self,
transfer: &mut TransferState,
ctx_uri: Option<String>,
) {
let current_context_metadata = self.context.as_ref().map(|c| c.metadata.clone());
let player = self.player_mut();

Expand Down Expand Up @@ -86,8 +90,14 @@ impl ConnectState {
}
}

player.context_url = format!("context://{ctx_uri}");
player.context_uri = ctx_uri;
if let Some(ctx_uri) = ctx_uri {
player.context_url = format!("context://{ctx_uri}");
player.context_uri = ctx_uri;
} else {
// it's important to always set the url/uri to a value so that the player is active
player.context_url = String::from("context://spotify:unknown");
player.context_uri = String::from("spotify:unknown");
}

if let Some(metadata) = current_context_metadata {
for (key, value) in metadata {
Expand Down
Loading