Files
RedBear-OS/src/scheme.rs
T
2018-12-29 19:14:42 -07:00

86 lines
2.2 KiB
Rust

use std::collections::{BTreeMap, VecDeque};
use syscall::error::{EBADF, EWOULDBLOCK, Error, Result};
use syscall::flag::O_NONBLOCK;
use syscall::scheme::SchemeBlockMut;
// The strict buffer size of the hda: driver
const HDA_BUFFER_SIZE: usize = 512;
// The desired buffer size of each handle
const HANDLE_BUFFER_SIZE: usize = 4096;
struct Handle {
flags: usize,
buffer: VecDeque<(i16, i16)>,
}
pub struct AudioScheme {
next_id: usize,
handles: BTreeMap<usize, Handle>
}
impl AudioScheme {
pub fn new() -> Self {
AudioScheme {
next_id: 0,
handles: BTreeMap::new()
}
}
pub fn buffer(&mut self) -> [(i16, i16); HDA_BUFFER_SIZE] {
let mut buffer = [(0i16, 0i16); HDA_BUFFER_SIZE];
for (_id, handle) in self.handles.iter_mut() {
let mut i = 0;
while i < buffer.len() {
if let Some(sample) = handle.buffer.pop_front() {
buffer[i].0 = buffer[i].0.saturating_add(sample.0);
buffer[i].1 = buffer[i].1.saturating_add(sample.1);
} else {
break;
}
i += 1;
}
}
buffer
}
}
impl SchemeBlockMut for AudioScheme {
fn open(&mut self, _path: &[u8], flags: usize, _uid: u32, _gid: u32) -> Result<Option<usize>> {
self.next_id += 1;
let id = self.next_id;
self.handles.insert(id, Handle {
flags,
buffer: VecDeque::new()
});
Ok(Some(id))
}
fn write(&mut self, id: usize, buf: &[u8]) -> Result<Option<usize>> {
let handle = self.handles.get_mut(&id).ok_or(Error::new(EBADF))?;
if handle.buffer.len() >= HANDLE_BUFFER_SIZE {
if handle.flags & O_NONBLOCK > 0 {
Err(Error::new(EWOULDBLOCK))
} else {
Ok(None)
}
} else {
let mut i = 0;
while i + 4 <= buf.len() {
handle.buffer.push_back((
(buf[i] as i16) | ((buf[i + 1] as i16) << 8),
(buf[i + 2] as i16) | ((buf[i + 3] as i16) << 8)
));
i += 4;
}
Ok(Some(i))
}
}
}