Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- [connect] Add method `add_to_queue` to `Spirc` to add tracks, episodes, albums, playlists, artists, and shows to the queue

### Changed

- [core] Made `SpotifyId::to_base62`, `SpotifyId::to_base16`, `FileId::to_base16`, `SpotifyUri::to_id`, `SpotifyUri::to_uri` infallible (breaking)
Expand Down
56 changes: 56 additions & 0 deletions connect/src/spirc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use crate::{
connect::{Cluster, ClusterUpdate, LogoutCommand, SetVolumeCommand},
context::Context,
explicit_content_pubsub::UserAttributesUpdate,
player::ProvidedTrack,
playlist4_external::PlaylistModificationInfo,
social_connect_v2::SessionUpdate,
transfer_state::TransferState,
Expand Down Expand Up @@ -132,6 +133,7 @@ enum SpircCommand {
Activate,
Transfer(Option<TransferRequest>),
Load(LoadRequest),
AddToQueue(SpotifyUri),
}

const CONTEXT_FETCH_THRESHOLD: usize = 2;
Expand Down Expand Up @@ -388,6 +390,27 @@ impl Spirc {
Ok(self.commands.send(SpircCommand::Load(command))?)
}

/// Adds a track, episode, album, playlist, artist, or show to the queue.
///
/// Does nothing if we are not the active device.
///
/// For albums, playlists, artists, and shows, all tracks/episodes are resolved
/// and added to the queue.
pub fn add_to_queue(&self, uri: SpotifyUri) -> Result<(), Error> {
if !matches!(
uri,
SpotifyUri::Track { .. }
| SpotifyUri::Episode { .. }
| SpotifyUri::Album { .. }
| SpotifyUri::Playlist { .. }
| SpotifyUri::Artist { .. }
| SpotifyUri::Show { .. }
) {
return Err(Error::invalid_argument("uri"));
}
Ok(self.commands.send(SpircCommand::AddToQueue(uri))?)
}

/// Disconnects the current device and pauses the playback according the value.
///
/// Does nothing if we are not the active device.
Expand Down Expand Up @@ -679,6 +702,7 @@ impl SpircTask {
SpircCommand::SetPosition(position) => self.handle_seek(position),
SpircCommand::SetVolume(volume) => self.set_volume(volume),
SpircCommand::Load(command) => self.handle_load(command, None, None).await?,
SpircCommand::AddToQueue(uri) => self.handle_add_to_queue(uri).await,
};

self.notify().await
Expand Down Expand Up @@ -1545,6 +1569,38 @@ impl SpircTask {
self.connect_state.set_repeat_track(repeat);
}

async fn handle_add_to_queue(&mut self, uri: SpotifyUri) {
let track_uris: Vec<String> = match uri {
SpotifyUri::Track { .. } | SpotifyUri::Episode { .. } => vec![uri.to_uri()],
SpotifyUri::Album { .. }
| SpotifyUri::Playlist { .. }
| SpotifyUri::Artist { .. }
| SpotifyUri::Show { .. } => {
Comment thread
photovoltex marked this conversation as resolved.
Outdated
match self.session.spclient().get_context(&uri.to_uri()).await {
Ok(context) => context
.pages
.iter()
.flat_map(|page| page.tracks.iter())
.filter_map(|track| track.uri.clone())
.collect(),
Err(e) => {
error!("failed to resolve context for {}: {e}", uri.item_type());
return;
}
}
}
_ => return,
};

for track_uri in track_uris {
let track = ProvidedTrack {
uri: track_uri,
..Default::default()
};
self.connect_state.add_to_queue(track, true);
}
}

fn handle_preload_next_track(&mut self) {
// Requests the player thread to preload the next track
match self.play_status {
Expand Down