aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/audio_player.rs23
-rw-r--r--src/bot/music.rs41
-rw-r--r--src/command.rs72
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 25c5d4b..879a140 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()));
@@ -339,14 +319,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 => {
@@ -365,9 +341,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 c907d51..695cdc4 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(
@@ -22,7 +25,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
@@ -31,7 +34,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)),
+ }
+ }
+}