use std::collections::HashMap;
use std::time::Duration;
use serde::ser::{SerializeStruct, Serializer};
use serde::{Deserialize, Serialize};
use crate::model::{Episode, ItemType, Track};
use crate::util;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Device {
pub id: Option<String>,
pub is_active: bool,
pub is_private_session: bool,
pub is_restricted: bool,
pub name: String,
#[serde(rename = "type")]
pub device_type: DeviceType,
pub volume_percent: Option<u32>,
}
#[derive(Debug, Clone, PartialEq, Eq, Copy, Hash, Serialize, Deserialize)]
#[allow(missing_docs)]
pub enum DeviceType {
Computer,
Tablet,
Smartphone,
Speaker,
TV,
AVR,
STB,
AudioDongle,
GameConsole,
CastVideo,
CastAudio,
Automobile,
Unknown,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CurrentlyPlaying {
pub context: Option<Context>,
#[serde(rename = "progress_ms", with = "util::serde_duration_millis_option")]
pub progress: Option<Duration>,
pub is_playing: bool,
#[serde(flatten)]
pub item: Option<PlayingType>,
pub actions: Actions,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CurrentPlayback {
pub device: Device,
pub repeat_state: RepeatState,
pub shuffle_state: bool,
#[serde(flatten)]
pub currently_playing: CurrentlyPlaying,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Actions {
#[serde(with = "util::serde_disallows")]
pub disallows: Vec<Disallow>,
}
#[derive(Debug, Clone, PartialEq, Eq, Copy, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
#[allow(missing_docs)]
pub enum Disallow {
InterruptingPlayback,
Pausing,
Resuming,
Seeking,
SkippingNext,
SkippingPrev,
TogglingRepeatContext,
TogglingShuffle,
TogglingRepeatTrack,
TransferringPlayback,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(
rename_all = "snake_case",
tag = "currently_playing_type",
content = "item"
)]
pub enum PlayingType {
Track(Track),
Episode(Episode),
Ad(Track),
Unknown(Track),
}
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
pub struct Context {
#[serde(rename = "type")]
pub context_type: ItemType,
pub external_urls: HashMap<String, String>,
#[serde(rename = "uri", deserialize_with = "util::de_any_uri")]
pub id: String,
}
impl Serialize for Context {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let mut context = serializer.serialize_struct("Context", 3)?;
context.serialize_field("type", &self.context_type)?;
context.serialize_field("external_urls", &self.external_urls)?;
context.serialize_field("uri", {
struct UriSerialize<'a> {
context_type: ItemType,
id: &'a str,
}
impl Serialize for UriSerialize<'_> {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
serializer.serialize_str(&format!(
"spotify:{}:{}",
self.context_type.as_str(),
self.id
))
}
}
&UriSerialize {
context_type: self.context_type,
id: &self.id,
}
})?;
context.end()
}
}
#[derive(Debug, Clone, PartialEq, Eq, Copy, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum RepeatState {
Off,
Track,
Context,
}
impl RepeatState {
#[must_use]
pub const fn as_str(self) -> &'static str {
match self {
Self::Off => "off",
Self::Track => "track",
Self::Context => "context",
}
}
}