chilen_ipc/library.rs
1use std::{path::PathBuf, time::Duration};
2
3use serde::{Deserialize, Serialize};
4
5// TODO: Add more tags for this
6/// Struct representing a track from the [music library](MusicLibrary).
7#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
8pub struct Track {
9 /// The path to the audio file.
10 pub path: PathBuf,
11 /// The path to the extracted cover file.
12 pub cover_path: Option<PathBuf>,
13 /// The duration of the track.
14 pub duration: Duration,
15 // TODO: Add an option to split the tag with separators like ",", ";", "/", etc.
16 /// The track artist.
17 pub artist: Option<String>,
18 /// The track title.
19 pub title: Option<String>,
20 /// The track album.
21 pub album: Option<String>,
22 // TODO: Same as with artist
23 /// The track genre.
24 pub genre: Option<String>,
25 // TODO: Add easy access to synced lyrics
26 /// Possibly synchronized lyrics text.
27 pub lyrics: Option<String>,
28 /// Contents of the comment tag.
29 pub comment: Option<String>,
30 pub track: Option<u32>,
31 pub track_total: Option<u32>,
32 pub disc: Option<u32>,
33 pub disc_total: Option<u32>,
34 /// Release year.
35 pub year: Option<u32>,
36}
37
38impl std::fmt::Display for Track {
39 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
40 write!(
41 f,
42 "{} - {} ({})",
43 self.artist.clone().unwrap_or(String::from("Unknown")),
44 self.title.clone().unwrap_or(String::from("Unknown")),
45 self.path.to_string_lossy()
46 )
47 }
48}
49
50/// Struct representing a playlist in the [music library](MusicLibrary).
51#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
52pub struct Playlist {
53 /// The name of the playlist.
54 ///
55 /// Playlist names are unique.
56 pub name: String,
57 /// The content of the playlist.
58 ///
59 /// All tracks must already be in the [music library](MusicLibrary). If a track is removed from
60 /// the library (eg. by removing an audio file from the music directory and reloading the
61 /// library), it will also be removed from all the playlists.
62 pub tracks: Vec<Track>,
63}
64
65/// Struct representing the contents of the music library.
66#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
67pub struct MusicLibrary {
68 /// The list of playlists in the music library.
69 pub playlists: Vec<Playlist>,
70 /// The list of all tracks in the music library.
71 pub tracks: Vec<Track>,
72}
73
74/// Subcommand of [`Command`](crate::Command) for managing the music library.
75///
76/// The expected response may be different depending on the command sent. If it isn't specified in
77/// the variant documentation, assume [`Response::Ok`](crate::Response::Ok) is the expected
78/// response.
79#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
80pub enum LibraryCommand {
81 /// Create a new playlist, optionally with some tracks in it.
82 NewPlaylist {
83 /// The name for the new playlist. Must not already exist in the music library.
84 ///
85 /// If a playlist with the specified name already exists,
86 /// [`Error::PlaylistExists`](crate::Error::PlaylistExists) will be returned, and no
87 /// changes to the [music library](MusicLibrary) will be made.
88 name: String,
89 /// Optional list of paths to tracks to be added to the playlist.
90 ///
91 /// This command will fail if any of the tracks are not registered in the
92 /// [music library](MusicLibrary), or if the list contains duplicates.
93 tracks: Option<Vec<PathBuf>>,
94 },
95 /// Import a playlist from an M3U8 file.
96 PlaylistFromM3U8 {
97 /// The name for the imported playlist. Must not already exist in the music library.
98 ///
99 /// If left unspecified, it will be derived from the name set in the M3U8 playlist.
100 ///
101 /// If a playlist with the specified name already exists,
102 /// [`Error::PlaylistExists`](crate::Error::PlaylistExists) will be returned, and no changes
103 /// to the [music library](MusicLibrary) will be made.
104 name: Option<String>,
105 /// The path to the M3U8 file to import.
106 m3u8_file: PathBuf,
107 },
108 /// Export a playlist from the music library as an M3U8 file.
109 ExportPlaylistToM3U {
110 /// The name of the playlist to export.
111 ///
112 /// /// If no such playlist exists in the music library,
113 /// [`Error::UnknownPlaylist`](crate::Error::UnknownPlaylist) will be returned, and no
114 /// changes to the [music library](MusicLibrary) will be made.
115 name: String,
116 /// File path to which export the playlist file.
117 path: PathBuf,
118 },
119 /// Delete playlists from the music library.
120 DeletePlaylists {
121 /// List of the playlists to delete.
122 ///
123 /// If any of the provided playlists don't exist in the music library,
124 /// [`Error::UnkownPlaylist`](crate::Error::UnknownPlaylist) will be returned, and no changes to the
125 /// [music library](MusicLibrary) will be made.
126 names: Vec<String>,
127 },
128 /// Add tracks to an already existing playlist.
129 AddTracksToPlaylist {
130 /// The name of the playlist to add tracks to.
131 ///
132 /// If no such playlist exists in the music library,
133 /// [`Error::UnknownPlaylist`](crate::Error::UnknownPlaylist) will be returned, and no
134 /// changes to the [music library](MusicLibrary) will be made.
135 name: String,
136 /// List of paths to tracks to add to the playlist.
137 ///
138 /// **Note:** the daemon will return an error if any of the tracks are not registered in
139 /// the music library or if the list contains duplicates.
140 tracks: Vec<PathBuf>,
141 },
142 /// Remove tracks from a playlist.
143 RemoveTracksFromPlaylist {
144 /// The name of the playlist to remove tracks from.
145 ///
146 /// If a playlist with the specified name doesn't exist in the music library,
147 /// [`Error::UnknownPlaylist`](crate::Error::UnknownPlaylist) will be returned, and no
148 /// changes to the [music library](MusicLibrary) will be made.
149 name: String,
150 /// The list of track indices in the playlist to remove.
151 ///
152 /// Eg. to remove the first track you would pass `[0]`, to remove the first three
153 /// `[0, 1, 2]`, etc.
154 ///
155 /// If one or more of the indices is out of range,
156 /// [`Error::IndexOutOfBounds`](crate::Error::IndexOutOfBounds) will be returned, and no
157 /// changes to the [music library](MusicLibrary) will be made.
158 ids: Vec<usize>,
159 },
160 /// Get the contents of the [music library](MusicLibrary).
161 ///
162 /// The daemon will respond to this with [`Response::Library`](crate::Response::Library) if
163 /// successful.
164 GetLibrary,
165 /// Reload the library and rebuild the cache ignoring already cached covers.
166 ///
167 /// Will take more time than just reloading the cache.
168 Rebuild,
169 /// Reload the library using cached data if possible.
170 ///
171 /// This can be used to discover newly added tracks.
172 Reload,
173}