Files
empidee/src/common.rs
2024-12-13 17:05:08 +01:00

287 lines
9.4 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
use std::str::FromStr;
use serde::{Deserialize, Serialize};
pub type SongPosition = u32;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum AbsouluteRelativeSongPosition {
Absolute(SongPosition),
RelativePlus(SongPosition),
RelativeMinus(SongPosition),
}
impl FromStr for AbsouluteRelativeSongPosition {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(match s {
s if s.starts_with('+') => Self::RelativePlus(s[1..].parse().map_err(|_| ())?),
s if s.starts_with('-') => Self::RelativeMinus(s[1..].parse().map_err(|_| ())?),
s => Self::Absolute(s.parse().map_err(|_| ())?),
})
}
}
pub type SongId = u32;
pub type Seconds = u32;
pub type TimeWithFractions = f64;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum OneOrRange {
One(SongPosition),
Range(SongPosition, SongPosition),
}
impl FromStr for OneOrRange {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut parts = s.split(':');
let start = parts.next().ok_or(())?.parse().map_err(|_| ())?;
Ok(match parts.next() {
Some(end) => Self::Range(start, end.parse().map_err(|_| ())?),
None => Self::One(start),
})
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct WindowRange {
pub start: SongPosition,
pub end: Option<SongPosition>,
}
impl FromStr for WindowRange {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut parts = s.split(':');
let start = parts.next().ok_or(())?.parse().map_err(|_| ())?;
let end = parts.next().map(|s| s.parse().map_err(|_| ()));
Ok(Self {
start,
end: end.transpose()?,
})
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct TimeInterval {
pub start: Option<TimeWithFractions>,
pub end: Option<TimeWithFractions>,
}
impl FromStr for TimeInterval {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut parts = s.split(':');
let start = parts.next().map(|s| s.parse().map_err(|_| ()));
let end = parts.next().map(|s| s.parse().map_err(|_| ()));
Ok(Self {
start: start.transpose()?,
end: end.transpose()?,
})
}
}
pub type Priority = u8;
pub type PlaylistName = String;
pub type Offset = u32;
// TODO: use a proper types
pub type TagName = String;
pub type TagValue = String;
pub type Uri = String;
pub type Path = String;
pub type Sort = String;
pub type Version = String;
pub type Feature = String;
pub type PartitionName = String;
pub type AudioOutputId = String;
pub type ChannelName = String;
pub type StickerType = String;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum Tag {
/// The artist name. Its meaning is not well-defined; see “composer” and “performer” for more specific tags.
Artist(String),
/// Same as artist, but for sorting. This usually omits prefixes such as “The”.
ArtistSort(String),
/// The album name.
Album(String),
/// Same as album, but for sorting.
AlbumSort(String),
/// 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.
AlbumArtist(String),
/// Same as albumartist, but for sorting.
AlbumArtistSort(String),
/// The song title.
Title(String),
/// Same as title, but for sorting.
TitleSort(String),
/// The decimal track number within the album.
Track(String),
/// 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.
Name(String),
/// The music genre.
Genre(String),
/// The mood of the audio with a few keywords.
Mood(String),
/// The song's release date. This is usually a 4-digit year.
Date(String),
/// The song's original release date.
OriginalDate(String),
/// The artist who composed the song.
Composer(String),
/// Same as composer, but for sorting.
ComposerSort(String),
/// The artist who performed the song.
Performer(String),
/// The conductor who conducted the song.
Conductor(String),
/// “a work is a distinct intellectual or artistic creation, which can be expressed in the form of one or more audio recordings”
Work(String),
/// The ensemble performing this song, e.g. “Wiener Philharmoniker”.
Ensemble(String),
/// Name of the movement, e.g. “Andante con moto”.
Movement(String),
/// Movement number, e.g. “2” or “II”.
MovementNumber(String),
/// If this tag is set to “1” players supporting this tag will display the work, movement, and movementnumber` instead of the track title.
ShowMovement(String),
/// Location of the recording, e.g. “Royal Albert Hall”.
Location(String),
/// “used if the sound belongs to a larger category of sounds/music” (from the IDv2.4.0 TIT1 description).
Grouping(String),
/// A human-readable comment about this song. The exact meaning of this tag is not well-defined.
Comment(String),
/// The decimal disc number in a multi-disc album.
Disc(String),
/// The name of the label or publisher.
Label(String),
/// The artist id in the MusicBrainz database.
MusicBrainzArtistId(String),
/// The album id in the MusicBrainz database.
MusicBrainzAlbumId(String),
/// The album artist id in the MusicBrainz database.
MusicBrainzAlbumArtistId(String),
/// The track id in the MusicBrainz database.
MusicBrainzTrackId(String),
/// The release group id in the MusicBrainz database.
MusicBrainzReleaseGroupId(String),
/// The release track id in the MusicBrainz database.
MusicBrainzReleaseTrackId(String),
/// The work id in the MusicBrainz database.
MusicBrainzWorkId(String),
/// Other tags not covered by the above
Other(String, String),
}
/// These are different parts of the canonical MPD server.
/// They are mostly used in the protocol with the `idle` command,
/// signalling that the client is waiting for changes in any, one or multiple of these subsystems.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum SubSystem {
/// The song database has been modified after update.
Database,
/// A database update has started or finished. If the database was modified during the update, the database event is also emitted.
Update,
/// A stored playlist has been modified, renamed, created or deleted
StoredPlaylist,
/// The queue (i.e. the current playlist) has been modified
Playlist,
/// The player has been started, stopped or seeked or tags of the currently playing song have changed (e.g. received from stream)
Player,
/// The volume has been changed
Mixer,
/// An audio output has been added, removed or modified (e.g. renamed, enabled or disabled)
Output,
/// Options like repeat, random, crossfade, replay gain
Options,
/// A partition was added, removed or changed
Partition,
/// The sticker database has been modified.
Sticker,
/// A client has subscribed or unsubscribed to a channel
Subscription,
/// A message was received on a channel this client is subscribed to; this event is only emitted when the clients message queue is empty
Message,
/// A neighbor was found or lost
Neighbor,
/// The mount list has changed
Mount,
/// Other subsystems not covered by the above
Other(String),
}
impl FromStr for SubSystem {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(match s {
"database" => Self::Database,
"update" => Self::Update,
"stored_playlist" => Self::StoredPlaylist,
"playlist" => Self::Playlist,
"player" => Self::Player,
"mixer" => Self::Mixer,
"output" => Self::Output,
"options" => Self::Options,
"partition" => Self::Partition,
"sticker" => Self::Sticker,
"subscription" => Self::Subscription,
"message" => Self::Message,
"neighbor" => Self::Neighbor,
"mount" => Self::Mount,
other => Self::Other(other.to_string()),
})
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Audio {
pub sample_rate: u64,
pub bits: u8,
pub channels: u8,
}
impl FromStr for Audio {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut parts = s.split(':');
let sample_rate = parts.next().ok_or(())?.parse().map_err(|_| ())?;
let bits = u8::from_str_radix(parts.next().ok_or(())?, 16).map_err(|_| ())? + 1;
let channels = parts.next().ok_or(())?.parse().map_err(|_| ())?;
Ok(Self {
sample_rate,
bits,
channels,
})
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum BoolOrOneshot {
True,
False,
Oneshot,
}
impl FromStr for BoolOrOneshot {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(match s {
"0" => Self::False,
"1" => Self::True,
"oneshot" => Self::Oneshot,
_ => return Err(()),
})
}
}