Add Status
struct
This commit is contained in:
parent
ce5b87769c
commit
fe2730a7d6
50
src/lib.rs
50
src/lib.rs
|
@ -3,7 +3,7 @@ use std::collections::HashMap;
|
||||||
mod error;
|
mod error;
|
||||||
use error::{Error, MpdResult};
|
use error::{Error, MpdResult};
|
||||||
mod structs;
|
mod structs;
|
||||||
pub use structs::{Position, Track};
|
pub use structs::{Position, Status, Track};
|
||||||
|
|
||||||
/// some unprintable character to separate repeated keys
|
/// some unprintable character to separate repeated keys
|
||||||
const SEPARATOR: char = '\x02';
|
const SEPARATOR: char = '\x02';
|
||||||
|
@ -38,6 +38,7 @@ pub fn deserialize_response<'a, I: Iterator<Item = &'a str>, T: de::DeserializeO
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use chrono::DateTime;
|
use chrono::DateTime;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn track_de_test() {
|
fn track_de_test() {
|
||||||
|
@ -69,7 +70,7 @@ OK";
|
||||||
item_position: 1,
|
item_position: 1,
|
||||||
total_items: None,
|
total_items: None,
|
||||||
}),
|
}),
|
||||||
duration: std::time::Duration::from_secs_f64(512.380),
|
duration: Some(Duration::from_secs_f64(512.380)),
|
||||||
pos: 1367,
|
pos: 1367,
|
||||||
id: 1368,
|
id: 1368,
|
||||||
..Track::default()
|
..Track::default()
|
||||||
|
@ -129,7 +130,7 @@ OK"#;
|
||||||
item_position: 6,
|
item_position: 6,
|
||||||
total_items: Some(6),
|
total_items: Some(6),
|
||||||
}),
|
}),
|
||||||
duration: std::time::Duration::from_secs_f64(682.840),
|
duration: Some(Duration::from_secs_f64(682.840)),
|
||||||
pos: 3439,
|
pos: 3439,
|
||||||
id: 3440,
|
id: 3440,
|
||||||
performers: vec!["Royal Philharmonic Orchestra".to_string(), "Jane Glover".to_string()],
|
performers: vec!["Royal Philharmonic Orchestra".to_string(), "Jane Glover".to_string()],
|
||||||
|
@ -142,4 +143,47 @@ OK"#;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
#[test]
|
||||||
|
fn de_status_test() {
|
||||||
|
let input_str = "volume: 74
|
||||||
|
repeat: 0
|
||||||
|
random: 1
|
||||||
|
single: 0
|
||||||
|
consume: 0
|
||||||
|
playlist: 6
|
||||||
|
playlistlength: 5364
|
||||||
|
mixrampdb: 0.000000
|
||||||
|
state: play
|
||||||
|
song: 3833
|
||||||
|
songid: 3834
|
||||||
|
time: 70:164
|
||||||
|
elapsed: 69.642
|
||||||
|
bitrate: 702
|
||||||
|
duration: 163.760
|
||||||
|
audio: 44100:16:2
|
||||||
|
nextsong: 4036
|
||||||
|
nextsongid: 4037
|
||||||
|
OK";
|
||||||
|
let s: Status = deserialize_response(input_str.lines()).unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
s,
|
||||||
|
Status {
|
||||||
|
volume: Some(74),
|
||||||
|
random: true,
|
||||||
|
playlist: 6,
|
||||||
|
playlistlength: 5364,
|
||||||
|
mixrampdb: 0.0,
|
||||||
|
state: String::from("play"),
|
||||||
|
song: Some(3833),
|
||||||
|
songid: Some(3834),
|
||||||
|
elapsed: Some(Duration::from_secs_f64(69.642)),
|
||||||
|
bitrate: Some(702),
|
||||||
|
duration: Some(Duration::from_secs_f64(163.760)),
|
||||||
|
audio: Some(String::from("44100:16:2")),
|
||||||
|
nextsong: Some(4036),
|
||||||
|
nextsongid: Some(4037),
|
||||||
|
..Status::default()
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ use helpers::*;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
/// All information about a track. This is returned by the `currentsong` or `queue` commands.
|
||||||
#[derive(Deserialize, Clone, Debug, Default, PartialEq)]
|
#[derive(Deserialize, Clone, Debug, Default, PartialEq)]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub struct Track {
|
pub struct Track {
|
||||||
|
@ -30,11 +31,9 @@ pub struct Track {
|
||||||
pub last_modified: Option<DateTime<FixedOffset>>,
|
pub last_modified: Option<DateTime<FixedOffset>>,
|
||||||
#[serde(rename = "originaldate")]
|
#[serde(rename = "originaldate")]
|
||||||
pub original_date: Option<u16>,
|
pub original_date: Option<u16>,
|
||||||
// probably not needed. it’s just the duration but as an int
|
|
||||||
// pub time: u16,
|
|
||||||
pub format: Option<String>,
|
pub format: Option<String>,
|
||||||
#[serde(deserialize_with = "de_time_float")]
|
#[serde(deserialize_with = "de_time_float")]
|
||||||
pub duration: Duration,
|
pub duration: Option<Duration>,
|
||||||
pub label: Option<String>,
|
pub label: Option<String>,
|
||||||
pub date: Option<u16>,
|
pub date: Option<u16>,
|
||||||
#[serde(deserialize_with = "de_position")]
|
#[serde(deserialize_with = "de_position")]
|
||||||
|
@ -58,6 +57,52 @@ pub struct Position {
|
||||||
pub total_items: Option<u16>,
|
pub total_items: Option<u16>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Current status as returned by `status`.
|
||||||
|
///
|
||||||
|
/// Regarding optional `volume`:
|
||||||
|
/// The volume is None if mpd is running without local audio output,
|
||||||
|
/// i.e. on a server with no pulse or alsa output configured.
|
||||||
|
/// Output via httpd might be used instead
|
||||||
|
/// but will result in empty `volume` and `audio` fields.
|
||||||
|
#[derive(Deserialize, Clone, Debug, Default, PartialEq)]
|
||||||
|
#[serde(default)]
|
||||||
|
pub struct Status {
|
||||||
|
pub volume: Option<u8>,
|
||||||
|
#[serde(deserialize_with = "de_bint")]
|
||||||
|
pub repeat: bool,
|
||||||
|
#[serde(deserialize_with = "de_bint")]
|
||||||
|
pub random: bool,
|
||||||
|
// TODO: make enum
|
||||||
|
pub single: u8,
|
||||||
|
#[serde(deserialize_with = "de_bint")]
|
||||||
|
pub consume: bool,
|
||||||
|
// an empty playlist still has an ID
|
||||||
|
pub playlist: u32,
|
||||||
|
// mpd returns 0 if there is no current playlist
|
||||||
|
pub playlistlength: u32,
|
||||||
|
// play, stop, pause. TODO: make an enum
|
||||||
|
pub state: String,
|
||||||
|
pub song: Option<u32>,
|
||||||
|
pub songid: Option<u32>,
|
||||||
|
pub nextsong: Option<u32>,
|
||||||
|
pub nextsongid: Option<u32>,
|
||||||
|
#[serde(deserialize_with = "de_time_float")]
|
||||||
|
pub elapsed: Option<Duration>,
|
||||||
|
#[serde(deserialize_with = "de_time_float")]
|
||||||
|
pub duration: Option<Duration>,
|
||||||
|
pub bitrate: Option<u16>,
|
||||||
|
pub xfade: Option<u8>,
|
||||||
|
// 0 if unset
|
||||||
|
pub mixrampdb: f32,
|
||||||
|
pub mixrampdelay: Option<u8>,
|
||||||
|
// “audio: The format emitted by the decoder plugin during playback, format: samplerate:bits:channels.
|
||||||
|
// See Global Audio Format for a detailed explanation.”
|
||||||
|
// TODO: make struct
|
||||||
|
pub audio: Option<String>,
|
||||||
|
pub updating_db: Option<u32>,
|
||||||
|
pub error: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
/// Deserialization helpers to handle the quirks of mpd’s output.
|
/// Deserialization helpers to handle the quirks of mpd’s output.
|
||||||
mod helpers {
|
mod helpers {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -74,9 +119,9 @@ mod helpers {
|
||||||
|
|
||||||
/// Deserialize time from a float that represents the seconds.
|
/// Deserialize time from a float that represents the seconds.
|
||||||
/// mpd uses floats for the current status (e.g. time elapsed in song).
|
/// mpd uses floats for the current status (e.g. time elapsed in song).
|
||||||
pub fn de_time_float<'de, D>(deserializer: D) -> Result<Duration, D::Error>
|
pub fn de_time_float<'de, D>(deserializer: D) -> Result<Option<Duration>, D::Error>
|
||||||
where D: de::Deserializer<'de> {
|
where D: de::Deserializer<'de> {
|
||||||
f64::deserialize(deserializer).map(Duration::from_secs_f64)
|
f64::deserialize(deserializer).map(Duration::from_secs_f64).map(Some)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn de_string_or_vec<'de, D>(deserializer: D) -> Result<Vec<String>, D::Error>
|
pub fn de_string_or_vec<'de, D>(deserializer: D) -> Result<Vec<String>, D::Error>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user