audio_state.rs 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. use std::{
  2. sync::Arc,
  3. mem::drop,
  4. };
  5. use rand::seq::SliceRandom;
  6. use super::{
  7. song_queue::SongQueue,
  8. song::{
  9. Song,
  10. },
  11. song_searcher::{
  12. process_query,
  13. song_recommender,
  14. },
  15. subprocess::ffmpeg_pcm,
  16. };
  17. use crate::util::send_embed_http;
  18. use songbird::{Call, Event, EventContext, EventHandler as VoiceEventHandler, TrackEvent,
  19. input::{
  20. self,
  21. reader::Reader,
  22. },
  23. tracks::{
  24. TrackHandle,
  25. TrackCommand,
  26. }
  27. };
  28. use tokio::sync::Mutex;
  29. use serenity::{
  30. async_trait,
  31. prelude::{
  32. Mutex as SerenityMutex,
  33. },
  34. http::Http,
  35. client::Context,
  36. model::{
  37. id::ChannelId,
  38. channel::Message,
  39. },
  40. };
  41. pub struct AudioState{
  42. queue: SongQueue,
  43. handler: Arc<SerenityMutex<Call>>,
  44. current_song: Mutex<Option<Song>>,
  45. track_handle: Mutex<Option<TrackHandle>>,
  46. is_looping: Mutex<bool>,
  47. channel_id: Mutex<ChannelId>,
  48. http: Mutex<Arc<Http>>,
  49. }
  50. impl AudioState{
  51. pub fn new(handler: Arc<SerenityMutex<Call>>, ctx: &Context, msg: &Message) -> Arc<AudioState>{
  52. let audio_state = AudioState{
  53. queue: SongQueue::new(),
  54. handler,
  55. current_song: Mutex::new(None),
  56. track_handle: Mutex::new(None),
  57. is_looping: Mutex::new(false),
  58. channel_id: Mutex::new(msg.channel_id),
  59. http: Mutex::new(ctx.http.clone()),
  60. };
  61. let audio_state = Arc::new(audio_state);
  62. {
  63. let audio_state = audio_state.clone();
  64. tokio::spawn(async {
  65. AudioState::play_audio(audio_state).await;
  66. });
  67. }
  68. audio_state
  69. }
  70. pub async fn set_context(audio_state: Arc<AudioState>, ctx: &Context, msg: &Message){
  71. {
  72. let mut channel_id = audio_state.channel_id.lock().await;
  73. *channel_id = msg.channel_id;
  74. }
  75. {
  76. let mut http = audio_state.http.lock().await;
  77. *http = ctx.http.clone();
  78. }
  79. }
  80. async fn play_audio(audio_state: Arc<AudioState>){
  81. let is_looping = audio_state.is_looping.lock().await;
  82. let mut song = if *is_looping{
  83. let mut current_song = audio_state.current_song.lock().await;
  84. current_song.take().expect("logical error: expected current_song to be non-empty")
  85. }else{
  86. audio_state.queue.pop().await
  87. };
  88. drop(is_looping);
  89. let url = song.get_url().await;
  90. let source = ffmpeg_pcm(url).await;
  91. let source = match source {
  92. Ok(source) => source,
  93. Err(why) => {
  94. println!("Error in AudioState::play_audio: {}",why);
  95. return
  96. }
  97. };
  98. let reader = Reader::Extension(source);
  99. let source = input::Input::float_pcm(true, reader);
  100. let mut handler = audio_state.handler.lock().await;
  101. let handle = handler.play_source(source);
  102. if let Err(why) = handle.add_event(
  103. Event::Track(TrackEvent::End),
  104. SongEndNotifier{
  105. audio_state: audio_state.clone(),
  106. }
  107. ){
  108. panic!("Err AudioState::play_audio: {:?}", why);
  109. }
  110. {
  111. let text = song.get_string().await;
  112. let channel_id = audio_state.channel_id.lock().await;
  113. let http = audio_state.http.lock().await;
  114. send_embed_http(*channel_id, http.clone(), &format!(
  115. "Now playing:\n\n {}", text
  116. )).await;
  117. }
  118. {
  119. let mut current_song = audio_state.current_song.lock().await;
  120. *current_song = Some(song);
  121. let mut track_handle = audio_state.track_handle.lock().await;
  122. *track_handle = Some(handle);
  123. }
  124. }
  125. pub async fn add_audio(audio_state: Arc<AudioState>, query: &str, shuffle: bool){
  126. let mut songs = match process_query(query).await{
  127. Ok(songs) => songs,
  128. Err(why) => {
  129. println!("Error add_audio: {}", why);
  130. return;
  131. },
  132. };
  133. if shuffle {
  134. songs.shuffle(&mut rand::thread_rng());
  135. }
  136. audio_state.queue.push(songs).await;
  137. }
  138. pub async fn add_recommended_songs(audio_state: Arc<AudioState>, query: &str, amount: usize){
  139. let songs = match song_recommender(query, amount).await{
  140. Ok(songs) => songs,
  141. Err(why) => {
  142. println!("Error add_recommended_songs: {}", why);
  143. return;
  144. },
  145. };
  146. audio_state.queue.push(songs).await;
  147. }
  148. pub async fn extend_songs(audio_state: Arc<AudioState>, query: &str, extend_ratio: f64){
  149. let mut songs = match process_query(query).await{
  150. Ok(songs) => songs,
  151. Err(why) => {
  152. println!("Error extend_songs: {}", why);
  153. return;
  154. },
  155. };
  156. let recommended_songs = match song_recommender(query, (songs.len() as f64 * extend_ratio) as usize).await{
  157. Ok(songs) => songs,
  158. Err(why) => {
  159. println!("Error add_recommended_songs: {}", why);
  160. return;
  161. },
  162. };
  163. songs.extend(recommended_songs);
  164. songs.shuffle(&mut rand::thread_rng());
  165. audio_state.queue.push(songs).await;
  166. }
  167. pub async fn send_track_command(audio_state: Arc<AudioState>, cmd: TrackCommand) -> Result<(), String>{
  168. let track_handle = audio_state.track_handle.lock().await;
  169. match &*track_handle {
  170. Some(track_handle) => {
  171. match track_handle.send(cmd){
  172. Ok(()) => Ok(()),
  173. Err(why) => Err(format!("{:?}",why))
  174. }
  175. },
  176. None => Err("no song currently playing".to_string())
  177. }
  178. }
  179. pub async fn shuffle(audio_state: Arc<AudioState>) -> Result<(), String>{
  180. audio_state.queue.shuffle().await
  181. }
  182. pub async fn clear(audio_state: Arc<AudioState>) -> Result<(), String>{
  183. audio_state.queue.clear().await
  184. }
  185. pub async fn change_looping(audio_state: Arc<AudioState>) -> Result<bool, String>{
  186. {
  187. let current_song = audio_state.current_song.lock().await;
  188. if current_song.is_none() {
  189. return Err("no song is playing".to_string());
  190. }
  191. }
  192. let mut is_looping = audio_state.is_looping.lock().await;
  193. *is_looping = !*is_looping;
  194. Ok(*is_looping)
  195. /*
  196. if looping{
  197. if *is_looping{
  198. Err("already looping".to_string())
  199. }else{
  200. *is_looping = true;
  201. Ok(())
  202. }
  203. }else{
  204. if !*is_looping{
  205. Err("not looping at the moment".to_string())
  206. }else{
  207. *is_looping = false;
  208. Ok(())
  209. }
  210. }*/
  211. }
  212. pub async fn cleanup(audio_state: Arc<AudioState>) {
  213. audio_state.queue.cleanup().await;
  214. }
  215. pub async fn get_string(audio_state: Arc<AudioState>) -> String {
  216. let current_song = audio_state.current_song.lock().await;
  217. let current_song = match &*current_song {
  218. Some(song) => song.get_string().await,
  219. None => "*Not playing*\n".to_string(),
  220. };
  221. format!("**Current Song:**\n{}\n\n**Queue:**\n{}", current_song, audio_state.queue.get_string().await)
  222. }
  223. }
  224. struct SongEndNotifier {
  225. //chan_id: ChannelId,
  226. //http: Arc<Http>,
  227. audio_state: Arc<AudioState>,
  228. }
  229. #[async_trait]
  230. impl VoiceEventHandler for SongEndNotifier {
  231. async fn act(&self, _ctx: &EventContext<'_>) -> Option<Event> {
  232. AudioState::play_audio(self.audio_state.clone()).await;
  233. None
  234. }
  235. }