1use std::time::Duration;
4
5use mecomp_storage::db::schemas::dynamic::query::Compile;
6
7#[allow(clippy::cast_possible_wrap)]
8#[must_use]
9pub fn convert_std_duration(duration: Duration) -> prost_types::Duration {
10 prost_types::Duration {
11 seconds: duration.as_secs().clamp(0, i64::MAX as u64) as i64,
12 nanos: duration.subsec_nanos().clamp(0, i32::MAX as u32) as i32,
13 }
14}
15
16impl From<crate::Song> for mecomp_storage::db::schemas::song::Song {
17 fn from(value: crate::Song) -> Self {
18 Self {
19 id: mecomp_storage::db::schemas::RecordId::from(value.id).into(),
20 title: value.title,
21 artist: value.artists.into(),
22 album_artist: value.album_artists.into(),
23 album: value.album,
24 genre: value.genres.into(),
25 runtime: value.runtime.normalized().try_into().unwrap_or_default(),
26 track: value.track,
27 disc: value.disc,
28 release_year: value.release_year,
29 extension: value.extension,
30 path: value.path.into(),
31 }
32 }
33}
34
35impl From<mecomp_storage::db::schemas::song::Song> for crate::Song {
36 fn from(value: mecomp_storage::db::schemas::song::Song) -> Self {
37 Self {
38 id: crate::RecordId::new(value.id.table(), value.id.key()),
39 title: value.title,
40 artists: value.artist.into(),
41 album_artists: value.album_artist.into(),
42 album: value.album,
43 genres: value.genre.into(),
44 runtime: convert_std_duration(value.runtime),
45 track: value.track,
46 disc: value.disc,
47 release_year: value.release_year,
48 extension: value.extension,
49 path: format!("{}", value.path.display()),
50 }
51 }
52}
53
54impl From<crate::SongBrief> for mecomp_storage::db::schemas::song::SongBrief {
55 fn from(value: crate::SongBrief) -> Self {
56 Self {
57 id: mecomp_storage::db::schemas::RecordId::from(value.id).into(),
58 title: value.title,
59 artist: value.artists.into(),
60 album_artist: value.album_artists.into(),
61 album: value.album,
62 genre: value.genres.into(),
63 runtime: value.runtime.normalized().try_into().unwrap_or_default(),
64 track: value.track,
65 disc: value.disc,
66 release_year: value.release_year,
67 path: value.path.into(),
68 }
69 }
70}
71
72impl From<mecomp_storage::db::schemas::song::SongBrief> for crate::SongBrief {
73 fn from(value: mecomp_storage::db::schemas::song::SongBrief) -> Self {
74 Self {
75 id: crate::RecordId::new(value.id.table(), value.id.key()),
76 title: value.title,
77 artists: value.artist.into(),
78 album_artists: value.album_artist.into(),
79 album: value.album,
80 genres: value.genre.into(),
81 runtime: convert_std_duration(value.runtime),
82 track: value.track,
83 disc: value.disc,
84 release_year: value.release_year,
85 path: format!("{}", value.path.display()),
86 }
87 }
88}
89
90impl From<mecomp_storage::db::schemas::song::Song> for crate::SongBrief {
91 fn from(value: mecomp_storage::db::schemas::song::Song) -> Self {
92 Self {
93 id: crate::RecordId::new(value.id.table(), value.id.key()),
94 title: value.title,
95 artists: value.artist.into(),
96 album_artists: value.album_artist.into(),
97 album: value.album,
98 genres: value.genre.into(),
99 runtime: convert_std_duration(value.runtime),
100 track: value.track,
101 disc: value.disc,
102 release_year: value.release_year,
103 path: format!("{}", value.path.display()),
104 }
105 }
106}
107
108impl From<crate::Song> for crate::SongBrief {
109 fn from(value: crate::Song) -> Self {
110 Self {
111 id: value.id,
112 title: value.title,
113 artists: value.artists,
114 album_artists: value.album_artists,
115 album: value.album,
116 genres: value.genres,
117 runtime: value.runtime,
118 track: value.track,
119 disc: value.disc,
120 release_year: value.release_year,
121 path: value.path,
122 }
123 }
124}
125
126impl From<crate::RepeatMode> for mecomp_core::state::RepeatMode {
127 fn from(value: crate::RepeatMode) -> Self {
128 match value {
129 crate::RepeatMode::None | crate::RepeatMode::Unspecified => Self::None,
130 crate::RepeatMode::One => Self::One,
131 crate::RepeatMode::All => Self::All,
132 }
133 }
134}
135
136impl From<mecomp_core::state::RepeatMode> for crate::RepeatMode {
137 fn from(val: mecomp_core::state::RepeatMode) -> Self {
138 match val {
139 mecomp_core::state::RepeatMode::None => Self::None,
140 mecomp_core::state::RepeatMode::One => Self::One,
141 mecomp_core::state::RepeatMode::All => Self::All,
142 }
143 }
144}
145
146impl From<crate::PlaybackStatus> for mecomp_core::state::Status {
147 fn from(value: crate::PlaybackStatus) -> Self {
148 match value {
149 crate::PlaybackStatus::Unspecified | crate::PlaybackStatus::Stopped => Self::Stopped,
150 crate::PlaybackStatus::Playing => Self::Playing,
151 crate::PlaybackStatus::Paused => Self::Paused,
152 }
153 }
154}
155
156impl From<mecomp_core::state::Status> for crate::PlaybackStatus {
157 fn from(val: mecomp_core::state::Status) -> Self {
158 match val {
159 mecomp_core::state::Status::Stopped => Self::Stopped,
160 mecomp_core::state::Status::Playing => Self::Playing,
161 mecomp_core::state::Status::Paused => Self::Paused,
162 }
163 }
164}
165
166impl From<crate::StateRuntime> for mecomp_core::state::StateRuntime {
167 fn from(value: crate::StateRuntime) -> Self {
168 Self {
169 seek_position: value
170 .seek_position
171 .normalized()
172 .try_into()
173 .unwrap_or_default(),
174 seek_percent: mecomp_core::state::Percent::new(value.seek_percent),
175 duration: value.duration.normalized().try_into().unwrap_or_default(),
176 }
177 }
178}
179
180impl From<mecomp_core::state::StateRuntime> for crate::StateRuntime {
181 fn from(value: mecomp_core::state::StateRuntime) -> Self {
182 Self {
183 seek_position: convert_std_duration(value.seek_position),
184 seek_percent: value.seek_percent.into_inner(),
185 duration: convert_std_duration(value.duration),
186 }
187 }
188}
189
190impl From<crate::StateAudio> for mecomp_core::state::StateAudio {
191 #[allow(clippy::cast_possible_truncation)]
192 fn from(value: crate::StateAudio) -> Self {
193 Self {
194 queue: value.queue.into_iter().map(Into::into).collect(),
195 queue_position: value.queue_position.map(|v| v as usize),
196 current_song: value.current_song.map(Into::into),
197 repeat_mode: crate::RepeatMode::try_from(value.repeat_mode)
198 .map(Into::into)
199 .unwrap_or_default(),
200 runtime: value.runtime.map(Into::into),
201 status: crate::PlaybackStatus::try_from(value.status)
202 .map(Into::into)
203 .unwrap_or_default(),
204 muted: value.muted,
205 volume: value.volume,
206 }
207 }
208}
209
210impl From<mecomp_core::state::StateAudio> for crate::StateAudio {
211 fn from(value: mecomp_core::state::StateAudio) -> Self {
212 Self {
213 queue: value.queue.into_iter().map(Into::into).collect(),
214 queue_position: value.queue_position.map(|v| v as u64),
215 current_song: value.current_song.map(Into::into),
216 repeat_mode: crate::RepeatMode::from(value.repeat_mode) as i32,
217 runtime: value.runtime.map(Into::into),
218 status: crate::PlaybackStatus::from(value.status) as i32,
219 muted: value.muted,
220 volume: value.volume,
221 }
222 }
223}
224
225impl From<mecomp_storage::db::schemas::RecordId> for crate::RecordId {
226 fn from(value: mecomp_storage::db::schemas::RecordId) -> Self {
227 Self {
228 id: value.id.to_string(),
229 tb: value.tb,
230 }
231 }
232}
233
234impl From<crate::RecordId> for mecomp_storage::db::schemas::RecordId {
235 fn from(value: crate::RecordId) -> Self {
236 Self {
237 id: mecomp_storage::db::schemas::Id::String(value.id),
238 tb: value.tb,
239 }
240 }
241}
242
243impl From<crate::SeekType> for mecomp_core::state::SeekType {
244 fn from(value: crate::SeekType) -> Self {
245 match value {
246 crate::SeekType::Unspecified | crate::SeekType::Absolute => Self::Absolute,
247 crate::SeekType::RelativeForwards => Self::RelativeForwards,
248 crate::SeekType::RelativeBackwards => Self::RelativeBackwards,
249 }
250 }
251}
252
253impl From<mecomp_core::state::SeekType> for crate::SeekType {
254 fn from(val: mecomp_core::state::SeekType) -> Self {
255 match val {
256 mecomp_core::state::SeekType::Absolute => Self::Absolute,
257 mecomp_core::state::SeekType::RelativeForwards => Self::RelativeForwards,
258 mecomp_core::state::SeekType::RelativeBackwards => Self::RelativeBackwards,
259 }
260 }
261}
262
263impl<T> From<T> for crate::Ulid
264where
265 T: Into<String>,
266{
267 fn from(value: T) -> Self {
268 Self::new(value.into())
269 }
270}
271
272impl From<crate::RecordId> for crate::Ulid {
273 fn from(value: crate::RecordId) -> Self {
274 Self { id: value.id }
275 }
276}
277
278impl From<mecomp_storage::db::schemas::artist::Artist> for crate::Artist {
279 fn from(value: mecomp_storage::db::schemas::artist::Artist) -> Self {
280 Self {
281 id: crate::RecordId::new(value.id.table(), value.id.key()),
282 name: value.name,
283 runtime: convert_std_duration(value.runtime),
284 album_count: value.album_count,
285 song_count: value.song_count,
286 }
287 }
288}
289
290impl From<mecomp_storage::db::schemas::artist::Artist> for crate::ArtistBrief {
291 fn from(value: mecomp_storage::db::schemas::artist::Artist) -> Self {
292 Self {
293 id: crate::RecordId::new(value.id.table(), value.id.key()),
294 name: value.name,
295 }
296 }
297}
298
299impl From<mecomp_storage::db::schemas::artist::ArtistBrief> for crate::ArtistBrief {
300 fn from(value: mecomp_storage::db::schemas::artist::ArtistBrief) -> Self {
301 Self {
302 id: crate::RecordId::new(value.id.table(), value.id.key()),
303 name: value.name,
304 }
305 }
306}
307
308impl From<crate::Artist> for crate::ArtistBrief {
309 fn from(value: crate::Artist) -> Self {
310 Self {
311 id: value.id,
312 name: value.name,
313 }
314 }
315}
316
317impl From<mecomp_storage::db::schemas::album::Album> for crate::Album {
318 fn from(value: mecomp_storage::db::schemas::album::Album) -> Self {
319 Self {
320 id: crate::RecordId::new(value.id.table(), value.id.key()),
321 title: value.title,
322 artists: value.artist.into(),
323 release: value.release,
324 runtime: convert_std_duration(value.runtime),
325 song_count: value.song_count,
326 discs: value.discs,
327 genres: value.genre.into(),
328 }
329 }
330}
331
332impl From<mecomp_storage::db::schemas::album::AlbumBrief> for crate::AlbumBrief {
333 fn from(value: mecomp_storage::db::schemas::album::AlbumBrief) -> Self {
334 Self {
335 id: crate::RecordId::new(value.id.table(), value.id.key()),
336 title: value.title,
337 artists: value.artist.into(),
338 release: value.release,
339 discs: value.discs,
340 genres: value.genre.into(),
341 }
342 }
343}
344
345impl From<mecomp_storage::db::schemas::album::Album> for crate::AlbumBrief {
346 fn from(value: mecomp_storage::db::schemas::album::Album) -> Self {
347 Self {
348 id: crate::RecordId::new(value.id.table(), value.id.key()),
349 title: value.title,
350 artists: value.artist.into(),
351 release: value.release,
352 discs: value.discs,
353 genres: value.genre.into(),
354 }
355 }
356}
357
358impl From<crate::Album> for crate::AlbumBrief {
359 fn from(value: crate::Album) -> Self {
360 Self {
361 id: value.id,
362 title: value.title,
363 artists: value.artists,
364 release: value.release,
365 discs: value.discs,
366 genres: value.genres,
367 }
368 }
369}
370
371impl From<mecomp_storage::db::schemas::playlist::Playlist> for crate::Playlist {
372 fn from(value: mecomp_storage::db::schemas::playlist::Playlist) -> Self {
373 Self {
374 id: crate::RecordId::new(value.id.table(), value.id.key()),
375 name: value.name,
376 runtime: convert_std_duration(value.runtime),
377 song_count: value.song_count,
378 }
379 }
380}
381impl From<mecomp_storage::db::schemas::playlist::PlaylistBrief> for crate::PlaylistBrief {
382 fn from(value: mecomp_storage::db::schemas::playlist::PlaylistBrief) -> Self {
383 Self {
384 id: crate::RecordId::new(value.id.table(), value.id.key()),
385 name: value.name,
386 }
387 }
388}
389impl From<mecomp_storage::db::schemas::playlist::Playlist> for crate::PlaylistBrief {
390 fn from(value: mecomp_storage::db::schemas::playlist::Playlist) -> Self {
391 Self {
392 id: crate::RecordId::new(value.id.table(), value.id.key()),
393 name: value.name,
394 }
395 }
396}
397
398impl From<crate::Playlist> for crate::PlaylistBrief {
399 fn from(value: crate::Playlist) -> Self {
400 Self {
401 id: value.id,
402 name: value.name,
403 }
404 }
405}
406
407impl From<mecomp_storage::db::schemas::collection::Collection> for crate::Collection {
408 fn from(value: mecomp_storage::db::schemas::collection::Collection) -> Self {
409 Self {
410 id: crate::RecordId::new(value.id.table(), value.id.key()),
411 name: value.name,
412 runtime: convert_std_duration(value.runtime),
413 song_count: value.song_count,
414 }
415 }
416}
417
418impl From<mecomp_storage::db::schemas::collection::CollectionBrief> for crate::CollectionBrief {
419 fn from(value: mecomp_storage::db::schemas::collection::CollectionBrief) -> Self {
420 Self {
421 id: crate::RecordId::new(value.id.table(), value.id.key()),
422 name: value.name,
423 }
424 }
425}
426
427impl From<crate::Collection> for crate::CollectionBrief {
428 fn from(value: crate::Collection) -> Self {
429 Self {
430 id: value.id,
431 name: value.name,
432 }
433 }
434}
435
436impl From<mecomp_storage::db::schemas::dynamic::DynamicPlaylist> for crate::DynamicPlaylist {
437 fn from(value: mecomp_storage::db::schemas::dynamic::DynamicPlaylist) -> Self {
438 Self {
439 id: crate::RecordId::new(value.id.table(), value.id.key()),
440 name: value.name,
441 query: value.query.compile_for_storage(),
442 }
443 }
444}