use educe::Educe;
use qstring::QString;
use serde::{Deserialize, Serialize};
use std::net::IpAddr;
use std::str::FromStr;
use strum::EnumString;
use super::*;
use crate::command::CommandError;
use crate::data::group::GroupId;
id_type! {
pub struct PlayerId(pub i64);
}
impl_try_from_qs!(PlayerId, "pid");
#[derive(Serialize, Deserialize, EnumString, strum::Display, Debug, Clone, Copy, PartialEq, Eq)]
#[serde(into = "String", try_from = "String")]
#[strum(serialize_all = "lowercase")]
pub enum NetworkType {
Wired,
WiFi,
Unknown,
}
impl_enum_string_conversions!(NetworkType);
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq)]
#[serde(try_from = "i64", into = "i64")]
pub enum LineOutLevelType {
None,
Variable,
Fixed,
}
impl TryFrom<i64> for LineOutLevelType {
type Error = String;
#[inline]
fn try_from(value: i64) -> Result<Self, Self::Error> {
match value {
0 => Ok(LineOutLevelType::None),
1 => Ok(LineOutLevelType::Variable),
2 => Ok(LineOutLevelType::Fixed),
other => Err(format!("Unknown line_out type: '{other}'")),
}
}
}
impl From<LineOutLevelType> for i64 {
#[inline]
fn from(value: LineOutLevelType) -> Self {
match value {
LineOutLevelType::None => 0,
LineOutLevelType::Variable => 1,
LineOutLevelType::Fixed => 2,
}
}
}
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq)]
#[serde(try_from = "i64", into = "i64")]
pub enum LineOutLevelControlType {
None,
IR,
Trigger,
Network,
}
impl TryFrom<i64> for LineOutLevelControlType {
type Error = String;
#[inline]
fn try_from(value: i64) -> Result<Self, Self::Error> {
match value {
0 | 1 => Ok(LineOutLevelControlType::None),
2 => Ok(LineOutLevelControlType::IR),
3 => Ok(LineOutLevelControlType::Trigger),
4 => Ok(LineOutLevelControlType::Network),
other => Err(format!("Unknown line_out_control type: '{other}'")),
}
}
}
impl From<LineOutLevelControlType> for i64 {
#[inline]
fn from(value: LineOutLevelControlType) -> Self {
match value {
LineOutLevelControlType::None => 1,
LineOutLevelControlType::IR => 2,
LineOutLevelControlType::Trigger => 3,
LineOutLevelControlType::Network => 4,
}
}
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct PlayerInfo {
pub name: String,
#[serde(rename = "pid")]
pub player_id: PlayerId,
#[serde(rename = "gid")]
pub group_id: Option<GroupId>,
pub model: String,
pub version: String,
pub ip: IpAddr,
pub network: NetworkType,
#[serde(rename = "lineout")]
pub line_out: LineOutLevelType,
#[serde(rename = "control")]
pub line_out_control: Option<LineOutLevelControlType>,
pub serial: Option<String>,
}
impl_try_from_response_payload!(PlayerInfo);
impl_try_from_response_payload!(Vec<PlayerInfo>);
#[derive(Serialize, Deserialize, EnumString, strum::Display, Debug, Clone, Copy, PartialEq, Eq)]
#[serde(into = "String", try_from = "String")]
#[strum(serialize_all = "lowercase")]
pub enum PlayState {
Play,
Pause,
Stop,
}
impl_enum_string_conversions!(PlayState);
impl_try_from_qs!(PlayState, "state");
impl_try_from_response_qs!(PlayState);
#[derive(Serialize, Deserialize, EnumString, strum::Display, Debug, Clone, Copy, PartialEq, Eq)]
#[serde(into = "String", try_from = "String")]
#[strum(serialize_all = "lowercase")]
pub enum RepeatMode {
#[strum(serialize = "on_all")]
All,
#[strum(serialize = "on_one")]
One,
Off,
}
impl_enum_string_conversions!(RepeatMode);
impl_try_from_qs!(RepeatMode, "repeat");
impl_try_from_response_qs!(RepeatMode);
#[derive(Serialize, Deserialize, EnumString, strum::Display, Debug, Clone, Copy, PartialEq, Eq)]
#[serde(into = "String", try_from = "String")]
#[strum(serialize_all = "lowercase")]
pub enum ShuffleMode {
On,
Off,
}
impl_enum_string_conversions!(ShuffleMode);
impl_try_from_qs!(ShuffleMode, "shuffle");
impl_try_from_response_qs!(ShuffleMode);
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct PlayMode {
pub repeat: RepeatMode,
pub shuffle: ShuffleMode,
}
impl_try_from_response_qs!(PlayMode);
impl TryFrom<QString> for PlayMode {
type Error = CommandError;
#[inline]
fn try_from(qs: QString) -> Result<Self, Self::Error> {
let repeat = RepeatMode::try_from(&qs)?;
let shuffle = ShuffleMode::try_from(qs)?;
Ok(Self {
repeat,
shuffle,
})
}
}
#[derive(Serialize, Deserialize, EnumString, strum::Display, Debug, Clone, Copy, PartialEq, Eq)]
#[serde(into = "String", try_from = "String")]
pub enum UpdateAvailable {
#[strum(serialize = "update_none")]
None,
#[strum(serialize = "update_exist")]
Exists,
}
impl_enum_string_conversions!(UpdateAvailable);
#[derive(Serialize, Deserialize, Educe, Debug, Clone, Copy)]
#[educe(Into(UpdateAvailable))]
pub struct UpdatePayload {
pub update: UpdateAvailable,
}
impl_try_from_response_payload!(UpdatePayload);
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq)]
#[serde(into = "i64", try_from = "i64")]
pub enum AddToQueueType {
PlayNow,
PlayNext,
AddToEnd,
ReplaceAndPlay,
}
#[derive(thiserror::Error, Debug, Clone)]
pub enum AddToQueueTypeParseError {
#[error("unknown type id '{0}'")]
UnknownId(i64),
#[error(transparent)]
ParseIntError(#[from] ParseIntError),
}
impl TryFrom<i64> for AddToQueueType {
type Error = AddToQueueTypeParseError;
fn try_from(value: i64) -> Result<Self, Self::Error> {
match value {
1 => Ok(AddToQueueType::PlayNow),
2 => Ok(AddToQueueType::PlayNext),
3 => Ok(AddToQueueType::AddToEnd),
4 => Ok(AddToQueueType::ReplaceAndPlay),
value => Err(AddToQueueTypeParseError::UnknownId(value)),
}
}
}
impl From<AddToQueueType> for i64 {
#[inline]
fn from(value: AddToQueueType) -> Self {
match value {
AddToQueueType::PlayNow => 1,
AddToQueueType::PlayNext => 2,
AddToQueueType::AddToEnd => 3,
AddToQueueType::ReplaceAndPlay => 4,
}
}
}
impl FromStr for AddToQueueType {
type Err = AddToQueueTypeParseError;
#[inline]
fn from_str(s: &str) -> Result<Self, Self::Err> {
let value: i64 = s.parse()?;
let aid = Self::try_from(value)?;
Ok(aid)
}
}