use std::ffi::CStr;
use std::os::raw::c_void;
mod ffi;
#[repr(i32)]
pub enum SeekOptions {
None = 0,
Mpeg = 1 << 0,
Key = 1 << 1,
}
pub type Block = [u8; 2048];
#[repr(transparent)]
pub struct DVD {
ptr: ffi::dvdcss_t,
}
impl DVD {
pub fn new(location: &CStr) -> Option<Self> {
let ptr = unsafe { ffi::dvdcss_open(location.as_ptr()) };
match !ptr.is_null() {
true => Some(Self { ptr }),
false => None,
}
}
pub fn seek(&self, blocks: u32, flags: SeekOptions) -> Result<u32, ()> {
let val = unsafe { ffi::dvdcss_seek(self.ptr, blocks as i32, flags as i32) };
match val >= 0 {
true => Ok(val as u32),
false => Err(()),
}
}
pub fn read(&self, buffer: &mut [Block], decrypt: bool) -> Result<u32, ()> {
let val = unsafe {
ffi::dvdcss_read(
self.ptr,
buffer.as_mut_ptr() as *mut c_void,
buffer.len() as i32,
decrypt as i32,
)
};
match val >= 0 {
true => Ok(val as u32),
false => Err(()),
}
}
pub fn is_scrambled(&self) -> bool {
match unsafe { ffi::dvdcss_is_scrambled(self.ptr) } {
0 => false,
1 => true,
_ => unreachable!(),
}
}
pub fn latest_error(&self) -> &CStr {
unsafe { CStr::from_ptr(ffi::dvdcss_error(self.ptr)) }
}
}
impl Drop for DVD {
fn drop(&mut self) {
let val = unsafe { ffi::dvdcss_close(self.ptr) };
assert_eq!(val, 0);
}
}