mirror of
https://github.com/librespot-org/librespot.git
synced 2025-10-03 09:49:31 +02:00
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
This commit is contained in:
parent
0ad1f7249b
commit
2a574267ae
335 changed files with 3331 additions and 1204 deletions
|
@ -35,6 +35,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
|
- [core] Removed `get_canvases` from SpClient (breaking)
|
||||||
|
- [metadata] Removed `genres` from Album (breaking)
|
||||||
|
- [metadata] Removed `genre` from Artists (breaking)
|
||||||
|
|
||||||
## [0.6.0] - 2024-10-30
|
## [0.6.0] - 2024-10-30
|
||||||
|
|
||||||
This version takes another step into the direction of the HTTP API, fixes a
|
This version takes another step into the direction of the HTTP API, fixes a
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::state::ConnectState;
|
use crate::state::ConnectState;
|
||||||
use librespot_core::dealer::protocol::SkipTo;
|
use librespot_core::dealer::protocol::SkipTo;
|
||||||
use librespot_protocol::player::Context;
|
use librespot_protocol::context::Context;
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ impl ResolveContext {
|
||||||
let fallback_uri = fallback.into();
|
let fallback_uri = fallback.into();
|
||||||
Self {
|
Self {
|
||||||
context: Context {
|
context: Context {
|
||||||
uri: uri.into(),
|
uri: Some(uri.into()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
fallback: (!fallback_uri.is_empty()).then_some(fallback_uri),
|
fallback: (!fallback_uri.is_empty()).then_some(fallback_uri),
|
||||||
|
@ -114,7 +114,7 @@ impl ResolveContext {
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
context: Context {
|
context: Context {
|
||||||
uri,
|
uri: Some(uri),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
fallback: None,
|
fallback: None,
|
||||||
|
@ -134,7 +134,7 @@ impl ResolveContext {
|
||||||
|
|
||||||
/// the actual context uri
|
/// the actual context uri
|
||||||
pub fn context_uri(&self) -> &str {
|
pub fn context_uri(&self) -> &str {
|
||||||
&self.context.uri
|
self.context.uri.as_deref().unwrap_or_default()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn autoplay(&self) -> bool {
|
pub fn autoplay(&self) -> bool {
|
||||||
|
@ -150,7 +150,7 @@ impl Display for ResolveContext {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
"resolve_uri: <{:?}>, context_uri: <{}>, autoplay: <{}>, update: <{}>",
|
"resolve_uri: <{:?}>, context_uri: <{:?}>, autoplay: <{}>, update: <{}>",
|
||||||
self.resolve_uri(),
|
self.resolve_uri(),
|
||||||
self.context.uri,
|
self.context.uri,
|
||||||
self.autoplay,
|
self.autoplay,
|
||||||
|
|
|
@ -17,10 +17,11 @@ use crate::{
|
||||||
protocol::{
|
protocol::{
|
||||||
autoplay_context_request::AutoplayContextRequest,
|
autoplay_context_request::AutoplayContextRequest,
|
||||||
connect::{Cluster, ClusterUpdate, LogoutCommand, SetVolumeCommand},
|
connect::{Cluster, ClusterUpdate, LogoutCommand, SetVolumeCommand},
|
||||||
|
context::Context,
|
||||||
explicit_content_pubsub::UserAttributesUpdate,
|
explicit_content_pubsub::UserAttributesUpdate,
|
||||||
player::{Context, TransferState},
|
|
||||||
playlist4_external::PlaylistModificationInfo,
|
playlist4_external::PlaylistModificationInfo,
|
||||||
social_connect_v2::{session::_host_active_device_id, SessionUpdate},
|
social_connect_v2::SessionUpdate,
|
||||||
|
transfer_state::TransferState,
|
||||||
user_attributes::UserAttributesMutation,
|
user_attributes::UserAttributesMutation,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -49,6 +50,8 @@ use tokio::{sync::mpsc, time::sleep};
|
||||||
pub enum SpircError {
|
pub enum SpircError {
|
||||||
#[error("response payload empty")]
|
#[error("response payload empty")]
|
||||||
NoData,
|
NoData,
|
||||||
|
#[error("{0} had no uri")]
|
||||||
|
NoUri(&'static str),
|
||||||
#[error("message pushed for another URI")]
|
#[error("message pushed for another URI")]
|
||||||
InvalidUri(String),
|
InvalidUri(String),
|
||||||
#[error("tried resolving not allowed context: {0:?}")]
|
#[error("tried resolving not allowed context: {0:?}")]
|
||||||
|
@ -63,7 +66,7 @@ impl From<SpircError> for Error {
|
||||||
fn from(err: SpircError) -> Self {
|
fn from(err: SpircError) -> Self {
|
||||||
use SpircError::*;
|
use SpircError::*;
|
||||||
match err {
|
match err {
|
||||||
NoData | NotAllowedContext(_) => Error::unavailable(err),
|
NoData | NoUri(_) | NotAllowedContext(_) => Error::unavailable(err),
|
||||||
InvalidUri(_) | FailedDealerSetup => Error::aborted(err),
|
InvalidUri(_) | FailedDealerSetup => Error::aborted(err),
|
||||||
UnknownEndpoint(_) => Error::unimplemented(err),
|
UnknownEndpoint(_) => Error::unimplemented(err),
|
||||||
}
|
}
|
||||||
|
@ -522,14 +525,14 @@ impl SpircTask {
|
||||||
let mut ctx = self.session.spclient().get_context(resolve_uri).await?;
|
let mut ctx = self.session.spclient().get_context(resolve_uri).await?;
|
||||||
|
|
||||||
if update {
|
if update {
|
||||||
ctx.uri = context_uri.to_string();
|
ctx.uri = Some(context_uri.to_string());
|
||||||
ctx.url = format!("context://{context_uri}");
|
ctx.url = Some(format!("context://{context_uri}"));
|
||||||
|
|
||||||
self.connect_state
|
self.connect_state
|
||||||
.update_context(ctx, UpdateContext::Default)?
|
.update_context(ctx, UpdateContext::Default)?
|
||||||
} else if matches!(ctx.pages.first(), Some(p) if !p.tracks.is_empty()) {
|
} else if matches!(ctx.pages.first(), Some(p) if !p.tracks.is_empty()) {
|
||||||
debug!(
|
debug!(
|
||||||
"update context from single page, context {} had {} pages",
|
"update context from single page, context {:?} had {} pages",
|
||||||
ctx.uri,
|
ctx.uri,
|
||||||
ctx.pages.len()
|
ctx.pages.len()
|
||||||
);
|
);
|
||||||
|
@ -883,7 +886,7 @@ impl SpircTask {
|
||||||
let attributes: UserAttributes = update
|
let attributes: UserAttributes = update
|
||||||
.pairs
|
.pairs
|
||||||
.iter()
|
.iter()
|
||||||
.map(|pair| (pair.key().to_owned(), pair.value().to_owned()))
|
.map(|(key, value)| (key.to_owned(), value.to_owned()))
|
||||||
.collect();
|
.collect();
|
||||||
self.session.set_user_attributes(attributes)
|
self.session.set_user_attributes(attributes)
|
||||||
}
|
}
|
||||||
|
@ -998,9 +1001,10 @@ impl SpircTask {
|
||||||
Unknown(unknown) => Err(SpircError::UnknownEndpoint(unknown))?,
|
Unknown(unknown) => Err(SpircError::UnknownEndpoint(unknown))?,
|
||||||
// implicit update of the connect_state
|
// implicit update of the connect_state
|
||||||
UpdateContext(update_context) => {
|
UpdateContext(update_context) => {
|
||||||
if &update_context.context.uri != self.connect_state.context_uri() {
|
if matches!(update_context.context.uri, Some(ref uri) if uri != self.connect_state.context_uri())
|
||||||
|
{
|
||||||
debug!(
|
debug!(
|
||||||
"ignoring context update for <{}>, because it isn't the current context <{}>",
|
"ignoring context update for <{:?}>, because it isn't the current context <{}>",
|
||||||
update_context.context.uri, self.connect_state.context_uri()
|
update_context.context.uri, self.connect_state.context_uri()
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
@ -1020,24 +1024,30 @@ impl SpircTask {
|
||||||
.options
|
.options
|
||||||
.player_options_override
|
.player_options_override
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|o| o.shuffling_context)
|
.map(|o| o.shuffling_context.unwrap_or_default())
|
||||||
.unwrap_or_else(|| self.connect_state.shuffling_context());
|
.unwrap_or_else(|| self.connect_state.shuffling_context());
|
||||||
let repeat = play
|
let repeat = play
|
||||||
.options
|
.options
|
||||||
.player_options_override
|
.player_options_override
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|o| o.repeating_context)
|
.map(|o| o.repeating_context.unwrap_or_default())
|
||||||
.unwrap_or_else(|| self.connect_state.repeat_context());
|
.unwrap_or_else(|| self.connect_state.repeat_context());
|
||||||
let repeat_track = play
|
let repeat_track = play
|
||||||
.options
|
.options
|
||||||
.player_options_override
|
.player_options_override
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|o| o.repeating_track)
|
.map(|o| o.repeating_track.unwrap_or_default())
|
||||||
.unwrap_or_else(|| self.connect_state.repeat_track());
|
.unwrap_or_else(|| self.connect_state.repeat_track());
|
||||||
|
|
||||||
|
let context_uri = play
|
||||||
|
.context
|
||||||
|
.uri
|
||||||
|
.clone()
|
||||||
|
.ok_or(SpircError::NoUri("context"))?;
|
||||||
|
|
||||||
self.handle_load(
|
self.handle_load(
|
||||||
SpircLoadCommand {
|
SpircLoadCommand {
|
||||||
context_uri: play.context.uri.clone(),
|
context_uri,
|
||||||
start_playing: true,
|
start_playing: true,
|
||||||
seek_to: play.options.seek_to.unwrap_or_default(),
|
seek_to: play.options.seek_to.unwrap_or_default(),
|
||||||
playing_track: play.options.skip_to.unwrap_or_default().into(),
|
playing_track: play.options.skip_to.unwrap_or_default().into(),
|
||||||
|
@ -1088,12 +1098,13 @@ impl SpircTask {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_transfer(&mut self, mut transfer: TransferState) -> Result<(), Error> {
|
fn handle_transfer(&mut self, mut transfer: TransferState) -> Result<(), Error> {
|
||||||
self.connect_state
|
let mut ctx_uri = match transfer.current_session.context.uri {
|
||||||
.reset_context(ResetContext::WhenDifferent(
|
None => Err(SpircError::NoUri("transfer context"))?,
|
||||||
&transfer.current_session.context.uri,
|
Some(ref uri) => uri.clone(),
|
||||||
));
|
};
|
||||||
|
|
||||||
let mut ctx_uri = transfer.current_session.context.uri.clone();
|
self.connect_state
|
||||||
|
.reset_context(ResetContext::WhenDifferent(&ctx_uri));
|
||||||
|
|
||||||
match self.connect_state.current_track_from_transfer(&transfer) {
|
match self.connect_state.current_track_from_transfer(&transfer) {
|
||||||
Err(why) => warn!("didn't find initial track: {why}"),
|
Err(why) => warn!("didn't find initial track: {why}"),
|
||||||
|
@ -1118,17 +1129,18 @@ impl SpircTask {
|
||||||
state.set_active(true);
|
state.set_active(true);
|
||||||
state.handle_initial_transfer(&mut transfer);
|
state.handle_initial_transfer(&mut transfer);
|
||||||
|
|
||||||
// update position if the track continued playing
|
let transfer_timestamp = transfer.playback.timestamp.unwrap_or_default();
|
||||||
let position = if transfer.playback.is_paused {
|
let position = match transfer.playback.position_as_of_timestamp {
|
||||||
transfer.playback.position_as_of_timestamp.into()
|
Some(position) if transfer.playback.is_paused.unwrap_or_default() => position.into(),
|
||||||
} else if transfer.playback.position_as_of_timestamp > 0 {
|
// update position if the track continued playing
|
||||||
let time_since_position_update = timestamp - transfer.playback.timestamp;
|
Some(position) if position > 0 => {
|
||||||
i64::from(transfer.playback.position_as_of_timestamp) + time_since_position_update
|
let time_since_position_update = timestamp - transfer_timestamp;
|
||||||
} else {
|
i64::from(position) + time_since_position_update
|
||||||
0
|
}
|
||||||
|
_ => 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
let is_playing = !transfer.playback.is_paused;
|
let is_playing = matches!(transfer.playback.is_paused, Some(is_playing) if is_playing);
|
||||||
|
|
||||||
if self.connect_state.current_track(|t| t.is_autoplay()) || autoplay {
|
if self.connect_state.current_track(|t| t.is_autoplay()) || autoplay {
|
||||||
debug!("currently in autoplay context, async resolving autoplay for {ctx_uri}");
|
debug!("currently in autoplay context, async resolving autoplay for {ctx_uri}");
|
||||||
|
@ -1514,7 +1526,9 @@ impl SpircTask {
|
||||||
&mut self,
|
&mut self,
|
||||||
playlist_modification_info: PlaylistModificationInfo,
|
playlist_modification_info: PlaylistModificationInfo,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let uri = playlist_modification_info.uri.ok_or(SpircError::NoData)?;
|
let uri = playlist_modification_info
|
||||||
|
.uri
|
||||||
|
.ok_or(SpircError::NoUri("playlist modification"))?;
|
||||||
let uri = String::from_utf8(uri)?;
|
let uri = String::from_utf8(uri)?;
|
||||||
|
|
||||||
if self.connect_state.context_uri() != &uri {
|
if self.connect_state.context_uri() != &uri {
|
||||||
|
@ -1540,14 +1554,7 @@ impl SpircTask {
|
||||||
Some(session) => session,
|
Some(session) => session,
|
||||||
};
|
};
|
||||||
|
|
||||||
let active_device = session._host_active_device_id.take().map(|id| match id {
|
let active_device = session.host_active_device_id.take();
|
||||||
_host_active_device_id::HostActiveDeviceId(id) => id,
|
|
||||||
other => {
|
|
||||||
warn!("unexpected active device id {other:?}");
|
|
||||||
String::new()
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if matches!(active_device, Some(ref device) if device == self.session.device_id()) {
|
if matches!(active_device, Some(ref device) if device == self.session.device_id()) {
|
||||||
info!(
|
info!(
|
||||||
"session update: <{:?}> for self, current session_id {}, new session_id {}",
|
"session update: <{:?}> for self, current session_id {}, new session_id {}",
|
||||||
|
|
|
@ -8,21 +8,25 @@ mod tracks;
|
||||||
mod transfer;
|
mod transfer;
|
||||||
|
|
||||||
use crate::model::SpircPlayStatus;
|
use crate::model::SpircPlayStatus;
|
||||||
use crate::state::{
|
use crate::{
|
||||||
context::{ContextType, ResetContext, StateContext},
|
core::{
|
||||||
provider::{IsProvider, Provider},
|
config::DeviceType, date::Date, dealer::protocol::Request, spclient::SpClientResult,
|
||||||
};
|
version, Error, Session,
|
||||||
use librespot_core::{
|
},
|
||||||
config::DeviceType, date::Date, dealer::protocol::Request, spclient::SpClientResult, version,
|
protocol::{
|
||||||
Error, Session,
|
connect::{Capabilities, Device, DeviceInfo, MemberType, PutStateReason, PutStateRequest},
|
||||||
};
|
context_page::ContextPage,
|
||||||
use librespot_protocol::connect::{
|
player::{
|
||||||
Capabilities, Device, DeviceInfo, MemberType, PutStateReason, PutStateRequest,
|
ContextIndex, ContextPlayerOptions, PlayOrigin, PlayerState, ProvidedTrack,
|
||||||
};
|
Suppressions,
|
||||||
use librespot_protocol::player::{
|
},
|
||||||
ContextIndex, ContextPage, ContextPlayerOptions, PlayOrigin, PlayerState, ProvidedTrack,
|
},
|
||||||
Suppressions,
|
state::{
|
||||||
|
context::{ContextType, ResetContext, StateContext},
|
||||||
|
provider::{IsProvider, Provider},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use log::LevelFilter;
|
use log::LevelFilter;
|
||||||
use protobuf::{EnumOrUnknown, MessageField};
|
use protobuf::{EnumOrUnknown, MessageField};
|
||||||
use std::{
|
use std::{
|
||||||
|
@ -40,20 +44,21 @@ const SPOTIFY_MAX_NEXT_TRACKS_SIZE: usize = 80;
|
||||||
pub enum StateError {
|
pub enum StateError {
|
||||||
#[error("the current track couldn't be resolved from the transfer state")]
|
#[error("the current track couldn't be resolved from the transfer state")]
|
||||||
CouldNotResolveTrackFromTransfer,
|
CouldNotResolveTrackFromTransfer,
|
||||||
#[error("message field {0} was not available")]
|
|
||||||
MessageFieldNone(String),
|
|
||||||
#[error("context is not available. type: {0:?}")]
|
#[error("context is not available. type: {0:?}")]
|
||||||
NoContext(ContextType),
|
NoContext(ContextType),
|
||||||
#[error("could not find track {0:?} in context of {1}")]
|
#[error("could not find track {0:?} in context of {1}")]
|
||||||
CanNotFindTrackInContext(Option<usize>, usize),
|
CanNotFindTrackInContext(Option<usize>, usize),
|
||||||
#[error("currently {action} is not allowed because {reason}")]
|
#[error("currently {action} is not allowed because {reason}")]
|
||||||
CurrentlyDisallowed { action: String, reason: String },
|
CurrentlyDisallowed {
|
||||||
|
action: &'static str,
|
||||||
|
reason: String,
|
||||||
|
},
|
||||||
#[error("the provided context has no tracks")]
|
#[error("the provided context has no tracks")]
|
||||||
ContextHasNoTracks,
|
ContextHasNoTracks,
|
||||||
#[error("playback of local files is not supported")]
|
#[error("playback of local files is not supported")]
|
||||||
UnsupportedLocalPlayBack,
|
UnsupportedLocalPlayBack,
|
||||||
#[error("track uri <{0}> contains invalid characters")]
|
#[error("track uri <{0:?}> contains invalid characters")]
|
||||||
InvalidTrackUri(String),
|
InvalidTrackUri(Option<String>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<StateError> for Error {
|
impl From<StateError> for Error {
|
||||||
|
@ -61,7 +66,6 @@ impl From<StateError> for Error {
|
||||||
use StateError::*;
|
use StateError::*;
|
||||||
match err {
|
match err {
|
||||||
CouldNotResolveTrackFromTransfer
|
CouldNotResolveTrackFromTransfer
|
||||||
| MessageFieldNone(_)
|
|
||||||
| NoContext(_)
|
| NoContext(_)
|
||||||
| CanNotFindTrackInContext(_, _)
|
| CanNotFindTrackInContext(_, _)
|
||||||
| ContextHasNoTracks
|
| ContextHasNoTracks
|
||||||
|
|
|
@ -1,7 +1,13 @@
|
||||||
use crate::state::{metadata::Metadata, provider::Provider, ConnectState, StateError};
|
use crate::{
|
||||||
use librespot_core::{Error, SpotifyId};
|
core::{Error, SpotifyId},
|
||||||
use librespot_protocol::player::{
|
protocol::{
|
||||||
Context, ContextIndex, ContextPage, ContextTrack, ProvidedTrack, Restrictions,
|
context::Context,
|
||||||
|
context_page::ContextPage,
|
||||||
|
context_track::ContextTrack,
|
||||||
|
player::{ContextIndex, ProvidedTrack},
|
||||||
|
restrictions::Restrictions,
|
||||||
|
},
|
||||||
|
state::{metadata::Metadata, provider::Provider, ConnectState, StateError},
|
||||||
};
|
};
|
||||||
use protobuf::MessageField;
|
use protobuf::MessageField;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
@ -104,14 +110,16 @@ impl ConnectState {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_context_uri_from_context(context: &Context) -> Option<&String> {
|
pub fn get_context_uri_from_context(context: &Context) -> Option<&String> {
|
||||||
if !context.uri.starts_with(SEARCH_IDENTIFIER) {
|
let context_uri = context.uri.as_ref()?;
|
||||||
return Some(&context.uri);
|
|
||||||
|
if !context_uri.starts_with(SEARCH_IDENTIFIER) {
|
||||||
|
return Some(context_uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
context
|
context
|
||||||
.pages
|
.pages
|
||||||
.first()
|
.first()
|
||||||
.and_then(|p| p.tracks.first().map(|t| &t.uri))
|
.and_then(|p| p.tracks.first().and_then(|t| t.uri.as_ref()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_active_context(&mut self, new_context: ContextType) {
|
pub fn set_active_context(&mut self, new_context: ContextType) {
|
||||||
|
@ -134,7 +142,7 @@ impl ConnectState {
|
||||||
player.restrictions.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.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (key, value) in metadata {
|
for (key, value) in metadata {
|
||||||
|
@ -146,7 +154,7 @@ impl ConnectState {
|
||||||
if context.pages.iter().all(|p| p.tracks.is_empty()) {
|
if context.pages.iter().all(|p| p.tracks.is_empty()) {
|
||||||
error!("context didn't have any tracks: {context:#?}");
|
error!("context didn't have any tracks: {context:#?}");
|
||||||
return Err(StateError::ContextHasNoTracks.into());
|
return Err(StateError::ContextHasNoTracks.into());
|
||||||
} else if context.uri.starts_with(LOCAL_FILES_IDENTIFIER) {
|
} else if matches!(context.uri, Some(ref uri) if uri.starts_with(LOCAL_FILES_IDENTIFIER)) {
|
||||||
return Err(StateError::UnsupportedLocalPlayBack.into());
|
return Err(StateError::UnsupportedLocalPlayBack.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,7 +182,7 @@ impl ConnectState {
|
||||||
};
|
};
|
||||||
|
|
||||||
debug!(
|
debug!(
|
||||||
"updated context {ty:?} from <{}> ({} tracks) to <{}> ({} tracks)",
|
"updated context {ty:?} from <{:?}> ({} tracks) to <{:?}> ({} tracks)",
|
||||||
self.context_uri(),
|
self.context_uri(),
|
||||||
prev_context
|
prev_context
|
||||||
.map(|c| c.tracks.len().to_string())
|
.map(|c| c.tracks.len().to_string())
|
||||||
|
@ -188,14 +196,14 @@ impl ConnectState {
|
||||||
let mut new_context = self.state_context_from_page(
|
let mut new_context = self.state_context_from_page(
|
||||||
page,
|
page,
|
||||||
context.restrictions.take(),
|
context.restrictions.take(),
|
||||||
Some(&context.uri),
|
context.uri.as_deref(),
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
|
||||||
// when we update the same context, we should try to preserve the previous position
|
// when we update the same context, we should try to preserve the previous position
|
||||||
// otherwise we might load the entire context twice
|
// otherwise we might load the entire context twice
|
||||||
if !self.context_uri().contains(SEARCH_IDENTIFIER)
|
if !self.context_uri().contains(SEARCH_IDENTIFIER)
|
||||||
&& self.context_uri() == &context.uri
|
&& matches!(context.uri, Some(ref uri) if uri == self.context_uri())
|
||||||
{
|
{
|
||||||
match Self::find_index_in_context(Some(&new_context), |t| {
|
match Self::find_index_in_context(Some(&new_context), |t| {
|
||||||
self.current_track(|t| &t.uri) == &t.uri
|
self.current_track(|t| &t.uri) == &t.uri
|
||||||
|
@ -217,18 +225,18 @@ impl ConnectState {
|
||||||
|
|
||||||
self.context = Some(new_context);
|
self.context = Some(new_context);
|
||||||
|
|
||||||
if !context.url.contains(SEARCH_IDENTIFIER) {
|
if !matches!(context.url, Some(ref url) if url.contains(SEARCH_IDENTIFIER)) {
|
||||||
self.player_mut().context_url = context.url;
|
self.player_mut().context_url = context.url.take().unwrap_or_default();
|
||||||
} else {
|
} else {
|
||||||
self.player_mut().context_url.clear()
|
self.player_mut().context_url.clear()
|
||||||
}
|
}
|
||||||
self.player_mut().context_uri = context.uri;
|
self.player_mut().context_uri = context.uri.take().unwrap_or_default();
|
||||||
}
|
}
|
||||||
UpdateContext::Autoplay => {
|
UpdateContext::Autoplay => {
|
||||||
self.autoplay_context = Some(self.state_context_from_page(
|
self.autoplay_context = Some(self.state_context_from_page(
|
||||||
page,
|
page,
|
||||||
context.restrictions.take(),
|
context.restrictions.take(),
|
||||||
Some(&context.uri),
|
context.uri.as_deref(),
|
||||||
Some(Provider::Autoplay),
|
Some(Provider::Autoplay),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -271,7 +279,7 @@ impl ConnectState {
|
||||||
|
|
||||||
pub fn merge_context(&mut self, context: Option<Context>) -> Option<()> {
|
pub fn merge_context(&mut self, context: Option<Context>) -> Option<()> {
|
||||||
let mut context = context?;
|
let mut context = context?;
|
||||||
if self.context_uri() != &context.uri {
|
if matches!(context.uri, Some(ref uri) if uri != self.context_uri()) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,12 +287,13 @@ impl ConnectState {
|
||||||
let new_page = context.pages.pop()?;
|
let new_page = context.pages.pop()?;
|
||||||
|
|
||||||
for new_track in new_page.tracks {
|
for new_track in new_page.tracks {
|
||||||
if new_track.uri.is_empty() {
|
if new_track.uri.is_none() || matches!(new_track.uri, Some(ref uri) if uri.is_empty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let new_track_uri = new_track.uri.unwrap_or_default();
|
||||||
if let Ok(position) =
|
if let Ok(position) =
|
||||||
Self::find_index_in_context(Some(current_context), |t| t.uri == new_track.uri)
|
Self::find_index_in_context(Some(current_context), |t| t.uri == new_track_uri)
|
||||||
{
|
{
|
||||||
let context_track = current_context.tracks.get_mut(position)?;
|
let context_track = current_context.tracks.get_mut(position)?;
|
||||||
|
|
||||||
|
@ -294,8 +303,10 @@ impl ConnectState {
|
||||||
}
|
}
|
||||||
|
|
||||||
// the uid provided from another context might be actual uid of an item
|
// the uid provided from another context might be actual uid of an item
|
||||||
if !new_track.uid.is_empty() {
|
if new_track.uid.is_some()
|
||||||
context_track.uid = new_track.uid;
|
|| matches!(new_track.uid, Some(ref uid) if uid.is_empty())
|
||||||
|
{
|
||||||
|
context_track.uid = new_track.uid.unwrap_or_default();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -325,19 +336,19 @@ impl ConnectState {
|
||||||
context_uri: Option<&str>,
|
context_uri: Option<&str>,
|
||||||
provider: Option<Provider>,
|
provider: Option<Provider>,
|
||||||
) -> Result<ProvidedTrack, Error> {
|
) -> Result<ProvidedTrack, Error> {
|
||||||
let id = if !ctx_track.uri.is_empty() {
|
let id = match (ctx_track.uri.as_ref(), ctx_track.gid.as_ref()) {
|
||||||
if ctx_track.uri.contains(['?', '%']) {
|
(None, None) => Err(StateError::InvalidTrackUri(None))?,
|
||||||
Err(StateError::InvalidTrackUri(ctx_track.uri.clone()))?
|
(Some(uri), _) if uri.contains(['?', '%']) => {
|
||||||
|
Err(StateError::InvalidTrackUri(Some(uri.clone())))?
|
||||||
}
|
}
|
||||||
|
(Some(uri), _) if !uri.is_empty() => SpotifyId::from_uri(uri)?,
|
||||||
SpotifyId::from_uri(&ctx_track.uri)?
|
(None, Some(gid)) if !gid.is_empty() => SpotifyId::from_raw(gid)?,
|
||||||
} else if !ctx_track.gid.is_empty() {
|
_ => Err(StateError::InvalidTrackUri(None))?,
|
||||||
SpotifyId::from_raw(&ctx_track.gid)?
|
|
||||||
} else {
|
|
||||||
Err(StateError::InvalidTrackUri(String::new()))?
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let provider = if self.unavailable_uri.contains(&ctx_track.uri) {
|
let uri = id.to_uri()?.replace("unknown", "track");
|
||||||
|
|
||||||
|
let provider = if self.unavailable_uri.contains(&uri) {
|
||||||
Provider::Unavailable
|
Provider::Unavailable
|
||||||
} else {
|
} else {
|
||||||
provider.unwrap_or(Provider::Context)
|
provider.unwrap_or(Provider::Context)
|
||||||
|
@ -346,11 +357,10 @@ impl ConnectState {
|
||||||
// assumption: the uid is used as unique-id of any item
|
// assumption: the uid is used as unique-id of any item
|
||||||
// - queue resorting is done by each client and orients itself by the given uid
|
// - queue resorting is done by each client and orients itself by the given uid
|
||||||
// - if no uid is present, resorting doesn't work or behaves not as intended
|
// - if no uid is present, resorting doesn't work or behaves not as intended
|
||||||
let uid = if ctx_track.uid.is_empty() {
|
let uid = match ctx_track.uid.as_ref() {
|
||||||
// so setting providing a unique id should allow to resort the queue
|
Some(uid) if !uid.is_empty() => uid.to_string(),
|
||||||
Uuid::new_v4().as_simple().to_string()
|
// so providing a unique id should allow to resort the queue
|
||||||
} else {
|
_ => Uuid::new_v4().as_simple().to_string(),
|
||||||
ctx_track.uid.to_string()
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut metadata = HashMap::new();
|
let mut metadata = HashMap::new();
|
||||||
|
@ -359,7 +369,7 @@ impl ConnectState {
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut track = ProvidedTrack {
|
let mut track = ProvidedTrack {
|
||||||
uri: id.to_uri()?.replace("unknown", "track"),
|
uri,
|
||||||
uid,
|
uid,
|
||||||
metadata,
|
metadata,
|
||||||
provider: provider.to_string(),
|
provider: provider.to_string(),
|
||||||
|
@ -399,12 +409,13 @@ impl ConnectState {
|
||||||
};
|
};
|
||||||
|
|
||||||
if next.tracks.is_empty() {
|
if next.tracks.is_empty() {
|
||||||
if next.page_url.is_empty() {
|
let next_page_url = match next.page_url {
|
||||||
Err(StateError::NoContext(ContextType::Default))?
|
Some(page_url) if !page_url.is_empty() => page_url,
|
||||||
}
|
_ => Err(StateError::NoContext(ContextType::Default))?,
|
||||||
|
};
|
||||||
|
|
||||||
self.update_current_index(|i| i.page += 1);
|
self.update_current_index(|i| i.page += 1);
|
||||||
return Ok(LoadNext::PageUrl(next.page_url));
|
return Ok(LoadNext::PageUrl(next_page_url));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.fill_context_from_page(next)?;
|
self.fill_context_from_page(next)?;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use librespot_protocol::player::{ContextTrack, ProvidedTrack};
|
use librespot_protocol::{context_track::ContextTrack, player::ProvidedTrack};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
const CONTEXT_URI: &str = "context_uri";
|
const CONTEXT_URI: &str = "context_uri";
|
||||||
|
|
|
@ -41,7 +41,7 @@ impl ConnectState {
|
||||||
.first()
|
.first()
|
||||||
{
|
{
|
||||||
Err(StateError::CurrentlyDisallowed {
|
Err(StateError::CurrentlyDisallowed {
|
||||||
action: "shuffle".to_string(),
|
action: "shuffle",
|
||||||
reason: reason.clone(),
|
reason: reason.clone(),
|
||||||
})?
|
})?
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,13 @@
|
||||||
use crate::state::context::ContextType;
|
use crate::{
|
||||||
use crate::state::metadata::Metadata;
|
core::Error,
|
||||||
use crate::state::provider::{IsProvider, Provider};
|
protocol::{player::ProvidedTrack, transfer_state::TransferState},
|
||||||
use crate::state::{ConnectState, StateError};
|
state::{
|
||||||
use librespot_core::Error;
|
context::ContextType,
|
||||||
use librespot_protocol::player::{ProvidedTrack, TransferState};
|
metadata::Metadata,
|
||||||
|
provider::{IsProvider, Provider},
|
||||||
|
{ConnectState, StateError},
|
||||||
|
},
|
||||||
|
};
|
||||||
use protobuf::MessageField;
|
use protobuf::MessageField;
|
||||||
|
|
||||||
impl ConnectState {
|
impl ConnectState {
|
||||||
|
@ -11,7 +15,7 @@ impl ConnectState {
|
||||||
&self,
|
&self,
|
||||||
transfer: &TransferState,
|
transfer: &TransferState,
|
||||||
) -> Result<ProvidedTrack, Error> {
|
) -> Result<ProvidedTrack, Error> {
|
||||||
let track = if transfer.queue.is_playing_queue {
|
let track = if transfer.queue.is_playing_queue.unwrap_or_default() {
|
||||||
transfer.queue.tracks.first()
|
transfer.queue.tracks.first()
|
||||||
} else {
|
} else {
|
||||||
transfer.playback.current_track.as_ref()
|
transfer.playback.current_track.as_ref()
|
||||||
|
@ -20,8 +24,11 @@ impl ConnectState {
|
||||||
|
|
||||||
self.context_to_provided_track(
|
self.context_to_provided_track(
|
||||||
track,
|
track,
|
||||||
Some(&transfer.current_session.context.uri),
|
transfer.current_session.context.uri.as_deref(),
|
||||||
transfer.queue.is_playing_queue.then_some(Provider::Queue),
|
transfer
|
||||||
|
.queue
|
||||||
|
.is_playing_queue
|
||||||
|
.and_then(|b| b.then_some(Provider::Queue)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,23 +40,22 @@ impl ConnectState {
|
||||||
player.is_buffering = false;
|
player.is_buffering = false;
|
||||||
|
|
||||||
if let Some(options) = transfer.options.take() {
|
if let Some(options) = transfer.options.take() {
|
||||||
player.options = MessageField::some(options);
|
player.options = MessageField::some(options.into());
|
||||||
}
|
}
|
||||||
player.is_paused = transfer.playback.is_paused;
|
player.is_paused = transfer.playback.is_paused.unwrap_or_default();
|
||||||
player.is_playing = !transfer.playback.is_paused;
|
player.is_playing = !player.is_paused;
|
||||||
|
|
||||||
if transfer.playback.playback_speed != 0. {
|
match transfer.playback.playback_speed {
|
||||||
player.playback_speed = transfer.playback.playback_speed
|
Some(speed) if speed != 0. => player.playback_speed = speed,
|
||||||
} else {
|
_ => player.playback_speed = 1.,
|
||||||
player.playback_speed = 1.;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(session) = transfer.current_session.as_mut() {
|
if let Some(session) = transfer.current_session.as_mut() {
|
||||||
player.play_origin = session.play_origin.take().into();
|
player.play_origin = session.play_origin.take().map(Into::into).into();
|
||||||
player.suppressions = session.suppressions.take().into();
|
player.suppressions = session.suppressions.take().map(Into::into).into();
|
||||||
|
|
||||||
if let Some(mut ctx) = session.context.take() {
|
if let Some(mut ctx) = session.context.take() {
|
||||||
player.restrictions = ctx.restrictions.take().into();
|
player.restrictions = ctx.restrictions.take().map(Into::into).into();
|
||||||
for (key, value) in ctx.metadata {
|
for (key, value) in ctx.metadata {
|
||||||
player.context_metadata.insert(key, value);
|
player.context_metadata.insert(key, value);
|
||||||
}
|
}
|
||||||
|
@ -87,11 +93,10 @@ impl ConnectState {
|
||||||
|
|
||||||
let ctx = self.get_context(&self.active_context).ok();
|
let ctx = self.get_context(&self.active_context).ok();
|
||||||
|
|
||||||
let current_index = if track.is_queue() {
|
let current_index = match transfer.current_session.current_uid.as_ref() {
|
||||||
Self::find_index_in_context(ctx, |c| c.uid == transfer.current_session.current_uid)
|
Some(uid) if track.is_queue() => Self::find_index_in_context(ctx, |c| &c.uid == uid)
|
||||||
.map(|i| if i > 0 { i - 1 } else { i })
|
.map(|i| if i > 0 { i - 1 } else { i }),
|
||||||
} else {
|
_ => Self::find_index_in_context(ctx, |c| c.uri == track.uri || c.uid == track.uid),
|
||||||
Self::find_index_in_context(ctx, |c| c.uri == track.uri || c.uid == track.uid)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
debug!(
|
debug!(
|
||||||
|
@ -116,7 +121,7 @@ impl ConnectState {
|
||||||
);
|
);
|
||||||
|
|
||||||
for (i, track) in transfer.queue.tracks.iter().enumerate() {
|
for (i, track) in transfer.queue.tracks.iter().enumerate() {
|
||||||
if transfer.queue.is_playing_queue && i == 0 {
|
if transfer.queue.is_playing_queue.unwrap_or_default() && i == 0 {
|
||||||
// if we are currently playing from the queue,
|
// if we are currently playing from the queue,
|
||||||
// don't add the first queued item, because we are currently playing that item
|
// don't add the first queued item, because we are currently playing that item
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
use crate::deserialize_with::*;
|
use crate::{
|
||||||
use librespot_protocol::player::{
|
deserialize_with::*,
|
||||||
Context, ContextPlayerOptionOverrides, PlayOrigin, ProvidedTrack, TransferState,
|
protocol::{
|
||||||
|
context::Context,
|
||||||
|
context_player_options::ContextPlayerOptionOverrides,
|
||||||
|
player::{PlayOrigin, ProvidedTrack},
|
||||||
|
transfer_state::TransferState,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
|
@ -10,12 +10,13 @@ use crate::{
|
||||||
config::SessionConfig,
|
config::SessionConfig,
|
||||||
error::ErrorKind,
|
error::ErrorKind,
|
||||||
protocol::{
|
protocol::{
|
||||||
canvaz::EntityCanvazRequest,
|
autoplay_context_request::AutoplayContextRequest,
|
||||||
clienttoken_http::{
|
clienttoken_http::{
|
||||||
ChallengeAnswer, ChallengeType, ClientTokenRequest, ClientTokenRequestType,
|
ChallengeAnswer, ChallengeType, ClientTokenRequest, ClientTokenRequestType,
|
||||||
ClientTokenResponse, ClientTokenResponseType,
|
ClientTokenResponse, ClientTokenResponseType,
|
||||||
},
|
},
|
||||||
connect::PutStateRequest,
|
connect::PutStateRequest,
|
||||||
|
context::Context,
|
||||||
extended_metadata::BatchedEntityRequest,
|
extended_metadata::BatchedEntityRequest,
|
||||||
},
|
},
|
||||||
token::Token,
|
token::Token,
|
||||||
|
@ -32,7 +33,6 @@ use hyper::{
|
||||||
HeaderMap, Method, Request,
|
HeaderMap, Method, Request,
|
||||||
};
|
};
|
||||||
use hyper_util::client::legacy::ResponseFuture;
|
use hyper_util::client::legacy::ResponseFuture;
|
||||||
use librespot_protocol::{autoplay_context_request::AutoplayContextRequest, player::Context};
|
|
||||||
use protobuf::{Enum, Message, MessageFull};
|
use protobuf::{Enum, Message, MessageFull};
|
||||||
use rand::RngCore;
|
use rand::RngCore;
|
||||||
use sysinfo::System;
|
use sysinfo::System;
|
||||||
|
@ -716,13 +716,6 @@ impl SpClient {
|
||||||
// TODO: Seen-in-the-wild but unimplemented endpoints
|
// TODO: Seen-in-the-wild but unimplemented endpoints
|
||||||
// - /presence-view/v1/buddylist
|
// - /presence-view/v1/buddylist
|
||||||
|
|
||||||
// TODO: Find endpoint for newer canvas.proto and upgrade to that.
|
|
||||||
pub async fn get_canvases(&self, request: EntityCanvazRequest) -> SpClientResult {
|
|
||||||
let endpoint = "/canvaz-cache/v0/canvases";
|
|
||||||
self.request_with_protobuf(&Method::POST, endpoint, None, &request)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn get_extended_metadata(&self, request: BatchedEntityRequest) -> SpClientResult {
|
pub async fn get_extended_metadata(&self, request: BatchedEntityRequest) -> SpClientResult {
|
||||||
let endpoint = "/extended-metadata/v0/extended-metadata";
|
let endpoint = "/extended-metadata/v0/extended-metadata";
|
||||||
self.request_with_protobuf(&Method::POST, endpoint, None, &request)
|
self.request_with_protobuf(&Method::POST, endpoint, None, &request)
|
||||||
|
|
|
@ -17,19 +17,26 @@ pub const SEMVER: &str = env!("CARGO_PKG_VERSION");
|
||||||
pub const BUILD_ID: &str = env!("LIBRESPOT_BUILD_ID");
|
pub const BUILD_ID: &str = env!("LIBRESPOT_BUILD_ID");
|
||||||
|
|
||||||
/// The protocol version of the Spotify desktop client.
|
/// The protocol version of the Spotify desktop client.
|
||||||
pub const SPOTIFY_VERSION: u64 = 117300517;
|
pub const SPOTIFY_VERSION: u64 = 124200290;
|
||||||
|
|
||||||
/// The semantic version of the Spotify desktop client.
|
/// The semantic version of the Spotify desktop client.
|
||||||
pub const SPOTIFY_SEMANTIC_VERSION: &str = "1.2.31.1205.g4d59ad7c";
|
pub const SPOTIFY_SEMANTIC_VERSION: &str = "1.2.52.442";
|
||||||
|
|
||||||
|
/// `property_set_id` related to desktop version 1.2.52.442
|
||||||
|
pub const SPOTIFY_PROPERTY_SET_ID: &str = "b4c7e4b5835079ed94391b2e65fca0fdba65eb50";
|
||||||
|
|
||||||
/// The protocol version of the Spotify mobile app.
|
/// The protocol version of the Spotify mobile app.
|
||||||
pub const SPOTIFY_MOBILE_VERSION: &str = "8.6.84";
|
pub const SPOTIFY_MOBILE_VERSION: &str = "8.9.82.620";
|
||||||
|
|
||||||
|
/// `property_set_id` related to mobile version 8.9.82.620
|
||||||
|
pub const SPOTIFY_MOBILE_PROPERTY_SET_ID: &str =
|
||||||
|
"5ec87c2cc32e7c509703582cfaaa3c7ad253129d5701127c1f5eab5c9531736c";
|
||||||
|
|
||||||
/// The general spirc version
|
/// The general spirc version
|
||||||
pub const SPOTIFY_SPIRC_VERSION: &str = "3.2.6";
|
pub const SPOTIFY_SPIRC_VERSION: &str = "3.2.6";
|
||||||
|
|
||||||
/// The user agent to fall back to, if one could not be determined dynamically.
|
/// The user agent to fall back to, if one could not be determined dynamically.
|
||||||
pub const FALLBACK_USER_AGENT: &str = "Spotify/117300517 Linux/0 (librespot)";
|
pub const FALLBACK_USER_AGENT: &str = "Spotify/124200290 Linux/0 (librespot)";
|
||||||
|
|
||||||
pub fn spotify_version() -> String {
|
pub fn spotify_version() -> String {
|
||||||
match crate::config::OS {
|
match crate::config::OS {
|
||||||
|
|
|
@ -32,7 +32,6 @@ pub struct Album {
|
||||||
pub label: String,
|
pub label: String,
|
||||||
pub date: Date,
|
pub date: Date,
|
||||||
pub popularity: i32,
|
pub popularity: i32,
|
||||||
pub genres: Vec<String>,
|
|
||||||
pub covers: Images,
|
pub covers: Images,
|
||||||
pub external_ids: ExternalIds,
|
pub external_ids: ExternalIds,
|
||||||
pub discs: Discs,
|
pub discs: Discs,
|
||||||
|
@ -95,7 +94,6 @@ impl TryFrom<&<Self as Metadata>::Message> for Album {
|
||||||
label: album.label().to_owned(),
|
label: album.label().to_owned(),
|
||||||
date: album.date.get_or_default().try_into()?,
|
date: album.date.get_or_default().try_into()?,
|
||||||
popularity: album.popularity(),
|
popularity: album.popularity(),
|
||||||
genres: album.genre.to_vec(),
|
|
||||||
covers: album.cover_group.get_or_default().into(),
|
covers: album.cover_group.get_or_default().into(),
|
||||||
external_ids: album.external_id.as_slice().into(),
|
external_ids: album.external_id.as_slice().into(),
|
||||||
discs: album.disc.as_slice().try_into()?,
|
discs: album.disc.as_slice().try_into()?,
|
||||||
|
|
|
@ -37,7 +37,6 @@ pub struct Artist {
|
||||||
pub singles: AlbumGroups,
|
pub singles: AlbumGroups,
|
||||||
pub compilations: AlbumGroups,
|
pub compilations: AlbumGroups,
|
||||||
pub appears_on_albums: AlbumGroups,
|
pub appears_on_albums: AlbumGroups,
|
||||||
pub genre: Vec<String>,
|
|
||||||
pub external_ids: ExternalIds,
|
pub external_ids: ExternalIds,
|
||||||
pub portraits: Images,
|
pub portraits: Images,
|
||||||
pub biographies: Biographies,
|
pub biographies: Biographies,
|
||||||
|
@ -193,7 +192,6 @@ impl TryFrom<&<Self as Metadata>::Message> for Artist {
|
||||||
singles: artist.single_group.as_slice().try_into()?,
|
singles: artist.single_group.as_slice().try_into()?,
|
||||||
compilations: artist.compilation_group.as_slice().try_into()?,
|
compilations: artist.compilation_group.as_slice().try_into()?,
|
||||||
appears_on_albums: artist.appears_on_group.as_slice().try_into()?,
|
appears_on_albums: artist.appears_on_group.as_slice().try_into()?,
|
||||||
genre: artist.genre.to_vec(),
|
|
||||||
external_ids: artist.external_id.as_slice().into(),
|
external_ids: artist.external_id.as_slice().into(),
|
||||||
portraits: artist.portrait.as_slice().into(),
|
portraits: artist.portrait.as_slice().into(),
|
||||||
biographies: artist.biography.as_slice().into(),
|
biographies: artist.biography.as_slice().into(),
|
||||||
|
|
|
@ -907,27 +907,24 @@ impl PlayerTrackLoader {
|
||||||
|
|
||||||
fn stream_data_rate(&self, format: AudioFileFormat) -> Option<usize> {
|
fn stream_data_rate(&self, format: AudioFileFormat) -> Option<usize> {
|
||||||
let kbps = match format {
|
let kbps = match format {
|
||||||
AudioFileFormat::OGG_VORBIS_96 => 12,
|
AudioFileFormat::OGG_VORBIS_96 => 12.,
|
||||||
AudioFileFormat::OGG_VORBIS_160 => 20,
|
AudioFileFormat::OGG_VORBIS_160 => 20.,
|
||||||
AudioFileFormat::OGG_VORBIS_320 => 40,
|
AudioFileFormat::OGG_VORBIS_320 => 40.,
|
||||||
AudioFileFormat::MP3_256 => 32,
|
AudioFileFormat::MP3_256 => 32.,
|
||||||
AudioFileFormat::MP3_320 => 40,
|
AudioFileFormat::MP3_320 => 40.,
|
||||||
AudioFileFormat::MP3_160 => 20,
|
AudioFileFormat::MP3_160 => 20.,
|
||||||
AudioFileFormat::MP3_96 => 12,
|
AudioFileFormat::MP3_96 => 12.,
|
||||||
AudioFileFormat::MP3_160_ENC => 20,
|
AudioFileFormat::MP3_160_ENC => 20.,
|
||||||
AudioFileFormat::AAC_24 => 3,
|
AudioFileFormat::AAC_24 => 3.,
|
||||||
AudioFileFormat::AAC_48 => 6,
|
AudioFileFormat::AAC_48 => 6.,
|
||||||
AudioFileFormat::AAC_160 => 20,
|
AudioFileFormat::FLAC_FLAC => 112., // assume 900 kbit/s on average
|
||||||
AudioFileFormat::AAC_320 => 40,
|
AudioFileFormat::XHE_AAC_12 => 1.5,
|
||||||
AudioFileFormat::MP4_128 => 16,
|
AudioFileFormat::XHE_AAC_16 => 2.,
|
||||||
AudioFileFormat::OTHER5 => 40,
|
AudioFileFormat::XHE_AAC_24 => 3.,
|
||||||
AudioFileFormat::FLAC_FLAC => 112, // assume 900 kbit/s on average
|
AudioFileFormat::FLAC_FLAC_24BIT => 3.,
|
||||||
AudioFileFormat::UNKNOWN_FORMAT => {
|
|
||||||
error!("Unknown stream data rate");
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
Some(kbps * 1024)
|
let data_rate: f32 = kbps * 1024.;
|
||||||
|
Some(data_rate.ceil() as usize)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn load_track(
|
async fn load_track(
|
||||||
|
|
|
@ -17,6 +17,7 @@ fn compile() {
|
||||||
|
|
||||||
let files = &[
|
let files = &[
|
||||||
proto_dir.join("connect.proto"),
|
proto_dir.join("connect.proto"),
|
||||||
|
proto_dir.join("media.proto"),
|
||||||
proto_dir.join("connectivity.proto"),
|
proto_dir.join("connectivity.proto"),
|
||||||
proto_dir.join("devices.proto"),
|
proto_dir.join("devices.proto"),
|
||||||
proto_dir.join("entity_extension_data.proto"),
|
proto_dir.join("entity_extension_data.proto"),
|
||||||
|
@ -27,6 +28,8 @@ fn compile() {
|
||||||
proto_dir.join("playlist_annotate3.proto"),
|
proto_dir.join("playlist_annotate3.proto"),
|
||||||
proto_dir.join("playlist_permission.proto"),
|
proto_dir.join("playlist_permission.proto"),
|
||||||
proto_dir.join("playlist4_external.proto"),
|
proto_dir.join("playlist4_external.proto"),
|
||||||
|
proto_dir.join("lens-model.proto"),
|
||||||
|
proto_dir.join("signal-model.proto"),
|
||||||
proto_dir.join("spotify/clienttoken/v0/clienttoken_http.proto"),
|
proto_dir.join("spotify/clienttoken/v0/clienttoken_http.proto"),
|
||||||
proto_dir.join("spotify/login5/v3/challenges/code.proto"),
|
proto_dir.join("spotify/login5/v3/challenges/code.proto"),
|
||||||
proto_dir.join("spotify/login5/v3/challenges/hashcash.proto"),
|
proto_dir.join("spotify/login5/v3/challenges/hashcash.proto"),
|
||||||
|
@ -39,6 +42,19 @@ fn compile() {
|
||||||
proto_dir.join("user_attributes.proto"),
|
proto_dir.join("user_attributes.proto"),
|
||||||
proto_dir.join("autoplay_context_request.proto"),
|
proto_dir.join("autoplay_context_request.proto"),
|
||||||
proto_dir.join("social_connect_v2.proto"),
|
proto_dir.join("social_connect_v2.proto"),
|
||||||
|
proto_dir.join("transfer_state.proto"),
|
||||||
|
proto_dir.join("context_player_options.proto"),
|
||||||
|
proto_dir.join("playback.proto"),
|
||||||
|
proto_dir.join("play_history.proto"),
|
||||||
|
proto_dir.join("session.proto"),
|
||||||
|
proto_dir.join("queue.proto"),
|
||||||
|
proto_dir.join("context_track.proto"),
|
||||||
|
proto_dir.join("context.proto"),
|
||||||
|
proto_dir.join("restrictions.proto"),
|
||||||
|
proto_dir.join("context_page.proto"),
|
||||||
|
proto_dir.join("play_origin.proto"),
|
||||||
|
proto_dir.join("suppressions.proto"),
|
||||||
|
proto_dir.join("instrumentation_params.proto"),
|
||||||
// TODO: remove these legacy protobufs when we are on the new API completely
|
// TODO: remove these legacy protobufs when we are on the new API completely
|
||||||
proto_dir.join("authentication.proto"),
|
proto_dir.join("authentication.proto"),
|
||||||
proto_dir.join("canvaz.proto"),
|
proto_dir.join("canvaz.proto"),
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// No longer present in Spotify 1.1.73.517 (macOS)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ message ListDevicesResponse {
|
||||||
|
|
||||||
message PutDeviceRequest {
|
message PutDeviceRequest {
|
||||||
string user_id = 1;
|
string user_id = 1;
|
||||||
|
|
||||||
Body body = 2;
|
Body body = 2;
|
||||||
message Body {
|
message Body {
|
||||||
Device device = 1;
|
Device device = 1;
|
||||||
|
@ -39,8 +39,27 @@ message RemoveDeviceRequest {
|
||||||
bool is_force_remove = 2;
|
bool is_force_remove = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message OfflineEnableDeviceRequest {
|
||||||
|
message Body {
|
||||||
|
bool auto_opc = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
DeviceKey key = 1;
|
||||||
|
Body body = 2;
|
||||||
|
string name = 9;
|
||||||
|
int32 platform = 7;
|
||||||
|
string client_id = 8;
|
||||||
|
}
|
||||||
|
|
||||||
message OfflineEnableDeviceResponse {
|
message OfflineEnableDeviceResponse {
|
||||||
|
enum StatusCode {
|
||||||
|
UNKNOWN = 0;
|
||||||
|
OK = 1;
|
||||||
|
DEVICE_LIMIT_REACHED = 2;
|
||||||
|
}
|
||||||
|
|
||||||
Restrictions restrictions = 1;
|
Restrictions restrictions = 1;
|
||||||
|
StatusCode status_code = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ListResourcesResponse {
|
message ListResourcesResponse {
|
||||||
|
@ -50,7 +69,7 @@ message ListResourcesResponse {
|
||||||
|
|
||||||
message WriteResourcesRequest {
|
message WriteResourcesRequest {
|
||||||
DeviceKey key = 1;
|
DeviceKey key = 1;
|
||||||
|
|
||||||
Body body = 2;
|
Body body = 2;
|
||||||
message Body {
|
message Body {
|
||||||
repeated ResourceOperation operations = 1;
|
repeated ResourceOperation operations = 1;
|
||||||
|
@ -66,7 +85,7 @@ message ResourcesUpdate {
|
||||||
|
|
||||||
message DeltaResourcesRequest {
|
message DeltaResourcesRequest {
|
||||||
DeviceKey key = 1;
|
DeviceKey key = 1;
|
||||||
|
|
||||||
Body body = 2;
|
Body body = 2;
|
||||||
message Body {
|
message Body {
|
||||||
google.protobuf.Timestamp last_known_server_time = 1;
|
google.protobuf.Timestamp last_known_server_time = 1;
|
||||||
|
@ -90,7 +109,7 @@ message GetResourceResponse {
|
||||||
|
|
||||||
message WriteResourcesDetailsRequest {
|
message WriteResourcesDetailsRequest {
|
||||||
DeviceKey key = 1;
|
DeviceKey key = 1;
|
||||||
|
|
||||||
Body body = 2;
|
Body body = 2;
|
||||||
message Body {
|
message Body {
|
||||||
repeated Resource resources = 1;
|
repeated Resource resources = 1;
|
||||||
|
@ -106,3 +125,39 @@ message GetResourceForDevicesResponse {
|
||||||
repeated Device devices = 1;
|
repeated Device devices = 1;
|
||||||
repeated ResourceForDevice resources = 2;
|
repeated ResourceForDevice resources = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message ListDevicesWithResourceRequest {
|
||||||
|
message Body {
|
||||||
|
string uri = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
string user_id = 1;
|
||||||
|
string username = 2;
|
||||||
|
Body body = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ListDevicesWithResourceResponse {
|
||||||
|
message DeviceWithResource {
|
||||||
|
Device device = 1;
|
||||||
|
bool is_supported = 2;
|
||||||
|
optional Resource resource = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
repeated DeviceWithResource deviceWithResource = 1;
|
||||||
|
FetchStrategy fetch_strategy = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message FetchStrategy {
|
||||||
|
oneof fetch_strategy {
|
||||||
|
PollStrategy poll_strategy = 1;
|
||||||
|
SubStrategy sub_strategy = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
message PollStrategy {
|
||||||
|
int32 interval_ms = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SubStrategy {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.61.583 (Windows)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
|
@ -15,13 +15,15 @@ message NormalizationParams {
|
||||||
}
|
}
|
||||||
|
|
||||||
message ExtendedAudioFile {
|
message ExtendedAudioFile {
|
||||||
|
reserved 2;
|
||||||
|
reserved 3;
|
||||||
metadata.AudioFile file = 1;
|
metadata.AudioFile file = 1;
|
||||||
NormalizationParams file_normalization_params = 2;
|
int32 average_bitrate = 4;
|
||||||
NormalizationParams album_normalization_params = 3;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message AudioFilesExtensionResponse {
|
message AudioFilesExtensionResponse {
|
||||||
repeated ExtendedAudioFile files = 1;
|
repeated ExtendedAudioFile files = 1;
|
||||||
NormalizationParams default_file_normalization_params = 2;
|
NormalizationParams default_file_normalization_params = 2;
|
||||||
NormalizationParams default_album_normalization_params = 3;
|
NormalizationParams default_album_normalization_params = 3;
|
||||||
|
bytes audio_id = 4;
|
||||||
}
|
}
|
||||||
|
|
35
protocol/proto/audio_format.proto
Normal file
35
protocol/proto/audio_format.proto
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package spotify.stream_reporting_esperanto.proto;
|
||||||
|
|
||||||
|
option java_package = "com.spotify.stream_reporting_esperanto.proto";
|
||||||
|
option objc_class_prefix = "ESP";
|
||||||
|
|
||||||
|
enum AudioFormat {
|
||||||
|
FORMAT_UNKNOWN = 0;
|
||||||
|
FORMAT_OGG_VORBIS_96 = 1;
|
||||||
|
FORMAT_OGG_VORBIS_160 = 2;
|
||||||
|
FORMAT_OGG_VORBIS_320 = 3;
|
||||||
|
FORMAT_MP3_256 = 4;
|
||||||
|
FORMAT_MP3_320 = 5;
|
||||||
|
FORMAT_MP3_160 = 6;
|
||||||
|
FORMAT_MP3_96 = 7;
|
||||||
|
FORMAT_MP3_160_ENCRYPTED = 8;
|
||||||
|
FORMAT_AAC_24 = 9;
|
||||||
|
FORMAT_AAC_48 = 10;
|
||||||
|
FORMAT_MP4_128 = 11;
|
||||||
|
FORMAT_MP4_128_DUAL = 12;
|
||||||
|
FORMAT_MP4_128_CBCS = 13;
|
||||||
|
FORMAT_MP4_256 = 14;
|
||||||
|
FORMAT_MP4_256_DUAL = 15;
|
||||||
|
FORMAT_MP4_256_CBCS = 16;
|
||||||
|
FORMAT_FLAC_FLAC = 17;
|
||||||
|
FORMAT_MP4_FLAC = 18;
|
||||||
|
FORMAT_MP4_Unknown = 19;
|
||||||
|
FORMAT_MP3_Unknown = 20;
|
||||||
|
FORMAT_XHE_AAC_12 = 21;
|
||||||
|
FORMAT_XHE_AAC_16 = 22;
|
||||||
|
FORMAT_XHE_AAC_24 = 23;
|
||||||
|
FORMAT_FLAC_FLAC_24 = 24;
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.73.517 (macOS)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.73.517 (macOS)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
|
@ -32,10 +32,14 @@ enum AutomixStyle {
|
||||||
SLEEP = 5;
|
SLEEP = 5;
|
||||||
MIXED = 6;
|
MIXED = 6;
|
||||||
CUSTOM = 7;
|
CUSTOM = 7;
|
||||||
|
HEURISTIC = 8;
|
||||||
|
BACKEND = 9;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum TransitionType {
|
enum TransitionType {
|
||||||
CUEPOINTS = 0;
|
CUEPOINTS = 0;
|
||||||
CROSSFADE = 1;
|
CROSSFADE = 1;
|
||||||
GAPLESS = 2;
|
GAPLESS = 2;
|
||||||
|
HEURISTIC_TRANSITION = 3;
|
||||||
|
BACKEND_TRANSITION = 4;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.61.583 (Windows)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto2";
|
syntax = "proto2";
|
||||||
|
|
||||||
|
@ -9,4 +9,5 @@ option optimize_for = CODE_SIZE;
|
||||||
message AutoplayContextRequest {
|
message AutoplayContextRequest {
|
||||||
required string context_uri = 1;
|
required string context_uri = 1;
|
||||||
repeated string recent_track_uri = 2;
|
repeated string recent_track_uri = 2;
|
||||||
|
optional bool is_video = 3;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.61.583 (Windows)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto2";
|
syntax = "proto2";
|
||||||
|
|
||||||
|
@ -12,4 +12,5 @@ message AutoplayNode {
|
||||||
map<string, bytes> filler_node = 1;
|
map<string, bytes> filler_node = 1;
|
||||||
required bool is_playing_filler = 2;
|
required bool is_playing_filler = 2;
|
||||||
required LoggingParams logging_params = 3;
|
required LoggingParams logging_params = 3;
|
||||||
|
optional bool called_play_on_filler = 4;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
// Extracted from: Spotify 1.1.73.517 (macOS)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
package spotify.canvaz.cache;
|
package spotify.canvaz.cache;
|
||||||
|
|
||||||
import "canvaz-meta.proto";
|
|
||||||
|
|
||||||
option java_multiple_files = true;
|
option java_multiple_files = true;
|
||||||
option optimize_for = CODE_SIZE;
|
option optimize_for = CODE_SIZE;
|
||||||
option java_package = "com.spotify.canvazcache.proto";
|
option java_package = "com.spotify.canvazcache.proto";
|
||||||
|
@ -17,12 +15,11 @@ message Artist {
|
||||||
}
|
}
|
||||||
|
|
||||||
message EntityCanvazResponse {
|
message EntityCanvazResponse {
|
||||||
repeated Canvaz canvases = 1;
|
|
||||||
message Canvaz {
|
message Canvaz {
|
||||||
string id = 1;
|
string id = 1;
|
||||||
string url = 2;
|
string url = 2;
|
||||||
string file_id = 3;
|
string file_id = 3;
|
||||||
spotify.canvaz.Type type = 4;
|
Type type = 4;
|
||||||
string entity_uri = 5;
|
string entity_uri = 5;
|
||||||
Artist artist = 6;
|
Artist artist = 6;
|
||||||
bool explicit = 7;
|
bool explicit = 7;
|
||||||
|
@ -31,14 +28,14 @@ message EntityCanvazResponse {
|
||||||
string canvas_uri = 11;
|
string canvas_uri = 11;
|
||||||
string storylines_id = 12;
|
string storylines_id = 12;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64 ttl_in_seconds = 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message EntityCanvazRequest {
|
enum Type {
|
||||||
repeated Entity entities = 1;
|
IMAGE = 0;
|
||||||
message Entity {
|
VIDEO = 1;
|
||||||
string entity_uri = 1;
|
VIDEO_LOOPING = 2;
|
||||||
string etag = 2;
|
VIDEO_LOOPING_RANDOM = 3;
|
||||||
}
|
GIF = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
// Extracted from: Spotify 1.1.73.517 (macOS)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
package spotify.narration_injection.proto;
|
package spotify.narration.proto;
|
||||||
|
|
||||||
import "tts-resolve.proto";
|
import "tts-resolve.proto";
|
||||||
|
|
||||||
|
@ -18,7 +18,6 @@ message TtsRequest {
|
||||||
ResolveRequest.TtsVoice tts_voice = 5;
|
ResolveRequest.TtsVoice tts_voice = 5;
|
||||||
ResolveRequest.TtsProvider tts_provider = 6;
|
ResolveRequest.TtsProvider tts_provider = 6;
|
||||||
int32 sample_rate_hz = 7;
|
int32 sample_rate_hz = 7;
|
||||||
|
|
||||||
oneof prompt {
|
oneof prompt {
|
||||||
string text = 1;
|
string text = 1;
|
||||||
string ssml = 2;
|
string ssml = 2;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.73.517 (macOS)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.61.583 (Windows)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.61.583 (Windows)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto2";
|
syntax = "proto2";
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.61.583 (Windows)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto2";
|
syntax = "proto2";
|
||||||
|
|
||||||
|
@ -15,4 +15,5 @@ message ArtistCollectionState {
|
||||||
optional uint32 num_albums_in_collection = 4;
|
optional uint32 num_albums_in_collection = 4;
|
||||||
optional bool is_banned = 5;
|
optional bool is_banned = 5;
|
||||||
optional bool can_ban = 6;
|
optional bool can_ban = 6;
|
||||||
|
optional uint32 num_explicitly_liked_tracks = 7;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.73.517 (macOS)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto2";
|
syntax = "proto2";
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.61.583 (Windows)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto2";
|
syntax = "proto2";
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.61.583 (Windows)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto2";
|
syntax = "proto2";
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.61.583 (Windows)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@ message CollectionItem {
|
||||||
string uri = 1;
|
string uri = 1;
|
||||||
int32 added_at = 2;
|
int32 added_at = 2;
|
||||||
bool is_removed = 3;
|
bool is_removed = 3;
|
||||||
|
optional string context_uri = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
message PageResponse {
|
message PageResponse {
|
||||||
|
@ -45,13 +46,6 @@ message WriteRequest {
|
||||||
string client_update_id = 4;
|
string client_update_id = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
message PubSubUpdate {
|
|
||||||
string username = 1;
|
|
||||||
string set = 2;
|
|
||||||
repeated CollectionItem items = 3;
|
|
||||||
string client_update_id = 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
message InitializedRequest {
|
message InitializedRequest {
|
||||||
string username = 1;
|
string username = 1;
|
||||||
string set = 2;
|
string set = 2;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.73.517 (macOS)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
|
@ -6,12 +6,15 @@ package spotify.collection_cosmos.proto;
|
||||||
|
|
||||||
import "status.proto";
|
import "status.proto";
|
||||||
|
|
||||||
|
option java_package = "spotify.collection.esperanto.proto";
|
||||||
|
option java_multiple_files = true;
|
||||||
|
option objc_class_prefix = "ESP";
|
||||||
option optimize_for = CODE_SIZE;
|
option optimize_for = CODE_SIZE;
|
||||||
|
|
||||||
message CollectionAddRemoveItemsRequest {
|
message CollectionAddRemoveItemsRequest {
|
||||||
repeated string item = 1;
|
repeated string uri = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message CollectionAddRemoveItemsResponse {
|
message CollectionAddRemoveItemsResponse {
|
||||||
Status status = 1;
|
Status status = 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.73.517 (macOS)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
|
@ -6,6 +6,9 @@ package spotify.collection_cosmos.proto;
|
||||||
|
|
||||||
import "status.proto";
|
import "status.proto";
|
||||||
|
|
||||||
|
option java_package = "spotify.collection.esperanto.proto";
|
||||||
|
option java_multiple_files = true;
|
||||||
|
option objc_class_prefix = "ESP";
|
||||||
option optimize_for = CODE_SIZE;
|
option optimize_for = CODE_SIZE;
|
||||||
|
|
||||||
message CollectionBanRequest {
|
message CollectionBanRequest {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.73.517 (macOS)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
|
@ -7,7 +7,12 @@ package spotify.collection_cosmos.proto;
|
||||||
import "policy/artist_decoration_policy.proto";
|
import "policy/artist_decoration_policy.proto";
|
||||||
import "policy/album_decoration_policy.proto";
|
import "policy/album_decoration_policy.proto";
|
||||||
import "policy/track_decoration_policy.proto";
|
import "policy/track_decoration_policy.proto";
|
||||||
|
import "policy/show_decoration_policy.proto";
|
||||||
|
import "policy/episode_decoration_policy.proto";
|
||||||
|
|
||||||
|
option java_package = "spotify.collection.esperanto.proto";
|
||||||
|
option java_multiple_files = true;
|
||||||
|
option objc_class_prefix = "ESP";
|
||||||
option optimize_for = CODE_SIZE;
|
option optimize_for = CODE_SIZE;
|
||||||
|
|
||||||
message CollectionArtistDecorationPolicy {
|
message CollectionArtistDecorationPolicy {
|
||||||
|
@ -35,4 +40,22 @@ message CollectionTrackDecorationPolicy {
|
||||||
CollectionAlbumDecorationPolicy album_policy = 5;
|
CollectionAlbumDecorationPolicy album_policy = 5;
|
||||||
cosmos_util.proto.ArtistDecorationPolicy artist_policy = 6;
|
cosmos_util.proto.ArtistDecorationPolicy artist_policy = 6;
|
||||||
bool decorated = 7;
|
bool decorated = 7;
|
||||||
|
cosmos_util.proto.ArtistCollectionDecorationPolicy artist_collection_policy = 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message CollectionShowDecorationPolicy {
|
||||||
|
cosmos_util.proto.ShowDecorationPolicy show_policy = 1;
|
||||||
|
cosmos_util.proto.ShowPlayedStateDecorationPolicy played_state_policy = 2;
|
||||||
|
cosmos_util.proto.ShowCollectionDecorationPolicy collection_policy = 3;
|
||||||
|
bool decorated = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CollectionEpisodeDecorationPolicy {
|
||||||
|
cosmos_util.proto.EpisodeDecorationPolicy episode_policy = 1;
|
||||||
|
cosmos_util.proto.EpisodeCollectionDecorationPolicy collection_policy = 2;
|
||||||
|
cosmos_util.proto.EpisodeSyncDecorationPolicy sync_policy = 3;
|
||||||
|
cosmos_util.proto.EpisodePlayedStateDecorationPolicy played_state_policy = 4;
|
||||||
|
CollectionShowDecorationPolicy show_policy = 5;
|
||||||
|
bool decorated = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,21 +1,21 @@
|
||||||
// Extracted from: Spotify 1.1.73.517 (macOS)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
package spotify.collection_cosmos.proto;
|
package spotify.collection_cosmos.proto;
|
||||||
|
|
||||||
import "policy/track_decoration_policy.proto";
|
import "collection_decoration_policy.proto";
|
||||||
import "policy/artist_decoration_policy.proto";
|
import "collection_item.proto";
|
||||||
import "metadata/track_metadata.proto";
|
|
||||||
import "metadata/artist_metadata.proto";
|
|
||||||
import "status.proto";
|
import "status.proto";
|
||||||
|
|
||||||
|
option java_multiple_files = true;
|
||||||
|
option java_package = "spotify.collection.esperanto.proto";
|
||||||
option objc_class_prefix = "SPTCollectionCosmos";
|
option objc_class_prefix = "SPTCollectionCosmos";
|
||||||
option optimize_for = CODE_SIZE;
|
option optimize_for = CODE_SIZE;
|
||||||
|
|
||||||
message CollectionGetBansRequest {
|
message CollectionGetBansRequest {
|
||||||
cosmos_util.proto.TrackDecorationPolicy track_policy = 1;
|
CollectionTrackDecorationPolicy track_policy = 1;
|
||||||
cosmos_util.proto.ArtistDecorationPolicy artist_policy = 2;
|
CollectionArtistDecorationPolicy artist_policy = 2;
|
||||||
string sort = 3;
|
string sort = 3;
|
||||||
bool timestamp = 4;
|
bool timestamp = 4;
|
||||||
uint32 update_throttling = 5;
|
uint32 update_throttling = 5;
|
||||||
|
@ -23,8 +23,8 @@ message CollectionGetBansRequest {
|
||||||
|
|
||||||
message Item {
|
message Item {
|
||||||
uint32 add_time = 1;
|
uint32 add_time = 1;
|
||||||
cosmos_util.proto.TrackMetadata track_metadata = 2;
|
CollectionTrack track_metadata = 2;
|
||||||
cosmos_util.proto.ArtistMetadata artist_metadata = 3;
|
CollectionArtist artist_metadata = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message CollectionGetBansResponse {
|
message CollectionGetBansResponse {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.73.517 (macOS)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
|
@ -11,6 +11,10 @@ message IndexRepairerState {
|
||||||
int64 last_full_check_finished_at = 2;
|
int64 last_full_check_finished_at = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message AddTime {
|
||||||
|
int64 timestamp = 1;
|
||||||
|
}
|
||||||
|
|
||||||
message CollectionTrackEntry {
|
message CollectionTrackEntry {
|
||||||
string uri = 1;
|
string uri = 1;
|
||||||
string track_name = 2;
|
string track_name = 2;
|
||||||
|
@ -23,16 +27,52 @@ message CollectionTrackEntry {
|
||||||
int64 add_time = 9;
|
int64 add_time = 9;
|
||||||
}
|
}
|
||||||
|
|
||||||
message CollectionAlbumLikeEntry {
|
message CollectionAlbumEntry {
|
||||||
string uri = 1;
|
string uri = 1;
|
||||||
string album_name = 2;
|
string album_name = 2;
|
||||||
string creator_uri = 4;
|
string artist_uri = 4;
|
||||||
|
string artist_name = 5;
|
||||||
|
int64 add_time = 6;
|
||||||
|
int64 last_played = 8;
|
||||||
|
int64 release_date = 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CollectionShowEntry {
|
||||||
|
string uri = 1;
|
||||||
|
string show_name = 2;
|
||||||
string creator_name = 5;
|
string creator_name = 5;
|
||||||
int64 add_time = 6;
|
int64 add_time = 6;
|
||||||
|
int64 publish_date = 7;
|
||||||
|
int64 last_played = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CollectionBookEntry {
|
||||||
|
string uri = 1;
|
||||||
|
string book_name = 2;
|
||||||
|
string author_name = 5;
|
||||||
|
int64 add_time = 6;
|
||||||
|
int64 last_played = 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
message CollectionArtistEntry {
|
message CollectionArtistEntry {
|
||||||
string uri = 1;
|
string uri = 1;
|
||||||
string artist_name = 2;
|
string artist_name = 2;
|
||||||
int64 add_time = 4;
|
int64 add_time = 4;
|
||||||
|
int64 last_played = 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message CollectionAuthorEntry {
|
||||||
|
string uri = 1;
|
||||||
|
string author_name = 2;
|
||||||
|
int64 add_time = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CollectionEpisodeEntry {
|
||||||
|
string uri = 1;
|
||||||
|
string episode_name = 2;
|
||||||
|
string show_uri = 3;
|
||||||
|
string show_name = 4;
|
||||||
|
int64 add_time = 5;
|
||||||
|
int64 publish_time = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.73.517 (macOS)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
|
@ -7,14 +7,24 @@ package spotify.collection_cosmos.proto;
|
||||||
import "metadata/album_metadata.proto";
|
import "metadata/album_metadata.proto";
|
||||||
import "metadata/artist_metadata.proto";
|
import "metadata/artist_metadata.proto";
|
||||||
import "metadata/track_metadata.proto";
|
import "metadata/track_metadata.proto";
|
||||||
|
import "metadata/show_metadata.proto";
|
||||||
|
import "metadata/episode_metadata.proto";
|
||||||
import "collection/artist_collection_state.proto";
|
import "collection/artist_collection_state.proto";
|
||||||
import "collection/album_collection_state.proto";
|
import "collection/album_collection_state.proto";
|
||||||
import "collection/track_collection_state.proto";
|
import "collection/track_collection_state.proto";
|
||||||
|
import "collection/show_collection_state.proto";
|
||||||
|
import "collection/episode_collection_state.proto";
|
||||||
import "sync/artist_sync_state.proto";
|
import "sync/artist_sync_state.proto";
|
||||||
import "sync/album_sync_state.proto";
|
import "sync/album_sync_state.proto";
|
||||||
import "sync/track_sync_state.proto";
|
import "sync/track_sync_state.proto";
|
||||||
|
import "sync/episode_sync_state.proto";
|
||||||
import "played_state/track_played_state.proto";
|
import "played_state/track_played_state.proto";
|
||||||
|
import "played_state/show_played_state.proto";
|
||||||
|
import "played_state/episode_played_state.proto";
|
||||||
|
|
||||||
|
option java_package = "spotify.collection.esperanto.proto";
|
||||||
|
option java_multiple_files = true;
|
||||||
|
option objc_class_prefix = "ESP";
|
||||||
option optimize_for = CODE_SIZE;
|
option optimize_for = CODE_SIZE;
|
||||||
|
|
||||||
message CollectionTrack {
|
message CollectionTrack {
|
||||||
|
@ -27,6 +37,8 @@ message CollectionTrack {
|
||||||
bool decorated = 7;
|
bool decorated = 7;
|
||||||
CollectionAlbum album = 8;
|
CollectionAlbum album = 8;
|
||||||
string cover = 9;
|
string cover = 9;
|
||||||
|
string link = 10;
|
||||||
|
repeated cosmos_util.proto.ArtistCollectionState artist_collection_state = 11;
|
||||||
}
|
}
|
||||||
|
|
||||||
message CollectionAlbum {
|
message CollectionAlbum {
|
||||||
|
@ -37,6 +49,7 @@ message CollectionAlbum {
|
||||||
bool decorated = 5;
|
bool decorated = 5;
|
||||||
string album_type = 6;
|
string album_type = 6;
|
||||||
repeated CollectionTrack track = 7;
|
repeated CollectionTrack track = 7;
|
||||||
|
string link = 11;
|
||||||
}
|
}
|
||||||
|
|
||||||
message CollectionArtist {
|
message CollectionArtist {
|
||||||
|
@ -45,4 +58,23 @@ message CollectionArtist {
|
||||||
cosmos_util.proto.ArtistSyncState artist_sync_state = 3;
|
cosmos_util.proto.ArtistSyncState artist_sync_state = 3;
|
||||||
bool decorated = 4;
|
bool decorated = 4;
|
||||||
repeated CollectionAlbum album = 5;
|
repeated CollectionAlbum album = 5;
|
||||||
|
string link = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message CollectionShow {
|
||||||
|
cosmos_util.proto.ShowMetadata show_metadata = 1;
|
||||||
|
cosmos_util.proto.ShowCollectionState show_collection_state = 2;
|
||||||
|
cosmos_util.proto.ShowPlayState show_play_state = 3;
|
||||||
|
uint32 add_time = 4;
|
||||||
|
string link = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CollectionEpisode {
|
||||||
|
cosmos_util.proto.EpisodeMetadata episode_metadata = 1;
|
||||||
|
cosmos_util.proto.EpisodeCollectionState episode_collection_state = 2;
|
||||||
|
cosmos_util.proto.EpisodeSyncState episode_offline_state = 3;
|
||||||
|
cosmos_util.proto.EpisodePlayState episode_play_state = 4;
|
||||||
|
CollectionShow show = 5;
|
||||||
|
string link = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
19
protocol/proto/collection_platform_items.proto
Normal file
19
protocol/proto/collection_platform_items.proto
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package spotify.collection_platform.proto;
|
||||||
|
|
||||||
|
option java_package = "com.spotify.collection_platform.esperanto.proto";
|
||||||
|
option java_multiple_files = true;
|
||||||
|
option objc_class_prefix = "ESP";
|
||||||
|
|
||||||
|
message CollectionPlatformItem {
|
||||||
|
string uri = 1;
|
||||||
|
int64 add_time = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CollectionPlatformContextItem {
|
||||||
|
string uri = 1;
|
||||||
|
int64 add_time = 2;
|
||||||
|
string context_uri = 3;
|
||||||
|
}
|
||||||
|
|
|
@ -1,9 +1,14 @@
|
||||||
// Extracted from: Spotify 1.1.73.517 (macOS)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
package spotify.collection_platform.proto;
|
package spotify.collection_platform.proto;
|
||||||
|
|
||||||
|
import "collection_platform_items.proto";
|
||||||
|
|
||||||
|
option java_package = "com.spotify.collection_platform.esperanto.proto";
|
||||||
|
option java_multiple_files = true;
|
||||||
|
option objc_class_prefix = "ESP";
|
||||||
option optimize_for = CODE_SIZE;
|
option optimize_for = CODE_SIZE;
|
||||||
|
|
||||||
message CollectionPlatformItemsRequest {
|
message CollectionPlatformItemsRequest {
|
||||||
|
@ -11,11 +16,21 @@ message CollectionPlatformItemsRequest {
|
||||||
repeated string items = 2;
|
repeated string items = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message CollectionPlatformContextItemsRequest {
|
||||||
|
CollectionSet set = 1;
|
||||||
|
repeated CollectionPlatformContextItem items = 2;
|
||||||
|
}
|
||||||
|
|
||||||
enum CollectionSet {
|
enum CollectionSet {
|
||||||
UNKNOWN = 0;
|
UNKNOWN = 0;
|
||||||
SHOW = 1;
|
|
||||||
BAN = 2;
|
|
||||||
LISTENLATER = 3;
|
|
||||||
IGNOREINRECS = 4;
|
IGNOREINRECS = 4;
|
||||||
ENHANCED = 5;
|
ENHANCED = 5;
|
||||||
|
BANNED_ARTISTS = 8;
|
||||||
|
CONCERTS = 10;
|
||||||
|
TAGS = 11;
|
||||||
|
PRERELEASE = 12;
|
||||||
|
MARKED_AS_FINISHED = 13;
|
||||||
|
NOT_INTERESTED = 14;
|
||||||
|
LOCAL_BANS = 15;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,20 +1,20 @@
|
||||||
// Extracted from: Spotify 1.1.73.517 (macOS)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
package spotify.collection_platform.proto;
|
package spotify.collection_platform.proto;
|
||||||
|
|
||||||
|
import "collection_platform_items.proto";
|
||||||
|
|
||||||
|
option java_package = "com.spotify.collection_platform.esperanto.proto";
|
||||||
|
option java_multiple_files = true;
|
||||||
|
option objc_class_prefix = "ESP";
|
||||||
option optimize_for = CODE_SIZE;
|
option optimize_for = CODE_SIZE;
|
||||||
|
|
||||||
message CollectionPlatformSimpleResponse {
|
message CollectionPlatformSimpleResponse {
|
||||||
string error_msg = 1;
|
string error_msg = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message CollectionPlatformItem {
|
|
||||||
string uri = 1;
|
|
||||||
int64 add_time = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
message CollectionPlatformItemsResponse {
|
message CollectionPlatformItemsResponse {
|
||||||
repeated CollectionPlatformItem items = 1;
|
repeated CollectionPlatformItem items = 1;
|
||||||
}
|
}
|
||||||
|
@ -22,3 +22,29 @@ message CollectionPlatformItemsResponse {
|
||||||
message CollectionPlatformContainsResponse {
|
message CollectionPlatformContainsResponse {
|
||||||
repeated bool found = 1;
|
repeated bool found = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message Status {
|
||||||
|
int32 code = 1;
|
||||||
|
string reason = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CollectionPlatformEsperantoContainsResponse {
|
||||||
|
Status status = 1;
|
||||||
|
CollectionPlatformContainsResponse contains = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CollectionPlatformEsperantoItemsResponse {
|
||||||
|
Status status = 1;
|
||||||
|
repeated CollectionPlatformItem items = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CollectionPlatformContextItemsResponse {
|
||||||
|
Status status = 1;
|
||||||
|
repeated CollectionPlatformContextItem items = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CollectionPlatformContainsContextItemsResponse {
|
||||||
|
Status status = 1;
|
||||||
|
repeated bool found = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.73.517 (macOS)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
|
@ -6,9 +6,10 @@ package spotify.connectstate;
|
||||||
|
|
||||||
import "player.proto";
|
import "player.proto";
|
||||||
import "devices.proto";
|
import "devices.proto";
|
||||||
|
import "media.proto";
|
||||||
|
|
||||||
option optimize_for = CODE_SIZE;
|
|
||||||
option java_package = "com.spotify.connectstate.model";
|
option java_package = "com.spotify.connectstate.model";
|
||||||
|
option optimize_for = CODE_SIZE;
|
||||||
|
|
||||||
message ClusterUpdate {
|
message ClusterUpdate {
|
||||||
Cluster cluster = 1;
|
Cluster cluster = 1;
|
||||||
|
@ -17,10 +18,6 @@ message ClusterUpdate {
|
||||||
repeated string devices_that_changed = 4;
|
repeated string devices_that_changed = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
message PostCommandResponse {
|
|
||||||
string ack_id = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
message Device {
|
message Device {
|
||||||
DeviceInfo device_info = 1;
|
DeviceInfo device_info = 1;
|
||||||
PlayerState player_state = 2;
|
PlayerState player_state = 2;
|
||||||
|
@ -29,15 +26,18 @@ message Device {
|
||||||
}
|
}
|
||||||
|
|
||||||
message Cluster {
|
message Cluster {
|
||||||
|
reserved 7;
|
||||||
|
|
||||||
int64 changed_timestamp_ms = 1;
|
int64 changed_timestamp_ms = 1;
|
||||||
string active_device_id = 2;
|
string active_device_id = 2;
|
||||||
PlayerState player_state = 3;
|
PlayerState player_state = 3;
|
||||||
map<string, DeviceInfo> device = 4;
|
map<string, DeviceInfo> device = 4;
|
||||||
bytes transfer_data = 5;
|
bytes transfer_data = 5;
|
||||||
uint64 transfer_data_timestamp = 6;
|
uint64 transfer_data_timestamp = 6;
|
||||||
int64 not_playing_since_timestamp = 7;
|
|
||||||
bool need_full_player_state = 8;
|
bool need_full_player_state = 8;
|
||||||
int64 server_timestamp_ms = 9;
|
int64 server_timestamp_ms = 9;
|
||||||
|
optional bool needs_state_updates = 10;
|
||||||
|
optional uint64 started_playing_at_timestamp = 11;
|
||||||
}
|
}
|
||||||
|
|
||||||
message PutStateRequest {
|
message PutStateRequest {
|
||||||
|
@ -59,18 +59,15 @@ message PrivateDeviceInfo {
|
||||||
string platform = 1;
|
string platform = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message SubscribeRequest {
|
|
||||||
string callback_url = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
message DeviceInfo {
|
message DeviceInfo {
|
||||||
|
reserved 5;
|
||||||
|
|
||||||
bool can_play = 1;
|
bool can_play = 1;
|
||||||
uint32 volume = 2;
|
uint32 volume = 2;
|
||||||
string name = 3;
|
string name = 3;
|
||||||
Capabilities capabilities = 4;
|
Capabilities capabilities = 4;
|
||||||
repeated DeviceMetadata metadata = 5;
|
|
||||||
string device_software_version = 6;
|
string device_software_version = 6;
|
||||||
spotify.connectstate.devices.DeviceType device_type = 7;
|
devices.DeviceType device_type = 7;
|
||||||
string spirc_version = 9;
|
string spirc_version = 9;
|
||||||
string device_id = 10;
|
string device_id = 10;
|
||||||
bool is_private_session = 11;
|
bool is_private_session = 11;
|
||||||
|
@ -82,7 +79,7 @@ message DeviceInfo {
|
||||||
string product_id = 17;
|
string product_id = 17;
|
||||||
string deduplication_id = 18;
|
string deduplication_id = 18;
|
||||||
uint32 selected_alias_id = 19;
|
uint32 selected_alias_id = 19;
|
||||||
map<uint32, spotify.connectstate.devices.DeviceAlias> device_aliases = 20;
|
map<string, devices.DeviceAlias> device_aliases = 20;
|
||||||
bool is_offline = 21;
|
bool is_offline = 21;
|
||||||
string public_ip = 22;
|
string public_ip = 22;
|
||||||
string license = 23;
|
string license = 23;
|
||||||
|
@ -90,29 +87,20 @@ message DeviceInfo {
|
||||||
bool is_dynamic_device = 26;
|
bool is_dynamic_device = 26;
|
||||||
repeated string disallow_playback_reasons = 27;
|
repeated string disallow_playback_reasons = 27;
|
||||||
repeated string disallow_transfer_reasons = 28;
|
repeated string disallow_transfer_reasons = 28;
|
||||||
|
optional AudioOutputDeviceInfo audio_output_device_info = 24;
|
||||||
oneof _audio_output_device_info {
|
|
||||||
AudioOutputDeviceInfo audio_output_device_info = 24;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message AudioOutputDeviceInfo {
|
message AudioOutputDeviceInfo {
|
||||||
oneof _audio_output_device_type {
|
optional AudioOutputDeviceType audio_output_device_type = 1;
|
||||||
AudioOutputDeviceType audio_output_device_type = 1;
|
optional string device_name = 2;
|
||||||
}
|
|
||||||
|
|
||||||
oneof _device_name {
|
|
||||||
string device_name = 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
message DeviceMetadata {
|
|
||||||
option deprecated = true;
|
|
||||||
string type = 1;
|
|
||||||
string metadata = 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message Capabilities {
|
message Capabilities {
|
||||||
|
reserved "supported_contexts";
|
||||||
|
reserved "supports_lossless_audio";
|
||||||
|
reserved 1;
|
||||||
|
reserved 4;
|
||||||
|
reserved 24;
|
||||||
bool can_be_player = 2;
|
bool can_be_player = 2;
|
||||||
bool restrict_to_local = 3;
|
bool restrict_to_local = 3;
|
||||||
bool gaia_eq_connect_id = 5;
|
bool gaia_eq_connect_id = 5;
|
||||||
|
@ -137,8 +125,9 @@ message Capabilities {
|
||||||
bool supports_set_options_command = 25;
|
bool supports_set_options_command = 25;
|
||||||
CapabilitySupportDetails supports_hifi = 26;
|
CapabilitySupportDetails supports_hifi = 26;
|
||||||
string connect_capabilities = 27;
|
string connect_capabilities = 27;
|
||||||
|
bool supports_rooms = 28;
|
||||||
//reserved 1, 4, 24, "supported_contexts", "supports_lossless_audio";
|
bool supports_dj = 29;
|
||||||
|
common.media.AudioQuality supported_audio_quality = 30;
|
||||||
}
|
}
|
||||||
|
|
||||||
message CapabilitySupportDetails {
|
message CapabilitySupportDetails {
|
||||||
|
@ -152,6 +141,11 @@ message ConnectCommandOptions {
|
||||||
uint32 target_alias_id = 3;
|
uint32 target_alias_id = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message ConnectLoggingParams {
|
||||||
|
repeated string interaction_ids = 1;
|
||||||
|
repeated string page_instance_ids = 2;
|
||||||
|
}
|
||||||
|
|
||||||
message LogoutCommand {
|
message LogoutCommand {
|
||||||
ConnectCommandOptions command_options = 1;
|
ConnectCommandOptions command_options = 1;
|
||||||
}
|
}
|
||||||
|
@ -159,6 +153,8 @@ message LogoutCommand {
|
||||||
message SetVolumeCommand {
|
message SetVolumeCommand {
|
||||||
int32 volume = 1;
|
int32 volume = 1;
|
||||||
ConnectCommandOptions command_options = 2;
|
ConnectCommandOptions command_options = 2;
|
||||||
|
ConnectLoggingParams logging_params = 3;
|
||||||
|
string connection_type = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
message RenameCommand {
|
message RenameCommand {
|
||||||
|
@ -166,35 +162,18 @@ message RenameCommand {
|
||||||
ConnectCommandOptions command_options = 2;
|
ConnectCommandOptions command_options = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ConnectPlayerCommand {
|
|
||||||
string player_command_json = 1;
|
|
||||||
ConnectCommandOptions command_options = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
message SetBackendMetadataCommand {
|
message SetBackendMetadataCommand {
|
||||||
map<string, string> metadata = 1;
|
map<string, string> metadata = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message CommandAndSourceDevice {
|
|
||||||
string command = 1;
|
|
||||||
DeviceInfo source_device_info = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
message ActiveDeviceUpdate {
|
|
||||||
string device_id = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
message StartedPlayingEvent {
|
|
||||||
bytes user_info_header = 1;
|
|
||||||
string device_id = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum AudioOutputDeviceType {
|
enum AudioOutputDeviceType {
|
||||||
UNKNOWN_AUDIO_OUTPUT_DEVICE_TYPE = 0;
|
UNKNOWN_AUDIO_OUTPUT_DEVICE_TYPE = 0;
|
||||||
BUILT_IN_SPEAKER = 1;
|
BUILT_IN_SPEAKER = 1;
|
||||||
LINE_OUT = 2;
|
LINE_OUT = 2;
|
||||||
BLUETOOTH = 3;
|
BLUETOOTH = 3;
|
||||||
AIRPLAY = 4;
|
AIRPLAY = 4;
|
||||||
|
AUTOMOTIVE = 5;
|
||||||
|
CAR_PROJECTED = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum PutStateReason {
|
enum PutStateReason {
|
||||||
|
@ -207,6 +186,11 @@ enum PutStateReason {
|
||||||
PICKER_OPENED = 6;
|
PICKER_OPENED = 6;
|
||||||
BECAME_INACTIVE = 7;
|
BECAME_INACTIVE = 7;
|
||||||
ALIAS_CHANGED = 8;
|
ALIAS_CHANGED = 8;
|
||||||
|
NEW_CONNECTION = 9;
|
||||||
|
PULL_PLAYBACK = 10;
|
||||||
|
AUDIO_DRIVER_INFO_CHANGED = 11;
|
||||||
|
PUT_STATE_RATE_LIMITED = 12;
|
||||||
|
BACKEND_METADATA_APPLIED = 13;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum MemberType {
|
enum MemberType {
|
||||||
|
@ -225,15 +209,6 @@ enum ClusterUpdateReason {
|
||||||
NEW_DEVICE_APPEARED = 3;
|
NEW_DEVICE_APPEARED = 3;
|
||||||
DEVICE_VOLUME_CHANGED = 4;
|
DEVICE_VOLUME_CHANGED = 4;
|
||||||
DEVICE_ALIAS_CHANGED = 5;
|
DEVICE_ALIAS_CHANGED = 5;
|
||||||
|
DEVICE_NEW_CONNECTION = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum SendCommandResult {
|
|
||||||
UNKNOWN_SEND_COMMAND_RESULT = 0;
|
|
||||||
SUCCESS = 1;
|
|
||||||
DEVICE_NOT_FOUND = 2;
|
|
||||||
CONTEXT_PLAYER_ERROR = 3;
|
|
||||||
DEVICE_DISAPPEARED = 4;
|
|
||||||
UPSTREAM_ERROR = 5;
|
|
||||||
DEVICE_DOES_NOT_SUPPORT_COMMAND = 6;
|
|
||||||
RATE_LIMITED = 7;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.61.583 (Windows)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.61.583 (Windows)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto2";
|
syntax = "proto2";
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.73.517 (macOS)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
|
@ -9,4 +9,5 @@ option optimize_for = CODE_SIZE;
|
||||||
message ApplicationDesktop {
|
message ApplicationDesktop {
|
||||||
string version_string = 1;
|
string version_string = 1;
|
||||||
int64 version_code = 2;
|
int64 version_code = 2;
|
||||||
|
bytes session_id = 3;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.61.583 (Windows)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.73.517 (macOS)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.61.583 (Windows)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto2";
|
syntax = "proto2";
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.61.583 (Windows)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.61.583 (Windows)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.73.517 (macOS)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto2";
|
syntax = "proto2";
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ import "play_origin.proto";
|
||||||
import "prepare_play_options.proto";
|
import "prepare_play_options.proto";
|
||||||
import "track_instance.proto";
|
import "track_instance.proto";
|
||||||
import "track_instantiator.proto";
|
import "track_instantiator.proto";
|
||||||
|
import "context_track.proto";
|
||||||
|
|
||||||
option optimize_for = CODE_SIZE;
|
option optimize_for = CODE_SIZE;
|
||||||
|
|
||||||
|
@ -21,4 +22,5 @@ message ContextNode {
|
||||||
optional string session_id = 7;
|
optional string session_id = 7;
|
||||||
optional sint32 iteration = 8;
|
optional sint32 iteration = 8;
|
||||||
optional bool pending_pause = 9;
|
optional bool pending_pause = 9;
|
||||||
|
optional ContextTrack injected_connect_transfer_track = 10;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.61.583 (Windows)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto2";
|
syntax = "proto2";
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.61.583 (Windows)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto2";
|
syntax = "proto2";
|
||||||
|
|
||||||
|
@ -10,10 +10,15 @@ message ContextPlayerOptions {
|
||||||
optional bool shuffling_context = 1;
|
optional bool shuffling_context = 1;
|
||||||
optional bool repeating_context = 2;
|
optional bool repeating_context = 2;
|
||||||
optional bool repeating_track = 3;
|
optional bool repeating_track = 3;
|
||||||
|
optional float playback_speed = 4;
|
||||||
|
map<string, string> modes = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ContextPlayerOptionOverrides {
|
message ContextPlayerOptionOverrides {
|
||||||
optional bool shuffling_context = 1;
|
optional bool shuffling_context = 1;
|
||||||
optional bool repeating_context = 2;
|
optional bool repeating_context = 2;
|
||||||
optional bool repeating_track = 3;
|
optional bool repeating_track = 3;
|
||||||
|
optional float playback_speed = 4;
|
||||||
|
map<string, string> modes = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.61.583 (Windows)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto2";
|
syntax = "proto2";
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.73.517 (macOS)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.61.583 (Windows)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.61.583 (Windows)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto2";
|
syntax = "proto2";
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.61.583 (Windows)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto2";
|
syntax = "proto2";
|
||||||
|
|
||||||
|
@ -13,6 +13,5 @@ message ContextView {
|
||||||
map<string, player.proto.ContextTrack> patch_map = 1;
|
map<string, player.proto.ContextTrack> patch_map = 1;
|
||||||
optional uint32 iteration_size = 2;
|
optional uint32 iteration_size = 2;
|
||||||
optional cyclic_list.proto.CyclicEntryKeyList cyclic_list = 3;
|
optional cyclic_list.proto.CyclicEntryKeyList cyclic_list = 3;
|
||||||
|
|
||||||
reserved 4;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.61.583 (Windows)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto2";
|
syntax = "proto2";
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.61.583 (Windows)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto2";
|
syntax = "proto2";
|
||||||
|
|
||||||
|
@ -10,14 +10,14 @@ import "context_track.proto";
|
||||||
option optimize_for = CODE_SIZE;
|
option optimize_for = CODE_SIZE;
|
||||||
|
|
||||||
message Entry {
|
message Entry {
|
||||||
optional Type type = 1;
|
|
||||||
enum Type {
|
enum Type {
|
||||||
TRACK = 0;
|
TRACK = 0;
|
||||||
DELIMITER = 1;
|
DELIMITER = 1;
|
||||||
PAGE_PLACEHOLDER = 2;
|
PAGE_PLACEHOLDER = 2;
|
||||||
CONTEXT_PLACEHOLDER = 3;
|
CONTEXT_PLACEHOLDER = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
optional Type type = 1;
|
||||||
optional player.proto.ContextTrack track = 2;
|
optional player.proto.ContextTrack track = 2;
|
||||||
optional player.proto.ContextIndex index = 3;
|
optional player.proto.ContextIndex index = 3;
|
||||||
optional int32 page_index = 4;
|
optional int32 page_index = 4;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.61.583 (Windows)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto2";
|
syntax = "proto2";
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.73.517 (macOS)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto2";
|
syntax = "proto2";
|
||||||
|
|
||||||
|
@ -8,5 +8,4 @@ option objc_class_prefix = "SPTCollectionCosmosChanges";
|
||||||
option optimize_for = CODE_SIZE;
|
option optimize_for = CODE_SIZE;
|
||||||
|
|
||||||
message Response {
|
message Response {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.73.517 (macOS)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto2";
|
syntax = "proto2";
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.73.517 (macOS)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto2";
|
syntax = "proto2";
|
||||||
|
|
||||||
|
@ -34,5 +34,4 @@ message Response {
|
||||||
optional bool loading_contents = 4;
|
optional bool loading_contents = 4;
|
||||||
optional string offline = 5;
|
optional string offline = 5;
|
||||||
optional uint32 sync_progress = 6;
|
optional uint32 sync_progress = 6;
|
||||||
repeated GroupHeader group_index = 7;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.73.517 (macOS)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto2";
|
syntax = "proto2";
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.73.517 (macOS)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
|
@ -7,6 +7,9 @@ package spotify.collection_cosmos.tags_info_request.proto;
|
||||||
option objc_class_prefix = "SPTCollectionCosmosTagsInfo";
|
option objc_class_prefix = "SPTCollectionCosmosTagsInfo";
|
||||||
option optimize_for = CODE_SIZE;
|
option optimize_for = CODE_SIZE;
|
||||||
|
|
||||||
|
message Request {
|
||||||
|
}
|
||||||
|
|
||||||
message Response {
|
message Response {
|
||||||
bool is_synced = 1;
|
bool is_synced = 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.73.517 (macOS)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto2";
|
syntax = "proto2";
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
// Extracted from: Spotify 1.1.73.517 (macOS)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto2";
|
syntax = "proto2";
|
||||||
|
|
||||||
package spotify.collection_cosmos.track_list_request.proto;
|
package spotify.collection_cosmos.track_list_request.proto;
|
||||||
|
|
||||||
|
import "collection/artist_collection_state.proto";
|
||||||
import "collection/track_collection_state.proto";
|
import "collection/track_collection_state.proto";
|
||||||
import "played_state/track_played_state.proto";
|
import "played_state/track_played_state.proto";
|
||||||
import "sync/track_sync_state.proto";
|
import "sync/track_sync_state.proto";
|
||||||
|
@ -21,6 +22,7 @@ message Item {
|
||||||
optional cosmos_util.proto.TrackPlayState track_play_state = 6;
|
optional cosmos_util.proto.TrackPlayState track_play_state = 6;
|
||||||
optional cosmos_util.proto.TrackCollectionState track_collection_state = 7;
|
optional cosmos_util.proto.TrackCollectionState track_collection_state = 7;
|
||||||
optional string group_label = 8;
|
optional string group_label = 8;
|
||||||
|
repeated cosmos_util.proto.ArtistCollectionState artist_collection_state = 9;
|
||||||
}
|
}
|
||||||
|
|
||||||
message GroupHeader {
|
message GroupHeader {
|
||||||
|
@ -36,5 +38,4 @@ message Response {
|
||||||
optional bool loading_contents = 4;
|
optional bool loading_contents = 4;
|
||||||
optional string offline = 5;
|
optional string offline = 5;
|
||||||
optional uint32 sync_progress = 6;
|
optional uint32 sync_progress = 6;
|
||||||
repeated GroupHeader group_index = 7;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.73.517 (macOS)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto2";
|
syntax = "proto2";
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.61.583 (Windows)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.73.517 (macOS)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto2";
|
syntax = "proto2";
|
||||||
|
|
||||||
|
@ -7,45 +7,38 @@ package spotify.show_cosmos.decorate_request.proto;
|
||||||
import "metadata/episode_metadata.proto";
|
import "metadata/episode_metadata.proto";
|
||||||
import "metadata/show_metadata.proto";
|
import "metadata/show_metadata.proto";
|
||||||
import "played_state/episode_played_state.proto";
|
import "played_state/episode_played_state.proto";
|
||||||
import "show_access.proto";
|
import "played_state/show_played_state.proto";
|
||||||
import "show_episode_state.proto";
|
import "show_episode_state.proto";
|
||||||
import "show_show_state.proto";
|
import "show_show_state.proto";
|
||||||
import "podcast_segments.proto";
|
import "show_offline_state.proto";
|
||||||
import "podcast_virality.proto";
|
|
||||||
import "podcastextensions.proto";
|
|
||||||
import "podcast_poll.proto";
|
|
||||||
import "podcast_qna.proto";
|
|
||||||
import "podcast_ratings.proto";
|
|
||||||
import "transcripts.proto";
|
|
||||||
import "clips_cover.proto";
|
|
||||||
|
|
||||||
option objc_class_prefix = "SPTShowCosmosDecorate";
|
option objc_class_prefix = "SPTShowCosmosDecorate";
|
||||||
option optimize_for = CODE_SIZE;
|
option optimize_for = CODE_SIZE;
|
||||||
|
|
||||||
message Show {
|
message Show {
|
||||||
|
reserved 5;
|
||||||
|
reserved 6;
|
||||||
optional cosmos_util.proto.ShowMetadata show_metadata = 1;
|
optional cosmos_util.proto.ShowMetadata show_metadata = 1;
|
||||||
optional show_cosmos.proto.ShowCollectionState show_collection_state = 2;
|
optional show_cosmos.proto.ShowCollectionState show_collection_state = 2;
|
||||||
optional show_cosmos.proto.ShowPlayState show_play_state = 3;
|
optional cosmos_util.proto.ShowPlayState show_play_state = 3;
|
||||||
optional string link = 4;
|
optional string link = 4;
|
||||||
optional podcast_paywalls.ShowAccess access_info = 5;
|
optional show_cosmos.proto.ShowOfflineState show_offline_state = 7;
|
||||||
optional ratings.PodcastRating podcast_rating = 6;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message Episode {
|
message Episode {
|
||||||
|
reserved 6;
|
||||||
|
reserved 7;
|
||||||
|
reserved 8;
|
||||||
|
reserved 9;
|
||||||
|
reserved 10;
|
||||||
|
reserved 11;
|
||||||
|
reserved 12;
|
||||||
|
reserved 13;
|
||||||
optional cosmos_util.proto.EpisodeMetadata episode_metadata = 1;
|
optional cosmos_util.proto.EpisodeMetadata episode_metadata = 1;
|
||||||
optional show_cosmos.proto.EpisodeCollectionState episode_collection_state = 2;
|
optional show_cosmos.proto.EpisodeCollectionState episode_collection_state = 2;
|
||||||
optional show_cosmos.proto.EpisodeOfflineState episode_offline_state = 3;
|
optional show_cosmos.proto.EpisodeOfflineState episode_offline_state = 3;
|
||||||
optional cosmos_util.proto.EpisodePlayState episode_play_state = 4;
|
optional cosmos_util.proto.EpisodePlayState episode_play_state = 4;
|
||||||
optional string link = 5;
|
optional string link = 5;
|
||||||
optional podcast_segments.PodcastSegments segments = 6;
|
|
||||||
optional podcast.extensions.PodcastHtmlDescription html_description = 7;
|
|
||||||
optional corex.transcripts.metadata.EpisodeTranscript transcripts = 9;
|
|
||||||
optional podcastvirality.v1.PodcastVirality virality = 10;
|
|
||||||
optional polls.PodcastPoll podcast_poll = 11;
|
|
||||||
optional qanda.PodcastQna podcast_qna = 12;
|
|
||||||
optional clips.ClipsCover clips = 13;
|
|
||||||
|
|
||||||
reserved 8;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message Response {
|
message Response {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.61.583 (Windows)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
// Extracted from: Spotify 1.1.73.517 (macOS)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
package spotify.displaysegments.v1;
|
package spotify.displaysegments.v1;
|
||||||
|
|
||||||
|
option objc_class_prefix = "ESP";
|
||||||
option java_multiple_files = true;
|
option java_multiple_files = true;
|
||||||
option optimize_for = CODE_SIZE;
|
option optimize_for = CODE_SIZE;
|
||||||
option java_outer_classname = "DisplaySegmentsExtensionProto";
|
option java_outer_classname = "DisplaySegmentsExtensionProto";
|
||||||
|
@ -13,9 +14,9 @@ message DisplaySegmentsExtension {
|
||||||
string episode_uri = 1;
|
string episode_uri = 1;
|
||||||
repeated DisplaySegment segments = 2;
|
repeated DisplaySegment segments = 2;
|
||||||
int32 duration_ms = 3;
|
int32 duration_ms = 3;
|
||||||
|
|
||||||
oneof decoration {
|
oneof decoration {
|
||||||
MusicAndTalkDecoration music_and_talk_decoration = 4;
|
MusicAndTalkDecoration music_and_talk_decoration = 4;
|
||||||
|
PodcastChaptersDecoration podcast_chapters_decoration = 5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,28 +26,20 @@ message DisplaySegment {
|
||||||
int32 duration_ms = 3;
|
int32 duration_ms = 3;
|
||||||
int32 seek_start_ms = 4;
|
int32 seek_start_ms = 4;
|
||||||
int32 seek_stop_ms = 5;
|
int32 seek_stop_ms = 5;
|
||||||
|
optional string title = 6;
|
||||||
oneof _title {
|
optional string subtitle = 7;
|
||||||
string title = 6;
|
optional string image_url = 8;
|
||||||
}
|
optional bool is_preview = 9;
|
||||||
|
|
||||||
oneof _subtitle {
|
|
||||||
string subtitle = 7;
|
|
||||||
}
|
|
||||||
|
|
||||||
oneof _image_url {
|
|
||||||
string image_url = 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
oneof _is_preview {
|
|
||||||
bool is_preview = 9;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message MusicAndTalkDecoration {
|
message MusicAndTalkDecoration {
|
||||||
bool can_upsell = 1;
|
bool can_upsell = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message PodcastChaptersDecoration {
|
||||||
|
repeated string tags = 1;
|
||||||
|
}
|
||||||
|
|
||||||
enum SegmentType {
|
enum SegmentType {
|
||||||
SEGMENT_TYPE_UNSPECIFIED = 0;
|
SEGMENT_TYPE_UNSPECIFIED = 0;
|
||||||
SEGMENT_TYPE_TALK = 1;
|
SEGMENT_TYPE_TALK = 1;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.61.583 (Windows)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
|
@ -30,7 +30,6 @@ message PlainListAssoc {
|
||||||
}
|
}
|
||||||
|
|
||||||
message AssocHeader {
|
message AssocHeader {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message Assoc {
|
message Assoc {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.61.583 (Windows)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.73.517 (macOS)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.61.583 (Windows)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
|
@ -16,6 +16,6 @@ message Context {
|
||||||
map<string, string> metadata = 2;
|
map<string, string> metadata = 2;
|
||||||
string uri = 3;
|
string uri = 3;
|
||||||
string url = 4;
|
string url = 4;
|
||||||
bool is_loaded = 5;
|
bool is_loading = 5;
|
||||||
Restrictions restrictions = 6;
|
Restrictions restrictions = 6;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.61.583 (Windows)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
|
@ -15,5 +15,5 @@ message ContextPage {
|
||||||
map<string, string> metadata = 2;
|
map<string, string> metadata = 2;
|
||||||
string page_url = 3;
|
string page_url = 3;
|
||||||
string next_page_url = 4;
|
string next_page_url = 4;
|
||||||
bool is_loaded = 5;
|
bool is_loading = 5;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.61.583 (Windows)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
|
@ -9,7 +9,6 @@ option optimize_for = CODE_SIZE;
|
||||||
option java_package = "com.spotify.player.esperanto.proto";
|
option java_package = "com.spotify.player.esperanto.proto";
|
||||||
|
|
||||||
message ContextPlayerError {
|
message ContextPlayerError {
|
||||||
ErrorCode code = 1;
|
|
||||||
enum ErrorCode {
|
enum ErrorCode {
|
||||||
SUCCESS = 0;
|
SUCCESS = 0;
|
||||||
PLAYBACK_STUCK = 1;
|
PLAYBACK_STUCK = 1;
|
||||||
|
@ -48,8 +47,15 @@ message ContextPlayerError {
|
||||||
TIMEOUT = 34;
|
TIMEOUT = 34;
|
||||||
PLAYBACK_REPORTING_ERROR = 35;
|
PLAYBACK_REPORTING_ERROR = 35;
|
||||||
UNKNOWN = 36;
|
UNKNOWN = 36;
|
||||||
|
ADD_TO_QUEUE_RESTRICTED = 37;
|
||||||
|
PICK_AND_SHUFFLE_CAPPED = 38;
|
||||||
|
PICK_AND_SHUFFLE_CONNECT_RESTRICTED = 39;
|
||||||
|
CONTEXT_LOADING_FAILED = 40;
|
||||||
|
AUDIOBOOK_NOT_PLAYABLE = 41;
|
||||||
|
SIGNAL_NOT_AVAILABLE = 42;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ErrorCode code = 1;
|
||||||
string message = 2;
|
string message = 2;
|
||||||
map<string, string> data = 3;
|
map<string, string> data = 3;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.61.583 (Windows)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
|
@ -14,10 +14,14 @@ message ContextPlayerOptions {
|
||||||
bool shuffling_context = 1;
|
bool shuffling_context = 1;
|
||||||
bool repeating_context = 2;
|
bool repeating_context = 2;
|
||||||
bool repeating_track = 3;
|
bool repeating_track = 3;
|
||||||
|
map<string, string> modes = 5;
|
||||||
|
optional float playback_speed = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ContextPlayerOptionOverrides {
|
message ContextPlayerOptionOverrides {
|
||||||
OptionalBoolean shuffling_context = 1;
|
OptionalBoolean shuffling_context = 1;
|
||||||
OptionalBoolean repeating_context = 2;
|
OptionalBoolean repeating_context = 2;
|
||||||
OptionalBoolean repeating_track = 3;
|
OptionalBoolean repeating_track = 3;
|
||||||
|
map<string, string> modes = 5;
|
||||||
|
optional float playback_speed = 4;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.61.583 (Windows)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
|
@ -21,7 +21,6 @@ message ContextIndex {
|
||||||
}
|
}
|
||||||
|
|
||||||
message PlaybackQuality {
|
message PlaybackQuality {
|
||||||
BitrateLevel bitrate_level = 1;
|
|
||||||
enum BitrateLevel {
|
enum BitrateLevel {
|
||||||
UNKNOWN = 0;
|
UNKNOWN = 0;
|
||||||
LOW = 1;
|
LOW = 1;
|
||||||
|
@ -29,9 +28,9 @@ message PlaybackQuality {
|
||||||
HIGH = 3;
|
HIGH = 3;
|
||||||
VERY_HIGH = 4;
|
VERY_HIGH = 4;
|
||||||
HIFI = 5;
|
HIFI = 5;
|
||||||
|
HIFI24 = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
BitrateStrategy strategy = 2;
|
|
||||||
enum BitrateStrategy {
|
enum BitrateStrategy {
|
||||||
UNKNOWN_STRATEGY = 0;
|
UNKNOWN_STRATEGY = 0;
|
||||||
BEST_MATCHING = 1;
|
BEST_MATCHING = 1;
|
||||||
|
@ -40,16 +39,18 @@ message PlaybackQuality {
|
||||||
CACHED_FILE = 4;
|
CACHED_FILE = 4;
|
||||||
LOCAL_FILE = 5;
|
LOCAL_FILE = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
BitrateLevel target_bitrate_level = 3;
|
|
||||||
bool target_bitrate_available = 4;
|
|
||||||
|
|
||||||
HiFiStatus hifi_status = 5;
|
|
||||||
enum HiFiStatus {
|
enum HiFiStatus {
|
||||||
NONE = 0;
|
NONE = 0;
|
||||||
OFF = 1;
|
OFF = 1;
|
||||||
ON = 2;
|
ON = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BitrateLevel bitrate_level = 1;
|
||||||
|
BitrateStrategy strategy = 2;
|
||||||
|
BitrateLevel target_bitrate_level = 3;
|
||||||
|
bool target_bitrate_available = 4;
|
||||||
|
HiFiStatus hifi_status = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ContextPlayerState {
|
message ContextPlayerState {
|
||||||
|
@ -79,4 +80,6 @@ message ContextPlayerState {
|
||||||
string session_id = 24;
|
string session_id = 24;
|
||||||
uint64 queue_revision = 25;
|
uint64 queue_revision = 25;
|
||||||
PreparePlayOptions.AudioStream audio_stream = 26;
|
PreparePlayOptions.AudioStream audio_stream = 26;
|
||||||
|
repeated string signals = 27;
|
||||||
|
string session_command_id = 28;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.61.583 (Windows)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.61.583 (Windows)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
|
@ -13,5 +13,4 @@ message DeleteSessionRequest {
|
||||||
}
|
}
|
||||||
|
|
||||||
message DeleteSessionResponse {
|
message DeleteSessionResponse {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.61.583 (Windows)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
|
@ -9,5 +9,4 @@ option optimize_for = CODE_SIZE;
|
||||||
option java_package = "com.spotify.player.esperanto.proto";
|
option java_package = "com.spotify.player.esperanto.proto";
|
||||||
|
|
||||||
message GetErrorRequest {
|
message GetErrorRequest {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.61.583 (Windows)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
|
@ -11,7 +11,6 @@ option optimize_for = CODE_SIZE;
|
||||||
option java_package = "com.spotify.player.esperanto.proto";
|
option java_package = "com.spotify.player.esperanto.proto";
|
||||||
|
|
||||||
message GetPlayHistoryRequest {
|
message GetPlayHistoryRequest {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message GetPlayHistoryResponse {
|
message GetPlayHistoryResponse {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.61.583 (Windows)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
|
@ -9,16 +9,15 @@ option optimize_for = CODE_SIZE;
|
||||||
option java_package = "com.spotify.player.esperanto.proto";
|
option java_package = "com.spotify.player.esperanto.proto";
|
||||||
|
|
||||||
message GetPositionStateRequest {
|
message GetPositionStateRequest {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message GetPositionStateResponse {
|
message GetPositionStateResponse {
|
||||||
Error error = 1;
|
|
||||||
enum Error {
|
enum Error {
|
||||||
OK = 0;
|
OK = 0;
|
||||||
NOT_FOUND = 1;
|
NOT_FOUND = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Error error = 1;
|
||||||
uint64 timestamp = 2;
|
uint64 timestamp = 2;
|
||||||
uint64 position = 3;
|
uint64 position = 3;
|
||||||
double playback_speed = 4;
|
double playback_speed = 4;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.61.583 (Windows)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
|
@ -9,5 +9,4 @@ option optimize_for = CODE_SIZE;
|
||||||
option java_package = "com.spotify.player.esperanto.proto";
|
option java_package = "com.spotify.player.esperanto.proto";
|
||||||
|
|
||||||
message GetQueueRequest {
|
message GetQueueRequest {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.61.583 (Windows)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.61.583 (Windows)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.61.583 (Windows)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ package spotify.player.esperanto.proto;
|
||||||
|
|
||||||
import "es_command_options.proto";
|
import "es_command_options.proto";
|
||||||
import "es_logging_params.proto";
|
import "es_logging_params.proto";
|
||||||
|
import "es_pauseresume_origin.proto";
|
||||||
|
|
||||||
option objc_class_prefix = "ESP";
|
option objc_class_prefix = "ESP";
|
||||||
option optimize_for = CODE_SIZE;
|
option optimize_for = CODE_SIZE;
|
||||||
|
@ -14,4 +15,5 @@ option java_package = "com.spotify.player.esperanto.proto";
|
||||||
message PauseRequest {
|
message PauseRequest {
|
||||||
CommandOptions options = 1;
|
CommandOptions options = 1;
|
||||||
LoggingParams logging_params = 2;
|
LoggingParams logging_params = 2;
|
||||||
|
PauseResumeOrigin pause_origin = 3;
|
||||||
}
|
}
|
||||||
|
|
11
protocol/proto/es_pauseresume_origin.proto
Normal file
11
protocol/proto/es_pauseresume_origin.proto
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package spotify.player.esperanto.proto;
|
||||||
|
|
||||||
|
option java_package = "com.spotify.player.esperanto.proto";
|
||||||
|
option objc_class_prefix = "ESP";
|
||||||
|
|
||||||
|
message PauseResumeOrigin {
|
||||||
|
string feature_identifier = 1;
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.61.583 (Windows)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.61.583 (Windows)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
|
@ -16,4 +16,5 @@ message PlayOrigin {
|
||||||
string referrer_identifier = 5;
|
string referrer_identifier = 5;
|
||||||
string device_identifier = 6;
|
string device_identifier = 6;
|
||||||
repeated string feature_classes = 7;
|
repeated string feature_classes = 7;
|
||||||
|
string restriction_identifier = 8;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.73.517 (macOS)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
|
@ -25,11 +25,9 @@ message SubParams {
|
||||||
}
|
}
|
||||||
|
|
||||||
message GetAllParams {
|
message GetAllParams {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message SubAllParams {
|
message SubAllParams {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message Value {
|
message Value {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.61.583 (Windows)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.61.583 (Windows)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
|
@ -21,19 +21,19 @@ message PreparePlayOptions {
|
||||||
bool system_initiated = 6;
|
bool system_initiated = 6;
|
||||||
ContextPlayerOptionOverrides player_options_override = 7;
|
ContextPlayerOptionOverrides player_options_override = 7;
|
||||||
repeated string suppressions = 8;
|
repeated string suppressions = 8;
|
||||||
|
|
||||||
PrefetchLevel prefetch_level = 9;
|
PrefetchLevel prefetch_level = 9;
|
||||||
enum PrefetchLevel {
|
enum PrefetchLevel {
|
||||||
NONE = 0;
|
NONE = 0;
|
||||||
MEDIA = 1;
|
MEDIA = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioStream audio_stream = 10;
|
AudioStream audio_stream = 10;
|
||||||
enum AudioStream {
|
enum AudioStream {
|
||||||
DEFAULT = 0;
|
DEFAULT = 0;
|
||||||
ALARM = 1;
|
ALARM = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
string session_id = 11;
|
string session_id = 11;
|
||||||
string license = 12;
|
string license = 12;
|
||||||
map<string, string> configuration_override = 13;
|
map<string, string> configuration_override = 13;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.61.583 (Windows)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.61.583 (Windows)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
|
|
|
@ -1,21 +1,33 @@
|
||||||
// Extracted from: Spotify 1.1.73.517 (macOS)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
package spotify.remote_config.esperanto.proto;
|
package spotify.remote_config.esperanto.proto;
|
||||||
|
|
||||||
|
import "esperanto_options.proto";
|
||||||
|
|
||||||
option objc_class_prefix = "ESP";
|
option objc_class_prefix = "ESP";
|
||||||
option java_package = "com.spotify.remoteconfig.esperanto.proto";
|
option java_package = "com.spotify.remoteconfig.esperanto.proto";
|
||||||
|
|
||||||
service RemoteConfig {
|
service RemoteConfig {
|
||||||
rpc lookupBool(LookupRequest) returns (BoolResponse);
|
rpc lookupBool(LookupRequest) returns (.spotify.remote_config.esperanto.proto.BoolResponse) {}
|
||||||
|
rpc lookupInt(LookupRequest) returns (.spotify.remote_config.esperanto.proto.IntResponse) {}
|
||||||
|
rpc lookupEnum(LookupRequest) returns (.spotify.remote_config.esperanto.proto.EnumResponse) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
message LookupRequest {
|
message LookupRequest {
|
||||||
string component_id = 1;
|
string scope = 1;
|
||||||
string key = 2;
|
string name = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
message BoolResponse {
|
message BoolResponse {
|
||||||
bool value = 1;
|
optional bool value = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message IntResponse {
|
||||||
|
optional int32 value = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message EnumResponse {
|
||||||
|
optional string value = 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Extracted from: Spotify 1.1.73.517 (macOS)
|
// Extracted from: Spotify 1.2.52.442 (windows)
|
||||||
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
|
@ -24,4 +24,6 @@ message RequestInfo {
|
||||||
int64 event_first_byte_received = 11;
|
int64 event_first_byte_received = 11;
|
||||||
int64 event_last_byte_received = 12;
|
int64 event_last_byte_received = 12;
|
||||||
int64 event_ended = 13;
|
int64 event_ended = 13;
|
||||||
|
string protocol = 14;
|
||||||
|
int64 event_redirects_done = 15;
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue