aboutsummaryrefslogtreecommitdiffstats
path: root/src/command.rs
blob: 695cdc484ed626bb0dfa86ef0c6dc94b28f1f4d7 (plain) (blame)
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
101
102
103
104
105
use std::time::Duration;

use structopt::clap::AppSettings::*;
use structopt::StructOpt;
use log::debug;

#[derive(StructOpt, Debug)]
#[structopt(
    rename_all = "kebab-case",
    template = "{subcommands}",
    raw(global_settings = "&[VersionlessSubcommands,
                            DisableHelpFlags,
                            DisableVersion,
                            ColorNever,
                            NoBinaryName,
                            AllowLeadingHyphen]",)
)]
pub enum Command {
    /// Adds url to playlist
    Add { url: String },
    /// Adds the first video found on YouTube
    Search { query: Vec<String> },
    /// Starts audio playback
    Play,
    /// Pauses audio playback
    Pause,
    /// Seeks by a specified amount
    Seek { amount: Seek },
    /// Stops audio playback
    Stop,
    /// Switches to the next queue entry
    #[structopt(alias = "skip")]
    Next,
    /// Clears the playback queue
    Clear,
    /// Changes the volume to the specified value
    Volume { volume: VolumeChange },
    /// Leaves the channel
    Leave,
}

#[derive(Copy, Clone, Debug)]
pub enum Seek {
    Positive(Duration),
    Negative(Duration),
    Absolute(Duration),
}

impl std::str::FromStr for Seek {
    type Err = humantime::DurationError;

    fn from_str(mut amount: &str) -> std::result::Result<Self, Self::Err> {
        let sign = match amount.chars().next() {
            Some('+') => 1,
            Some('-') => -1,
            _ => 0,
        };
        let is_relative = sign != 0;

        if is_relative {
            amount = &amount[1..];
        }

        let duration = humantime::parse_duration(amount)?;

        match sign {
            1 => Ok(Seek::Positive(duration)),
            -1 => Ok(Seek::Negative(duration)),
            _ => Ok(Seek::Absolute(duration)),
        }
    }
}

#[derive(Copy, Clone, Debug)]
pub enum VolumeChange {
    Positive(f64),
    Negative(f64),
    Absolute(f64),
}

// TODO This runs twice, report to clap?
impl std::str::FromStr for VolumeChange {
    type Err = std::num::ParseFloatError;

    fn from_str(mut amount: &str) -> std::result::Result<Self, Self::Err> {
        let sign = match amount.chars().next() {
            Some('+') => 1,
            Some('-') => -1,
            _ => 0,
        };
        let is_relative = sign != 0;

        if is_relative {
            amount = &amount[1..];
        }

        let amount = f64::from_str(amount)? * 0.01;

        match sign {
            1 => Ok(VolumeChange::Positive(amount)),
            -1 => Ok(VolumeChange::Negative(amount)),
            _ => Ok(VolumeChange::Absolute(amount)),
        }
    }
}