1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
//! The module defines structers and protocols for asynchrnonous MPD communication
//!
//! The MPD supports very simple protocol for asyncrhonous client notifications about
//! different player events. First user issues `idle` command with optional argument
//! to filter events by source subsystem (like "database", "player", "mixer" etc.)
//!
//! Once in "idle" mode, client connection timeout is disabled, and MPD will notify
//! client about next event when one occurs (if originated from one of designated
//! subsystems, if specified).
//!
//! (Actually MPD notifies only about general subsystem source of event, e.g.
//! if user changed volume, client will get `mixer` event in idle mode, so
//! it should issue `status` command then and check for any mixer-related field
//! changes.)
//!
//! Once some such event occurs, and client is nofified about it, idle mode is interrupted,
//! and client must issue another `idle` command to continue listening for interesting
//! events.
//!
//! While in "idle" mode, client can't issue any commands, except for special `noidle`
//! command, which interrupts "idle" mode, and provides a list queued events
//! since last `idle` command, if they occurred.
//!
//! The module describes subsystems enum only, but the main workflow is determined by
//! [`IdleGuard`](client/struct.IdleGuard.html) struct, which catches mutable reference
//! to original `Client` struct, thus enforcing MPD contract in regards of (im)possibility
//! to send commands while in "idle" mode.

use std::fmt;
use std::str::FromStr;

use error::ParseError;

/// Subsystems for `idle` command
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Subsystem {
    /// database: the song database has been modified after update.
    Database,
    /// update: a database update has started or finished. If the database was modified during the update, the database event is also emitted.
    Update,
    /// stored_playlist: a stored playlist has been modified, renamed, created or deleted
    Playlist,
    /// playlist: the current playlist has been modified
    Queue,
    /// player: the player has been started, stopped or seeked
    Player,
    /// mixer: the volume has been changed
    Mixer,
    /// output: an audio output has been enabled or disabled
    Output,
    /// options: options like repeat, random, crossfade, replay gain
    Options,
    /// sticker: the sticker database has been modified.
    Sticker,
    /// subscription: a client has subscribed or unsubscribed to a channel
    Subscription,
    /// message: a message was received on a channel this client is subscribed to; this event is only emitted when the queue is empty
    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 fmt::Display for Subsystem {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Subsystem::*;
        f.write_str(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"
        })
    }
}