diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/audio_player.rs | 23 | ||||
| -rw-r--r-- | src/bot/music.rs | 41 | ||||
| -rw-r--r-- | src/command.rs | 72 |
3 files changed, 90 insertions, 46 deletions
diff --git a/src/audio_player.rs b/src/audio_player.rs index d231c72..5f9c625 100644 --- a/src/audio_player.rs +++ b/src/audio_player.rs @@ -14,16 +14,10 @@ use std::sync::{Arc, RwLock}; use tokio02::sync::mpsc::UnboundedSender; use crate::youtube_dl::AudioMetadata; +use crate::command::{Seek, VolumeChange}; static GST_INIT: Once = Once::new(); -#[derive(Copy, Clone, Debug)] -pub enum Seek { - Positive(Duration), - Negative(Duration), - Absolute(Duration), -} - #[derive(PartialEq, Eq, Debug, Clone, Copy)] pub enum PollResult { Continue, @@ -201,10 +195,17 @@ impl AudioPlayer { Ok(()) } - pub fn set_volume(&self, volume: f64) -> Result<(), AudioPlayerError> { - *self.volume_f64.write().unwrap() = volume; - let db = 50.0 * volume.log10(); - info!("Setting volume: {} -> {} dB", volume, db); + pub fn change_volume(&self, volume: VolumeChange) -> Result<(), AudioPlayerError> { + let new_volume = match volume { + VolumeChange::Positive(vol) => self.volume() + vol, + VolumeChange::Negative(vol) => self.volume() - vol, + VolumeChange::Absolute(vol) => vol, + }; + let new_volume = new_volume.max(0.0).min(1.0); + + *self.volume_f64.write().unwrap() = new_volume; + let db = 50.0 * new_volume.log10(); + info!("Setting volume: {} -> {} dB", new_volume, db); let linear = StreamVolume::convert_volume(StreamVolumeFormat::Db, StreamVolumeFormat::Linear, db); diff --git a/src/bot/music.rs b/src/bot/music.rs index 5f7928e..1b125b5 100644 --- a/src/bot/music.rs +++ b/src/bot/music.rs @@ -11,11 +11,12 @@ use structopt::StructOpt; use tokio02::sync::mpsc::UnboundedSender; use tsclientlib::{data, ChannelId, ClientId, ConnectOptions, Identity, Invoker, MessageTarget}; -use crate::audio_player::{AudioPlayer, AudioPlayerError, PollResult, Seek}; +use crate::audio_player::{AudioPlayer, AudioPlayerError, PollResult}; use crate::command::Command; use crate::playlist::Playlist; use crate::teamspeak as ts; use crate::youtube_dl::AudioMetadata; +use crate::command::VolumeChange; use ts::TeamSpeakConnection; #[derive(Debug)] @@ -25,27 +26,6 @@ pub struct Message { pub text: String, } -fn parse_seek(mut amount: &str) -> Result<Seek, ()> { - 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).map_err(|_| ())?; - - match sign { - 1 => Ok(Seek::Positive(duration)), - -1 => Ok(Seek::Negative(duration)), - _ => Ok(Seek::Absolute(duration)), - } -} - #[derive(Debug, PartialEq, Eq, Clone, Copy, Serialize)] pub enum State { Playing, @@ -139,7 +119,7 @@ impl MusicBot { (audio_player, Some(connection)) }; - player.set_volume(0.5).unwrap(); + player.change_volume(VolumeChange::Absolute(0.5)).unwrap(); let player = Arc::new(player); let playlist = Arc::new(RwLock::new(Playlist::new())); @@ -336,14 +316,10 @@ impl MusicBot { self.player.reset()?; } Command::Seek { amount } => { - if let Ok(seek) = parse_seek(&amount) { - if let Ok(time) = self.player.seek(seek) { - self.send_message(&format!("New position: {}", ts::bold(&time))); - } else { - self.send_message("Failed to seek"); - } + if let Ok(time) = self.player.seek(amount) { + self.send_message(&format!("New position: {}", ts::bold(&time))); } else { - info!("Failed to parse seeking command"); + self.send_message("Failed to seek"); } } Command::Next => { @@ -362,9 +338,8 @@ impl MusicBot { .expect("RwLock was not poisoned") .clear(); } - Command::Volume { percent: volume } => { - let volume = volume.max(0.0).min(100.0) * 0.01; - self.player.set_volume(volume)?; + Command::Volume { volume } => { + self.player.change_volume(volume)?; self.update_name(self.state()); } Command::Leave => { diff --git a/src/command.rs b/src/command.rs index db22028..35070b8 100644 --- a/src/command.rs +++ b/src/command.rs @@ -1,5 +1,8 @@ +use std::time::Duration; + use structopt::clap::AppSettings::*; use structopt::StructOpt; +use log::debug; #[derive(StructOpt, Debug)] #[structopt( @@ -20,7 +23,7 @@ pub enum Command { /// Pauses audio playback Pause, /// Seeks by a specified amount - Seek { amount: String }, + Seek { amount: Seek }, /// Stops audio playback Stop, /// Switches to the next queue entry @@ -29,7 +32,72 @@ pub enum Command { /// Clears the playback queue Clear, /// Changes the volume to the specified value - Volume { percent: f64 }, + 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)), + } + } +} |
