diff --git a/src/channel.rs b/src/channel.rs index 6c45f5d..7d8d33f 100644 --- a/src/channel.rs +++ b/src/channel.rs @@ -12,11 +12,11 @@ impl Requester { pub fn send(&self, data: T) -> Result, SendError> { let (response_tx, response_rx) = mpsc::channel(); match self.tx.send(Request { - data, + data: Some(data), tx: response_tx, }) { Ok(_) => Ok(Response { rx: response_rx }), - Err(e) => Err(SendError(e.0.data)), + Err(e) => Err(SendError(e.0.data.unwrap())), } } } @@ -47,7 +47,7 @@ pub fn channel() -> (Requester, Responder) { } pub struct Request { - pub data: T, + pub data: Option, tx: Sender, } diff --git a/src/download.rs b/src/download.rs index e67172c..501839c 100644 --- a/src/download.rs +++ b/src/download.rs @@ -1,6 +1,6 @@ use std::{path::Path, process::Command}; -use crate::{file::FileHandle, track::Track}; +use crate::{file::FileHandle, track::{Track, TrackInfo}}; #[derive(Debug, Clone, Copy)] pub struct DownloadError; @@ -17,6 +17,7 @@ pub fn download_from_youtube(url: &str) -> Result { "%(id)s", "--no-simulate", "--no-playlist", + "--no-warnings", "--", url, ]) @@ -24,6 +25,8 @@ pub fn download_from_youtube(url: &str) -> Result { .unwrap(); if !output.stderr.is_empty() || output.stdout.is_empty() { + println!("{}", std::str::from_utf8(output.stderr.as_slice()).unwrap()); + println!("{}", std::str::from_utf8(output.stdout.as_slice()).unwrap()); return Err(DownloadError); } @@ -32,7 +35,10 @@ pub fn download_from_youtube(url: &str) -> Result { .replace('\n', "") + ".mp3"; - let file_handle = FileHandle::new(Path::new(filename.as_str())); + println!("{}", filename); - Ok(Track::new(file_handle)) + let file_handle = FileHandle::new(Path::new(filename.as_str())); + let info = TrackInfo::new(&filename); + + Ok(Track::new(info, file_handle)) } diff --git a/src/player.rs b/src/player.rs index f2edbbc..4ea60a7 100644 --- a/src/player.rs +++ b/src/player.rs @@ -2,9 +2,9 @@ use rodio::{Decoder, OutputStream, OutputStreamHandle, Sink}; use std::{collections::VecDeque, fs::File, io::BufReader, thread, thread::JoinHandle}; use crate::channel::{self, Requester, Responder, TryRecvError}; -use crate::track::Track; +use crate::track::{Track, TrackInfo}; -#[derive(Debug, Clone)] +#[derive(Debug)] enum WorkerRequest { AddTrack(Track), Pause, @@ -14,9 +14,9 @@ enum WorkerRequest { ListTracks, } -#[derive(Debug, Clone)] +#[derive(Debug)] enum WorkerResponse { - TrackList(VecDeque), + TrackList(VecDeque), None, } @@ -25,7 +25,7 @@ use WorkerResponse::*; pub struct MusicPlayer { requester: Requester, - _worker: JoinHandle<()>, + worker: Option>, } struct Worker { @@ -33,10 +33,11 @@ struct Worker { _handle: OutputStreamHandle, sink: Sink, queue: VecDeque, + current: Option, responder: Responder, } -fn get_source(track: Track) -> Decoder> { +fn get_source(track: &Track) -> Decoder> { let file = BufReader::new(File::open(track.file.get_path()).unwrap()); Decoder::new(file).unwrap() } @@ -59,28 +60,34 @@ impl Worker { Stop => { self.sink.stop(); self.queue.clear(); + self.current.take(); None } SkipOne => { self.sink.skip_one(); + self.current.take(); None } - ListTracks => TrackList(self.queue.clone()), + ListTracks => TrackList(self.queue.iter().map(|track| track.info.clone()).collect::>().clone()), } } pub fn main(&mut self) { loop { match self.responder.try_recv() { - Ok(req) => { - let _ = req.respond(self.match_request(req.data.clone())); + Ok(mut req) => { + let data = req.data.take().unwrap(); + let _ = req.respond(self.match_request(data)); } Err(TryRecvError::Empty) => {} Err(TryRecvError::Disconnected) => break, }; if self.sink.empty() && !self.queue.is_empty() { let next_track = self.queue.pop_front().unwrap(); - self.sink.append(get_source(next_track)); + self.sink.append(get_source(&next_track)); + self.current = Some(next_track); + } else if self.sink.empty() { + self.current.take(); } } } @@ -94,6 +101,7 @@ impl Worker { _handle, sink, queue, + current: Option::None, responder, } } @@ -102,8 +110,8 @@ impl Worker { impl MusicPlayer { pub fn build() -> MusicPlayer { let (requester, responder) = channel::channel(); - let _worker = thread::spawn(move || Worker::build(responder).main()); - MusicPlayer { requester, _worker } + let worker = thread::spawn(move || Worker::build(responder).main()); + MusicPlayer { requester, worker: Some(worker) } } pub fn enqueue(&mut self, track: Track) { @@ -126,7 +134,7 @@ impl MusicPlayer { self.requester.send(Stop).unwrap(); } - pub fn list_tracks(&self) -> VecDeque { + pub fn list_tracks(&self) -> VecDeque { let response = self.requester.send(ListTracks).unwrap(); match response.recv().unwrap() { TrackList(tracks) => tracks, @@ -134,3 +142,10 @@ impl MusicPlayer { } } } + +impl Drop for MusicPlayer { + fn drop(&mut self) { + self.stop(); + self.worker.take().unwrap().join().unwrap(); + } +} diff --git a/src/telegram.rs b/src/telegram.rs index cd82a21..076c812 100644 --- a/src/telegram.rs +++ b/src/telegram.rs @@ -74,7 +74,7 @@ impl TelegramBot { } else { message = tracks .iter() - .map(|t| t.file.get_path().to_str().unwrap()) + .map(|t| t.name.as_str()) .collect::>() .join("\n"); } diff --git a/src/track.rs b/src/track.rs index df1d0e5..820abc9 100644 --- a/src/track.rs +++ b/src/track.rs @@ -1,12 +1,24 @@ use crate::file::FileHandle; #[derive(Debug, Clone)] +pub struct TrackInfo { + pub name: String, +} + +impl TrackInfo { + pub fn new(name: &str) -> TrackInfo { + TrackInfo { name: String::from(name) } + } +} + +#[derive(Debug)] pub struct Track { + pub info: TrackInfo, pub file: FileHandle, } impl Track { - pub fn new(file: FileHandle) -> Track { - Track { file } + pub fn new(info: TrackInfo, file: FileHandle) -> Track { + Track { info, file } } }