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