use client::Client;
use error::{Error, ParseError};
use proto::Proto;
use std::fmt;
use std::io::{Read, Write};
use std::mem::forget;
use std::str::FromStr;
#[derive(Clone, Copy, Debug, PartialEq, RustcEncodable)]
pub enum Subsystem {
Database,
Update,
Playlist,
Queue,
Player,
Mixer,
Output,
Options,
Sticker,
Subscription,
Message,
}
impl FromStr for Subsystem {
type Err = ParseError;
fn from_str(s: &str) -> Result<Subsystem, ParseError> {
use self::Subsystem::*;
match s {
"database" => Ok(Database),
"update" => Ok(Update),
"stored_playlist" => Ok(Playlist),
"playlist" => Ok(Queue),
"player" => Ok(Player),
"mixer" => Ok(Mixer),
"output" => Ok(Output),
"options" => Ok(Options),
"sticker" => Ok(Sticker),
"subscription" => Ok(Subscription),
"message" => Ok(Message),
_ => Err(ParseError::BadValue(s.to_owned())),
}
}
}
impl Subsystem {
fn to_str(self) -> &'static str {
use self::Subsystem::*;
match self {
Database => "database",
Update => "update",
Playlist => "stored_playlist",
Queue => "playlist",
Player => "player",
Mixer => "mixer",
Output => "output",
Options => "options",
Sticker => "sticker",
Subscription => "subscription",
Message => "message",
}
}
}
impl fmt::Display for Subsystem {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(self.to_str())
}
}
use std::result::Result as StdResult;
impl<'a> ::proto::ToArguments for Subsystem {
fn to_arguments<F, E>(&self, f: &mut F) -> StdResult<(), E>
where F: FnMut(&str) -> StdResult<(), E>
{
f(self.to_str())
}
}
pub struct IdleGuard<'a, S: 'a + Read + Write>(&'a mut Client<S>);
impl<'a, S: 'a + Read + Write> IdleGuard<'a, S> {
pub fn get(self) -> Result<Vec<Subsystem>, Error> {
let result = self.0.read_list("changed").and_then(|v| v.into_iter().map(|b| b.parse().map_err(From::from)).collect());
forget(self);
result
}
}
impl<'a, S: 'a + Read + Write> Drop for IdleGuard<'a, S> {
fn drop(&mut self) {
let _ = self.0.run_command("noidle", ()).map(|_| self.0.drain());
}
}
pub trait Idle {
type Stream: Read + Write;
fn idle<'a>(&'a mut self, subsystems: &[Subsystem]) -> Result<IdleGuard<'a, Self::Stream>, Error>;
fn wait(&mut self, subsystems: &[Subsystem]) -> Result<Vec<Subsystem>, Error> {
self.idle(subsystems).and_then(IdleGuard::get)
}
}
impl<S: Read + Write> Idle for Client<S> {
type Stream = S;
fn idle<'a>(&'a mut self, subsystems: &[Subsystem]) -> Result<IdleGuard<'a, S>, Error> {
self.run_command("idle", subsystems)?;
Ok(IdleGuard(self))
}
}