Skip to content

Commit 2a57426

Browse files
authored
Update protobuf files (#1424)
* update protobuf definitions * add additionally required proto files * update version.rs * adjust code to protobuf changes * fix formatting * apply suggestions, improve errors
1 parent 0ad1f72 commit 2a57426

335 files changed

Lines changed: 3321 additions & 1194 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3535

3636
### Removed
3737

38+
- [core] Removed `get_canvases` from SpClient (breaking)
39+
- [metadata] Removed `genres` from Album (breaking)
40+
- [metadata] Removed `genre` from Artists (breaking)
41+
3842
## [0.6.0] - 2024-10-30
3943

4044
This version takes another step into the direction of the HTTP API, fixes a

connect/src/model.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::state::ConnectState;
22
use librespot_core::dealer::protocol::SkipTo;
3-
use librespot_protocol::player::Context;
3+
use librespot_protocol::context::Context;
44
use std::fmt::{Display, Formatter};
55
use std::hash::{Hash, Hasher};
66

@@ -77,7 +77,7 @@ impl ResolveContext {
7777
let fallback_uri = fallback.into();
7878
Self {
7979
context: Context {
80-
uri: uri.into(),
80+
uri: Some(uri.into()),
8181
..Default::default()
8282
},
8383
fallback: (!fallback_uri.is_empty()).then_some(fallback_uri),
@@ -114,7 +114,7 @@ impl ResolveContext {
114114

115115
Self {
116116
context: Context {
117-
uri,
117+
uri: Some(uri),
118118
..Default::default()
119119
},
120120
fallback: None,
@@ -134,7 +134,7 @@ impl ResolveContext {
134134

135135
/// the actual context uri
136136
pub fn context_uri(&self) -> &str {
137-
&self.context.uri
137+
self.context.uri.as_deref().unwrap_or_default()
138138
}
139139

140140
pub fn autoplay(&self) -> bool {
@@ -150,7 +150,7 @@ impl Display for ResolveContext {
150150
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
151151
write!(
152152
f,
153-
"resolve_uri: <{:?}>, context_uri: <{}>, autoplay: <{}>, update: <{}>",
153+
"resolve_uri: <{:?}>, context_uri: <{:?}>, autoplay: <{}>, update: <{}>",
154154
self.resolve_uri(),
155155
self.context.uri,
156156
self.autoplay,

connect/src/spirc.rs

Lines changed: 43 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,11 @@ use crate::{
1717
protocol::{
1818
autoplay_context_request::AutoplayContextRequest,
1919
connect::{Cluster, ClusterUpdate, LogoutCommand, SetVolumeCommand},
20+
context::Context,
2021
explicit_content_pubsub::UserAttributesUpdate,
21-
player::{Context, TransferState},
2222
playlist4_external::PlaylistModificationInfo,
23-
social_connect_v2::{session::_host_active_device_id, SessionUpdate},
23+
social_connect_v2::SessionUpdate,
24+
transfer_state::TransferState,
2425
user_attributes::UserAttributesMutation,
2526
},
2627
};
@@ -49,6 +50,8 @@ use tokio::{sync::mpsc, time::sleep};
4950
pub enum SpircError {
5051
#[error("response payload empty")]
5152
NoData,
53+
#[error("{0} had no uri")]
54+
NoUri(&'static str),
5255
#[error("message pushed for another URI")]
5356
InvalidUri(String),
5457
#[error("tried resolving not allowed context: {0:?}")]
@@ -63,7 +66,7 @@ impl From<SpircError> for Error {
6366
fn from(err: SpircError) -> Self {
6467
use SpircError::*;
6568
match err {
66-
NoData | NotAllowedContext(_) => Error::unavailable(err),
69+
NoData | NoUri(_) | NotAllowedContext(_) => Error::unavailable(err),
6770
InvalidUri(_) | FailedDealerSetup => Error::aborted(err),
6871
UnknownEndpoint(_) => Error::unimplemented(err),
6972
}
@@ -522,14 +525,14 @@ impl SpircTask {
522525
let mut ctx = self.session.spclient().get_context(resolve_uri).await?;
523526

524527
if update {
525-
ctx.uri = context_uri.to_string();
526-
ctx.url = format!("context://{context_uri}");
528+
ctx.uri = Some(context_uri.to_string());
529+
ctx.url = Some(format!("context://{context_uri}"));
527530

528531
self.connect_state
529532
.update_context(ctx, UpdateContext::Default)?
530533
} else if matches!(ctx.pages.first(), Some(p) if !p.tracks.is_empty()) {
531534
debug!(
532-
"update context from single page, context {} had {} pages",
535+
"update context from single page, context {:?} had {} pages",
533536
ctx.uri,
534537
ctx.pages.len()
535538
);
@@ -883,7 +886,7 @@ impl SpircTask {
883886
let attributes: UserAttributes = update
884887
.pairs
885888
.iter()
886-
.map(|pair| (pair.key().to_owned(), pair.value().to_owned()))
889+
.map(|(key, value)| (key.to_owned(), value.to_owned()))
887890
.collect();
888891
self.session.set_user_attributes(attributes)
889892
}
@@ -998,9 +1001,10 @@ impl SpircTask {
9981001
Unknown(unknown) => Err(SpircError::UnknownEndpoint(unknown))?,
9991002
// implicit update of the connect_state
10001003
UpdateContext(update_context) => {
1001-
if &update_context.context.uri != self.connect_state.context_uri() {
1004+
if matches!(update_context.context.uri, Some(ref uri) if uri != self.connect_state.context_uri())
1005+
{
10021006
debug!(
1003-
"ignoring context update for <{}>, because it isn't the current context <{}>",
1007+
"ignoring context update for <{:?}>, because it isn't the current context <{}>",
10041008
update_context.context.uri, self.connect_state.context_uri()
10051009
)
10061010
} else {
@@ -1020,24 +1024,30 @@ impl SpircTask {
10201024
.options
10211025
.player_options_override
10221026
.as_ref()
1023-
.map(|o| o.shuffling_context)
1027+
.map(|o| o.shuffling_context.unwrap_or_default())
10241028
.unwrap_or_else(|| self.connect_state.shuffling_context());
10251029
let repeat = play
10261030
.options
10271031
.player_options_override
10281032
.as_ref()
1029-
.map(|o| o.repeating_context)
1033+
.map(|o| o.repeating_context.unwrap_or_default())
10301034
.unwrap_or_else(|| self.connect_state.repeat_context());
10311035
let repeat_track = play
10321036
.options
10331037
.player_options_override
10341038
.as_ref()
1035-
.map(|o| o.repeating_track)
1039+
.map(|o| o.repeating_track.unwrap_or_default())
10361040
.unwrap_or_else(|| self.connect_state.repeat_track());
10371041

1042+
let context_uri = play
1043+
.context
1044+
.uri
1045+
.clone()
1046+
.ok_or(SpircError::NoUri("context"))?;
1047+
10381048
self.handle_load(
10391049
SpircLoadCommand {
1040-
context_uri: play.context.uri.clone(),
1050+
context_uri,
10411051
start_playing: true,
10421052
seek_to: play.options.seek_to.unwrap_or_default(),
10431053
playing_track: play.options.skip_to.unwrap_or_default().into(),
@@ -1088,12 +1098,13 @@ impl SpircTask {
10881098
}
10891099

10901100
fn handle_transfer(&mut self, mut transfer: TransferState) -> Result<(), Error> {
1091-
self.connect_state
1092-
.reset_context(ResetContext::WhenDifferent(
1093-
&transfer.current_session.context.uri,
1094-
));
1101+
let mut ctx_uri = match transfer.current_session.context.uri {
1102+
None => Err(SpircError::NoUri("transfer context"))?,
1103+
Some(ref uri) => uri.clone(),
1104+
};
10951105

1096-
let mut ctx_uri = transfer.current_session.context.uri.clone();
1106+
self.connect_state
1107+
.reset_context(ResetContext::WhenDifferent(&ctx_uri));
10971108

10981109
match self.connect_state.current_track_from_transfer(&transfer) {
10991110
Err(why) => warn!("didn't find initial track: {why}"),
@@ -1118,17 +1129,18 @@ impl SpircTask {
11181129
state.set_active(true);
11191130
state.handle_initial_transfer(&mut transfer);
11201131

1121-
// update position if the track continued playing
1122-
let position = if transfer.playback.is_paused {
1123-
transfer.playback.position_as_of_timestamp.into()
1124-
} else if transfer.playback.position_as_of_timestamp > 0 {
1125-
let time_since_position_update = timestamp - transfer.playback.timestamp;
1126-
i64::from(transfer.playback.position_as_of_timestamp) + time_since_position_update
1127-
} else {
1128-
0
1132+
let transfer_timestamp = transfer.playback.timestamp.unwrap_or_default();
1133+
let position = match transfer.playback.position_as_of_timestamp {
1134+
Some(position) if transfer.playback.is_paused.unwrap_or_default() => position.into(),
1135+
// update position if the track continued playing
1136+
Some(position) if position > 0 => {
1137+
let time_since_position_update = timestamp - transfer_timestamp;
1138+
i64::from(position) + time_since_position_update
1139+
}
1140+
_ => 0,
11291141
};
11301142

1131-
let is_playing = !transfer.playback.is_paused;
1143+
let is_playing = matches!(transfer.playback.is_paused, Some(is_playing) if is_playing);
11321144

11331145
if self.connect_state.current_track(|t| t.is_autoplay()) || autoplay {
11341146
debug!("currently in autoplay context, async resolving autoplay for {ctx_uri}");
@@ -1514,7 +1526,9 @@ impl SpircTask {
15141526
&mut self,
15151527
playlist_modification_info: PlaylistModificationInfo,
15161528
) -> Result<(), Error> {
1517-
let uri = playlist_modification_info.uri.ok_or(SpircError::NoData)?;
1529+
let uri = playlist_modification_info
1530+
.uri
1531+
.ok_or(SpircError::NoUri("playlist modification"))?;
15181532
let uri = String::from_utf8(uri)?;
15191533

15201534
if self.connect_state.context_uri() != &uri {
@@ -1540,14 +1554,7 @@ impl SpircTask {
15401554
Some(session) => session,
15411555
};
15421556

1543-
let active_device = session._host_active_device_id.take().map(|id| match id {
1544-
_host_active_device_id::HostActiveDeviceId(id) => id,
1545-
other => {
1546-
warn!("unexpected active device id {other:?}");
1547-
String::new()
1548-
}
1549-
});
1550-
1557+
let active_device = session.host_active_device_id.take();
15511558
if matches!(active_device, Some(ref device) if device == self.session.device_id()) {
15521559
info!(
15531560
"session update: <{:?}> for self, current session_id {}, new session_id {}",

connect/src/state.rs

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,25 @@ mod tracks;
88
mod transfer;
99

1010
use crate::model::SpircPlayStatus;
11-
use crate::state::{
12-
context::{ContextType, ResetContext, StateContext},
13-
provider::{IsProvider, Provider},
14-
};
15-
use librespot_core::{
16-
config::DeviceType, date::Date, dealer::protocol::Request, spclient::SpClientResult, version,
17-
Error, Session,
18-
};
19-
use librespot_protocol::connect::{
20-
Capabilities, Device, DeviceInfo, MemberType, PutStateReason, PutStateRequest,
21-
};
22-
use librespot_protocol::player::{
23-
ContextIndex, ContextPage, ContextPlayerOptions, PlayOrigin, PlayerState, ProvidedTrack,
24-
Suppressions,
11+
use crate::{
12+
core::{
13+
config::DeviceType, date::Date, dealer::protocol::Request, spclient::SpClientResult,
14+
version, Error, Session,
15+
},
16+
protocol::{
17+
connect::{Capabilities, Device, DeviceInfo, MemberType, PutStateReason, PutStateRequest},
18+
context_page::ContextPage,
19+
player::{
20+
ContextIndex, ContextPlayerOptions, PlayOrigin, PlayerState, ProvidedTrack,
21+
Suppressions,
22+
},
23+
},
24+
state::{
25+
context::{ContextType, ResetContext, StateContext},
26+
provider::{IsProvider, Provider},
27+
},
2528
};
29+
2630
use log::LevelFilter;
2731
use protobuf::{EnumOrUnknown, MessageField};
2832
use std::{
@@ -40,28 +44,28 @@ const SPOTIFY_MAX_NEXT_TRACKS_SIZE: usize = 80;
4044
pub enum StateError {
4145
#[error("the current track couldn't be resolved from the transfer state")]
4246
CouldNotResolveTrackFromTransfer,
43-
#[error("message field {0} was not available")]
44-
MessageFieldNone(String),
4547
#[error("context is not available. type: {0:?}")]
4648
NoContext(ContextType),
4749
#[error("could not find track {0:?} in context of {1}")]
4850
CanNotFindTrackInContext(Option<usize>, usize),
4951
#[error("currently {action} is not allowed because {reason}")]
50-
CurrentlyDisallowed { action: String, reason: String },
52+
CurrentlyDisallowed {
53+
action: &'static str,
54+
reason: String,
55+
},
5156
#[error("the provided context has no tracks")]
5257
ContextHasNoTracks,
5358
#[error("playback of local files is not supported")]
5459
UnsupportedLocalPlayBack,
55-
#[error("track uri <{0}> contains invalid characters")]
56-
InvalidTrackUri(String),
60+
#[error("track uri <{0:?}> contains invalid characters")]
61+
InvalidTrackUri(Option<String>),
5762
}
5863

5964
impl From<StateError> for Error {
6065
fn from(err: StateError) -> Self {
6166
use StateError::*;
6267
match err {
6368
CouldNotResolveTrackFromTransfer
64-
| MessageFieldNone(_)
6569
| NoContext(_)
6670
| CanNotFindTrackInContext(_, _)
6771
| ContextHasNoTracks

0 commit comments

Comments
 (0)