use crate::space::*;
use lv2_core::port::PortType;
use std::ffi::c_void;
use std::ptr::NonNull;
use urid::URID;
pub struct PortReader<'a> {
space: Space<'a>,
}
impl<'a> PortReader<'a> {
fn new(space: Space<'a>) -> Self {
Self { space }
}
pub fn read<'b, A: crate::Atom<'a, 'b>>(
&'b self,
urid: URID<A>,
parameter: A::ReadParameter,
) -> Option<A::ReadHandle> {
A::read(self.space.split_atom_body(urid)?.0, parameter)
}
}
pub struct PortWriter<'a> {
space: RootMutSpace<'a>,
has_been_written: bool,
}
impl<'a> PortWriter<'a> {
fn new(space: RootMutSpace<'a>) -> Self {
Self {
space,
has_been_written: false,
}
}
pub fn init<'b, A: crate::Atom<'a, 'b>>(
&'b mut self,
urid: URID<A>,
parameter: A::WriteParameter,
) -> Option<A::WriteHandle> {
if !self.has_been_written {
self.has_been_written = true;
(&mut self.space as &mut dyn MutSpace).init(urid, parameter)
} else {
None
}
}
}
pub struct AtomPort;
impl PortType for AtomPort {
type InputPortType = PortReader<'static>;
type OutputPortType = PortWriter<'static>;
unsafe fn input_from_raw(pointer: NonNull<c_void>, _sample_count: u32) -> PortReader<'static> {
let space = Space::from_atom(pointer.cast().as_ref());
PortReader::new(space)
}
unsafe fn output_from_raw(pointer: NonNull<c_void>, _sample_count: u32) -> PortWriter<'static> {
let space = RootMutSpace::from_atom(pointer.cast().as_mut());
PortWriter::new(space)
}
}
#[cfg(test)]
mod tests {
use crate::prelude::*;
use crate::space::*;
use lv2_core::prelude::*;
use std::mem::size_of;
use std::ptr::NonNull;
use urid::*;
#[test]
fn test_atom_port() {
let map = HashURIDMapper::new();
let urids = AtomURIDCollection::from_map(&map).unwrap();
let mut raw_space: Box<[u8]> = Box::new([0; 256]);
{
let mut space = RootMutSpace::new(raw_space.as_mut());
let mut writer = (&mut space as &mut dyn MutSpace)
.init(urids.chunk, ())
.unwrap();
writer
.allocate(256 - size_of::<sys::LV2_Atom>(), false)
.unwrap();
}
{
let mut writer =
unsafe { AtomPort::output_from_raw(NonNull::from(raw_space.as_mut()).cast(), 0) };
writer.init::<Int>(urids.int, 42).unwrap();
}
{
let reader =
unsafe { AtomPort::input_from_raw(NonNull::from(raw_space.as_mut()).cast(), 0) };
assert_eq!(reader.read::<Int>(urids.int, ()).unwrap(), 42);
}
}
}