librespot_metadata/
track.rs1use std::{
2 fmt::Debug,
3 ops::{Deref, DerefMut},
4};
5
6use uuid::Uuid;
7
8use crate::{
9 Album, Metadata, RequestResult,
10 artist::{Artists, ArtistsWithRole},
11 audio::file::AudioFiles,
12 availability::Availabilities,
13 content_rating::ContentRatings,
14 external_id::ExternalIds,
15 restriction::Restrictions,
16 sale_period::SalePeriods,
17 util::{impl_deref_wrapped, impl_try_from_repeated},
18};
19
20use librespot_core::{Error, Session, SpotifyId, date::Date};
21use librespot_protocol as protocol;
22
23#[derive(Debug, Clone)]
24pub struct Track {
25 pub id: SpotifyId,
26 pub name: String,
27 pub album: Album,
28 pub artists: Artists,
29 pub number: i32,
30 pub disc_number: i32,
31 pub duration: i32,
32 pub popularity: i32,
33 pub is_explicit: bool,
34 pub external_ids: ExternalIds,
35 pub restrictions: Restrictions,
36 pub files: AudioFiles,
37 pub alternatives: Tracks,
38 pub sale_periods: SalePeriods,
39 pub previews: AudioFiles,
40 pub tags: Vec<String>,
41 pub earliest_live_timestamp: Date,
42 pub has_lyrics: bool,
43 pub availability: Availabilities,
44 pub licensor: Uuid,
45 pub language_of_performance: Vec<String>,
46 pub content_ratings: ContentRatings,
47 pub original_title: String,
48 pub version_title: String,
49 pub artists_with_role: ArtistsWithRole,
50}
51
52#[derive(Debug, Clone, Default)]
53pub struct Tracks(pub Vec<SpotifyId>);
54
55impl_deref_wrapped!(Tracks, Vec<SpotifyId>);
56
57#[async_trait]
58impl Metadata for Track {
59 type Message = protocol::metadata::Track;
60
61 async fn request(session: &Session, track_id: &SpotifyId) -> RequestResult {
62 session.spclient().get_track_metadata(track_id).await
63 }
64
65 fn parse(msg: &Self::Message, _: &SpotifyId) -> Result<Self, Error> {
66 Self::try_from(msg)
67 }
68}
69
70impl TryFrom<&<Self as Metadata>::Message> for Track {
71 type Error = librespot_core::Error;
72 fn try_from(track: &<Self as Metadata>::Message) -> Result<Self, Self::Error> {
73 Ok(Self {
74 id: track.try_into()?,
75 name: track.name().to_owned(),
76 album: track.album.get_or_default().try_into()?,
77 artists: track.artist.as_slice().try_into()?,
78 number: track.number(),
79 disc_number: track.disc_number(),
80 duration: track.duration(),
81 popularity: track.popularity(),
82 is_explicit: track.explicit(),
83 external_ids: track.external_id.as_slice().into(),
84 restrictions: track.restriction.as_slice().into(),
85 files: track.file.as_slice().into(),
86 alternatives: track.alternative.as_slice().try_into()?,
87 sale_periods: track.sale_period.as_slice().try_into()?,
88 previews: track.preview.as_slice().into(),
89 tags: track.tags.to_vec(),
90 earliest_live_timestamp: Date::from_timestamp_ms(track.earliest_live_timestamp())?,
91 has_lyrics: track.has_lyrics(),
92 availability: track.availability.as_slice().try_into()?,
93 licensor: Uuid::from_slice(track.licensor.uuid()).unwrap_or_else(|_| Uuid::nil()),
94 language_of_performance: track.language_of_performance.to_vec(),
95 content_ratings: track.content_rating.as_slice().into(),
96 original_title: track.original_title().to_owned(),
97 version_title: track.version_title().to_owned(),
98 artists_with_role: track.artist_with_role.as_slice().try_into()?,
99 })
100 }
101}
102
103impl_try_from_repeated!(<Track as Metadata>::Message, Tracks);