Skip to main content

tanuki_common/capabilities/
media.rs

1use alloc::{string::String, vec::Vec};
2
3use serde::{Deserialize, Serialize};
4
5use crate::{Property, property};
6
7pub trait MediaProperty: Property {}
8
9#[property(MediaProperty, State, key = "capabilities")]
10#[derive(Default)]
11#[non_exhaustive]
12pub struct MediaCapabilities {
13    pub play: bool,
14    pub pause: bool,
15    pub stop: bool,
16    pub next: bool,
17    pub previous: bool,
18    pub seek: bool,
19    pub repeat: bool,
20    pub shuffle: bool,
21}
22
23#[property(MediaProperty, State, key = "state")]
24#[derive(Default)]
25#[non_exhaustive]
26pub struct MediaState {
27    pub status: MediaStatus,
28    pub duration_ms: Option<u64>,
29    pub position_ms: Option<MediaPosition>,
30    pub repeat: Repeat,
31    pub shuffle: bool,
32    pub info: MediaInfo,
33    pub message: Option<String>,
34}
35
36#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
37#[serde(rename_all = "snake_case")]
38pub enum MediaStatus {
39    Playing,
40    Paused,
41    Stopped,
42    Buffering,
43    Idle,
44    #[default]
45    Unknown,
46}
47
48#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
49pub struct MediaPosition {
50    pub position_ms: i64,
51    pub timestamp_ms: i64,
52    pub rate: f32,
53}
54
55impl MediaPosition {
56    pub fn current_position(&self, current_timestamp_ms: i64) -> i64 {
57        let elapsed_ms = ((current_timestamp_ms - self.timestamp_ms) as f32 * self.rate) as i64;
58        self.position_ms + elapsed_ms
59    }
60}
61
62#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
63#[serde(rename_all = "snake_case")]
64pub enum Repeat {
65    #[default]
66    Off,
67    One,
68    All,
69}
70
71#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
72#[non_exhaustive]
73pub struct MediaInfo {
74    pub title: Option<String>,
75    pub artists: Vec<String>,
76    pub album: Option<String>,
77    pub track_number: Option<u32>,
78    pub disc_number: Option<u32>,
79    pub genre: Option<String>,
80    pub artwork_url: Option<String>,
81    pub url: Option<String>,
82    pub live: bool,
83}
84
85#[property(MediaProperty, Command, key = "command")]
86#[serde(tag = "type", rename_all = "snake_case")]
87#[non_exhaustive]
88pub enum MediaCommand {
89    Play,
90    Pause,
91    PlayPause,
92    Stop,
93    Next,
94    Previous,
95    Seek { position_ms: u64 },
96    SetRepeat { repeat: Repeat },
97    SetShuffle { shuffle: bool },
98}