use session::Session; use stream; use util::FileId; use byteorder::{BigEndian, WriteBytesExt}; use std::io::Write; const CHUNK_SIZE: usize = 0x20000; pub enum Response { // Wait(H), Continue(H), Seek(H, usize), Close, } pub trait Handler : Sized + Send + 'static { fn on_header(self, header_id: u8, header_data: &[u8], session: &Session) -> Response; fn on_data(self, offset: usize, data: &[u8], session: &Session) -> Response; fn on_eof(self, session: &Session) -> Response; fn on_error(self, session: &Session); } pub struct AudioFile { handler: H, file_id: FileId, offset: usize, } impl AudioFile { pub fn new(file_id: FileId, offset: usize, handler: H, session: &Session) { let handler = AudioFile { handler: handler, file_id: file_id, offset: offset, }; session.stream(Box::new(handler)); } } impl stream::Handler for AudioFile { fn on_create(self, channel_id: stream::ChannelId, session: &Session) -> stream::Response { debug!("Got channel {}", channel_id); let mut data: Vec = Vec::new(); data.write_u16::(channel_id).unwrap(); data.write_u8(0).unwrap(); data.write_u8(1).unwrap(); data.write_u16::(0x0000).unwrap(); data.write_u32::(0x00000000).unwrap(); data.write_u32::(0x00009C40).unwrap(); data.write_u32::(0x00020000).unwrap(); data.write(&self.file_id.0).unwrap(); data.write_u32::(self.offset as u32 / 4).unwrap(); data.write_u32::((self.offset + CHUNK_SIZE) as u32 / 4).unwrap(); session.send_packet(0x8, &data).unwrap(); stream::Response::Continue(self) } fn on_header(mut self, header_id: u8, header_data: &[u8], session: &Session) -> stream::Response { match self.handler.on_header(header_id, header_data, session) { Response::Continue(handler) => { self.handler = handler; stream::Response::Continue(self) } Response::Seek(handler, offset) => { self.handler = handler; self.offset = offset; stream::Response::Spawn(self) } Response::Close => stream::Response::Close, } } fn on_data(mut self, data: &[u8], session: &Session) -> stream::Response { match self.handler.on_data(self.offset, data, session) { Response::Continue(handler) => { self.handler = handler; self.offset += data.len(); stream::Response::Continue(self) } Response::Seek(handler, offset) => { self.handler = handler; self.offset = offset; stream::Response::Spawn(self) } Response::Close => stream::Response::Close, } } fn on_close(self, _session: &Session) -> stream::Response { // End of chunk, request a new one stream::Response::Spawn(self) } fn on_error(mut self, session: &Session) -> stream::Response { match self.handler.on_eof(session) { Response::Continue(_) => stream::Response::Close, Response::Seek(handler, offset) => { self.handler = handler; self.offset = offset; stream::Response::Spawn(self) } Response::Close => stream::Response::Close, } } fn box_on_create(self: Box, channel_id: stream::ChannelId, session: &Session) -> stream::Response> { self.on_create(channel_id, session).boxed() } fn box_on_header(self: Box, header_id: u8, header_data: &[u8], session: &Session) -> stream::Response> { self.on_header(header_id, header_data, session).boxed() } fn box_on_data(self: Box, data: &[u8], session: &Session) -> stream::Response> { self.on_data(data, session).boxed() } fn box_on_error(self: Box, session: &Session) -> stream::Response> { self.on_error(session).boxed() } fn box_on_close(self: Box, session: &Session) -> stream::Response> { self.on_close(session).boxed() } }