use {
anyhow::{Context, Result},
nix::{ioctl_write_int_bad, ioctl_none_bad, ioctl_write_ptr, request_code_none},
std::{
fs::{File, OpenOptions},
os::unix::{
fs::{OpenOptionsExt},
io::{AsRawFd, RawFd},
},
},
sys::*,
};
pub mod sys;
#[derive(Debug)]
pub struct DmxDevice {
file: File,
}
impl AsRawFd for DmxDevice {
#[inline]
fn as_raw_fd(&self) -> RawFd {
self.file.as_raw_fd()
}
}
impl DmxDevice {
fn open(adapter: u32, device: u32, is_write: bool) -> Result<Self> {
let path = format!("/dev/dvb/adapter{}/demux{}", adapter, device);
let file = OpenOptions::new()
.read(true)
.write(is_write)
.custom_flags(::nix::libc::O_NONBLOCK)
.open(&path)
.with_context(|| format!("DMX: failed to open device {}", &path))?;
Ok(DmxDevice {
file,
})
}
#[inline]
pub fn open_ro(adapter: u32, device: u32) -> Result<Self> {
Self::open(adapter, device, false)
}
#[inline]
pub fn open_rw(adapter: u32, device: u32) -> Result<Self> {
Self::open(adapter, device, true)
}
pub fn set_pes_filter(&self, filter: &DmxPesFilterParams) -> Result<()> {
ioctl_write_ptr!(
#[inline]
ioctl_call,
b'o',
44,
DmxPesFilterParams
);
unsafe { ioctl_call(self.as_raw_fd(), filter as *const _) }.context("DMX: set PES filter")?;
Ok(())
}
pub fn add_pid(&self, pid: u16) -> Result<()> {
ioctl_write_ptr!(
#[inline]
ioctl_call,
b'o',
51,
u16
);
unsafe { ioctl_call(self.as_raw_fd(), &pid as *const _) }.context("DMX: add PID")?;
Ok(())
}
pub fn remove_pid(&self, pid: u16) -> Result<()> {
ioctl_write_ptr!(
#[inline]
ioctl_call,
b'o',
52,
u16
);
unsafe { ioctl_call(self.as_raw_fd(), &pid as *const _) }.context("DMX: remove PID")?;
Ok(())
}
pub fn set_filter(&self, filter: &DmxSctFilterParams) -> Result<()> {
ioctl_write_ptr!(
#[inline]
ioctl_call,
b'o',
43,
DmxSctFilterParams
);
unsafe { ioctl_call(self.as_raw_fd(), filter as *const _) }.context("DMX: set SCT filter")?;
Ok(())
}
pub fn set_buffer_size(&self, size: u32) -> Result<()> {
ioctl_write_int_bad!(
#[inline]
ioctl_call,
request_code_none!(b'o', 45)
);
unsafe { ioctl_call(self.as_raw_fd(), size as _) }.context("DMX: set buffer size")?;
Ok(())
}
pub fn start(&self) -> Result<()> {
ioctl_none_bad!(
#[inline]
ioctl_call,
request_code_none!(b'o', 41)
);
unsafe { ioctl_call(self.as_raw_fd()) }.context("DMX: start")?;
Ok(())
}
pub fn stop(&self) -> Result<()> {
ioctl_none_bad!(
#[inline]
ioctl_call,
request_code_none!(b'o', 42)
);
unsafe { ioctl_call(self.as_raw_fd()) }.context("DMX: stop")?;
Ok(())
}
}