|
@@ -4,12 +4,12 @@ use serenity::{
|
|
async_trait,
|
|
async_trait,
|
|
client::Context,
|
|
client::Context,
|
|
http::Http,
|
|
http::Http,
|
|
- model::{channel::Message, id::ChannelId},
|
|
|
|
|
|
+ model::{channel::Message, id::ChannelId, user::User},
|
|
prelude::Mutex as SerenityMutex,
|
|
prelude::Mutex as SerenityMutex,
|
|
};
|
|
};
|
|
use songbird::{
|
|
use songbird::{
|
|
- input::{self, reader::Reader},
|
|
|
|
- tracks::{TrackCommand, TrackHandle},
|
|
|
|
|
|
+ input::{Input, RawAdapter},
|
|
|
|
+ tracks::TrackHandle,
|
|
Call, Event, EventContext, EventHandler as VoiceEventHandler, TrackEvent,
|
|
Call, Event, EventContext, EventHandler as VoiceEventHandler, TrackEvent,
|
|
};
|
|
};
|
|
use std::time::Duration;
|
|
use std::time::Duration;
|
|
@@ -17,6 +17,7 @@ use std::sync::Arc;
|
|
use tokio::sync::Mutex;
|
|
use tokio::sync::Mutex;
|
|
use tokio::time::sleep;
|
|
use tokio::time::sleep;
|
|
use tokio::task::JoinHandle;
|
|
use tokio::task::JoinHandle;
|
|
|
|
+use std::collections::HashSet;
|
|
|
|
|
|
pub struct AudioState {
|
|
pub struct AudioState {
|
|
queue: SongQueue,
|
|
queue: SongQueue,
|
|
@@ -26,6 +27,7 @@ pub struct AudioState {
|
|
track_handle: Option<TrackHandle>,
|
|
track_handle: Option<TrackHandle>,
|
|
is_looping: bool,
|
|
is_looping: bool,
|
|
volume: f32,
|
|
volume: f32,
|
|
|
|
+ skip_votes: HashSet<User>,
|
|
|
|
|
|
channel_id: ChannelId,
|
|
channel_id: ChannelId,
|
|
http: Arc<Http>,
|
|
http: Arc<Http>,
|
|
@@ -41,6 +43,7 @@ impl AudioState {
|
|
track_handle: None,
|
|
track_handle: None,
|
|
is_looping: false,
|
|
is_looping: false,
|
|
volume: 1.0,
|
|
volume: 1.0,
|
|
|
|
+ skip_votes: HashSet::new(),
|
|
|
|
|
|
channel_id: msg.channel_id,
|
|
channel_id: msg.channel_id,
|
|
http: ctx.http.clone(),
|
|
http: ctx.http.clone(),
|
|
@@ -98,13 +101,14 @@ impl AudioState {
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
};
|
|
};
|
|
- let reader = Reader::Extension(source);
|
|
|
|
- let source = input::Input::float_pcm(true, reader);
|
|
|
|
|
|
+ let source = RawAdapter::new(source, 48000, 2);
|
|
|
|
+ let input: Input = source.into();
|
|
|
|
+ let input = input.make_live_async().await.expect("Should work?");
|
|
|
|
|
|
let handler = state.handler.clone();
|
|
let handler = state.handler.clone();
|
|
let mut handler = handler.lock().await;
|
|
let mut handler = handler.lock().await;
|
|
|
|
|
|
- let handle = handler.play_source(source);
|
|
|
|
|
|
+ let handle = handler.play_input(input);
|
|
if let Err(e) = handle.set_volume(state.volume) {
|
|
if let Err(e) = handle.set_volume(state.volume) {
|
|
println!("{}", e);
|
|
println!("{}", e);
|
|
}
|
|
}
|
|
@@ -119,6 +123,7 @@ impl AudioState {
|
|
}
|
|
}
|
|
{
|
|
{
|
|
let text = song.get_string();
|
|
let text = song.get_string();
|
|
|
|
+ state.skip_votes.clear();
|
|
send_embed_http(
|
|
send_embed_http(
|
|
state.channel_id,
|
|
state.channel_id,
|
|
state.http.clone(),
|
|
state.http.clone(),
|
|
@@ -153,13 +158,12 @@ impl AudioState {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- pub async fn send_track_command(
|
|
|
|
|
|
+ pub async fn skip(
|
|
audio_state: Arc<Mutex<AudioState>>,
|
|
audio_state: Arc<Mutex<AudioState>>,
|
|
- cmd: TrackCommand,
|
|
|
|
) -> Result<(), String> {
|
|
) -> Result<(), String> {
|
|
let state = audio_state.lock().await;
|
|
let state = audio_state.lock().await;
|
|
match state.track_handle.as_ref() {
|
|
match state.track_handle.as_ref() {
|
|
- Some(track_handle) => match track_handle.send(cmd) {
|
|
|
|
|
|
+ Some(track_handle) => match track_handle.stop() {
|
|
Ok(()) => Ok(()),
|
|
Ok(()) => Ok(()),
|
|
Err(why) => Err(format!("{:?}", why)),
|
|
Err(why) => Err(format!("{:?}", why)),
|
|
},
|
|
},
|
|
@@ -167,6 +171,59 @@ impl AudioState {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ pub async fn pause(
|
|
|
|
+ audio_state: Arc<Mutex<AudioState>>,
|
|
|
|
+ ) -> Result<(), String> {
|
|
|
|
+ let state = audio_state.lock().await;
|
|
|
|
+ match state.track_handle.as_ref() {
|
|
|
|
+ Some(track_handle) => match track_handle.pause() {
|
|
|
|
+ Ok(()) => Ok(()),
|
|
|
|
+ Err(why) => Err(format!("{:?}", why)),
|
|
|
|
+ },
|
|
|
|
+ None => Err("no song currently playing".to_string()),
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ pub async fn play(
|
|
|
|
+ audio_state: Arc<Mutex<AudioState>>,
|
|
|
|
+ ) -> Result<(), String> {
|
|
|
|
+ let state = audio_state.lock().await;
|
|
|
|
+ match state.track_handle.as_ref() {
|
|
|
|
+ Some(track_handle) => match track_handle.play() {
|
|
|
|
+ Ok(()) => Ok(()),
|
|
|
|
+ Err(why) => Err(format!("{:?}", why)),
|
|
|
|
+ },
|
|
|
|
+ None => Err("no song currently playing".to_string()),
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ pub async fn vote_skip(audio_state: Arc<Mutex<AudioState>>, user: User, total_users: usize) -> Result<(), String> {
|
|
|
|
+ let audio_state_tmp = audio_state.clone();
|
|
|
|
+ let mut state = audio_state_tmp.lock().await;
|
|
|
|
+ if state.skip_votes.contains(&user) {
|
|
|
|
+ Err("You already voted to skip".to_string())
|
|
|
|
+ } else {
|
|
|
|
+ state.skip_votes.insert(user);
|
|
|
|
+
|
|
|
|
+ if state.skip_votes.len() > total_users / 2 {
|
|
|
|
+ let text = match &state.current_song {
|
|
|
|
+ Some(song) => song.get_string(),
|
|
|
|
+ None => "".to_string(),
|
|
|
|
+ };
|
|
|
|
+ send_embed_http(
|
|
|
|
+ state.channel_id,
|
|
|
|
+ state.http.clone(),
|
|
|
|
+ &format!("Skipping:\n\n {}", text),
|
|
|
|
+ )
|
|
|
|
+ .await;
|
|
|
|
+ drop(state);
|
|
|
|
+ AudioState::skip(audio_state).await
|
|
|
|
+ } else {
|
|
|
|
+ Ok(())
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
pub async fn shuffle(audio_state: Arc<Mutex<AudioState>>) -> Result<(), String> {
|
|
pub async fn shuffle(audio_state: Arc<Mutex<AudioState>>) -> Result<(), String> {
|
|
let mut state = audio_state.lock().await;
|
|
let mut state = audio_state.lock().await;
|
|
state.queue.shuffle()
|
|
state.queue.shuffle()
|