Files
empidee/src/request.rs

418 lines
17 KiB
Rust

use serde::{Deserialize, Serialize};
use crate::common::types::*;
use crate::filter::Filter;
// TODO: SingleLineString
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Request {
CommandList(Vec<Request>),
// -- Query Commands -- //
ClearError,
CurrentSong,
Idle(Option<Vec<SubSystem>>),
Status,
Stats,
// -- Playback Commands -- //
Consume(BoolOrOneshot),
Crossfade(Seconds),
MixRampDb(f32),
MixRampDelay(Seconds),
Random(bool),
Repeat(bool),
SetVol(VolumeValue),
GetVol,
Single(BoolOrOneshot),
ReplayGainMode(ReplayGainModeMode),
ReplayGainStatus,
Volume(VolumeValue),
// -- Playback Control Commands -- //
Next,
Pause(Option<bool>),
Play(SongPosition),
PlayId(SongId),
Previous,
Seek(SongPosition, TimeWithFractions),
SeekId(SongId, TimeWithFractions),
SeekCur(SeekMode, TimeWithFractions),
Stop,
// -- Queue Commands -- //
// TODO: relative mode
Add(String, Option<SongPosition>),
// TODO: relative mode
AddId(String, Option<SongPosition>),
Clear,
Delete(OneOrRange),
DeleteId(SongId),
// TODO: account for relative moves
Move(OneOrRange, AbsouluteRelativeSongPosition),
// TODO: account for relative moves
MoveId(SongId, AbsouluteRelativeSongPosition),
Playlist,
PlaylistFind(Filter, Option<Sort>, Option<WindowRange>),
PlaylistId(SongId),
PlaylistInfo(Option<OneOrRange>),
PlaylistSearch(Filter, Option<Sort>, Option<WindowRange>),
// TODO: which type of range?
PlChanges(PlaylistVersion, Option<WindowRange>),
// TODO: which type of range?
PlChangesPosId(PlaylistVersion, Option<WindowRange>),
// TODO: which type of range?
Prio(Priority, WindowRange),
PrioId(Priority, Vec<SongId>),
RangeId(SongId, TimeInterval),
Shuffle(Option<OneOrRange>),
Swap(SongPosition, SongPosition),
SwapId(SongId, SongId),
AddTagId(SongId, TagName, TagValue),
ClearTagId(SongId, TagName),
// -- Stored Playlist Commands -- //
ListPlaylist(PlaylistName, Option<WindowRange>),
ListPlaylistInfo(PlaylistName, Option<WindowRange>),
SearchPlaylist(PlaylistName, Filter, Option<WindowRange>),
ListPlaylists,
Load(PlaylistName, Option<WindowRange>, Option<SongPosition>),
PlaylistAdd(PlaylistName, Uri, Option<SongPosition>),
PlaylistClear(PlaylistName),
PlaylistDelete(PlaylistName, OneOrRange),
PlaylistLength(PlaylistName),
// TODO: which type of range?
PlaylistMove(PlaylistName, Option<OneOrRange>, SongPosition),
Rename(PlaylistName, PlaylistName),
Rm(PlaylistName),
Save(PlaylistName, Option<SaveMode>),
// -- Music Database Commands -- //
AlbumArt(Uri, Offset),
Count(Filter, Option<GroupType>),
GetFingerprint(Uri),
Find(Filter, Option<Sort>, Option<WindowRange>),
FindAdd(
Filter,
Option<Sort>,
Option<WindowRange>,
Option<SongPosition>,
),
List(TagName, Option<Filter>, Vec<GroupType>, Option<WindowRange>),
#[deprecated]
ListAll(Option<Uri>),
#[deprecated]
ListAllInfo(Option<Uri>),
ListFiles(Option<Uri>),
LsInfo(Option<Uri>),
ReadComments(Uri),
ReadPicture(Uri, Offset),
Search(Filter, Option<Sort>, Option<WindowRange>),
SearchAdd(
Filter,
Option<Sort>,
Option<WindowRange>,
Option<SongPosition>,
),
SearchAddPl(
PlaylistName,
Filter,
Option<Sort>,
Option<WindowRange>,
Option<SongPosition>,
),
SearchCount(Filter, Option<GroupType>),
Update(Option<Uri>),
Rescan(Option<Uri>),
// -- Mount and Neighbor Commands -- //
Mount(MountPath, Uri),
Unmount(MountPath),
ListMounts,
ListNeighbors,
// -- Sticker Commands -- //
StickerGet(StickerType, Uri, String),
StickerSet(StickerType, Uri, String, String),
StickerInc(StickerType, Uri, String, usize),
StickerDec(StickerType, Uri, String, usize),
StickerDelete(StickerType, Uri, String),
StickerList(StickerType, Uri),
StickerFind(StickerType, Uri, String, Option<Sort>, Option<WindowRange>),
StickerFindValue(
StickerType,
Uri,
String,
String,
Option<Sort>,
Option<WindowRange>,
),
StickerNames,
StickerTypes,
StickerNamesTypes(Option<StickerType>),
// -- Connection Commands -- //
Close,
Kill,
Password(String),
Ping,
BinaryLimit(u64),
TagTypes,
TagTypesDisable(Vec<TagName>),
TagTypesEnable(Vec<TagName>),
TagTypesClear,
TagTypesAll,
TagTypesAvailable,
TagTypesReset(Vec<TagName>),
Protocol,
ProtocolDisable(Vec<Feature>),
ProtocolEnable(Vec<Feature>),
ProtocolClear,
ProtocolAll,
ProtocolAvailable,
// -- Partition Commands -- //
Partition(PartitionName),
ListPartitions,
NewPartition(PartitionName),
DelPartition(PartitionName),
MoveOutput(String),
// -- Audio Output Commands -- //
DisableOutput(AudioOutputId),
EnableOutput(AudioOutputId),
ToggleOutput(AudioOutputId),
Outputs,
OutputSet(AudioOutputId, String, String),
// -- Reflection Commands -- //
Config,
Commands,
NotCommands,
UrlHandlers,
Decoders,
// -- Client to Client Commands -- //
Subscribe(ChannelName),
Unsubscribe(ChannelName),
Channels,
ReadMessages,
SendMessage(ChannelName, String),
}
impl Request {
// pub enum RequestParserError {
// SyntaxError(u64, String),
// MissingCommandListEnd(u64),
// NestedCommandList(u64),
// UnexpectedCommandListEnd(u64),
// UnexpectedEOF,
// MissingNewline,
// }
// TODO: upon encountering an error, there should be a function that lets you skip to the next OK,
// and continue execution. Maybe "parse_next_or_skip(&str) -> RequestParserResponse", which
// could skip stuff internally? Or do we want to report back the error with the entire command
// and let the library user decide what to do?
// impl Request {
// pub fn parse_next(raw: &str) -> Result<Self::Request, RequestParserError> {
// let (line, rest) = raw
// .split_once('\n')
// .ok_or(RequestParserError::UnexpectedEOF)?;
// let mut parts = RequestTokenizer::new(line);
// match parts
// .next()
// .ok_or(RequestParserError::SyntaxError(0, line.to_string()))?
// .trim()
// {
// "command_list_begin" => {
// let mut commands = Vec::new();
// let mut i = 1;
// loop {
// i += 1;
// let (line, rest) = rest
// .split_once('\n')
// .ok_or(RequestParserError::MissingCommandListEnd(i))?;
// match line.trim() {
// "command_list_begin" => {
// return Err(RequestParserError::NestedCommandList(i));
// }
// "command_list_end" => {
// return Ok((Request::CommandList(commands), rest));
// }
// input => {
// let (command, _) = Request::parse_next(input)?;
// commands.push(command);
// }
// }
// }
// }
// "command_list_end" => Err(RequestParserError::UnexpectedCommandListEnd(0)),
// /* querying mpd status */
// ClearError::COMMAND => ClearError::parse_request(parts),
// CurrentSong::COMMAND => CurrentSong::parse_request(parts),
// Idle::COMMAND => Idle::parse_request(parts),
// Status::COMMAND => Status::parse_request(parts),
// Stats::COMMAND => Stats::parse_request(parts),
// /* playback options */
// Consume::COMMAND => Consume::parse_request(parts),
// Crossfade::COMMAND => Crossfade::parse_request(parts),
// MixRampDb::COMMAND => MixRampDb::parse_request(parts),
// MixRampDelay::COMMAND => MixRampDelay::parse_request(parts),
// Random::COMMAND => Random::parse_request(parts),
// Repeat::COMMAND => Repeat::parse_request(parts),
// SetVol::COMMAND => SetVol::parse_request(parts),
// GetVol::COMMAND => GetVol::parse_request(parts),
// Single::COMMAND => Single::parse_request(parts),
// ReplayGainMode::COMMAND => ReplayGainMode::parse_request(parts),
// ReplayGainStatus::COMMAND => ReplayGainStatus::parse_request(parts),
// Volume::COMMAND => Volume::parse_request(parts),
// /* playback control */
// Next::COMMAND => Next::parse_request(parts),
// Pause::COMMAND => Pause::parse_request(parts),
// Play::COMMAND => Play::parse_request(parts),
// PlayId::COMMAND => PlayId::parse_request(parts),
// Previous::COMMAND => Previous::parse_request(parts),
// Seek::COMMAND => Seek::parse_request(parts),
// SeekId::COMMAND => SeekId::parse_request(parts),
// SeekCur::COMMAND => SeekCur::parse_request(parts),
// Stop::COMMAND => Stop::parse_request(parts),
// /* queue */
// Add::COMMAND => Add::parse_request(parts),
// AddId::COMMAND => AddId::parse_request(parts),
// Clear::COMMAND => Clear::parse_request(parts),
// Delete::COMMAND => Delete::parse_request(parts),
// DeleteId::COMMAND => DeleteId::parse_request(parts),
// Move::COMMAND => Move::parse_request(parts),
// MoveId::COMMAND => MoveId::parse_request(parts),
// Playlist::COMMAND => Playlist::parse_request(parts),
// PlaylistFind::COMMAND => PlaylistFind::parse_request(parts),
// PlaylistId::COMMAND => PlaylistId::parse_request(parts),
// PlaylistInfo::COMMAND => PlaylistInfo::parse_request(parts),
// PlaylistSearch::COMMAND => PlaylistSearch::parse_request(parts),
// PlChanges::COMMAND => PlChanges::parse_request(parts),
// PlChangesPosId::COMMAND => PlChangesPosId::parse_request(parts),
// Prio::COMMAND => Prio::parse_request(parts),
// PrioId::COMMAND => PrioId::parse_request(parts),
// RangeId::COMMAND => RangeId::parse_request(parts),
// Shuffle::COMMAND => Shuffle::parse_request(parts),
// Swap::COMMAND => Swap::parse_request(parts),
// SwapId::COMMAND => SwapId::parse_request(parts),
// AddTagId::COMMAND => AddTagId::parse_request(parts),
// ClearTagId::COMMAND => ClearTagId::parse_request(parts),
// /* stored playlists */
// ListPlaylist::COMMAND => ListPlaylist::parse_request(parts),
// ListPlaylistInfo::COMMAND => ListPlaylistInfo::parse_request(parts),
// SearchPlaylist::COMMAND => SearchPlaylist::parse_request(parts),
// ListPlaylists::COMMAND => ListPlaylists::parse_request(parts),
// Load::COMMAND => Load::parse_request(parts),
// PlaylistAdd::COMMAND => PlaylistAdd::parse_request(parts),
// PlaylistClear::COMMAND => PlaylistClear::parse_request(parts),
// PlaylistDelete::COMMAND => PlaylistDelete::parse_request(parts),
// PlaylistLength::COMMAND => PlaylistLength::parse_request(parts),
// PlaylistMove::COMMAND => PlaylistMove::parse_request(parts),
// Rename::COMMAND => Rename::parse_request(parts),
// Rm::COMMAND => Rm::parse_request(parts),
// Save::COMMAND => Save::parse_request(parts),
// /* music database */
// AlbumArt::COMMAND => AlbumArt::parse_request(parts),
// Count::COMMAND => Count::parse_request(parts),
// GetFingerprint::COMMAND => GetFingerprint::parse_request(parts),
// Find::COMMAND => Find::parse_request(parts),
// FindAdd::COMMAND => FindAdd::parse_request(parts),
// List::COMMAND => List::parse_request(parts),
// ListAll::COMMAND => ListAll::parse_request(parts),
// ListAllInfo::COMMAND => ListAllInfo::parse_request(parts),
// ListFiles::COMMAND => ListFiles::parse_request(parts),
// LsInfo::COMMAND => LsInfo::parse_request(parts),
// ReadComments::COMMAND => ReadComments::parse_request(parts),
// ReadPicture::COMMAND => ReadPicture::parse_request(parts),
// Search::COMMAND => Search::parse_request(parts),
// SearchAdd::COMMAND => SearchAdd::parse_request(parts),
// SearchAddPl::COMMAND => SearchAddPl::parse_request(parts),
// SearchCount::COMMAND => SearchCount::parse_request(parts),
// Update::COMMAND => Update::parse_request(parts),
// Rescan::COMMAND => Rescan::parse_request(parts),
// /* mounts and neighbors */
// Mount::COMMAND => Mount::parse_request(parts),
// Unmount::COMMAND => Unmount::parse_request(parts),
// ListMounts::COMMAND => ListMounts::parse_request(parts),
// ListNeighbors::COMMAND => ListNeighbors::parse_request(parts),
// /* stickers */
// StickerGet::COMMAND => StickerGet::parse_request(parts),
// StickerSet::COMMAND => StickerSet::parse_request(parts),
// StickerInc::COMMAND => StickerInc::parse_request(parts),
// StickerDec::COMMAND => StickerDec::parse_request(parts),
// StickerDelete::COMMAND => StickerDelete::parse_request(parts),
// StickerList::COMMAND => StickerList::parse_request(parts),
// StickerFind::COMMAND => StickerFind::parse_request(parts),
// StickerNames::COMMAND => StickerNames::parse_request(parts),
// StickerTypes::COMMAND => StickerTypes::parse_request(parts),
// StickerNamesTypes::COMMAND => StickerNamesTypes::parse_request(parts),
// /* connection settings */
// Close::COMMAND => Close::parse_request(parts),
// Kill::COMMAND => Kill::parse_request(parts),
// Password::COMMAND => Password::parse_request(parts),
// Ping::COMMAND => Ping::parse_request(parts),
// BinaryLimit::COMMAND => BinaryLimit::parse_request(parts),
// TagTypes::COMMAND => TagTypes::parse_request(parts),
// TagTypesDisable::COMMAND => TagTypesDisable::parse_request(parts),
// TagTypesEnable::COMMAND => TagTypesEnable::parse_request(parts),
// TagTypesClear::COMMAND => TagTypesClear::parse_request(parts),
// TagTypesAll::COMMAND => TagTypesAll::parse_request(parts),
// TagTypesAvailable::COMMAND => TagTypesAvailable::parse_request(parts),
// TagTypesReset::COMMAND => TagTypesReset::parse_request(parts),
// Protocol::COMMAND => Protocol::parse_request(parts),
// ProtocolDisable::COMMAND => ProtocolDisable::parse_request(parts),
// ProtocolEnable::COMMAND => ProtocolEnable::parse_request(parts),
// ProtocolClear::COMMAND => ProtocolClear::parse_request(parts),
// ProtocolAll::COMMAND => ProtocolAll::parse_request(parts),
// ProtocolAvailable::COMMAND => ProtocolAvailable::parse_request(parts),
// /* partition commands */
// Partition::COMMAND => Partition::parse_request(parts),
// ListPartitions::COMMAND => ListPartitions::parse_request(parts),
// NewPartition::COMMAND => NewPartition::parse_request(parts),
// DelPartition::COMMAND => DelPartition::parse_request(parts),
// MoveOutput::COMMAND => MoveOutput::parse_request(parts),
// /* audio output devices */
// DisableOutput::COMMAND => DisableOutput::parse_request(parts),
// EnableOutput::COMMAND => EnableOutput::parse_request(parts),
// ToggleOutput::COMMAND => ToggleOutput::parse_request(parts),
// Outputs::COMMAND => Outputs::parse_request(parts),
// OutputSet::COMMAND => OutputSet::parse_request(parts),
// /* reflection */
// Config::COMMAND => Config::parse_request(parts),
// Commands::COMMAND => Commands::parse_request(parts),
// NotCommands::COMMAND => NotCommands::parse_request(parts),
// UrlHandlers::COMMAND => UrlHandlers::parse_request(parts),
// Decoders::COMMAND => Decoders::parse_request(parts),
// /* client to client */
// Subscribe::COMMAND => Subscribe::parse_request(parts),
// Unsubscribe::COMMAND => Unsubscribe::parse_request(parts),
// Channels::COMMAND => Channels::parse_request(parts),
// ReadMessages::COMMAND => ReadMessages::parse_request(parts),
// SendMessage::COMMAND => SendMessage::parse_request(parts),
// _ => unimplemented!(),
// }
// }
}