use core::{ffi::CStr, slice};
use crate::ffi::program_vector as ffi;
pub use ffi::MemorySegment;
#[repr(u8)]
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, num_derive :: FromPrimitive)]
pub enum ProgramVectorChecksum {
V11 = ffi::PROGRAM_VECTOR_CHECKSUM_V11 as u8,
V12 = ffi::PROGRAM_VECTOR_CHECKSUM_V12 as u8,
V13 = ffi::PROGRAM_VECTOR_CHECKSUM_V13 as u8,
}
pub const OWL_PEDAL_HARDWARE: u8 = ffi::OWL_PEDAL_HARDWARE as u8;
pub const OWL_MODULAR_HARDWARE: u8 = ffi::OWL_MODULAR_HARDWARE as u8;
pub const OWL_RACK_HARDWARE: u8 = ffi::OWL_RACK_HARDWARE as u8;
pub const PRISM_HARDWARE: u8 = ffi::PRISM_HARDWARE as u8;
pub const PLAYER_HARDWARE: u8 = ffi::PLAYER_HARDWARE as u8;
pub struct Meta {
cycles_per_block: &'static u32,
heap_bytes_used: &'static mut u32,
checksum: ProgramVectorChecksum,
hardware_version: u8,
heap_locations: *mut MemorySegment,
register_patch: Option<
unsafe extern "C" fn(
name: *const ::core::ffi::c_char,
input_channels: u8,
output_channels: u8,
),
>,
}
unsafe impl Send for Meta {}
impl Meta {
pub(crate) fn new(
cycles_per_block: &'static u32,
heap_bytes_used: &'static mut u32,
checksum: ProgramVectorChecksum,
hardware_version: u8,
heap_locations: *mut MemorySegment,
register_patch: Option<
unsafe extern "C" fn(
name: *const ::core::ffi::c_char,
input_channels: u8,
output_channels: u8,
),
>,
) -> Self {
Self {
cycles_per_block,
heap_bytes_used,
checksum,
hardware_version,
heap_locations,
register_patch,
}
}
pub fn register_patch(&self, patch_name: &CStr) {
if let Some(register_patch) = self.register_patch {
unsafe { register_patch(patch_name.as_ptr(), 2, 2) };
}
}
pub fn set_heap_bytes_used(&mut self, value: usize) {
*self.heap_bytes_used = value as u32;
}
pub fn cycles_per_block(&self) -> u32 {
*self.cycles_per_block
}
pub fn checksum(&self) -> ProgramVectorChecksum {
self.checksum
}
pub fn hardware_version(&self) -> u8 {
self.hardware_version
}
pub fn memory_segments(&self) -> &[MemorySegment] {
const MAX: usize = 5;
let count = (0..MAX)
.take_while(|i| {
if let Some(segment) = unsafe { self.heap_locations.add(*i).as_ref() } {
!segment.location.is_null()
} else {
false
}
})
.last()
.unwrap_or_else(|| {
panic!("pv.heapLocations.is_null");
});
unsafe { slice::from_raw_parts(self.heap_locations, count + 1) }
}
}