use std::os::raw::c_int;
use std::slice::from_raw_parts;
use std::ptr::null_mut;
use ::header::{read_header_setup, read_header_ident, IdentHeader, SetupHeader};
use ::audio::{PreviousWindowRight, read_audio_packet_generic};
pub struct LewtonContext {
pwr :PreviousWindowRight,
ident_hdr :IdentHeader,
setup_hdr :SetupHeader,
}
fn read_xiph_lacing(arr :&mut &[u8]) -> Option<u64> {
let mut r = 0;
loop {
if arr.len() == 0 {
return None;
}
let v = arr[0] as u64;
*arr = &arr[1..];
r += v;
if v < 255 {
return Some(r);
}
}
}
impl LewtonContext {
fn from_extradata(mut extradata :&[u8]) -> Option<Self> {
if extradata.len() == 0 || extradata[0] != 2 {
return None
}
extradata = &extradata[1..];
let ident_len = read_xiph_lacing(&mut extradata)? as usize;
let comment_len = read_xiph_lacing(&mut extradata)? as usize;
let ident_hdr = read_header_ident(&extradata[0..ident_len]).ok()?;
extradata = &extradata[ident_len..];
extradata = &extradata[comment_len..];
let setup_hdr = read_header_setup(extradata, ident_hdr.audio_channels,
(ident_hdr.blocksize_0, ident_hdr.blocksize_1))
.ok()?;
Some(LewtonContext {
pwr : PreviousWindowRight::new(),
ident_hdr,
setup_hdr,
})
}
}
pub struct LewtonSamples(Vec<Vec<f32>>);
#[no_mangle]
pub unsafe extern fn lewton_context_from_extradata(
data :*const u8, len :usize) -> *mut LewtonContext {
if data.is_null() {
return null_mut();
}
let extradata = from_raw_parts(data, len);
if let Some(cx) = LewtonContext::from_extradata(extradata) {
let boxed = Box::new(cx);
Box::into_raw(boxed)
} else {
null_mut()
}
}
#[no_mangle]
pub unsafe extern fn lewton_context_reset(ctx :*mut LewtonContext) {
(*ctx).pwr = PreviousWindowRight::new();
}
#[no_mangle]
pub unsafe extern fn lewton_decode_packet(ctx :*mut LewtonContext,
pkt :*const u8, len: usize,
sample_out :*mut *mut LewtonSamples) -> c_int {
if pkt.is_null() || ctx.is_null() || sample_out.is_null() {
return 1;
}
let pkt = from_raw_parts(pkt, len);
let decoded = read_audio_packet_generic(&(*ctx).ident_hdr,
&(*ctx).setup_hdr, &pkt, &mut (*ctx).pwr);
let decoded = if let Ok(v) = decoded {
v
} else {
return 2;
};
let boxed = Box::new(LewtonSamples(decoded));
*sample_out = Box::into_raw(boxed);
return 0;
}
#[no_mangle]
pub unsafe extern fn lewton_samples_count(samples :*const LewtonSamples) -> usize {
(*samples).0
.get(0)
.map(|v| v.len())
.unwrap_or(0)
}
pub unsafe extern fn lewton_samples_f32(samples :*const LewtonSamples, channel :usize) -> *const f32 {
(*samples).0
.get(channel)
.map(|v| v.as_ptr())
.unwrap_or(std::ptr::null())
}
#[no_mangle]
pub unsafe extern fn lewton_samples_drop(samples :*mut LewtonSamples) {
std::mem::drop(Box::from_raw(samples));
}
#[no_mangle]
pub unsafe extern fn lewton_context_drop(ctx :*mut LewtonContext) {
std::mem::drop(Box::from_raw(ctx));
}