1use std::{fmt, path::PathBuf, str::FromStr};
2
3use librespot_protocol::devices::DeviceType as ProtoDeviceType;
4use url::Url;
5
6pub(crate) const KEYMASTER_CLIENT_ID: &str = "65b708073fc0480ea92a077233ca87bd";
7pub(crate) const ANDROID_CLIENT_ID: &str = "9a8d2f0ce77a4e248bb71fefcb557637";
8pub(crate) const IOS_CLIENT_ID: &str = "58bd3c95768941ea9eb4350aaa033eb3";
9
10pub const OS: &str = std::env::consts::OS;
15
16pub fn os_version() -> String {
21 sysinfo::System::os_version().unwrap_or("0".into())
22}
23
24#[derive(Clone, Debug)]
25pub struct SessionConfig {
26 pub client_id: String,
27 pub device_id: String,
28 pub proxy: Option<Url>,
29 pub ap_port: Option<u16>,
30 pub tmp_dir: PathBuf,
31 pub autoplay: Option<bool>,
32}
33
34impl SessionConfig {
35 pub(crate) fn default_for_os(os: &str) -> Self {
36 let device_id = uuid::Uuid::new_v4().as_hyphenated().to_string();
37 let client_id = match os {
38 "android" => ANDROID_CLIENT_ID,
39 "ios" => IOS_CLIENT_ID,
40 _ => KEYMASTER_CLIENT_ID,
41 }
42 .to_owned();
43
44 Self {
45 client_id,
46 device_id,
47 proxy: None,
48 ap_port: None,
49 tmp_dir: std::env::temp_dir(),
50 autoplay: None,
51 }
52 }
53}
54
55impl Default for SessionConfig {
56 fn default() -> Self {
57 Self::default_for_os(OS)
58 }
59}
60
61#[derive(Clone, Copy, Debug, Hash, PartialOrd, Ord, PartialEq, Eq, Default)]
62pub enum DeviceType {
63 Unknown = 0,
64 Computer = 1,
65 Tablet = 2,
66 Smartphone = 3,
67 #[default]
68 Speaker = 4,
69 Tv = 5,
70 Avr = 6,
71 Stb = 7,
72 AudioDongle = 8,
73 GameConsole = 9,
74 CastAudio = 10,
75 CastVideo = 11,
76 Automobile = 12,
77 Smartwatch = 13,
78 Chromebook = 14,
79 UnknownSpotify = 100,
80 CarThing = 101,
81 Observer = 102,
82}
83
84impl FromStr for DeviceType {
85 type Err = ();
86 fn from_str(s: &str) -> Result<Self, Self::Err> {
87 use self::DeviceType::*;
88 match s.to_lowercase().as_ref() {
89 "computer" => Ok(Computer),
90 "tablet" => Ok(Tablet),
91 "smartphone" => Ok(Smartphone),
92 "speaker" => Ok(Speaker),
93 "tv" => Ok(Tv),
94 "avr" => Ok(Avr),
95 "stb" => Ok(Stb),
96 "audiodongle" => Ok(AudioDongle),
97 "gameconsole" => Ok(GameConsole),
98 "castaudio" => Ok(CastAudio),
99 "castvideo" => Ok(CastVideo),
100 "automobile" => Ok(Automobile),
101 "smartwatch" => Ok(Smartwatch),
102 "chromebook" => Ok(Chromebook),
103 "carthing" => Ok(CarThing),
104 _ => Err(()),
105 }
106 }
107}
108
109impl From<&DeviceType> for &str {
110 fn from(d: &DeviceType) -> &'static str {
111 use self::DeviceType::*;
112 match d {
113 Unknown => "Unknown",
114 Computer => "Computer",
115 Tablet => "Tablet",
116 Smartphone => "Smartphone",
117 Speaker => "Speaker",
118 Tv => "TV",
119 Avr => "AVR",
120 Stb => "STB",
121 AudioDongle => "AudioDongle",
122 GameConsole => "GameConsole",
123 CastAudio => "CastAudio",
124 CastVideo => "CastVideo",
125 Automobile => "Automobile",
126 Smartwatch => "Smartwatch",
127 Chromebook => "Chromebook",
128 UnknownSpotify => "UnknownSpotify",
129 CarThing => "CarThing",
130 Observer => "Observer",
131 }
132 }
133}
134
135impl From<DeviceType> for &str {
136 fn from(d: DeviceType) -> &'static str {
137 (&d).into()
138 }
139}
140
141impl fmt::Display for DeviceType {
142 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
143 let str: &str = self.into();
144 f.write_str(str)
145 }
146}
147
148impl From<DeviceType> for ProtoDeviceType {
149 fn from(value: DeviceType) -> Self {
150 match value {
151 DeviceType::Unknown => ProtoDeviceType::UNKNOWN,
152 DeviceType::Computer => ProtoDeviceType::COMPUTER,
153 DeviceType::Tablet => ProtoDeviceType::TABLET,
154 DeviceType::Smartphone => ProtoDeviceType::SMARTPHONE,
155 DeviceType::Speaker => ProtoDeviceType::SPEAKER,
156 DeviceType::Tv => ProtoDeviceType::TV,
157 DeviceType::Avr => ProtoDeviceType::AVR,
158 DeviceType::Stb => ProtoDeviceType::STB,
159 DeviceType::AudioDongle => ProtoDeviceType::AUDIO_DONGLE,
160 DeviceType::GameConsole => ProtoDeviceType::GAME_CONSOLE,
161 DeviceType::CastAudio => ProtoDeviceType::CAST_VIDEO,
162 DeviceType::CastVideo => ProtoDeviceType::CAST_AUDIO,
163 DeviceType::Automobile => ProtoDeviceType::AUTOMOBILE,
164 DeviceType::Smartwatch => ProtoDeviceType::SMARTWATCH,
165 DeviceType::Chromebook => ProtoDeviceType::CHROMEBOOK,
166 DeviceType::UnknownSpotify => ProtoDeviceType::UNKNOWN_SPOTIFY,
167 DeviceType::CarThing => ProtoDeviceType::CAR_THING,
168 DeviceType::Observer => ProtoDeviceType::OBSERVER,
169 }
170 }
171}