1
use std::str::FromStr;
2

            
3
use serde::{Deserialize, Serialize};
4

            
5
pub type SongPosition = u32;
6

            
7
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
8
pub enum AbsouluteRelativeSongPosition {
9
    Absolute(SongPosition),
10
    RelativePlus(SongPosition),
11
    RelativeMinus(SongPosition),
12
}
13

            
14
impl FromStr for AbsouluteRelativeSongPosition {
15
    type Err = ();
16

            
17
    fn from_str(s: &str) -> Result<Self, Self::Err> {
18
        Ok(match s {
19
            s if s.starts_with('+') => Self::RelativePlus(s[1..].parse().map_err(|_| ())?),
20
            s if s.starts_with('-') => Self::RelativeMinus(s[1..].parse().map_err(|_| ())?),
21
            s => Self::Absolute(s.parse().map_err(|_| ())?),
22
        })
23
    }
24
}
25

            
26
pub type SongId = u32;
27
pub type Seconds = u32;
28
pub type TimeWithFractions = f64;
29

            
30
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
31
pub enum OneOrRange {
32
    One(SongPosition),
33
    Range(SongPosition, SongPosition),
34
}
35

            
36
impl FromStr for OneOrRange {
37
    type Err = ();
38

            
39
    fn from_str(s: &str) -> Result<Self, Self::Err> {
40
        let mut parts = s.split(':');
41
        let start = parts.next().ok_or(())?.parse().map_err(|_| ())?;
42
        Ok(match parts.next() {
43
            Some(end) => Self::Range(start, end.parse().map_err(|_| ())?),
44
            None => Self::One(start),
45
        })
46
    }
47
}
48

            
49
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
50
pub struct WindowRange {
51
    pub start: SongPosition,
52
    pub end: Option<SongPosition>,
53
}
54

            
55
impl FromStr for WindowRange {
56
    type Err = ();
57

            
58
    fn from_str(s: &str) -> Result<Self, Self::Err> {
59
        let mut parts = s.split(':');
60
        let start = parts.next().ok_or(())?.parse().map_err(|_| ())?;
61
        let end = parts.next().map(|s| s.parse().map_err(|_| ()));
62
        Ok(Self {
63
            start,
64
            end: end.transpose()?,
65
        })
66
    }
67
}
68

            
69
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
70
pub struct TimeInterval {
71
    pub start: Option<TimeWithFractions>,
72
    pub end: Option<TimeWithFractions>,
73
}
74

            
75
impl FromStr for TimeInterval {
76
    type Err = ();
77

            
78
    fn from_str(s: &str) -> Result<Self, Self::Err> {
79
        let mut parts = s.split(':');
80
        let start = parts.next().map(|s| s.parse().map_err(|_| ()));
81
        let end = parts.next().map(|s| s.parse().map_err(|_| ()));
82
        Ok(Self {
83
            start: start.transpose()?,
84
            end: end.transpose()?,
85
        })
86
    }
87
}
88

            
89
pub type Priority = u8;
90
pub type PlaylistName = String;
91
pub type Offset = u32;
92

            
93
// TODO: use a proper types
94
pub type TagName = String;
95
pub type TagValue = String;
96
pub type Uri = String;
97
pub type Path = String;
98
pub type Sort = String;
99
pub type Version = String;
100
pub type Feature = String;
101
pub type PartitionName = String;
102
pub type AudioOutputId = String;
103
pub type ChannelName = String;
104
pub type StickerType = String;
105

            
106
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
107
pub enum Tag {
108
    /// The artist name. Its meaning is not well-defined; see “composer” and “performer” for more specific tags.
109
    Artist(String),
110
    /// Same as artist, but for sorting. This usually omits prefixes such as “The”.
111
    ArtistSort(String),
112
    /// The album name.
113
    Album(String),
114
    /// Same as album, but for sorting.
115
    AlbumSort(String),
116
    /// On multi-artist albums, this is the artist name which shall be used for the whole album. The exact meaning of this tag is not well-defined.
117
    AlbumArtist(String),
118
    /// Same as albumartist, but for sorting.
119
    AlbumArtistSort(String),
120
    /// The song title.
121
    Title(String),
122
    /// Same as title, but for sorting.
123
    TitleSort(String),
124
    /// The decimal track number within the album.
125
    Track(String),
126
    /// A name for this song. This is not the song title. The exact meaning of this tag is not well-defined. It is often used by badly configured internet radio stations with broken tags to squeeze both the artist name and the song title in one tag.
127
    Name(String),
128
    /// The music genre.
129
    Genre(String),
130
    /// The mood of the audio with a few keywords.
131
    Mood(String),
132
    /// The song's release date. This is usually a 4-digit year.
133
    Date(String),
134
    /// The song's original release date.
135
    OriginalDate(String),
136
    /// The artist who composed the song.
137
    Composer(String),
138
    /// Same as composer, but for sorting.
139
    ComposerSort(String),
140
    /// The artist who performed the song.
141
    Performer(String),
142
    /// The conductor who conducted the song.
143
    Conductor(String),
144
    /// “a work is a distinct intellectual or artistic creation, which can be expressed in the form of one or more audio recordings”
145
    Work(String),
146
    /// The ensemble performing this song, e.g. “Wiener Philharmoniker”.
147
    Ensemble(String),
148
    /// Name of the movement, e.g. “Andante con moto”.
149
    Movement(String),
150
    /// Movement number, e.g. “2” or “II”.
151
    MovementNumber(String),
152
    /// If this tag is set to “1” players supporting this tag will display the work, movement, and movementnumber` instead of the track title.
153
    ShowMovement(String),
154
    /// Location of the recording, e.g. “Royal Albert Hall”.
155
    Location(String),
156
    /// “used if the sound belongs to a larger category of sounds/music” (from the IDv2.4.0 TIT1 description).
157
    Grouping(String),
158
    /// A human-readable comment about this song. The exact meaning of this tag is not well-defined.
159
    Comment(String),
160
    /// The decimal disc number in a multi-disc album.
161
    Disc(String),
162
    /// The name of the label or publisher.
163
    Label(String),
164
    /// The artist id in the MusicBrainz database.
165
    MusicBrainzArtistId(String),
166
    /// The album id in the MusicBrainz database.
167
    MusicBrainzAlbumId(String),
168
    /// The album artist id in the MusicBrainz database.
169
    MusicBrainzAlbumArtistId(String),
170
    /// The track id in the MusicBrainz database.
171
    MusicBrainzTrackId(String),
172
    /// The release group id in the MusicBrainz database.
173
    MusicBrainzReleaseGroupId(String),
174
    /// The release track id in the MusicBrainz database.
175
    MusicBrainzReleaseTrackId(String),
176
    /// The work id in the MusicBrainz database.
177
    MusicBrainzWorkId(String),
178

            
179
    /// Other tags not covered by the above
180
    Other(String, String),
181
}
182

            
183
/// These are different parts of the canonical MPD server.
184
/// They are mostly used in the protocol with the `idle` command,
185
/// signalling that the client is waiting for changes in any, one or multiple of these subsystems.
186
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
187
pub enum SubSystem {
188
    /// The song database has been modified after update.
189
    Database,
190
    /// A database update has started or finished. If the database was modified during the update, the database event is also emitted.
191
    Update,
192
    /// A stored playlist has been modified, renamed, created or deleted
193
    StoredPlaylist,
194
    /// The queue (i.e. the current playlist) has been modified
195
    Playlist,
196
    /// The player has been started, stopped or seeked or tags of the currently playing song have changed (e.g. received from stream)
197
    Player,
198
    /// The volume has been changed
199
    Mixer,
200
    /// An audio output has been added, removed or modified (e.g. renamed, enabled or disabled)
201
    Output,
202
    /// Options like repeat, random, crossfade, replay gain
203
    Options,
204
    /// A partition was added, removed or changed
205
    Partition,
206
    /// The sticker database has been modified.
207
    Sticker,
208
    /// A client has subscribed or unsubscribed to a channel
209
    Subscription,
210
    /// A message was received on a channel this client is subscribed to; this event is only emitted when the client’s message queue is empty
211
    Message,
212
    /// A neighbor was found or lost
213
    Neighbor,
214
    /// The mount list has changed
215
    Mount,
216

            
217
    /// Other subsystems not covered by the above
218
    Other(String),
219
}
220

            
221
impl FromStr for SubSystem {
222
    type Err = ();
223

            
224
    fn from_str(s: &str) -> Result<Self, Self::Err> {
225
        Ok(match s {
226
            "database" => Self::Database,
227
            "update" => Self::Update,
228
            "stored_playlist" => Self::StoredPlaylist,
229
            "playlist" => Self::Playlist,
230
            "player" => Self::Player,
231
            "mixer" => Self::Mixer,
232
            "output" => Self::Output,
233
            "options" => Self::Options,
234
            "partition" => Self::Partition,
235
            "sticker" => Self::Sticker,
236
            "subscription" => Self::Subscription,
237
            "message" => Self::Message,
238
            "neighbor" => Self::Neighbor,
239
            "mount" => Self::Mount,
240
            other => Self::Other(other.to_string()),
241
        })
242
    }
243
}
244

            
245
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
246
pub struct Audio {
247
    pub sample_rate: u64,
248
    pub bits: u8,
249
    pub channels: u8,
250
}
251

            
252
impl FromStr for Audio {
253
    type Err = ();
254

            
255
1
    fn from_str(s: &str) -> Result<Self, Self::Err> {
256
1
        let mut parts = s.split(':');
257
1
        let sample_rate = parts.next().ok_or(())?.parse().map_err(|_| ())?;
258
1
        let bits = u8::from_str_radix(parts.next().ok_or(())?, 16).map_err(|_| ())? + 1;
259
1
        let channels = parts.next().ok_or(())?.parse().map_err(|_| ())?;
260
1
        Ok(Self {
261
1
            sample_rate,
262
1
            bits,
263
1
            channels,
264
1
        })
265
1
    }
266
}
267

            
268
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
269
pub enum BoolOrOneshot {
270
    True,
271
    False,
272
    Oneshot,
273
}
274

            
275
impl FromStr for BoolOrOneshot {
276
    type Err = ();
277

            
278
2
    fn from_str(s: &str) -> Result<Self, Self::Err> {
279
2
        Ok(match s {
280
2
            "0" => Self::False,
281
            "1" => Self::True,
282
            "oneshot" => Self::Oneshot,
283
            _ => return Err(()),
284
        })
285
2
    }
286
}