1use std::{
2 fmt::{Display, Formatter, Result},
3 time::{SystemTime, UNIX_EPOCH},
4};
5
6#[cfg(feature = "artwork")]
7use image::DynamicImage;
8use objc2::{rc::Retained, runtime::AnyObject};
9
10pub type Id = *const AnyObject;
11
12#[derive(Debug, Clone)]
13pub enum Number {
14 Signed(i64),
15 Unsigned(u64),
16 Floating(f64),
17}
18
19impl Display for Number {
20 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
21 match self {
22 Number::Signed(i) => write!(f, "{}", i),
23 Number::Unsigned(u) => write!(f, "{}", u),
24 Number::Floating(fl) => write!(f, "{}", fl),
25 }
26 }
27}
28
29#[derive(Debug, Clone)]
30pub enum InfoTypes {
31 String(String),
32 SystemTime(SystemTime),
33 Data(Vec<u8>),
34 Number(Number),
35 Unsupported,
36}
37
38impl Display for InfoTypes {
39 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
40 match self {
41 InfoTypes::String(s) => write!(f, "{}", s),
42 InfoTypes::SystemTime(time) => match time.duration_since(UNIX_EPOCH) {
43 Ok(duration) => write!(f, "{} seconds since UNIX_EPOCH", duration.as_secs()),
44 Err(_) => write!(f, "Time is before UNIX_EPOCH"),
45 },
46 InfoTypes::Data(data) => write!(f, "[{} bytes of data]", data.len()),
47 InfoTypes::Number(num) => write!(f, "{}", num),
48 InfoTypes::Unsupported => write!(f, "Unsupported"),
49 }
50 }
51}
52
53#[derive(Debug, Clone)]
54pub enum Command {
55 Play = 0,
56 Pause = 1,
57 TogglePlayPause = 2,
58 Stop = 3,
59 NextTrack = 4,
60 PreviousTrack = 5,
61 ToggleShuffle = 6,
62 ToggleRepeat = 7,
63 StartForwardSeek = 8,
64 EndForwardSeek = 9,
65 StartBackwardSeek = 10,
66 EndBackwardSeek = 11,
67 GoBackFifteenSeconds = 12,
68 SkipFifteenSeconds = 13,
69}
70
71impl Into<i32> for Command {
72 fn into(self) -> i32 {
73 self as i32
74 }
75}
76
77#[derive(Debug, Clone)]
78pub enum Notification {
79 NowPlayingInfoDidChange,
80 NowPlayingPlaybackQueueDidChange,
81 NowPlayingApplicationDidChange,
82 NowPlayingApplicationIsPlayingDidChange,
83 PickableRoutesDidChange,
84 RouteStatusDidChange,
85 NowPlayingPlaybackQueueChanged,
86 PlaybackQueueContentItemsChanged,
87 NowPlayingApplicationClientStateDidChange,
88}
89
90pub type Observer = Retained<AnyObject>;
91
92impl Notification {
93 pub fn as_str(&self) -> &'static str {
94 match self {
95 Notification::NowPlayingInfoDidChange => {
96 "kMRMediaRemoteNowPlayingInfoDidChangeNotification"
97 }
98 Notification::NowPlayingPlaybackQueueDidChange => {
99 "kMRMediaRemoteNowPlayingPlaybackQueueDidChangeNotification"
100 }
101 Notification::NowPlayingApplicationDidChange => {
102 "kMRMediaRemoteNowPlayingApplicationDidChangeNotification"
103 }
104 Notification::NowPlayingApplicationIsPlayingDidChange => {
105 "kMRMediaRemoteNowPlayingApplicationIsPlayingDidChangeNotification"
106 }
107 Notification::PickableRoutesDidChange => {
108 "kMRMediaRemotePickableRoutesDidChangeNotification"
109 }
110 Notification::RouteStatusDidChange => "kMRMediaRemoteRouteStatusDidChangeNotification",
111 Notification::NowPlayingPlaybackQueueChanged => {
112 "kMRNowPlayingPlaybackQueueChangedNotification"
113 }
114 Notification::PlaybackQueueContentItemsChanged => {
115 "kMRPlaybackQueueContentItemsChangedNotification"
116 }
117 Notification::NowPlayingApplicationClientStateDidChange => {
118 "kMRMediaRemoteNowPlayingApplicationClientStateDidChange"
119 }
120 }
121 }
122}
123
124#[derive(Debug, Clone)]
125pub struct BundleInfo {
126 pub name: String,
127 #[cfg(feature = "artwork")]
128 pub icon: DynamicImage,
129}
130
131#[derive(PartialEq, Debug, Clone)]
132pub struct NowPlayingInfo {
133 pub is_playing: Option<bool>,
134
135 pub title: Option<String>,
136 pub artist: Option<String>,
137 pub album: Option<String>,
138 #[cfg(feature = "artwork")]
139 pub album_cover: Option<DynamicImage>,
140 pub elapsed_time: Option<f64>,
141 pub duration: Option<f64>,
142 pub playback_rate: Option<f64>,
143 pub info_update_time: Option<SystemTime>,
144
145 pub bundle_id: Option<String>,
146 pub bundle_name: Option<String>,
147 #[cfg(feature = "artwork")]
148 pub bundle_icon: Option<DynamicImage>,
149}