music_player_entity/
track.rs

1use music_player_types::types::{RemoteTrackUrl, Song, Track as TrackType};
2use sea_orm::{entity::prelude::*, ActiveValue};
3use serde::{Deserialize, Serialize};
4use upnp_client::types::Metadata;
5
6use crate::{album, artist, select_result};
7
8#[derive(Clone, Debug, Default, PartialEq, DeriveEntityModel, Serialize, Deserialize)]
9#[sea_orm(table_name = "track")]
10pub struct Model {
11    #[sea_orm(primary_key, auto_increment = false)]
12    pub id: String,
13    pub title: String,
14    pub artist: String,
15    pub genre: String,
16    pub year: Option<u32>,
17    pub track: Option<u32>,
18    pub bitrate: Option<u32>,
19    pub sample_rate: Option<u32>,
20    pub bit_depth: Option<u8>,
21    pub channels: Option<u8>,
22    pub duration: Option<f32>,
23    pub uri: String,
24    pub album_id: Option<String>,
25    pub artist_id: Option<String>,
26    #[sea_orm(ignore)]
27    pub artists: Vec<artist::Model>,
28    #[sea_orm(ignore)]
29    pub album: album::Model,
30}
31
32#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
33pub enum Relation {
34    #[sea_orm(
35        belongs_to = "super::album::Entity",
36        from = "Column::AlbumId",
37        to = "super::album::Column::Id"
38    )]
39    Album,
40    #[sea_orm(
41        belongs_to = "super::artist::Entity",
42        from = "Column::ArtistId",
43        to = "super::artist::Column::Id"
44    )]
45    Artist,
46}
47
48impl Related<super::album::Entity> for Entity {
49    fn to() -> RelationDef {
50        Relation::Album.def()
51    }
52}
53
54impl Related<super::playlist::Entity> for Entity {
55    fn to() -> RelationDef {
56        super::playlist_tracks::Relation::Playlist.def()
57    }
58
59    fn via() -> Option<RelationDef> {
60        Some(super::playlist_tracks::Relation::Track.def().rev())
61    }
62}
63
64impl Related<super::artist::Entity> for Entity {
65    fn to() -> RelationDef {
66        super::artist_tracks::Relation::Artist.def()
67    }
68
69    fn via() -> Option<RelationDef> {
70        Some(super::artist_tracks::Relation::Track.def().rev())
71    }
72}
73
74impl ActiveModelBehavior for ActiveModel {}
75
76#[derive(Debug)]
77pub struct TrackToAlbum;
78
79impl Linked for TrackToAlbum {
80    type FromEntity = super::track::Entity;
81    type ToEntity = super::album::Entity;
82
83    fn link(&self) -> Vec<RelationDef> {
84        vec![
85            super::album::Relation::Track.def().rev(),
86            super::track::Relation::Album.def(),
87        ]
88    }
89}
90
91#[derive(Debug)]
92pub struct TrackToArtist;
93
94impl Linked for TrackToArtist {
95    type FromEntity = super::track::Entity;
96    type ToEntity = super::artist::Entity;
97
98    fn link(&self) -> Vec<RelationDef> {
99        vec![
100            super::artist_tracks::Relation::Track.def().rev(),
101            super::artist_tracks::Relation::Artist.def(),
102        ]
103    }
104}
105
106#[derive(Debug)]
107pub struct TrackToPlaylist;
108
109impl Linked for TrackToPlaylist {
110    type FromEntity = super::track::Entity;
111    type ToEntity = super::playlist::Entity;
112
113    fn link(&self) -> Vec<RelationDef> {
114        vec![
115            super::playlist_tracks::Relation::Track.def().rev(),
116            super::playlist_tracks::Relation::Playlist.def(),
117        ]
118    }
119}
120
121impl From<&Song> for ActiveModel {
122    fn from(song: &Song) -> Self {
123        let id = format!("{:x}", md5::compute(song.uri.as_ref().unwrap()));
124        Self {
125            id: ActiveValue::set(id),
126            artist: ActiveValue::Set(song.artist.clone()),
127            title: ActiveValue::Set(song.title.clone()),
128            genre: ActiveValue::Set(song.genre.clone()),
129            year: ActiveValue::Set(song.year),
130            track: ActiveValue::Set(song.track),
131            bitrate: ActiveValue::Set(song.bitrate),
132            sample_rate: ActiveValue::Set(song.sample_rate),
133            bit_depth: ActiveValue::Set(song.bit_depth),
134            channels: ActiveValue::Set(song.channels),
135            duration: ActiveValue::Set(Some(song.duration.as_secs_f32())),
136            uri: ActiveValue::Set(song.uri.clone().unwrap_or_default()),
137            album_id: ActiveValue::Set(Some(format!(
138                "{:x}",
139                md5::compute(format!("{}", song.album))
140            ))),
141            artist_id: ActiveValue::Set(Some(format!(
142                "{:x}",
143                md5::compute(song.album_artist.to_owned())
144            ))),
145        }
146    }
147}
148
149impl From<select_result::PlaylistTrack> for Model {
150    fn from(playlist_track: select_result::PlaylistTrack) -> Self {
151        Self {
152            id: playlist_track.track_id,
153            title: playlist_track.track_title,
154            artist: playlist_track.track_artist,
155            uri: playlist_track.track_uri,
156            album_id: Some(playlist_track.album_id.clone()),
157            artist_id: Some(playlist_track.artist_id.clone()),
158            duration: Some(playlist_track.track_duration),
159            album: album::Model {
160                id: playlist_track.album_id,
161                title: playlist_track.album_title,
162                cover: playlist_track.album_cover,
163                ..Default::default()
164            },
165            artists: vec![artist::Model {
166                id: playlist_track.artist_id,
167                name: playlist_track.artist_name,
168                ..Default::default()
169            }],
170            ..Default::default()
171        }
172    }
173}
174
175impl From<TrackType> for Model {
176    fn from(track: TrackType) -> Self {
177        let track_album = track.album.unwrap();
178        Self {
179            id: track.id,
180            title: track.title,
181            artist: track.artist,
182            uri: track.uri,
183            album_id: Some(track_album.id.clone()),
184            artist_id: if track.artists.is_empty() {
185                None
186            } else {
187                Some(track.artists[0].id.clone())
188            },
189            duration: track.duration,
190            album: album::Model {
191                id: track_album.id,
192                title: track_album.title,
193                cover: track_album.cover,
194                year: track_album.year,
195                ..Default::default()
196            },
197            artists: track.artists.into_iter().map(Into::into).collect(),
198            ..Default::default()
199        }
200    }
201}
202
203impl Into<TrackType> for Model {
204    fn into(self) -> TrackType {
205        TrackType {
206            id: self.id,
207            title: self.title,
208            artist: self.artist,
209            uri: self.uri,
210            duration: self.duration,
211            album: Some(self.album.into()),
212            artists: self.artists.into_iter().map(Into::into).collect(),
213            ..Default::default()
214        }
215    }
216}
217
218impl Into<Metadata> for Model {
219    fn into(self) -> Metadata {
220        Metadata {
221            title: self.title,
222            artist: Some(self.artist),
223            album: Some(self.album.title),
224            album_art_uri: self.album.cover,
225            ..Default::default()
226        }
227    }
228}
229
230impl RemoteTrackUrl for Model {
231    fn with_remote_track_url(&self, base_url: &str) -> Self {
232        Self {
233            uri: format!("{}/tracks/{}", base_url, self.id),
234            ..self.clone()
235        }
236    }
237}