diff --git a/src/audio_file.rs b/src/audio_file.rs index 5d79ff5e..c594f202 100644 --- a/src/audio_file.rs +++ b/src/audio_file.rs @@ -14,11 +14,16 @@ const CHUNK_SIZE : usize = 0x40000; #[derive(Clone)] pub struct AudioFile { - file: FileId, - size: usize, + position: usize, seek: mpsc::Sender, + shared: Arc, +} - data: Arc<(Mutex, Condvar)>, +struct AudioFileShared { + fileid: FileId, + size: usize, + data: Mutex, + cond: Condvar } struct AudioFileData { @@ -27,11 +32,11 @@ struct AudioFileData { } impl AudioFile { - pub fn new(file: FileId, streams: mpsc::Sender) -> AudioFile { + pub fn new(fileid: FileId, streams: mpsc::Sender) -> AudioFile { let (tx, rx) = mpsc::channel(); streams.send(StreamRequest { - id: file, + id: fileid, offset: 0, size: 1, callback: tx @@ -55,29 +60,32 @@ impl AudioFile { let bufsize = size + (CHUNK_SIZE - size % CHUNK_SIZE); let (tx, rx) = mpsc::channel(); - - let ret = AudioFile { - file: file, - size: size, - seek: tx, - data: Arc::new((Mutex::new(AudioFileData { + let shared = Arc::new(AudioFileShared { + fileid: fileid, + size: size, + data: Mutex::new(AudioFileData { buffer: vec![0u8; bufsize], bitmap: BitSet::with_capacity(bufsize / CHUNK_SIZE as usize) - }), Condvar::new())), + }), + cond: Condvar::new(), + }); + + let file = AudioFile { + position: 0, + seek: tx, + shared: shared.clone(), }; - let f = ret.clone(); + thread::spawn( move || { AudioFile::fetch(shared, streams, rx); }); - thread::spawn( move || { f.fetch(streams, rx); }); - - ret + file } - - fn fetch_chunk(&self, streams: &mpsc::Sender, index: usize) { + + fn fetch_chunk(shared: &Arc, streams: &mpsc::Sender, index: usize) { let (tx, rx) = mpsc::channel(); streams.send(StreamRequest { - id: self.file, + id: shared.fileid, offset: (index * CHUNK_SIZE / 4) as u32, size: (CHUNK_SIZE / 4) as u32, callback: tx @@ -88,7 +96,7 @@ impl AudioFile { match event { StreamEvent::Header(_,_) => (), StreamEvent::Data(data) => { - let mut handle = self.data.0.lock().unwrap(); + let mut handle = shared.data.lock().unwrap(); copy_memory(&data, &mut handle.buffer[index * CHUNK_SIZE + offset ..]); offset += data.len(); @@ -98,18 +106,18 @@ impl AudioFile { } } } - + { - let mut handle = self.data.0.lock().unwrap(); + let mut handle = shared.data.lock().unwrap(); handle.bitmap.insert(index as usize); - self.data.1.notify_all(); + shared.cond.notify_all(); } } - fn fetch(&self, streams: mpsc::Sender, seek: mpsc::Receiver) { + fn fetch(shared: Arc, streams: mpsc::Sender, seek: mpsc::Receiver) { let mut index = 0; loop { - index = if index * CHUNK_SIZE < self.size { + index = if index * CHUNK_SIZE < shared.size { match seek.try_recv() { Ok(position) => position as usize / CHUNK_SIZE, Err(TryRecvError::Empty) => index, @@ -123,43 +131,29 @@ impl AudioFile { }; { - let handle = self.data.0.lock().unwrap(); - while handle.bitmap.contains(&index) && index * CHUNK_SIZE < self.size { + let handle = shared.data.lock().unwrap(); + while handle.bitmap.contains(&index) && index * CHUNK_SIZE < shared.size { index += 1; } } - if index * CHUNK_SIZE < self.size { - self.fetch_chunk(&streams, index) + if index * CHUNK_SIZE < shared.size { + AudioFile::fetch_chunk(&shared, &streams, index) } } } } -pub struct AudioFileReader { - file: AudioFile, - position: usize, -} - -impl AudioFileReader { - pub fn new(file: AudioFile) -> AudioFileReader { - AudioFileReader { - file: file, - position: 0 - } - } -} - -impl io::Read for AudioFileReader { +impl io::Read for AudioFile { fn read(&mut self, output: &mut [u8]) -> io::Result { let index = self.position / CHUNK_SIZE; let offset = self.position % CHUNK_SIZE; let len = min(output.len(), CHUNK_SIZE-offset); - let mut handle = self.file.data.0.lock().unwrap(); + let mut handle = self.shared.data.lock().unwrap(); while !handle.bitmap.contains(&index) { - handle = self.file.data.1.wait(handle).unwrap(); + handle = self.shared.cond.wait(handle).unwrap(); } copy_memory(&handle.buffer[self.position..self.position+len], output); @@ -169,16 +163,16 @@ impl io::Read for AudioFileReader { } } -impl io::Seek for AudioFileReader { +impl io::Seek for AudioFile { fn seek(&mut self, pos: io::SeekFrom) -> io::Result { let newpos = match pos { SeekFrom::Start(offset) => offset as i64, - SeekFrom::End(offset) => self.file.size as i64 + offset, + SeekFrom::End(offset) => self.shared.size as i64 + offset, SeekFrom::Current(offset) => self.position as i64 + offset, }; - self.position = min(newpos as usize, self.file.size); - self.file.seek.send(self.position as u64).unwrap(); + self.position = min(newpos as usize, self.shared.size); + self.seek.send(self.position as u64).unwrap(); Ok(self.position as u64) } } diff --git a/src/player.rs b/src/player.rs index 668328c8..896fdc89 100644 --- a/src/player.rs +++ b/src/player.rs @@ -5,7 +5,7 @@ use vorbis; use audio_key::{AudioKeyRequest, AudioKeyResponse}; use metadata::TrackRef; use session::Session; -use audio_file::{AudioFile, AudioFileReader}; +use audio_file::AudioFile; use audio_decrypt::AudioDecrypt; use util::Subfile; @@ -32,8 +32,7 @@ impl Player { vorbis::Decoder::new( Subfile::new( AudioDecrypt::new(key, - AudioFileReader::new( - AudioFile::new(file_id, session.stream.clone()))), 0xa7)).unwrap(); + AudioFile::new(file_id, session.stream.clone())), 0xa7)).unwrap(); //decoder.time_seek(60f64).unwrap(); portaudio::initialize().unwrap();