From a44fe9cd193a6d33dda1e17e72b0331a64a17b32 Mon Sep 17 00:00:00 2001
From: Yruama_Lairba <yruama_lairba@hotmail.com>
Date: Wed, 26 Jan 2022 01:53:37 +0100
Subject: [PATCH 01/18] implement correct pointer behaviour for ports

---
 core/src/port.rs         | 29 +++++++++++++++++++----------
 core/src/port/audio.rs   | 40 +++++++++++++++++++++++++++-------------
 core/src/port/control.rs | 25 ++++++++++++++-----------
 core/src/port/cv.rs      | 40 ++++++++++++++++++++++------------------
 4 files changed, 82 insertions(+), 52 deletions(-)

diff --git a/core/src/port.rs b/core/src/port.rs
index 0c7c16e6..f3a7b04d 100644
--- a/core/src/port.rs
+++ b/core/src/port.rs
@@ -21,9 +21,9 @@ pub use lv2_core_derive::*;
 /// A port can read input or create a pointer to the output, but the exact type of input/output (pointer) depends on the type of port. This trait generalizes these types and behaviour.
 pub trait PortType {
     /// The type of input read by the port.
-    type InputPortType: Sized;
+    type InputPortType: ?Sized;
     /// The type of output reference created by the port.
-    type OutputPortType: Sized;
+    type OutputPortType: ?Sized;
 
     /// Read data from the pointer or create a reference to the input.
     ///
@@ -32,7 +32,10 @@ pub trait PortType {
     /// # Safety
     ///
     /// This method is unsafe because one needs to de-reference a raw pointer to implement this method.
-    unsafe fn input_from_raw(pointer: NonNull<c_void>, sample_count: u32) -> Self::InputPortType;
+    unsafe fn input_from_raw(
+        pointer: NonNull<c_void>,
+        sample_count: u32,
+    ) -> *const Self::InputPortType;
 
     /// Create a reference to the data where output should be written to.
     ///
@@ -41,7 +44,10 @@ pub trait PortType {
     /// # Safety
     ///
     /// This method is unsafe because one needs to de-reference a raw pointer to implement this method.
-    unsafe fn output_from_raw(pointer: NonNull<c_void>, sample_count: u32) -> Self::OutputPortType;
+    unsafe fn output_from_raw(
+        pointer: NonNull<c_void>,
+        sample_count: u32,
+    ) -> *mut Self::OutputPortType;
 }
 
 /// Abstraction of safe port handles.
@@ -60,7 +66,7 @@ pub trait PortHandle: Sized {
 ///
 /// Fields of this type can be dereferenced to the input type of the port type.
 pub struct InputPort<T: PortType> {
-    port: T::InputPortType,
+    port: *const T::InputPortType,
 }
 
 impl<T: PortType> Deref for InputPort<T> {
@@ -68,11 +74,14 @@ impl<T: PortType> Deref for InputPort<T> {
 
     #[inline]
     fn deref(&self) -> &Self::Target {
-        &self.port
+        unsafe { &*self.port }
     }
 }
 
-impl<T: PortType> PortHandle for InputPort<T> {
+impl<T> PortHandle for InputPort<T>
+where
+    T: PortType,
+{
     #[inline]
     unsafe fn from_raw(pointer: *mut c_void, sample_count: u32) -> Option<Self> {
         Some(Self {
@@ -85,7 +94,7 @@ impl<T: PortType> PortHandle for InputPort<T> {
 ///
 /// Fields of this type can be dereferenced to the output type of the port type.
 pub struct OutputPort<T: PortType> {
-    port: T::OutputPortType,
+    port: *mut T::OutputPortType,
 }
 
 impl<T: PortType> Deref for OutputPort<T> {
@@ -93,14 +102,14 @@ impl<T: PortType> Deref for OutputPort<T> {
 
     #[inline]
     fn deref(&self) -> &Self::Target {
-        &self.port
+        unsafe { &*self.port }
     }
 }
 
 impl<T: PortType> DerefMut for OutputPort<T> {
     #[inline]
     fn deref_mut(&mut self) -> &mut Self::Target {
-        &mut self.port
+        unsafe { &mut *self.port }
     }
 }
 
diff --git a/core/src/port/audio.rs b/core/src/port/audio.rs
index ac755e90..2f3c51c1 100644
--- a/core/src/port/audio.rs
+++ b/core/src/port/audio.rs
@@ -66,16 +66,22 @@ unsafe impl UriBound for Audio {
 }
 
 impl PortType for Audio {
-    type InputPortType = &'static [f32];
-    type OutputPortType = &'static mut [f32];
+    type InputPortType = [f32];
+    type OutputPortType = [f32];
 
     #[inline]
-    unsafe fn input_from_raw(pointer: NonNull<c_void>, sample_count: u32) -> Self::InputPortType {
+    unsafe fn input_from_raw(
+        pointer: NonNull<c_void>,
+        sample_count: u32,
+    ) -> *const Self::InputPortType {
         std::slice::from_raw_parts(pointer.as_ptr() as *const f32, sample_count as usize)
     }
 
     #[inline]
-    unsafe fn output_from_raw(pointer: NonNull<c_void>, sample_count: u32) -> Self::OutputPortType {
+    unsafe fn output_from_raw(
+        pointer: NonNull<c_void>,
+        sample_count: u32,
+    ) -> *mut Self::OutputPortType {
         std::slice::from_raw_parts_mut(pointer.as_ptr() as *mut f32, sample_count as usize)
     }
 }
@@ -132,11 +138,15 @@ unsafe impl UriBound for InPlaceAudio {
 }
 
 impl PortType for InPlaceAudio {
-    type InputPortType = &'static [Cell<f32>];
-    type OutputPortType = &'static [Cell<f32>];
+    type InputPortType = [Cell<f32>];
+    type OutputPortType = [Cell<f32>];
 
     #[inline]
-    unsafe fn input_from_raw(pointer: NonNull<c_void>, sample_count: u32) -> Self::InputPortType {
+    unsafe fn input_from_raw(
+        pointer: NonNull<c_void>,
+        sample_count: u32,
+    ) -> *const Self::InputPortType {
+        //std::slice::from_raw_parts(pointer.as_ptr() as *const Cell<f32>, sample_count as usize)
         Cell::from_mut(std::slice::from_raw_parts_mut(
             pointer.as_ptr() as *mut f32,
             sample_count as usize,
@@ -145,11 +155,15 @@ impl PortType for InPlaceAudio {
     }
 
     #[inline]
-    unsafe fn output_from_raw(pointer: NonNull<c_void>, sample_count: u32) -> Self::OutputPortType {
-        Cell::from_mut(std::slice::from_raw_parts_mut(
-            pointer.as_ptr() as *mut f32,
-            sample_count as usize,
-        ))
-        .as_slice_of_cells()
+    unsafe fn output_from_raw(
+        pointer: NonNull<c_void>,
+        sample_count: u32,
+    ) -> *mut Self::OutputPortType {
+        std::slice::from_raw_parts_mut(pointer.as_ptr() as *mut Cell<f32>, sample_count as usize)
+        //Cell::from_mut(std::slice::from_raw_parts_mut(
+        //    pointer.as_ptr() as *mut f32,
+        //    sample_count as usize,
+        //))
+        //.as_slice_of_cells()
     }
 }
diff --git a/core/src/port/control.rs b/core/src/port/control.rs
index 4f9c953f..3cc378dc 100644
--- a/core/src/port/control.rs
+++ b/core/src/port/control.rs
@@ -66,16 +66,16 @@ unsafe impl UriBound for Control {
 
 impl PortType for Control {
     type InputPortType = f32;
-    type OutputPortType = &'static mut f32;
+    type OutputPortType = f32;
 
     #[inline]
-    unsafe fn input_from_raw(pointer: NonNull<c_void>, _sample_count: u32) -> f32 {
-        *(pointer.cast().as_ref())
+    unsafe fn input_from_raw(pointer: NonNull<c_void>, _sample_count: u32) -> *const f32 {
+        pointer.as_ptr() as *const f32
     }
 
     #[inline]
-    unsafe fn output_from_raw(pointer: NonNull<c_void>, _sample_count: u32) -> &'static mut f32 {
-        (pointer.as_ptr() as *mut f32).as_mut().unwrap()
+    unsafe fn output_from_raw(pointer: NonNull<c_void>, _sample_count: u32) -> *mut f32 {
+        pointer.as_ptr() as *mut f32
     }
 }
 
@@ -130,19 +130,22 @@ unsafe impl UriBound for InPlaceControl {
 }
 
 impl PortType for InPlaceControl {
-    type InputPortType = &'static Cell<f32>;
-    type OutputPortType = &'static Cell<f32>;
+    type InputPortType = Cell<f32>;
+    type OutputPortType = Cell<f32>;
 
     #[inline]
-    unsafe fn input_from_raw(pointer: NonNull<c_void>, _sample_count: u32) -> Self::InputPortType {
-        Cell::from_mut(&mut *(pointer.as_ptr() as *mut f32))
+    unsafe fn input_from_raw(
+        pointer: NonNull<c_void>,
+        _sample_count: u32,
+    ) -> *const Self::InputPortType {
+        pointer.as_ptr() as _
     }
 
     #[inline]
     unsafe fn output_from_raw(
         pointer: NonNull<c_void>,
         _sample_count: u32,
-    ) -> Self::OutputPortType {
-        Cell::from_mut(&mut *(pointer.as_ptr() as *mut f32))
+    ) -> *mut Self::OutputPortType {
+        pointer.as_ptr() as _
     }
 }
diff --git a/core/src/port/cv.rs b/core/src/port/cv.rs
index 9455aa0c..592f3f26 100644
--- a/core/src/port/cv.rs
+++ b/core/src/port/cv.rs
@@ -79,16 +79,22 @@ unsafe impl UriBound for CV {
 }
 
 impl PortType for CV {
-    type InputPortType = &'static [f32];
-    type OutputPortType = &'static mut [f32];
+    type InputPortType = [f32];
+    type OutputPortType = [f32];
 
     #[inline]
-    unsafe fn input_from_raw(pointer: NonNull<c_void>, sample_count: u32) -> Self::InputPortType {
+    unsafe fn input_from_raw(
+        pointer: NonNull<c_void>,
+        sample_count: u32,
+    ) -> *const Self::InputPortType {
         std::slice::from_raw_parts(pointer.as_ptr() as *const f32, sample_count as usize)
     }
 
     #[inline]
-    unsafe fn output_from_raw(pointer: NonNull<c_void>, sample_count: u32) -> Self::OutputPortType {
+    unsafe fn output_from_raw(
+        pointer: NonNull<c_void>,
+        sample_count: u32,
+    ) -> *mut Self::OutputPortType {
         std::slice::from_raw_parts_mut(pointer.as_ptr() as *mut f32, sample_count as usize)
     }
 }
@@ -158,24 +164,22 @@ unsafe impl UriBound for InPlaceCV {
 }
 
 impl PortType for InPlaceCV {
-    type InputPortType = &'static [Cell<f32>];
-    type OutputPortType = &'static [Cell<f32>];
+    type InputPortType = [Cell<f32>];
+    type OutputPortType = [Cell<f32>];
 
     #[inline]
-    unsafe fn input_from_raw(pointer: NonNull<c_void>, sample_count: u32) -> Self::InputPortType {
-        Cell::from_mut(std::slice::from_raw_parts_mut(
-            pointer.as_ptr() as *mut f32,
-            sample_count as usize,
-        ))
-        .as_slice_of_cells()
+    unsafe fn input_from_raw(
+        pointer: NonNull<c_void>,
+        sample_count: u32,
+    ) -> *const Self::InputPortType {
+        std::slice::from_raw_parts(pointer.as_ptr() as *const Cell<f32>, sample_count as usize)
     }
 
     #[inline]
-    unsafe fn output_from_raw(pointer: NonNull<c_void>, sample_count: u32) -> Self::OutputPortType {
-        Cell::from_mut(std::slice::from_raw_parts_mut(
-            pointer.as_ptr() as *mut f32,
-            sample_count as usize,
-        ))
-        .as_slice_of_cells()
+    unsafe fn output_from_raw(
+        pointer: NonNull<c_void>,
+        sample_count: u32,
+    ) -> *mut Self::OutputPortType {
+        std::slice::from_raw_parts_mut(pointer.as_ptr() as *mut Cell<f32>, sample_count as usize)
     }
 }

From a8682a2098d77d6af1e6744a5852f68122cdd904 Mon Sep 17 00:00:00 2001
From: Yruama_Lairba <yruama_lairba@hotmail.com>
Date: Wed, 26 Jan 2022 01:55:15 +0100
Subject: [PATCH 02/18] mark todo!() for Atom port to avoid compile error

---
 atom/src/port.rs | 20 ++++++++++++++------
 1 file changed, 14 insertions(+), 6 deletions(-)

diff --git a/atom/src/port.rs b/atom/src/port.rs
index 155c4df4..ab70cd10 100644
--- a/atom/src/port.rs
+++ b/atom/src/port.rs
@@ -110,15 +110,23 @@ impl PortType for AtomPort {
     type OutputPortType = PortWriter<'static>;
 
     #[inline]
-    unsafe fn input_from_raw(pointer: NonNull<c_void>, _sample_count: u32) -> PortReader<'static> {
-        let header = AtomHeader::from_raw(pointer.cast().as_ref());
-        PortReader::new(UnidentifiedAtom::from_header(header))
+    unsafe fn input_from_raw(
+        pointer: NonNull<c_void>,
+        _sample_count: u32,
+    ) -> *const PortReader<'static> {
+        todo!();
+        //let header = AtomHeader::from_raw(pointer.cast().as_ref());
+        //PortReader::new(UnidentifiedAtom::from_header(header))
     }
 
     #[inline]
-    unsafe fn output_from_raw(pointer: NonNull<c_void>, _sample_count: u32) -> PortWriter<'static> {
-        let header = AtomHeader::from_raw_mut(pointer.cast().as_mut());
-        PortWriter::new(UnidentifiedAtom::from_header_mut(header).body_mut())
+    unsafe fn output_from_raw(
+        pointer: NonNull<c_void>,
+        _sample_count: u32,
+    ) -> *mut PortWriter<'static> {
+        todo!();
+        //let header = AtomHeader::from_raw_mut(pointer.cast().as_mut());
+        //PortWriter::new(UnidentifiedAtom::from_header_mut(header).body_mut())
     }
 }
 

From 8767840e715b46b6e59035449564f8f89b589ddc Mon Sep 17 00:00:00 2001
From: Yruama_Lairba <yruama_lairba@hotmail.com>
Date: Sat, 5 Feb 2022 20:27:47 +0100
Subject: [PATCH 03/18] fix doc, proc macro need to be availlable only in doc

---
 core/src/port.rs | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/core/src/port.rs b/core/src/port.rs
index f3a7b04d..c844b968 100644
--- a/core/src/port.rs
+++ b/core/src/port.rs
@@ -13,9 +13,6 @@ use std::ffi::c_void;
 use std::ops::{Deref, DerefMut};
 use std::ptr::NonNull;
 
-#[cfg(feature = "lv2-core-derive")]
-pub use lv2_core_derive::*;
-
 /// Generalization of port types.
 ///
 /// A port can read input or create a pointer to the output, but the exact type of input/output (pointer) depends on the type of port. This trait generalizes these types and behaviour.
@@ -135,7 +132,8 @@ impl<T: PortHandle> PortHandle for Option<T> {
 /// # Implementing
 ///
 /// The most convenient way to create a port collections is to define a struct with port types from the [`port`](index.html) module and then simply derive `PortCollection` for it. An example:
-///
+/// ```
+///     # pub use lv2_core_derive::*;
 ///     use lv2_core::port::*;
 ///
 ///     #[derive(PortCollection)]
@@ -146,6 +144,7 @@ impl<T: PortHandle> PortHandle for Option<T> {
 ///         control_output: OutputPort<Control>,
 ///         optional_control_input: Option<InputPort<Control>>,
 ///     }
+/// ```
 ///
 /// Please note that port indices are mapped in the order of occurrence; In our example, the implementation will treat `audio_input` as port `0`, `audio_output` as port `1` and so on. Therefore, your plugin definition and your port collection have to match. Otherwise, undefined behaviour will occur.
 pub trait PortCollection: Sized {

From 40456395805e1b4d66ffd8d5a05a01dcbbddb69f Mon Sep 17 00:00:00 2001
From: Yruama_Lairba <yruama_lairba@hotmail.com>
Date: Sat, 2 Apr 2022 15:36:34 +0200
Subject: [PATCH 04/18] Fix, re export of FeatureCollection alongside trait

---
 core/src/feature/mod.rs | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/core/src/feature/mod.rs b/core/src/feature/mod.rs
index 3871d1eb..86fea5f2 100644
--- a/core/src/feature/mod.rs
+++ b/core/src/feature/mod.rs
@@ -9,6 +9,8 @@ pub use cache::FeatureCache;
 pub use core_features::*;
 pub use descriptor::FeatureDescriptor;
 
+pub use lv2_core_derive::FeatureCollection;
+
 use std::ffi::c_void;
 
 /// All threading contexts of LV2 interface methods.

From 2e3ab00bf5a01d57a4b7814869835c474ca38d24 Mon Sep 17 00:00:00 2001
From: Yruama_Lairba <yruama_lairba@hotmail.com>
Date: Sat, 2 Apr 2022 15:51:04 +0200
Subject: [PATCH 05/18] refix, conditional re export

---
 core/src/feature/mod.rs | 1 +
 1 file changed, 1 insertion(+)

diff --git a/core/src/feature/mod.rs b/core/src/feature/mod.rs
index 86fea5f2..d001e55d 100644
--- a/core/src/feature/mod.rs
+++ b/core/src/feature/mod.rs
@@ -9,6 +9,7 @@ pub use cache::FeatureCache;
 pub use core_features::*;
 pub use descriptor::FeatureDescriptor;
 
+#[cfg(feature = "lv2-core-derive")]
 pub use lv2_core_derive::FeatureCollection;
 
 use std::ffi::c_void;

From 17625a86f74f84a6e2c207893d01700a4b158983 Mon Sep 17 00:00:00 2001
From: Yruama_Lairba <yruama_lairba@hotmail.com>
Date: Sat, 2 Jul 2022 18:04:29 +0200
Subject: [PATCH 06/18] Create RCell and RwCell for inplace port.

---
 core/src/port.rs | 64 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 64 insertions(+)

diff --git a/core/src/port.rs b/core/src/port.rs
index c844b968..94c1b651 100644
--- a/core/src/port.rs
+++ b/core/src/port.rs
@@ -9,10 +9,74 @@ pub use audio::*;
 pub use control::*;
 pub use cv::*;
 
+use std::cell::Cell;
 use std::ffi::c_void;
 use std::ops::{Deref, DerefMut};
 use std::ptr::NonNull;
 
+/// A readonly cell. Used to give read only access for input port with inplace processing support.
+///
+/// This cell is used to give read only access to data when a writable alias may exist for the
+/// underlying memory location. This is used by inplace input port because it's allow inplace
+/// processing while preventing to write data through the current input port.
+#[repr(transparent)]
+pub struct RCell<T: ?Sized> {
+    value: Cell<T>,
+}
+
+impl<T: Copy> RCell<T> {
+    /// Returns a copy of the contained value.
+    #[inline]
+    pub fn get(&self) -> T {
+        self.value.get()
+    }
+}
+
+impl<T> RCell<[T]> {
+    /// Returns a `&[RCell<T>]` from a `&RCell<[T]>`
+    pub fn as_slice_of_cells(&self) -> &[RCell<T>] {
+        // SAFETY: `RCell<T>` has the same memory layout as `T`.
+        unsafe { &*(self as *const RCell<[T]> as *const [RCell<T>]) }
+    }
+}
+
+/// A read/write cell. Used to give read/write access for output port with inplace processing
+/// support.
+///
+/// This cell is used to give read and write access to data when an alias may exist for the
+/// underlying memory location. It works by giving interior mutability, like [`std::cell::Cell`].
+/// This is used by inplace output because it's allow inplace processing.
+// Note: technically, a std::Cell could be used, but custom cell is better to express the specific
+// usage.
+#[repr(transparent)]
+pub struct RwCell<T: ?Sized> {
+    value: Cell<T>,
+}
+
+impl<T: Copy> RwCell<T> {
+    /// Returns a copy of the contained value.
+    #[inline]
+    pub fn get(&self) -> T {
+        self.value.get()
+    }
+}
+
+impl<T> RwCell<T> {
+    ///Sets the contained value.
+    #[inline]
+    pub fn set(&self, val: T) {
+        self.value.set(val);
+    }
+}
+
+impl<T> RwCell<[T]> {
+    /// Returns a `&[RwCell<T>]` from a `&RwCell<[T]>`
+    pub fn as_slice_of_cells(&self) -> &[RwCell<T>] {
+        // SAFETY: `RwCell<T>` has the same memory layout as `T`.
+        unsafe { &*(self as *const RwCell<[T]> as *const [RwCell<T>]) }
+    }
+}
+
 /// Generalization of port types.
 ///
 /// A port can read input or create a pointer to the output, but the exact type of input/output (pointer) depends on the type of port. This trait generalizes these types and behaviour.

From dbd3cab7c00e75bc78ddbd9cf61371595daddc56 Mon Sep 17 00:00:00 2001
From: Yruama_Lairba <yruama_lairba@hotmail.com>
Date: Sat, 2 Jul 2022 18:36:45 +0200
Subject: [PATCH 07/18] Redesign of audio ports (input, output, inplace, not
 inplace)

---
 core/src/port/audio.rs | 281 +++++++++++++++++++----------------------
 1 file changed, 128 insertions(+), 153 deletions(-)

diff --git a/core/src/port/audio.rs b/core/src/port/audio.rs
index 2f3c51c1..ae2fe86d 100644
--- a/core/src/port/audio.rs
+++ b/core/src/port/audio.rs
@@ -1,169 +1,144 @@
-use crate::port::PortType;
-use std::cell::Cell;
-use std::ffi::c_void;
-use std::ptr::NonNull;
-use urid::UriBound;
+//! TODO!
+//! Audio ports definition. Audio ports are connected to an array of float audio samples.
+//!
+//! Ports of this type are connected to a buffer of float audio samples, represented as a slice.
+//!
+//! Audio samples are normalized between -1.0 and 1.0, though there is no requirement for samples to be strictly within this range.
+//!
+//! See the [LV2 reference](https://lv2plug.in/ns/lv2core#AudioPort) for more information.
+//!
+//! # Example
+//!
+//! This very simple amplifier plugin multiplies the input sample by 2 and outputs the result.
+//!
+//! ```
+//! # use lv2_core::prelude::*;
+//! # use urid::*;
+//! # #[uri("http://lv2plug.in/plugins.rs/simple_amp")]
+//! # struct SimpleAmp;
+//! #[derive(PortCollection)]
+//! struct SimpleAmpPorts {
+//!     input: InputPort<Audio>,
+//!     output: OutputPort<Audio>,
+//! }
+//!
+//! impl Plugin for SimpleAmp {
+//!     type Ports = SimpleAmpPorts;
+//! # type InitFeatures = ();
+//! # type AudioFeatures = ();
+//! # fn new(plugin_info: &PluginInfo,features: &mut Self::InitFeatures) -> Option<Self> {
+//! #         unimplemented!()
+//! # }
+//!     // some implementation details elided…
+//!
+//!     fn run(&mut self, ports: &mut SimpleAmpPorts, _: &mut (), _: u32) {
+//!         // Input and Output dereference to `&[f32]` and `&mut [f32]`, respectively.
+//!         let input = ports.input.iter();
+//!         let output = ports.output.iter_mut();
+//!
+//!         for (input_sample, output_sample) in input.zip(output) {
+//!             *output_sample = *input_sample * 2.0;
+//!         }
+//!     }
+//! }
+//!
+//!
+//! ```
 
-/// A port connected to an array of float audio samples. Using this port **requires** the `inPlaceBroken` feature.
-///
-/// Ports of this type are connected to a buffer of float audio samples, represented as a slice.
-///
-/// Audio samples are normalized between -1.0 and 1.0, though there is no requirement for samples to be strictly within this range.
-///
-/// See the [LV2 reference](https://lv2plug.in/ns/lv2core#AudioPort) for more information.
-///
-/// # Example
-///
-/// This very simple amplifier plugin multiplies the input sample by 2 and outputs the result.
-///
-/// ```
-/// # use lv2_core::prelude::*;
-/// # use urid::*;
-/// # #[uri("http://lv2plug.in/plugins.rs/simple_amp")]
-/// # struct SimpleAmp;
-/// #[derive(PortCollection)]
-/// struct SimpleAmpPorts {
-///     input: InputPort<Audio>,
-///     output: OutputPort<Audio>,
-/// }
-///
-/// impl Plugin for SimpleAmp {
-///     type Ports = SimpleAmpPorts;
-/// # type InitFeatures = ();
-/// # type AudioFeatures = ();
-/// # fn new(plugin_info: &PluginInfo,features: &mut Self::InitFeatures) -> Option<Self> {
-/// #         unimplemented!()
-/// # }
-///     // some implementation details elided…
-///
-///     fn run(&mut self, ports: &mut SimpleAmpPorts, _: &mut (), _: u32) {
-///         // Input and Output dereference to `&[f32]` and `&mut [f32]`, respectively.
-///         let input = ports.input.iter();
-///         let output = ports.output.iter_mut();
-///
-///         for (input_sample, output_sample) in input.zip(output) {
-///             *output_sample = *input_sample * 2.0;
-///         }
-///     }
-/// }
-///
-///
-/// ```
-///
-/// # Safety
-///
-/// Using this port type requires the `inPlaceBroken` LV2 feature in your plugin. Because this port
-/// type uses shared (`&[f32]`) and exclusive (`&mut [f32]`) references to its data, LV2 hosts
-/// MUST NOT use the same buffer for both the input and the output.
-/// However, do note that some hosts (Ardour, Zrythm, etc.) do not support `inPlaceBroken` plugins.
-///
-/// Use [`InPlaceAudio`] instead if you do not want to enforce this restriction on hosts,
-/// and do not need references pointing into the buffer's contents.
-pub struct Audio;
+pub mod inplace {
+    //! Audio ports supporting inplace processing.
+    use crate::port::{PortHandle, RCell, RwCell};
+    use core::ffi::c_void;
+    use core::ops::Deref;
+    use core::ptr::*;
 
-unsafe impl UriBound for Audio {
-    const URI: &'static [u8] = ::lv2_sys::LV2_CORE__AudioPort;
-}
+    pub struct AudioInput {
+        ptr: *const [RCell<f32>],
+    }
 
-impl PortType for Audio {
-    type InputPortType = [f32];
-    type OutputPortType = [f32];
+    impl PortHandle for AudioInput {
+        unsafe fn from_raw(pointer: *mut c_void, sample_count: u32) -> Option<Self> {
+            Some(Self {
+                ptr: slice_from_raw_parts(pointer as *const RCell<f32>, sample_count as usize),
+            })
+        }
+    }
 
-    #[inline]
-    unsafe fn input_from_raw(
-        pointer: NonNull<c_void>,
-        sample_count: u32,
-    ) -> *const Self::InputPortType {
-        std::slice::from_raw_parts(pointer.as_ptr() as *const f32, sample_count as usize)
+    impl Deref for AudioInput {
+        type Target = [RCell<f32>];
+        fn deref(&self) -> &[RCell<f32>] {
+            unsafe { &*self.ptr }
+        }
     }
 
-    #[inline]
-    unsafe fn output_from_raw(
-        pointer: NonNull<c_void>,
-        sample_count: u32,
-    ) -> *mut Self::OutputPortType {
-        std::slice::from_raw_parts_mut(pointer.as_ptr() as *mut f32, sample_count as usize)
+    pub struct AudioOutput {
+        ptr: *mut [RwCell<f32>],
     }
-}
 
-/// A port connected to an array of float audio samples. This port type can safely operate on shared input and output buffers.
-///
-/// Ports of this type are connected to a buffer of float audio samples, represented as a slice of [`Cell`s](std::cell::Cell).
-///
-/// Audio samples are normalized between -1.0 and 1.0, though there is no requirement for samples to be strictly within this range.
-///
-/// See the [LV2 reference](https://lv2plug.in/ns/lv2core#AudioPort) for more information.
-///
-/// # Example
-///
-/// This very simple amplifier plugin multiplies the input sample by 2 and outputs the result.
-///
-/// ```
-/// # use lv2_core::prelude::*;
-/// # use urid::*;
-/// # #[uri("http://lv2plug.in/plugins.rs/simple_amp")]
-/// # struct SimpleAmp;
-/// #[derive(PortCollection)]
-/// struct SimpleAmpPorts {
-///     input: InputPort<InPlaceAudio>,
-///     output: OutputPort<InPlaceAudio>,
-/// }
-///
-/// impl Plugin for SimpleAmp {
-///     type Ports = SimpleAmpPorts;
-/// # type InitFeatures = ();
-/// # type AudioFeatures = ();
-/// # fn new(plugin_info: &PluginInfo,features: &mut Self::InitFeatures) -> Option<Self> {
-/// #         unimplemented!()
-/// # }
-///     // some implementation details elided…
-///
-///     fn run(&mut self, ports: &mut SimpleAmpPorts, _: &mut (), _: u32) {
-///         // Input and Output both dereference to `&[Cell<f32>]`.
-///         let input = ports.input.iter();
-///         let output = ports.output.iter();
-///
-///         for (input_sample, output_sample) in input.zip(output) {
-///             output_sample.set(input_sample.get() * 2.0);
-///         }
-///     }
-/// }
-///
-///
-/// ```
-pub struct InPlaceAudio;
+    impl PortHandle for AudioOutput {
+        unsafe fn from_raw(pointer: *mut c_void, sample_count: u32) -> Option<Self> {
+            Some(Self {
+                ptr: slice_from_raw_parts_mut(pointer as *mut RwCell<f32>, sample_count as usize),
+            })
+        }
+    }
 
-unsafe impl UriBound for InPlaceAudio {
-    const URI: &'static [u8] = ::lv2_sys::LV2_CORE__AudioPort;
+    impl Deref for AudioOutput {
+        type Target = [RwCell<f32>];
+        fn deref(&self) -> &[RwCell<f32>] {
+            unsafe { &*self.ptr }
+        }
+    }
 }
 
-impl PortType for InPlaceAudio {
-    type InputPortType = [Cell<f32>];
-    type OutputPortType = [Cell<f32>];
+pub mod not_inplace {
+    //! Audio ports that doesn't support inplace processing
+    use crate::port::PortHandle;
+    use core::ffi::c_void;
+    use core::ops::{Deref, DerefMut};
+    use core::ptr::*;
+
+    pub struct AudioInput {
+        ptr: *const [f32],
+    }
+
+    impl PortHandle for AudioInput {
+        unsafe fn from_raw(pointer: *mut c_void, sample_count: u32) -> Option<Self> {
+            Some(Self {
+                ptr: slice_from_raw_parts(pointer as *const f32, sample_count as usize),
+            })
+        }
+    }
+
+    impl Deref for AudioInput {
+        type Target = [f32];
+        fn deref(&self) -> &[f32] {
+            unsafe { &*self.ptr }
+        }
+    }
+
+    pub struct AudioOutput {
+        ptr: *mut [f32],
+    }
+
+    impl PortHandle for AudioOutput {
+        unsafe fn from_raw(pointer: *mut c_void, sample_count: u32) -> Option<Self> {
+            Some(Self {
+                ptr: slice_from_raw_parts_mut(pointer as *mut f32, sample_count as usize),
+            })
+        }
+    }
 
-    #[inline]
-    unsafe fn input_from_raw(
-        pointer: NonNull<c_void>,
-        sample_count: u32,
-    ) -> *const Self::InputPortType {
-        //std::slice::from_raw_parts(pointer.as_ptr() as *const Cell<f32>, sample_count as usize)
-        Cell::from_mut(std::slice::from_raw_parts_mut(
-            pointer.as_ptr() as *mut f32,
-            sample_count as usize,
-        ))
-        .as_slice_of_cells()
+    impl Deref for AudioOutput {
+        type Target = [f32];
+        fn deref(&self) -> &[f32] {
+            unsafe { &*self.ptr }
+        }
     }
 
-    #[inline]
-    unsafe fn output_from_raw(
-        pointer: NonNull<c_void>,
-        sample_count: u32,
-    ) -> *mut Self::OutputPortType {
-        std::slice::from_raw_parts_mut(pointer.as_ptr() as *mut Cell<f32>, sample_count as usize)
-        //Cell::from_mut(std::slice::from_raw_parts_mut(
-        //    pointer.as_ptr() as *mut f32,
-        //    sample_count as usize,
-        //))
-        //.as_slice_of_cells()
+    impl DerefMut for AudioOutput {
+        fn deref_mut(&mut self) -> &mut [f32] {
+            unsafe { &mut *self.ptr }
+        }
     }
 }

From a0eb8719c8ddba242c34963470cb624f28e6a676 Mon Sep 17 00:00:00 2001
From: Yruama_Lairba <yruama_lairba@hotmail.com>
Date: Sat, 2 Jul 2022 19:30:50 +0200
Subject: [PATCH 08/18] Redesign of control ports (input, output, inplace, not
 inplace)

---
 core/src/port/control.rs | 144 ++++++++++++++++++++++++++-------------
 1 file changed, 95 insertions(+), 49 deletions(-)

diff --git a/core/src/port/control.rs b/core/src/port/control.rs
index 3cc378dc..ea8efa50 100644
--- a/core/src/port/control.rs
+++ b/core/src/port/control.rs
@@ -1,8 +1,98 @@
-use crate::port::PortType;
-use std::cell::Cell;
-use std::ffi::c_void;
-use std::ptr::NonNull;
-use urid::UriBound;
+pub mod inplace {
+    //! Control ports supporting inplace processing
+    use crate::port::{PortHandle, RCell, RwCell};
+    use core::ffi::c_void;
+    use core::ops::Deref;
+
+    pub struct ControlInput {
+        ptr: *const RCell<f32>,
+    }
+
+    impl PortHandle for ControlInput {
+        unsafe fn from_raw(pointer: *mut c_void, _sample_count: u32) -> Option<Self> {
+            Some(Self {
+                ptr: pointer as *const RCell<f32>,
+            })
+        }
+    }
+
+    impl Deref for ControlInput {
+        type Target = RCell<f32>;
+        fn deref(&self) -> &RCell<f32> {
+            unsafe { &*self.ptr }
+        }
+    }
+
+    pub struct ControlOutput {
+        ptr: *mut RwCell<f32>,
+    }
+
+    impl PortHandle for ControlOutput {
+        unsafe fn from_raw(pointer: *mut c_void, _sample_count: u32) -> Option<Self> {
+            Some(Self {
+                ptr: pointer as *mut RwCell<f32>,
+            })
+        }
+    }
+
+    impl Deref for ControlOutput {
+        type Target = RwCell<f32>;
+        fn deref(&self) -> &RwCell<f32> {
+            unsafe { &*self.ptr }
+        }
+    }
+}
+
+pub mod not_inplace {
+    //! Control ports that doesn't support inplace processing
+    use crate::port::PortHandle;
+    use core::ffi::c_void;
+    use core::ops::{Deref, DerefMut};
+
+    pub struct ControlInput {
+        ptr: *const f32,
+    }
+
+    impl PortHandle for ControlInput {
+        unsafe fn from_raw(pointer: *mut c_void, _sample_count: u32) -> Option<Self> {
+            Some(Self {
+                ptr: pointer as *const f32,
+            })
+        }
+    }
+
+    impl Deref for ControlInput {
+        type Target = f32;
+        fn deref(&self) -> &f32 {
+            unsafe { &*self.ptr }
+        }
+    }
+
+    pub struct ControlOutput {
+        ptr: *mut f32,
+    }
+
+    impl PortHandle for ControlOutput {
+        unsafe fn from_raw(pointer: *mut c_void, _sample_count: u32) -> Option<Self> {
+            Some(Self {
+                ptr: pointer as *mut f32,
+            })
+        }
+    }
+
+    impl Deref for ControlOutput {
+        type Target = f32;
+        fn deref(&self) -> &f32 {
+            unsafe { &*self.ptr }
+        }
+    }
+
+    impl DerefMut for ControlOutput {
+        fn deref_mut(&mut self) -> &mut f32 {
+            unsafe { &mut *self.ptr }
+        }
+    }
+}
 
 /// A port connected to a single float ([`f32`]). Using this port **requires** the `inPlaceBroken` feature.
 ///
@@ -60,25 +150,6 @@ use urid::UriBound;
 /// and do not need references pointing into the buffer's contents.
 pub struct Control;
 
-unsafe impl UriBound for Control {
-    const URI: &'static [u8] = ::lv2_sys::LV2_CORE__ControlPort;
-}
-
-impl PortType for Control {
-    type InputPortType = f32;
-    type OutputPortType = f32;
-
-    #[inline]
-    unsafe fn input_from_raw(pointer: NonNull<c_void>, _sample_count: u32) -> *const f32 {
-        pointer.as_ptr() as *const f32
-    }
-
-    #[inline]
-    unsafe fn output_from_raw(pointer: NonNull<c_void>, _sample_count: u32) -> *mut f32 {
-        pointer.as_ptr() as *mut f32
-    }
-}
-
 /// A port connected to a single float ([`f32`]). This port type can safely operate on shared input and output buffers.
 ///
 /// See the [LV2 reference](https://lv2plug.in/ns/lv2core#ControlPort) for more information.
@@ -124,28 +195,3 @@ impl PortType for Control {
 ///
 /// ```
 pub struct InPlaceControl;
-
-unsafe impl UriBound for InPlaceControl {
-    const URI: &'static [u8] = ::lv2_sys::LV2_CORE__ControlPort;
-}
-
-impl PortType for InPlaceControl {
-    type InputPortType = Cell<f32>;
-    type OutputPortType = Cell<f32>;
-
-    #[inline]
-    unsafe fn input_from_raw(
-        pointer: NonNull<c_void>,
-        _sample_count: u32,
-    ) -> *const Self::InputPortType {
-        pointer.as_ptr() as _
-    }
-
-    #[inline]
-    unsafe fn output_from_raw(
-        pointer: NonNull<c_void>,
-        _sample_count: u32,
-    ) -> *mut Self::OutputPortType {
-        pointer.as_ptr() as _
-    }
-}

From 5484021143b7622e63dd2926a67369e3cf7edfae Mon Sep 17 00:00:00 2001
From: Yruama_Lairba <yruama_lairba@hotmail.com>
Date: Sat, 2 Jul 2022 19:51:46 +0200
Subject: [PATCH 09/18] Redesign of CV ports (input, output, inplace, not
 inplace)

---
 core/src/port/cv.rs | 152 ++++++++++++++++++++++++++++----------------
 1 file changed, 97 insertions(+), 55 deletions(-)

diff --git a/core/src/port/cv.rs b/core/src/port/cv.rs
index 592f3f26..2c85a5e4 100644
--- a/core/src/port/cv.rs
+++ b/core/src/port/cv.rs
@@ -1,8 +1,100 @@
-use crate::port::PortType;
-use std::cell::Cell;
-use std::ffi::c_void;
-use std::ptr::NonNull;
-use urid::UriBound;
+pub mod inplace {
+    //! CV ports supporting inplace processing.
+    use crate::port::{PortHandle, RCell, RwCell};
+    use core::ffi::c_void;
+    use core::ops::Deref;
+    use core::ptr::*;
+
+    pub struct CVInput {
+        ptr: *const [RCell<f32>],
+    }
+
+    impl PortHandle for CVInput {
+        unsafe fn from_raw(pointer: *mut c_void, sample_count: u32) -> Option<Self> {
+            Some(Self {
+                ptr: slice_from_raw_parts(pointer as *const RCell<f32>, sample_count as usize),
+            })
+        }
+    }
+
+    impl Deref for CVInput {
+        type Target = [RCell<f32>];
+        fn deref(&self) -> &[RCell<f32>] {
+            unsafe { &*self.ptr }
+        }
+    }
+
+    pub struct CVOutput {
+        ptr: *mut [RwCell<f32>],
+    }
+
+    impl PortHandle for CVOutput {
+        unsafe fn from_raw(pointer: *mut c_void, sample_count: u32) -> Option<Self> {
+            Some(Self {
+                ptr: slice_from_raw_parts_mut(pointer as *mut RwCell<f32>, sample_count as usize),
+            })
+        }
+    }
+
+    impl Deref for CVOutput {
+        type Target = [RwCell<f32>];
+        fn deref(&self) -> &[RwCell<f32>] {
+            unsafe { &*self.ptr }
+        }
+    }
+}
+
+pub mod not_inplace {
+    //! CV ports that doesn't support inplace processing
+    use crate::port::PortHandle;
+    use core::ffi::c_void;
+    use core::ops::{Deref, DerefMut};
+    use core::ptr::*;
+
+    pub struct CVInput {
+        ptr: *const [f32],
+    }
+
+    impl PortHandle for CVInput {
+        unsafe fn from_raw(pointer: *mut c_void, sample_count: u32) -> Option<Self> {
+            Some(Self {
+                ptr: slice_from_raw_parts(pointer as *const f32, sample_count as usize),
+            })
+        }
+    }
+
+    impl Deref for CVInput {
+        type Target = [f32];
+        fn deref(&self) -> &[f32] {
+            unsafe { &*self.ptr }
+        }
+    }
+
+    pub struct CVOutput {
+        ptr: *mut [f32],
+    }
+
+    impl PortHandle for CVOutput {
+        unsafe fn from_raw(pointer: *mut c_void, sample_count: u32) -> Option<Self> {
+            Some(Self {
+                ptr: slice_from_raw_parts_mut(pointer as *mut f32, sample_count as usize),
+            })
+        }
+    }
+
+    impl Deref for CVOutput {
+        type Target = [f32];
+        fn deref(&self) -> &[f32] {
+            unsafe { &*self.ptr }
+        }
+    }
+
+    impl DerefMut for CVOutput {
+        fn deref_mut(&mut self) -> &mut [f32] {
+            unsafe { &mut *self.ptr }
+        }
+    }
+}
 
 /// A port connected to an array of float control values. Using this port **requires** the `inPlaceBroken` feature.
 ///
@@ -74,31 +166,6 @@ use urid::UriBound;
 /// and do not need references pointing into the buffer's contents.
 pub struct CV;
 
-unsafe impl UriBound for CV {
-    const URI: &'static [u8] = ::lv2_sys::LV2_CORE__CVPort;
-}
-
-impl PortType for CV {
-    type InputPortType = [f32];
-    type OutputPortType = [f32];
-
-    #[inline]
-    unsafe fn input_from_raw(
-        pointer: NonNull<c_void>,
-        sample_count: u32,
-    ) -> *const Self::InputPortType {
-        std::slice::from_raw_parts(pointer.as_ptr() as *const f32, sample_count as usize)
-    }
-
-    #[inline]
-    unsafe fn output_from_raw(
-        pointer: NonNull<c_void>,
-        sample_count: u32,
-    ) -> *mut Self::OutputPortType {
-        std::slice::from_raw_parts_mut(pointer.as_ptr() as *mut f32, sample_count as usize)
-    }
-}
-
 /// A port connected to an array of float control values. This port type can safely operate on shared input and output buffers.
 ///
 /// Ports of this type are connected to a buffer of float control values, represented as a slice of [`Cell`s](std::cell::Cell).
@@ -158,28 +225,3 @@ impl PortType for CV {
 ///
 /// ```
 pub struct InPlaceCV;
-
-unsafe impl UriBound for InPlaceCV {
-    const URI: &'static [u8] = ::lv2_sys::LV2_CORE__CVPort;
-}
-
-impl PortType for InPlaceCV {
-    type InputPortType = [Cell<f32>];
-    type OutputPortType = [Cell<f32>];
-
-    #[inline]
-    unsafe fn input_from_raw(
-        pointer: NonNull<c_void>,
-        sample_count: u32,
-    ) -> *const Self::InputPortType {
-        std::slice::from_raw_parts(pointer.as_ptr() as *const Cell<f32>, sample_count as usize)
-    }
-
-    #[inline]
-    unsafe fn output_from_raw(
-        pointer: NonNull<c_void>,
-        sample_count: u32,
-    ) -> *mut Self::OutputPortType {
-        std::slice::from_raw_parts_mut(pointer.as_ptr() as *mut Cell<f32>, sample_count as usize)
-    }
-}

From 610a5bada69e408ce27be15bd778a6b20ecba7ea Mon Sep 17 00:00:00 2001
From: Yruama_Lairba <yruama_lairba@hotmail.com>
Date: Sun, 3 Jul 2022 00:02:31 +0200
Subject: [PATCH 10/18] reorganisation of ports, inplace and not_inplace module

---
 core/src/port.rs             |   9 +-
 core/src/port/audio.rs       | 144 ----------------------
 core/src/port/control.rs     | 197 ------------------------------
 core/src/port/cv.rs          | 227 -----------------------------------
 core/src/port/inplace.rs     | 162 +++++++++++++++++++++++++
 core/src/port/not_inplace.rs | 176 +++++++++++++++++++++++++++
 6 files changed, 340 insertions(+), 575 deletions(-)
 delete mode 100644 core/src/port/audio.rs
 delete mode 100644 core/src/port/control.rs
 delete mode 100644 core/src/port/cv.rs
 create mode 100644 core/src/port/inplace.rs
 create mode 100644 core/src/port/not_inplace.rs

diff --git a/core/src/port.rs b/core/src/port.rs
index 94c1b651..b89d62c5 100644
--- a/core/src/port.rs
+++ b/core/src/port.rs
@@ -1,13 +1,8 @@
 //! Types to declare derivable port collections.
 //!
 //! Every plugin has a type of [`PortCollection`](trait.PortCollection.html) which is used to handle input/output ports. In order to make the creation of these port collection types easier, `PortCollection` can simply be derived. However, the macro that implements `PortCollection` requires the fields of the struct to have specific types. These types are provided in this module.
-mod audio;
-mod control;
-mod cv;
-
-pub use audio::*;
-pub use control::*;
-pub use cv::*;
+pub mod inplace;
+pub mod not_inplace;
 
 use std::cell::Cell;
 use std::ffi::c_void;
diff --git a/core/src/port/audio.rs b/core/src/port/audio.rs
deleted file mode 100644
index ae2fe86d..00000000
--- a/core/src/port/audio.rs
+++ /dev/null
@@ -1,144 +0,0 @@
-//! TODO!
-//! Audio ports definition. Audio ports are connected to an array of float audio samples.
-//!
-//! Ports of this type are connected to a buffer of float audio samples, represented as a slice.
-//!
-//! Audio samples are normalized between -1.0 and 1.0, though there is no requirement for samples to be strictly within this range.
-//!
-//! See the [LV2 reference](https://lv2plug.in/ns/lv2core#AudioPort) for more information.
-//!
-//! # Example
-//!
-//! This very simple amplifier plugin multiplies the input sample by 2 and outputs the result.
-//!
-//! ```
-//! # use lv2_core::prelude::*;
-//! # use urid::*;
-//! # #[uri("http://lv2plug.in/plugins.rs/simple_amp")]
-//! # struct SimpleAmp;
-//! #[derive(PortCollection)]
-//! struct SimpleAmpPorts {
-//!     input: InputPort<Audio>,
-//!     output: OutputPort<Audio>,
-//! }
-//!
-//! impl Plugin for SimpleAmp {
-//!     type Ports = SimpleAmpPorts;
-//! # type InitFeatures = ();
-//! # type AudioFeatures = ();
-//! # fn new(plugin_info: &PluginInfo,features: &mut Self::InitFeatures) -> Option<Self> {
-//! #         unimplemented!()
-//! # }
-//!     // some implementation details elided…
-//!
-//!     fn run(&mut self, ports: &mut SimpleAmpPorts, _: &mut (), _: u32) {
-//!         // Input and Output dereference to `&[f32]` and `&mut [f32]`, respectively.
-//!         let input = ports.input.iter();
-//!         let output = ports.output.iter_mut();
-//!
-//!         for (input_sample, output_sample) in input.zip(output) {
-//!             *output_sample = *input_sample * 2.0;
-//!         }
-//!     }
-//! }
-//!
-//!
-//! ```
-
-pub mod inplace {
-    //! Audio ports supporting inplace processing.
-    use crate::port::{PortHandle, RCell, RwCell};
-    use core::ffi::c_void;
-    use core::ops::Deref;
-    use core::ptr::*;
-
-    pub struct AudioInput {
-        ptr: *const [RCell<f32>],
-    }
-
-    impl PortHandle for AudioInput {
-        unsafe fn from_raw(pointer: *mut c_void, sample_count: u32) -> Option<Self> {
-            Some(Self {
-                ptr: slice_from_raw_parts(pointer as *const RCell<f32>, sample_count as usize),
-            })
-        }
-    }
-
-    impl Deref for AudioInput {
-        type Target = [RCell<f32>];
-        fn deref(&self) -> &[RCell<f32>] {
-            unsafe { &*self.ptr }
-        }
-    }
-
-    pub struct AudioOutput {
-        ptr: *mut [RwCell<f32>],
-    }
-
-    impl PortHandle for AudioOutput {
-        unsafe fn from_raw(pointer: *mut c_void, sample_count: u32) -> Option<Self> {
-            Some(Self {
-                ptr: slice_from_raw_parts_mut(pointer as *mut RwCell<f32>, sample_count as usize),
-            })
-        }
-    }
-
-    impl Deref for AudioOutput {
-        type Target = [RwCell<f32>];
-        fn deref(&self) -> &[RwCell<f32>] {
-            unsafe { &*self.ptr }
-        }
-    }
-}
-
-pub mod not_inplace {
-    //! Audio ports that doesn't support inplace processing
-    use crate::port::PortHandle;
-    use core::ffi::c_void;
-    use core::ops::{Deref, DerefMut};
-    use core::ptr::*;
-
-    pub struct AudioInput {
-        ptr: *const [f32],
-    }
-
-    impl PortHandle for AudioInput {
-        unsafe fn from_raw(pointer: *mut c_void, sample_count: u32) -> Option<Self> {
-            Some(Self {
-                ptr: slice_from_raw_parts(pointer as *const f32, sample_count as usize),
-            })
-        }
-    }
-
-    impl Deref for AudioInput {
-        type Target = [f32];
-        fn deref(&self) -> &[f32] {
-            unsafe { &*self.ptr }
-        }
-    }
-
-    pub struct AudioOutput {
-        ptr: *mut [f32],
-    }
-
-    impl PortHandle for AudioOutput {
-        unsafe fn from_raw(pointer: *mut c_void, sample_count: u32) -> Option<Self> {
-            Some(Self {
-                ptr: slice_from_raw_parts_mut(pointer as *mut f32, sample_count as usize),
-            })
-        }
-    }
-
-    impl Deref for AudioOutput {
-        type Target = [f32];
-        fn deref(&self) -> &[f32] {
-            unsafe { &*self.ptr }
-        }
-    }
-
-    impl DerefMut for AudioOutput {
-        fn deref_mut(&mut self) -> &mut [f32] {
-            unsafe { &mut *self.ptr }
-        }
-    }
-}
diff --git a/core/src/port/control.rs b/core/src/port/control.rs
deleted file mode 100644
index ea8efa50..00000000
--- a/core/src/port/control.rs
+++ /dev/null
@@ -1,197 +0,0 @@
-pub mod inplace {
-    //! Control ports supporting inplace processing
-    use crate::port::{PortHandle, RCell, RwCell};
-    use core::ffi::c_void;
-    use core::ops::Deref;
-
-    pub struct ControlInput {
-        ptr: *const RCell<f32>,
-    }
-
-    impl PortHandle for ControlInput {
-        unsafe fn from_raw(pointer: *mut c_void, _sample_count: u32) -> Option<Self> {
-            Some(Self {
-                ptr: pointer as *const RCell<f32>,
-            })
-        }
-    }
-
-    impl Deref for ControlInput {
-        type Target = RCell<f32>;
-        fn deref(&self) -> &RCell<f32> {
-            unsafe { &*self.ptr }
-        }
-    }
-
-    pub struct ControlOutput {
-        ptr: *mut RwCell<f32>,
-    }
-
-    impl PortHandle for ControlOutput {
-        unsafe fn from_raw(pointer: *mut c_void, _sample_count: u32) -> Option<Self> {
-            Some(Self {
-                ptr: pointer as *mut RwCell<f32>,
-            })
-        }
-    }
-
-    impl Deref for ControlOutput {
-        type Target = RwCell<f32>;
-        fn deref(&self) -> &RwCell<f32> {
-            unsafe { &*self.ptr }
-        }
-    }
-}
-
-pub mod not_inplace {
-    //! Control ports that doesn't support inplace processing
-    use crate::port::PortHandle;
-    use core::ffi::c_void;
-    use core::ops::{Deref, DerefMut};
-
-    pub struct ControlInput {
-        ptr: *const f32,
-    }
-
-    impl PortHandle for ControlInput {
-        unsafe fn from_raw(pointer: *mut c_void, _sample_count: u32) -> Option<Self> {
-            Some(Self {
-                ptr: pointer as *const f32,
-            })
-        }
-    }
-
-    impl Deref for ControlInput {
-        type Target = f32;
-        fn deref(&self) -> &f32 {
-            unsafe { &*self.ptr }
-        }
-    }
-
-    pub struct ControlOutput {
-        ptr: *mut f32,
-    }
-
-    impl PortHandle for ControlOutput {
-        unsafe fn from_raw(pointer: *mut c_void, _sample_count: u32) -> Option<Self> {
-            Some(Self {
-                ptr: pointer as *mut f32,
-            })
-        }
-    }
-
-    impl Deref for ControlOutput {
-        type Target = f32;
-        fn deref(&self) -> &f32 {
-            unsafe { &*self.ptr }
-        }
-    }
-
-    impl DerefMut for ControlOutput {
-        fn deref_mut(&mut self) -> &mut f32 {
-            unsafe { &mut *self.ptr }
-        }
-    }
-}
-
-/// A port connected to a single float ([`f32`]). Using this port **requires** the `inPlaceBroken` feature.
-///
-/// See the [LV2 reference](https://lv2plug.in/ns/lv2core#ControlPort) for more information.
-///
-/// # Example
-///
-/// This very simple amplifier plugin multiplies the input sample by the input control value and outputs the result.
-///
-/// ```
-/// # use lv2_core::prelude::*;
-/// # use urid::*;
-/// # #[uri("http://lv2plug.in/plugins.rs/simple_amp")]
-/// # struct ControlAmp;
-/// #[derive(PortCollection)]
-/// struct ControlAmpPorts {
-///     factor: InputPort<Control>,
-///     input: InputPort<Audio>,
-///     output: OutputPort<Audio>,
-/// }
-///
-/// impl Plugin for ControlAmp {
-///     type Ports = ControlAmpPorts;
-/// # type InitFeatures = ();
-/// # type AudioFeatures = ();
-/// # fn new(plugin_info: &PluginInfo,features: &mut Self::InitFeatures) -> Option<Self> {
-/// #         unimplemented!()
-/// # }
-///     // some implementation details elided…
-///
-///     fn run(&mut self, ports: &mut ControlAmpPorts, _: &mut (), _: u32) {
-///         // Input and Output dereference to `&f32` and `&mut f32`, respectively.
-///         let factor = *ports.factor;
-///
-///         let input = ports.input.iter();
-///         let output = ports.output.iter_mut();
-///
-///         for (input_sample, output_sample) in input.zip(output) {
-///             *output_sample = *input_sample * factor;
-///         }
-///     }
-/// }
-///
-///
-/// ```
-///
-/// # Safety
-///
-/// Using this port type requires the `inPlaceBroken` LV2 feature in your plugin. Because this port
-/// type uses shared (`&f32`) and exclusive (`&mut f32`) references to its data, LV2 hosts
-/// MUST NOT use the same buffer for both the input and the output.
-/// However, do note that some hosts (Ardour, Zrythm, etc.) do not support `inPlaceBroken` plugins.
-///
-/// Use [`InPlaceControl`] instead if you do not want to enforce this restriction on hosts,
-/// and do not need references pointing into the buffer's contents.
-pub struct Control;
-
-/// A port connected to a single float ([`f32`]). This port type can safely operate on shared input and output buffers.
-///
-/// See the [LV2 reference](https://lv2plug.in/ns/lv2core#ControlPort) for more information.
-///
-/// # Example
-///
-/// This very simple amplifier plugin multiplies the input sample by the input control value and outputs the result.
-///
-/// ```
-/// # use lv2_core::prelude::*;
-/// # use urid::*;
-/// # #[uri("http://lv2plug.in/plugins.rs/simple_amp")]
-/// # struct ControlAmp;
-/// #[derive(PortCollection)]
-/// struct ControlAmpPorts {
-///     factor: InputPort<InPlaceControl>,
-///     input: InputPort<InPlaceAudio>,
-///     output: OutputPort<InPlaceAudio>,
-/// }
-///
-/// impl Plugin for ControlAmp {
-///     type Ports = ControlAmpPorts;
-/// # type InitFeatures = ();
-/// # type AudioFeatures = ();
-/// # fn new(plugin_info: &PluginInfo,features: &mut Self::InitFeatures) -> Option<Self> {
-/// #         unimplemented!()
-/// # }
-///     // some implementation details elided…
-///
-///     fn run(&mut self, ports: &mut ControlAmpPorts, _: &mut (), _: u32) {
-///         // Input and Output dereference to `&Cell<f32>`.
-///         let factor = ports.factor.get();
-///
-///         let input = ports.input.iter();
-///         let output = ports.output.iter();
-///
-///         for (input_sample, output_sample) in input.zip(output) {
-///             output_sample.set(input_sample.get() * factor);
-///         }
-///     }
-/// }
-///
-///
-/// ```
-pub struct InPlaceControl;
diff --git a/core/src/port/cv.rs b/core/src/port/cv.rs
deleted file mode 100644
index 2c85a5e4..00000000
--- a/core/src/port/cv.rs
+++ /dev/null
@@ -1,227 +0,0 @@
-pub mod inplace {
-    //! CV ports supporting inplace processing.
-    use crate::port::{PortHandle, RCell, RwCell};
-    use core::ffi::c_void;
-    use core::ops::Deref;
-    use core::ptr::*;
-
-    pub struct CVInput {
-        ptr: *const [RCell<f32>],
-    }
-
-    impl PortHandle for CVInput {
-        unsafe fn from_raw(pointer: *mut c_void, sample_count: u32) -> Option<Self> {
-            Some(Self {
-                ptr: slice_from_raw_parts(pointer as *const RCell<f32>, sample_count as usize),
-            })
-        }
-    }
-
-    impl Deref for CVInput {
-        type Target = [RCell<f32>];
-        fn deref(&self) -> &[RCell<f32>] {
-            unsafe { &*self.ptr }
-        }
-    }
-
-    pub struct CVOutput {
-        ptr: *mut [RwCell<f32>],
-    }
-
-    impl PortHandle for CVOutput {
-        unsafe fn from_raw(pointer: *mut c_void, sample_count: u32) -> Option<Self> {
-            Some(Self {
-                ptr: slice_from_raw_parts_mut(pointer as *mut RwCell<f32>, sample_count as usize),
-            })
-        }
-    }
-
-    impl Deref for CVOutput {
-        type Target = [RwCell<f32>];
-        fn deref(&self) -> &[RwCell<f32>] {
-            unsafe { &*self.ptr }
-        }
-    }
-}
-
-pub mod not_inplace {
-    //! CV ports that doesn't support inplace processing
-    use crate::port::PortHandle;
-    use core::ffi::c_void;
-    use core::ops::{Deref, DerefMut};
-    use core::ptr::*;
-
-    pub struct CVInput {
-        ptr: *const [f32],
-    }
-
-    impl PortHandle for CVInput {
-        unsafe fn from_raw(pointer: *mut c_void, sample_count: u32) -> Option<Self> {
-            Some(Self {
-                ptr: slice_from_raw_parts(pointer as *const f32, sample_count as usize),
-            })
-        }
-    }
-
-    impl Deref for CVInput {
-        type Target = [f32];
-        fn deref(&self) -> &[f32] {
-            unsafe { &*self.ptr }
-        }
-    }
-
-    pub struct CVOutput {
-        ptr: *mut [f32],
-    }
-
-    impl PortHandle for CVOutput {
-        unsafe fn from_raw(pointer: *mut c_void, sample_count: u32) -> Option<Self> {
-            Some(Self {
-                ptr: slice_from_raw_parts_mut(pointer as *mut f32, sample_count as usize),
-            })
-        }
-    }
-
-    impl Deref for CVOutput {
-        type Target = [f32];
-        fn deref(&self) -> &[f32] {
-            unsafe { &*self.ptr }
-        }
-    }
-
-    impl DerefMut for CVOutput {
-        fn deref_mut(&mut self) -> &mut [f32] {
-            unsafe { &mut *self.ptr }
-        }
-    }
-}
-
-/// A port connected to an array of float control values. Using this port **requires** the `inPlaceBroken` feature.
-///
-/// Ports of this type are connected to a buffer of float control values, represented as a slice.
-/// They have the same buffer format as [`Audio`](crate::port::Audio) ports, except the buffer represents
-/// audio-rate control data rather than audio.
-/// Like a [`Control`](crate::port::Control) port, a CV port SHOULD have properties describing its value, in particular minimum, maximum, and default.
-///
-/// Hosts may present CV ports to users as controls in the same way as control ports.
-/// Conceptually, aside from the buffer format, a CV port is the same as a control port, so hosts can use all the same properties and expectations.
-///
-/// In particular, this port type does not imply any range, unit, or meaning for its values.
-/// However, if there is no inherent unit to the values, for example if the port is used to modulate some other value, then plugins SHOULD use a normalized range, either from -1.0 to 1.0, or from 0.0 to 1.0.
-///
-/// It is generally safe to connect an audio output to a CV input, but not vice-versa.
-/// Hosts must take care to prevent data from a CVPort port from being used as audio.
-///
-/// See the [LV2 reference](https://lv2plug.in/ns/lv2core#CVPort) for more information.
-///
-/// # Example
-///
-/// This very simple amplifier plugin multiplies the input sample by the input CV signal and outputs the result.
-///
-/// ```
-/// # use lv2_core::prelude::*;
-/// # use urid::*;
-/// # #[uri("http://lv2plug.in/plugins.rs/simple_amp")]
-/// # struct CVAmp;
-/// #[derive(PortCollection)]
-/// struct CVAmpPorts {
-///     factor: InputPort<CV>,
-///     input: InputPort<Audio>,
-///     output: OutputPort<Audio>,
-/// }
-///
-/// impl Plugin for CVAmp {
-///     type Ports = CVAmpPorts;
-/// # type InitFeatures = ();
-/// # type AudioFeatures = ();
-/// # fn new(plugin_info: &PluginInfo,features: &mut Self::InitFeatures) -> Option<Self> {
-/// #         unimplemented!()
-/// # }
-///     // some implementation details elided…
-///
-///     fn run(&mut self, ports: &mut CVAmpPorts, _: &mut (), _: u32) {
-///         // Input and Output dereference to `&[f32]` and `&mut [f32]`, respectively.
-///         let factor = ports.factor.iter();
-///
-///         let input = ports.input.iter();
-///         let output = ports.output.iter_mut();
-///
-///         for ((input_sample, output_sample), amp_factor) in input.zip(output).zip(factor) {
-///             *output_sample = *input_sample * *amp_factor;
-///         }
-///     }
-/// }
-///
-///
-/// ```
-///
-/// # Safety
-///
-/// Using this port type requires the `inPlaceBroken` LV2 feature in your plugin. Because this port
-/// type uses shared (`&[f32]`) and exclusive (`&mut [f32]`) references to its data, LV2 hosts
-/// MUST NOT use the same buffer for both the input and the output.
-/// However, do note that some hosts (Ardour, Zrythm, etc.) do not support `inPlaceBroken` plugins.
-///
-/// Use [`InPlaceCV`] instead if you do not want to enforce this restriction on hosts,
-/// and do not need references pointing into the buffer's contents.
-pub struct CV;
-
-/// A port connected to an array of float control values. This port type can safely operate on shared input and output buffers.
-///
-/// Ports of this type are connected to a buffer of float control values, represented as a slice of [`Cell`s](std::cell::Cell).
-/// They have the same buffer format as [`InPlaceAudio`](crate::port::InPlaceAudio) ports, except the buffer represents
-/// audio-rate control data rather than audio.
-/// Like a [`InPlaceControl`](crate::port::InPlaceControl) port, a CV port SHOULD have properties describing its value, in particular minimum, maximum, and default.
-///
-/// Hosts may present CV ports to users as controls in the same way as control ports.
-/// Conceptually, aside from the buffer format, a CV port is the same as a control port, so hosts can use all the same properties and expectations.
-///
-/// In particular, this port type does not imply any range, unit, or meaning for its values.
-/// However, if there is no inherent unit to the values, for example if the port is used to modulate some other value, then plugins SHOULD use a normalized range, either from -1.0 to 1.0, or from 0.0 to 1.0.
-///
-/// It is generally safe to connect an audio output to a CV input, but not vice-versa.
-/// Hosts must take care to prevent data from a CVPort port from being used as audio.
-///
-/// See the [LV2 reference](https://lv2plug.in/ns/lv2core#CVPort) for more information.
-///
-/// # Example
-///
-/// This very simple amplifier plugin multiplies the input sample by the input CV signal and outputs the result.
-///
-/// ```
-/// # use lv2_core::prelude::*;
-/// # use urid::*;
-/// # #[uri("http://lv2plug.in/plugins.rs/simple_amp")]
-/// # struct CVAmp;
-/// #[derive(PortCollection)]
-/// struct CVAmpPorts {
-///     factor: InputPort<InPlaceCV>,
-///     input: InputPort<InPlaceAudio>,
-///     output: OutputPort<InPlaceAudio>,
-/// }
-///
-/// impl Plugin for CVAmp {
-///     type Ports = CVAmpPorts;
-/// # type InitFeatures = ();
-/// # type AudioFeatures = ();
-/// # fn new(plugin_info: &PluginInfo,features: &mut Self::InitFeatures) -> Option<Self> {
-/// #         unimplemented!()
-/// # }
-///     // some implementation details elided…
-///
-///     fn run(&mut self, ports: &mut CVAmpPorts, _: &mut (), _: u32) {
-///         // Input and Output dereference to `&[Cell<f32>]`.
-///         let factor = ports.factor.iter();
-///
-///         let input = ports.input.iter();
-///         let output = ports.output.iter();
-///
-///         for ((input_sample, output_sample), amp_factor) in input.zip(output).zip(factor) {
-///             output_sample.set(input_sample.get() * amp_factor.get());
-///         }
-///     }
-/// }
-///
-///
-/// ```
-pub struct InPlaceCV;
diff --git a/core/src/port/inplace.rs b/core/src/port/inplace.rs
new file mode 100644
index 00000000..c8be65f2
--- /dev/null
+++ b/core/src/port/inplace.rs
@@ -0,0 +1,162 @@
+//! Ports version supporting inplace processing.
+//!
+//! These ports are safe to use when host provide same data location for input and output. Because
+//! of that:
+//!  - All ports of this module use [`RCell`] or [`RwCell`] to reflect potential aliasing of data
+//!  location.
+//!  - All output ports of this module are writted through the interior mutablility provided by
+//!  [`RwCell`].
+//!  - Care must be taken to read input datas before they are altered by writing to output.
+//!
+//!  TODO: Example and bad example
+
+use crate::port::{PortHandle, RCell, RwCell};
+use core::ffi::c_void;
+use core::ops::Deref;
+use core::ptr::*;
+
+/// Audio input port. Gives a read only access to a buffer of audio samples.
+///
+/// Audio samples are float data normalized between -1.0 and 1.0, though there is no requirement
+/// for samples to be strictly within this range.
+///
+/// See the [LV2 reference](https://lv2plug.in/ns/lv2core#AudioPort) for more information.
+pub struct AudioInput {
+    ptr: *const [RCell<f32>],
+}
+
+impl PortHandle for AudioInput {
+    unsafe fn from_raw(pointer: *mut c_void, sample_count: u32) -> Option<Self> {
+        Some(Self {
+            ptr: slice_from_raw_parts(pointer as *const RCell<f32>, sample_count as usize),
+        })
+    }
+}
+
+impl Deref for AudioInput {
+    type Target = [RCell<f32>];
+    fn deref(&self) -> &[RCell<f32>] {
+        unsafe { &*self.ptr }
+    }
+}
+
+/// Audio output port. Gives a read/write access to a buffer of audio samples.
+///
+/// Audio samples are float data normalized between -1.0 and 1.0, though there is no requirement
+/// for samples to be strictly within this range.
+///
+/// See the [LV2 reference](https://lv2plug.in/ns/lv2core#AudioPort) for more information.
+pub struct AudioOutput {
+    ptr: *mut [RwCell<f32>],
+}
+
+impl PortHandle for AudioOutput {
+    unsafe fn from_raw(pointer: *mut c_void, sample_count: u32) -> Option<Self> {
+        Some(Self {
+            ptr: slice_from_raw_parts_mut(pointer as *mut RwCell<f32>, sample_count as usize),
+        })
+    }
+}
+
+impl Deref for AudioOutput {
+    type Target = [RwCell<f32>];
+    fn deref(&self) -> &[RwCell<f32>] {
+        unsafe { &*self.ptr }
+    }
+}
+
+/// Control input port. Gives a read only access to a single float.
+///
+/// See the [LV2 reference](https://lv2plug.in/ns/lv2core#ControlPort) for more information.
+pub struct ControlInput {
+    ptr: *const RCell<f32>,
+}
+
+impl PortHandle for ControlInput {
+    unsafe fn from_raw(pointer: *mut c_void, _sample_count: u32) -> Option<Self> {
+        Some(Self {
+            ptr: pointer as *const RCell<f32>,
+        })
+    }
+}
+
+impl Deref for ControlInput {
+    type Target = RCell<f32>;
+    fn deref(&self) -> &RCell<f32> {
+        unsafe { &*self.ptr }
+    }
+}
+
+/// Control output port. Gives a read/write access to a single float.
+///
+/// See the [LV2 reference](https://lv2plug.in/ns/lv2core#ControlPort) for more information.
+pub struct ControlOutput {
+    ptr: *mut RwCell<f32>,
+}
+
+impl PortHandle for ControlOutput {
+    unsafe fn from_raw(pointer: *mut c_void, _sample_count: u32) -> Option<Self> {
+        Some(Self {
+            ptr: pointer as *mut RwCell<f32>,
+        })
+    }
+}
+
+impl Deref for ControlOutput {
+    type Target = RwCell<f32>;
+    fn deref(&self) -> &RwCell<f32> {
+        unsafe { &*self.ptr }
+    }
+}
+
+/// CV input port. Gives a read only acces to a buffer of audio rate control values.
+///
+/// Ports of this type have the same buffer format as [`AudioInput`] ports, except the buffer
+/// represents audio-rate control data rather than audio. It is generally safe to connect an audio
+/// output to a CV input, but not vice-versa.
+///
+/// See the [LV2 reference](https://lv2plug.in/ns/lv2core#CVPort) for more information.
+pub struct CVInput {
+    ptr: *const [RCell<f32>],
+}
+
+impl PortHandle for CVInput {
+    unsafe fn from_raw(pointer: *mut c_void, sample_count: u32) -> Option<Self> {
+        Some(Self {
+            ptr: slice_from_raw_parts(pointer as *const RCell<f32>, sample_count as usize),
+        })
+    }
+}
+
+impl Deref for CVInput {
+    type Target = [RCell<f32>];
+    fn deref(&self) -> &[RCell<f32>] {
+        unsafe { &*self.ptr }
+    }
+}
+
+/// CV output port. Gives a read/write acces to a buffer of audio rate control values.
+///
+/// Ports of this type have the same buffer format as [`AudioInput`] ports, except the buffer
+/// represents audio-rate control data rather than audio. It is generally safe to connect an audio
+/// output to a CV input, but not vice-versa.
+///
+/// See the [LV2 reference](https://lv2plug.in/ns/lv2core#CVPort) for more information.
+pub struct CVOutput {
+    ptr: *mut [RwCell<f32>],
+}
+
+impl PortHandle for CVOutput {
+    unsafe fn from_raw(pointer: *mut c_void, sample_count: u32) -> Option<Self> {
+        Some(Self {
+            ptr: slice_from_raw_parts_mut(pointer as *mut RwCell<f32>, sample_count as usize),
+        })
+    }
+}
+
+impl Deref for CVOutput {
+    type Target = [RwCell<f32>];
+    fn deref(&self) -> &[RwCell<f32>] {
+        unsafe { &*self.ptr }
+    }
+}
diff --git a/core/src/port/not_inplace.rs b/core/src/port/not_inplace.rs
new file mode 100644
index 00000000..ddc65f4b
--- /dev/null
+++ b/core/src/port/not_inplace.rs
@@ -0,0 +1,176 @@
+//! Ports version not supporting inplace processing.
+//!
+//! These ports are easier to use thant their inplace counterpart, but they **must not** be used
+//! when a host can provide same data location for input and output. Most of the time, this require
+//! `inPlaceBroken` LV2 feature for your plugin.  Using `inPlaceBroken` feature is discouraged
+//! because many host doesn't support it.
+//!
+//! TODO: example
+use crate::port::PortHandle;
+use core::ffi::c_void;
+use core::ops::{Deref, DerefMut};
+use core::ptr::*;
+
+/// Audio input port. Gives a read only access to a buffer of audio samples.
+///
+/// Audio samples are float data normalized between -1.0 and 1.0, though there is no requirement
+/// for samples to be strictly within this range.
+///
+/// See the [LV2 reference](https://lv2plug.in/ns/lv2core#AudioPort) for more information.
+pub struct AudioInput {
+    ptr: *const [f32],
+}
+
+impl PortHandle for AudioInput {
+    unsafe fn from_raw(pointer: *mut c_void, sample_count: u32) -> Option<Self> {
+        Some(Self {
+            ptr: slice_from_raw_parts(pointer as *const f32, sample_count as usize),
+        })
+    }
+}
+
+impl Deref for AudioInput {
+    type Target = [f32];
+    fn deref(&self) -> &[f32] {
+        unsafe { &*self.ptr }
+    }
+}
+
+/// Audio output port. Gives a read/write access to a buffer of audio samples.
+///
+/// Audio samples are float data normalized between -1.0 and 1.0, though there is no requirement
+/// for samples to be strictly within this range.
+///
+/// See the [LV2 reference](https://lv2plug.in/ns/lv2core#AudioPort) for more information.
+pub struct AudioOutput {
+    ptr: *mut [f32],
+}
+
+impl PortHandle for AudioOutput {
+    unsafe fn from_raw(pointer: *mut c_void, sample_count: u32) -> Option<Self> {
+        Some(Self {
+            ptr: slice_from_raw_parts_mut(pointer as *mut f32, sample_count as usize),
+        })
+    }
+}
+
+impl Deref for AudioOutput {
+    type Target = [f32];
+    fn deref(&self) -> &[f32] {
+        unsafe { &*self.ptr }
+    }
+}
+
+impl DerefMut for AudioOutput {
+    fn deref_mut(&mut self) -> &mut [f32] {
+        unsafe { &mut *self.ptr }
+    }
+}
+
+/// Control input port. Gives a read only access to a single float.
+///
+/// See the [LV2 reference](https://lv2plug.in/ns/lv2core#ControlPort) for more information.
+pub struct ControlInput {
+    ptr: *const f32,
+}
+
+impl PortHandle for ControlInput {
+    unsafe fn from_raw(pointer: *mut c_void, _sample_count: u32) -> Option<Self> {
+        Some(Self {
+            ptr: pointer as *const f32,
+        })
+    }
+}
+
+impl Deref for ControlInput {
+    type Target = f32;
+    fn deref(&self) -> &f32 {
+        unsafe { &*self.ptr }
+    }
+}
+
+/// Control output port. Gives a read/write access to a single float.
+///
+/// See the [LV2 reference](https://lv2plug.in/ns/lv2core#ControlPort) for more information.
+pub struct ControlOutput {
+    ptr: *mut f32,
+}
+
+impl PortHandle for ControlOutput {
+    unsafe fn from_raw(pointer: *mut c_void, _sample_count: u32) -> Option<Self> {
+        Some(Self {
+            ptr: pointer as *mut f32,
+        })
+    }
+}
+
+impl Deref for ControlOutput {
+    type Target = f32;
+    fn deref(&self) -> &f32 {
+        unsafe { &*self.ptr }
+    }
+}
+
+impl DerefMut for ControlOutput {
+    fn deref_mut(&mut self) -> &mut f32 {
+        unsafe { &mut *self.ptr }
+    }
+}
+
+/// CV input port. Gives a read only acces to a buffer of audio rate control values.
+///
+/// Ports of this type have the same buffer format as [`AudioInput`] ports, except the buffer
+/// represents audio-rate control data rather than audio. It is generally safe to connect an audio
+/// output to a CV input, but not vice-versa.
+///
+/// See the [LV2 reference](https://lv2plug.in/ns/lv2core#CVPort) for more information.
+pub struct CVInput {
+    ptr: *const [f32],
+}
+
+impl PortHandle for CVInput {
+    unsafe fn from_raw(pointer: *mut c_void, sample_count: u32) -> Option<Self> {
+        Some(Self {
+            ptr: slice_from_raw_parts(pointer as *const f32, sample_count as usize),
+        })
+    }
+}
+
+impl Deref for CVInput {
+    type Target = [f32];
+    fn deref(&self) -> &[f32] {
+        unsafe { &*self.ptr }
+    }
+}
+
+/// CV output port. Gives a read/write acces to a buffer of audio rate control values.
+///
+/// Ports of this type have the same buffer format as [`AudioInput`] ports, except the buffer
+/// represents audio-rate control data rather than audio. It is generally safe to connect an audio
+/// output to a CV input, but not vice-versa.
+///
+/// See the [LV2 reference](https://lv2plug.in/ns/lv2core#CVPort) for more information.
+pub struct CVOutput {
+    ptr: *mut [f32],
+}
+
+impl PortHandle for CVOutput {
+    unsafe fn from_raw(pointer: *mut c_void, sample_count: u32) -> Option<Self> {
+        Some(Self {
+            ptr: slice_from_raw_parts_mut(pointer as *mut f32, sample_count as usize),
+        })
+    }
+}
+
+impl Deref for CVOutput {
+    type Target = [f32];
+    fn deref(&self) -> &[f32] {
+        unsafe { &*self.ptr }
+    }
+}
+
+impl DerefMut for CVOutput {
+    fn deref_mut(&mut self) -> &mut [f32] {
+        unsafe { &mut *self.ptr }
+    }
+}

From 8563b7cee558b1fbdec0707f1d4471fa9238dc8b Mon Sep 17 00:00:00 2001
From: Yruama_Lairba <yruama_lairba@hotmail.com>
Date: Sun, 3 Jul 2022 00:17:31 +0200
Subject: [PATCH 11/18] remove unused stuff, avoid too long line of doc

---
 core/src/port.rs | 136 +++++++++++------------------------------------
 1 file changed, 30 insertions(+), 106 deletions(-)

diff --git a/core/src/port.rs b/core/src/port.rs
index b89d62c5..1c7b1542 100644
--- a/core/src/port.rs
+++ b/core/src/port.rs
@@ -1,13 +1,15 @@
 //! Types to declare derivable port collections.
 //!
-//! Every plugin has a type of [`PortCollection`](trait.PortCollection.html) which is used to handle input/output ports. In order to make the creation of these port collection types easier, `PortCollection` can simply be derived. However, the macro that implements `PortCollection` requires the fields of the struct to have specific types. These types are provided in this module.
+//! Every plugin has a type of [`PortCollection`](trait.PortCollection.html) which is used to
+//! handle input/output ports. In order to make the creation of these port collection types easier,
+//! `PortCollection` can simply be derived. However, the macro that implements `PortCollection`
+//! requires the fields of the struct to have specific types. These types are provided in this
+//! module.
 pub mod inplace;
 pub mod not_inplace;
 
 use std::cell::Cell;
 use std::ffi::c_void;
-use std::ops::{Deref, DerefMut};
-use std::ptr::NonNull;
 
 /// A readonly cell. Used to give read only access for input port with inplace processing support.
 ///
@@ -72,40 +74,6 @@ impl<T> RwCell<[T]> {
     }
 }
 
-/// Generalization of port types.
-///
-/// A port can read input or create a pointer to the output, but the exact type of input/output (pointer) depends on the type of port. This trait generalizes these types and behaviour.
-pub trait PortType {
-    /// The type of input read by the port.
-    type InputPortType: ?Sized;
-    /// The type of output reference created by the port.
-    type OutputPortType: ?Sized;
-
-    /// Read data from the pointer or create a reference to the input.
-    ///
-    /// If the resulting data is a slice, `sample_count` is the length of the slice.
-    ///
-    /// # Safety
-    ///
-    /// This method is unsafe because one needs to de-reference a raw pointer to implement this method.
-    unsafe fn input_from_raw(
-        pointer: NonNull<c_void>,
-        sample_count: u32,
-    ) -> *const Self::InputPortType;
-
-    /// Create a reference to the data where output should be written to.
-    ///
-    /// If the data is a slice, `sample_count` is the length of the slice.
-    ///
-    /// # Safety
-    ///
-    /// This method is unsafe because one needs to de-reference a raw pointer to implement this method.
-    unsafe fn output_from_raw(
-        pointer: NonNull<c_void>,
-        sample_count: u32,
-    ) -> *mut Self::OutputPortType;
-}
-
 /// Abstraction of safe port handles.
 pub trait PortHandle: Sized {
     /// Try to create a port handle from a port connection pointer and the sample count.
@@ -114,70 +82,11 @@ pub trait PortHandle: Sized {
     ///
     /// # Safety
     ///
-    /// Implementing this method requires a de-referentation of a raw pointer and therefore, it is unsafe.
+    /// Implementing this method requires a de-referentation of a raw pointer and therefore, it is
+    /// unsafe.
     unsafe fn from_raw(pointer: *mut c_void, sample_count: u32) -> Option<Self>;
 }
 
-/// Handle for input ports.
-///
-/// Fields of this type can be dereferenced to the input type of the port type.
-pub struct InputPort<T: PortType> {
-    port: *const T::InputPortType,
-}
-
-impl<T: PortType> Deref for InputPort<T> {
-    type Target = T::InputPortType;
-
-    #[inline]
-    fn deref(&self) -> &Self::Target {
-        unsafe { &*self.port }
-    }
-}
-
-impl<T> PortHandle for InputPort<T>
-where
-    T: PortType,
-{
-    #[inline]
-    unsafe fn from_raw(pointer: *mut c_void, sample_count: u32) -> Option<Self> {
-        Some(Self {
-            port: T::input_from_raw(NonNull::new(pointer)?, sample_count),
-        })
-    }
-}
-
-/// Handle for output ports.
-///
-/// Fields of this type can be dereferenced to the output type of the port type.
-pub struct OutputPort<T: PortType> {
-    port: *mut T::OutputPortType,
-}
-
-impl<T: PortType> Deref for OutputPort<T> {
-    type Target = T::OutputPortType;
-
-    #[inline]
-    fn deref(&self) -> &Self::Target {
-        unsafe { &*self.port }
-    }
-}
-
-impl<T: PortType> DerefMut for OutputPort<T> {
-    #[inline]
-    fn deref_mut(&mut self) -> &mut Self::Target {
-        unsafe { &mut *self.port }
-    }
-}
-
-impl<T: PortType> PortHandle for OutputPort<T> {
-    #[inline]
-    unsafe fn from_raw(pointer: *mut c_void, sample_count: u32) -> Option<Self> {
-        Some(Self {
-            port: T::output_from_raw(NonNull::new(pointer)?, sample_count),
-        })
-    }
-}
-
 impl<T: PortHandle> PortHandle for Option<T> {
     unsafe fn from_raw(pointer: *mut c_void, sample_count: u32) -> Option<Self> {
         Some(T::from_raw(pointer, sample_count))
@@ -186,11 +95,15 @@ impl<T: PortHandle> PortHandle for Option<T> {
 
 /// Collection of IO ports.
 ///
-/// Plugins do not handle port management on their own. Instead, they define a struct with all of the required ports. Then, the plugin instance will collect the port pointers from the host and create a `PortCollection` instance for every `run` call. Using this instance, plugins have access to all of their required ports.
+/// Plugins do not handle port management on their own. Instead, they define a struct with all of
+/// the required ports. Then, the plugin instance will collect the port pointers from the host and
+/// create a `PortCollection` instance for every `run` call. Using this instance, plugins have
+/// access to all of their required ports.
 ///
 /// # Implementing
 ///
-/// The most convenient way to create a port collections is to define a struct with port types from the [`port`](index.html) module and then simply derive `PortCollection` for it. An example:
+/// The most convenient way to create a port collections is to define a struct with port types from
+/// the [`port`](index.html) module and then simply derive `PortCollection` for it. An example:
 /// ```
 ///     # pub use lv2_core_derive::*;
 ///     use lv2_core::port::*;
@@ -205,20 +118,28 @@ impl<T: PortHandle> PortHandle for Option<T> {
 ///     }
 /// ```
 ///
-/// Please note that port indices are mapped in the order of occurrence; In our example, the implementation will treat `audio_input` as port `0`, `audio_output` as port `1` and so on. Therefore, your plugin definition and your port collection have to match. Otherwise, undefined behaviour will occur.
+/// Please note that port indices are mapped in the order of occurrence; In our example, the
+/// implementation will treat `audio_input` as port `0`, `audio_output` as port `1` and so on.
+/// Therefore, your plugin definition and your port collection have to match. Otherwise, undefined
+/// behaviour will occur.
 pub trait PortCollection: Sized {
     /// The type of the port pointer cache.
     ///
-    /// The host passes port pointers to the plugin one by one and in an undefined order. Therefore, the plugin instance can not collect these pointers in the port collection directly. Instead, the pointers are stored in a cache which is then used to create the proper port collection.
+    /// The host passes port pointers to the plugin one by one and in an undefined order.
+    /// Therefore, the plugin instance can not collect these pointers in the port collection
+    /// directly. Instead, the pointers are stored in a cache which is then used to create the
+    /// proper port collection.
     type Cache: PortPointerCache;
 
     /// Try to construct a port collection instance from a port pointer cache.
     ///
-    /// If one of the port connection pointers is null, this method will return `None`, because a `PortCollection` can not be constructed.
+    /// If one of the port connection pointers is null, this method will return `None`, because a
+    /// `PortCollection` can not be constructed.
     ///
     /// # Safety
     ///
-    /// Since the pointer cache is only storing the pointers, implementing this method requires the de-referencation of raw pointers and therefore, this method is unsafe.
+    /// Since the pointer cache is only storing the pointers, implementing this method requires the
+    /// de-referencation of raw pointers and therefore, this method is unsafe.
     unsafe fn from_connections(cache: &Self::Cache, sample_count: u32) -> Option<Self>;
 }
 
@@ -232,11 +153,14 @@ impl PortCollection for () {
 
 /// Cache for port connection pointers.
 ///
-/// The host will pass the port connection pointers one by one and in an undefined order. Therefore, the `PortCollection` struct can not be created instantly. Instead, the pointers will be stored in a cache, which is then used to create a proper port collection for the plugin.
+/// The host will pass the port connection pointers one by one and in an undefined order.
+/// Therefore, the `PortCollection` struct can not be created instantly. Instead, the pointers will
+/// be stored in a cache, which is then used to create a proper port collection for the plugin.
 pub trait PortPointerCache: Sized + Default {
     /// Store the connection pointer for the port with index `index`.
     ///
-    /// The passed pointer may not be valid yet and therefore, implementors should only store the pointer, not dereference it.
+    /// The passed pointer may not be valid yet and therefore, implementors should only store the
+    /// pointer, not dereference it.
     fn connect(&mut self, index: u32, pointer: *mut c_void);
 }
 

From f43bacd09f527644bf6a574e1e559d2a9b865f3b Mon Sep 17 00:00:00 2001
From: Yruama_Lairba <yruama_lairba@hotmail.com>
Date: Sun, 3 Jul 2022 00:45:52 +0200
Subject: [PATCH 12/18] fix the amp test

---
 core/Cargo.toml   |  3 +++
 core/tests/amp.rs | 11 ++++++-----
 2 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/core/Cargo.toml b/core/Cargo.toml
index 96a6465e..38a3d10e 100644
--- a/core/Cargo.toml
+++ b/core/Cargo.toml
@@ -18,5 +18,8 @@ urid = { version = "0.1.0", default-features = false }
 lv2-sys = "2.0.0"
 lv2-core-derive = { version = "2.1.0", optional = true }
 
+[dev-dependencies]
+urid = { version = "0.1.0", default-features = true }
+
 [features]
 default = ["lv2-core-derive"]
diff --git a/core/tests/amp.rs b/core/tests/amp.rs
index 3643ab03..c1e8e0b6 100644
--- a/core/tests/amp.rs
+++ b/core/tests/amp.rs
@@ -1,5 +1,6 @@
 use lv2_core::feature::{FeatureCache, FeatureCollection, MissingFeatureError};
 use lv2_core::feature::{HardRTCapable, IsLive};
+use lv2_core::port::inplace::*;
 use lv2_core::prelude::*;
 use std::ops::Drop;
 use std::os::raw::c_char;
@@ -12,9 +13,9 @@ struct Amp {
 
 #[derive(PortCollection)]
 struct AmpPorts {
-    gain: InputPort<InPlaceControl>,
-    input: InputPort<InPlaceAudio>,
-    output: OutputPort<InPlaceAudio>,
+    gain: ControlInput,
+    input: AudioInput,
+    output: AudioOutput,
 }
 
 #[derive(FeatureCollection)]
@@ -56,13 +57,13 @@ impl Plugin for Amp {
     fn run(&mut self, ports: &mut AmpPorts, _: &mut (), _: u32) {
         assert!(self.activated);
 
-        let coef = *(ports.gain);
+        let coef = ports.gain.get();
 
         let input = ports.input.iter();
         let output = ports.output.iter();
 
         for (input_sample, output_sample) in input.zip(output) {
-            output_sample.set(input_sample.get() * coef.get());
+            output_sample.set(input_sample.get() * coef);
         }
     }
 

From 5fcc320c9ed7b21369e3314d816178d3e5a18bdd Mon Sep 17 00:00:00 2001
From: Yruama_Lairba <yruama_lairba@hotmail.com>
Date: Sun, 3 Jul 2022 01:04:49 +0200
Subject: [PATCH 13/18] adapt prelude for port

---
 core/src/prelude.rs | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/core/src/prelude.rs b/core/src/prelude.rs
index eb9322c7..d7116c89 100644
--- a/core/src/prelude.rs
+++ b/core/src/prelude.rs
@@ -7,5 +7,6 @@ pub use crate::plugin::{Plugin, PluginInfo, PluginInstance, PluginInstanceDescri
 #[cfg(feature = "lv2-core-derive")]
 pub use crate::plugin::{lv2_descriptors, PortCollection};
 
-pub use crate::port::*;
+pub use crate::port;
+pub use crate::port::{PortCollection, PortHandle, PortPointerCache, RCell, RwCell};
 pub use crate::sys::LV2_Descriptor;

From 2e839232e2c8e59dc630398651b611705c737a83 Mon Sep 17 00:00:00 2001
From: Yruama_Lairba <yruama_lairba@hotmail.com>
Date: Sun, 3 Jul 2022 01:25:27 +0200
Subject: [PATCH 14/18] fix doc examples

---
 core/src/lib.rs  | 16 +++++++++-------
 core/src/port.rs | 14 +++++++-------
 2 files changed, 16 insertions(+), 14 deletions(-)

diff --git a/core/src/lib.rs b/core/src/lib.rs
index 369b2245..876d7951 100644
--- a/core/src/lib.rs
+++ b/core/src/lib.rs
@@ -7,6 +7,7 @@
 //! ```
 //! // Import everything we need.
 //! use lv2_core::prelude::*;
+//! use port::inplace::*; //imports ports supporting inplace processing
 //! use urid::*;
 //!
 //! // The input and output ports are defined by a struct which implements the `PortCollection` trait.
@@ -14,9 +15,9 @@
 //! // port and an output audio port.
 //! #[derive(PortCollection)]
 //! struct Ports {
-//!     gain: InputPort<Control>,
-//!     input: InputPort<Audio>,
-//!     output: OutputPort<Audio>,
+//!     gain: ControlInput,
+//!     input: AudioInput,
+//!     output: AudioOutput,
 //! }
 //!
 //! // The plugin struct. In this case, we don't need any data and therefore, this struct is empty.
@@ -44,14 +45,15 @@
 //!     // Process a chunk of audio. The audio ports are dereferenced to slices, which the plugin
 //!     // iterates over.
 //!     fn run(&mut self, ports: &mut Ports, _features: &mut (), _: u32) {
-//!         let coef = if *(ports.gain) > -90.0 {
-//!             10.0_f32.powf(*(ports.gain) * 0.05)
+//!         let gain = ports.gain.get();
+//!         let coef = if gain > -90.0 {
+//!             10.0_f32.powf(gain * 0.05)
 //!         } else {
 //!             0.0
 //!         };
 //!
-//!         for (in_frame, out_frame) in Iterator::zip(ports.input.iter(), ports.output.iter_mut()) {
-//!             *out_frame = in_frame * coef;
+//!         for (in_frame, out_frame) in Iterator::zip(ports.input.iter(), ports.output.iter()) {
+//!             out_frame.set(in_frame.get() *coef);
 //!         }
 //!     }
 //! }
diff --git a/core/src/port.rs b/core/src/port.rs
index 1c7b1542..6d5ae965 100644
--- a/core/src/port.rs
+++ b/core/src/port.rs
@@ -105,16 +105,16 @@ impl<T: PortHandle> PortHandle for Option<T> {
 /// The most convenient way to create a port collections is to define a struct with port types from
 /// the [`port`](index.html) module and then simply derive `PortCollection` for it. An example:
 /// ```
-///     # pub use lv2_core_derive::*;
-///     use lv2_core::port::*;
+///     use lv2_core::prelude::*;
+///     use lv2_core::port::inplace::*;
 ///
 ///     #[derive(PortCollection)]
 ///     struct MyPortCollection {
-///         audio_input: InputPort<Audio>,
-///         audio_output: OutputPort<Audio>,
-///         control_input: InputPort<Control>,
-///         control_output: OutputPort<Control>,
-///         optional_control_input: Option<InputPort<Control>>,
+///         audio_input: AudioInput,
+///         audio_output: AudioOutput,
+///         control_input: ControlInput,
+///         control_output: ControlOutput,
+///         optional_control_input: Option<ControlInput>,
 ///     }
 /// ```
 ///

From abab288616bd8bb48e45284bac81e086d6ab00ac Mon Sep 17 00:00:00 2001
From: Yruama_Lairba <yruama_lairba@hotmail.com>
Date: Sun, 3 Jul 2022 01:51:30 +0200
Subject: [PATCH 15/18] fix lv2 doc example + reformat lines of doc

---
 src/lib.rs | 63 ++++++++++++++++++++++++++++++++++--------------------
 1 file changed, 40 insertions(+), 23 deletions(-)

diff --git a/src/lib.rs b/src/lib.rs
index 262baae5..1b6810fa 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -2,7 +2,8 @@
 //!
 //! **This library is a work in progress.**
 //!
-//! It provides the following features, through the [LV2 Core specification](http://lv2plug.in/ns/lv2core/lv2core.html):
+//! It provides the following features, through the [LV2 Core
+//! specification](http://lv2plug.in/ns/lv2core/lv2core.html):
 //!
 //! * Lightweight, realtime non-blocking and allocation-free audio processing.
 //! * Generates all the boilerplate to make a LV2 plugin binary, usable by any LV2 host.
@@ -11,20 +12,23 @@
 //! * Can be extended to support any additional features, extensions and port types.
 //!   They can be official, unofficial or completely custom.
 //!
-//! Through the [LV2 official additional specifications](http://lv2plug.in/ns/), this library also provide many
-//! additional features, including:
+//! Through the [LV2 official additional specifications](http://lv2plug.in/ns/), this library also
+//! provide many additional features, including:
 //!
 //! * MIDI processing
-//! * Serialization of custom data structures, and plugin-plugin or plugin-GUI communication and property manipulation
+//! * Serialization of custom data structures, and plugin-plugin or plugin-GUI communication and
+//! property manipulation
 //! * State management
 //! * Asynchronous work processing
-//! * Custom Graphical User Interfaces, both in a toolkit-agnostic and in a platform-agnostic way **(Not yet implemented)**
+//! * Custom Graphical User Interfaces, both in a toolkit-agnostic and in a platform-agnostic way
+//! **(Not yet implemented)**
 //! * Presets handling **(Not yet implemented)**
 //! * ... and more! (Not yet implemented either)
 //!
-//! Note that this library will only provide Rust bindings for the official LV2 specifications, however it is compatible
-//! with any other arbitrary or custom specification, and other, external crates are able and welcome to provide Rust bindings
-//! to any other specification that will integrate with this library.
+//! Note that this library will only provide Rust bindings for the official LV2 specifications,
+//! however it is compatible with any other arbitrary or custom specification, and other, external
+//! crates are able and welcome to provide Rust bindings to any other specification that will
+//! integrate with this library.
 //!
 //! # Example
 //!
@@ -33,15 +37,16 @@
 //! ```
 //! // Import everything we need.
 //! use lv2::prelude::*;
+//! use lv2_core::port::inplace::*;
 //!
 //! // The input and output ports are defined by a struct which implements the `PortCollection` trait.
 //! // In this case, there is an input control port for the gain of the amplification, an input audio
 //! // port and an output audio port.
 //! #[derive(PortCollection)]
 //! struct Ports {
-//!     gain: InputPort<Control>,
-//!     input: InputPort<Audio>,
-//!     output: OutputPort<Audio>,
+//!     gain: ControlInput,
+//!     input: AudioInput,
+//!     output: AudioOutput,
 //! }
 //!
 //! // The plugin struct. In this case, we don't need any data and therefore, this struct is empty.
@@ -69,14 +74,15 @@
 //!     // Process a chunk of audio. The audio ports are dereferenced to slices, which the plugin
 //!     // iterates over.
 //!     fn run(&mut self, ports: &mut Ports, _features: &mut (), _: u32) {
-//!         let coef = if *(ports.gain) > -90.0 {
-//!             10.0_f32.powf(*(ports.gain) * 0.05)
+//!         let gain = ports.gain.get();
+//!         let coef = if gain > -90.0 {
+//!             10.0_f32.powf(gain * 0.05)
 //!         } else {
 //!             0.0
 //!         };
 //!
-//!         for (in_frame, out_frame) in Iterator::zip(ports.input.iter(), ports.output.iter_mut()) {
-//!             *out_frame = in_frame * coef;
+//!         for (in_frame, out_frame) in Iterator::zip(ports.input.iter(), ports.output.iter()) {
+//!             out_frame.set(in_frame.get() * coef);
 //!         }
 //!     }
 //! }
@@ -87,34 +93,45 @@
 //! ## Documentation
 //!
 //! There are multiple valuable sources of documentation:
-//! * ["The Rust-LV2 book"](https://rustaudio.github.io/rust-lv2/) describes how to use Rust-LV2 in general, broad terms. It's the ideal point to get started and is updated with every new version of Rust-LV2.
+//! * ["The Rust-LV2 book"](https://rustaudio.github.io/rust-lv2/) describes how to use Rust-LV2 in
+//! general, broad terms. It's the ideal point to get started and is updated with every new version
+//! of Rust-LV2.
 //! * [The API documentation](https://docs.rs/lv2).
 //! * [The LV2 specification reference](https://lv2plug.in/ns/).
 //!
 //! ## Features
 //!
-//! Internally, this framework is built of several sub-crates which are re-exported by the `lv2` crate. All dependencies are optional and can be enabled via features. These are:
+//! Internally, this framework is built of several sub-crates which are re-exported by the `lv2`
+//! crate. All dependencies are optional and can be enabled via features. These are:
 //!
 //! * `lv2-atom`: General data IO.
 //! * `lv2-core`: Implementation of the core LV2 specification.
-//! * `lv2-midi`: MIDI message extension for `lv2-midi`. Support for the [`wmidi` crate](https://crates.io/crates/wmidi) can be enabled with the `wmidi` feature.
+//! * `lv2-midi`: MIDI message extension for `lv2-midi`. Support for the [`wmidi`
+//! crate](https://crates.io/crates/wmidi) can be enabled with the `wmidi` feature.
 //! * `lv2-state`: Extension for LV2 plugins to store their state.
-//! * `lv2-time`: Specification to describe position in time and passage of time, in both real and musical terms.
+//! * `lv2-time`: Specification to describe position in time and passage of time, in both real and
+//! musical terms.
 //! * `lv2-units`: Measuring unit definitions.
 //! * `lv2-urid`: LV2 integration of the URID concept.
-//! * `lv2-worker`: Work scheduling library that allows real-time capable LV2 plugins to execute non-real-time actions.
+//! * `lv2-worker`: Work scheduling library that allows real-time capable LV2 plugins to execute
+//! non-real-time actions.
 //! * `urid`: Idiomatic URID support.
 //!
-//! Sub-crates with an `lv2-` prefix implement a certain LV2 specification, which can be looked up in [the reference](https://lv2plug.in/ns/). Enabling a crate only adds new content, it does not remove or break others.
+//! Sub-crates with an `lv2-` prefix implement a certain LV2 specification, which can be looked up
+//! in [the reference](https://lv2plug.in/ns/). Enabling a crate only adds new content, it does not
+//! remove or break others.
 //!
 //! There are also feature sets that account for common scenarios:
 //! * `minimal_plugin`: The bare minimum to create plugins. Includes `lv2-core` and `urid`.
-//! * `plugin`: Usual crates for standard plugins. Includes `lv2-core`, `lv2-atom`, `lv2-midi` with the `wmidi` feature, `lv2-units`, `lv2-urid`, and `urid`. **This is the default.**
+//! * `plugin`: Usual crates for standard plugins. Includes `lv2-core`, `lv2-atom`, `lv2-midi` with
+//! the `wmidi` feature, `lv2-units`, `lv2-urid`, and `urid`. **This is the default.**
 //! * `full`: All sub-crates.
 //!
 //! # Extending
 //!
-//! Please note that this re-export crate is only meant to be used by plugin projects. If you want to extend the framework with your own crates, please use the sub-crates as your dependencies instead. This will dramatically boost building durations and backwards compability.
+//! Please note that this re-export crate is only meant to be used by plugin projects. If you want
+//! to extend the framework with your own crates, please use the sub-crates as your dependencies
+//! instead. This will dramatically boost building durations and backwards compability.
 
 /// The super-prelude that contains the preludes of all enabled crates.
 pub mod prelude {

From abf126a91efd72d7e6f18e3f7f28d7e9b0050081 Mon Sep 17 00:00:00 2001
From: Yruama_Lairba <yruama_lairba@hotmail.com>
Date: Sun, 3 Jul 2022 02:42:12 +0200
Subject: [PATCH 16/18] make doc amp compiling

---
 docs/amp/src/lib.rs | 55 ++++++++++++++++++++++++++++++++-------------
 1 file changed, 40 insertions(+), 15 deletions(-)

diff --git a/docs/amp/src/lib.rs b/docs/amp/src/lib.rs
index 1e58657c..02adafe7 100644
--- a/docs/amp/src/lib.rs
+++ b/docs/amp/src/lib.rs
@@ -1,39 +1,64 @@
-// Include the prelude of `lv2`. This includes the preludes of every sub-crate and you are strongly encouraged to use it, since many macros depend on it.
+// Include the prelude of `lv2`. This includes the preludes of every sub-crate and you are strongly
+// encouraged to use it, since many macros depend on it.
 use lv2::prelude::*;
-// Most useful plugins will have ports for input and output data. In code, these ports are represented by a struct implementing the `PortCollection` trait. Internally, ports are referred to by index. These indices are assigned in ascending order, starting with 0 for the first port. The indices in `amp.ttl` have to match them.
+// Most useful plugins will have ports for input and output data. Here we import ports supporting
+// inplace processing.
+use lv2::lv2_core::port::inplace::*;
+// In code, these ports are represented by a struct implementing the `PortCollection` trait.
+// Internally, ports are referred to by index. These indices are assigned in ascending order,
+// starting with 0 for the first port.  The indices in `amp.ttl` have to match them.
 #[derive(PortCollection)]
 struct Ports {
-    gain: InputPort<Control>,
-    input: InputPort<Audio>,
-    output: OutputPort<Audio>,
+    gain: ControlInput,
+    input: AudioInput,
+    output: AudioOutput,
 }
-// Every plugin defines a struct for the plugin instance. All persistent data associated with a plugin instance is stored here, and is available to every instance method. In this simple plugin, there is no additional instance data and therefore, this struct is empty.
+// Every plugin defines a struct for the plugin instance. All persistent data associated with a
+// plugin instance is stored here, and is available to every instance method. In this simple
+// plugin, there is no additional instance data and therefore, this struct is empty.
 //
-// The URI is the identifier for a plugin, and how the host associates this implementation in code with its description in data. If this URI does not match that used in the data files, the host will fail to load the plugin. This attribute internally implements the `UriBound` trait for `Amp`, which is also used to identify many other things in the Rust-LV2 ecosystem.
+// The URI is the identifier for a plugin, and how the host associates this implementation in code
+// with its description in data. If this URI does not match that used in the data files, the host
+// will fail to load the plugin. This attribute internally implements the `UriBound` trait for
+// `Amp`, which is also used to identify many other things in the Rust-LV2 ecosystem.
 #[uri("https://github.com/RustAudio/rust-lv2/tree/master/docs/amp")]
 struct Amp;
-// Every plugin struct implements the `Plugin` trait. This trait contains both the methods that are called by the hosting application and the collection types for the ports and the used host features. This plugin does not use additional host features and therefore, we set both feature collection types to `()`. Other plugins may define separate structs with their required and optional features and set it here.
+// Every plugin struct implements the `Plugin` trait. This trait contains both the methods that are
+// called by the hosting application and the collection types for the ports and the used host
+// features. This plugin does not use additional host features and therefore, we set both feature
+// collection types to `()`. Other plugins may define separate structs with their required and
+// optional features and set it here.
 impl Plugin for Amp {
     type Ports = Ports;
 
     type InitFeatures = ();
     type AudioFeatures = ();
-    // The `new` method is called by the plugin backend when it creates a new plugin instance. The host passes the plugin URI, sample rate, and bundle path for plugins that need to load additional resources (e.g. waveforms). The features parameter contains host-provided features defined in LV2 extensions, but this simple plugin does not use any. This method is in the “instantiation” threading class, so no other methods on this instance will be called concurrently with it.
+    // The `new` method is called by the plugin backend when it creates a new plugin instance. The
+    // host passes the plugin URI, sample rate, and bundle path for plugins that need to load
+    // additional resources (e.g. waveforms). The features parameter contains host-provided
+    // features defined in LV2 extensions, but this simple plugin does not use any. This method is
+    // in the “instantiation” threading class, so no other methods on this instance will be called
+    // concurrently with it.
     fn new(_plugin_info: &PluginInfo, _features: &mut ()) -> Option<Self> {
         Some(Self)
     }
-    // The `run()` method is the main process function of the plugin. It processes a block of audio in the audio context. Since this plugin is `lv2:hardRTCapable`, `run()` must be real-time safe, so blocking (e.g. with a mutex) or memory allocation are not allowed.
+    // The `run()` method is the main process function of the plugin. It processes a block of audio
+    // in the audio context. Since this plugin is `lv2:hardRTCapable`, `run()` must be real-time
+    // safe, so blocking (e.g. with a mutex) or memory allocation are not allowed.
     fn run(&mut self, ports: &mut Ports, _features: &mut (), _: u32) {
-        let coef = if *(ports.gain) > -90.0 {
-            10.0_f32.powf(*(ports.gain) * 0.05)
+        let gain = ports.gain.get();
+        let coef = if gain > -90.0 {
+            10.0_f32.powf(gain * 0.05)
         } else {
             0.0
         };
 
-        for (in_frame, out_frame) in Iterator::zip(ports.input.iter(), ports.output.iter_mut()) {
-            *out_frame = in_frame * coef;
+        for (in_frame, out_frame) in Iterator::zip(ports.input.iter(), ports.output.iter()) {
+            out_frame.set(in_frame.get() * coef);
         }
     }
 }
-// The `lv2_descriptors` macro creates the entry point to the plugin library. It takes structs that implement `Plugin` and exposes them. The host will load the library and call a generated function to find all the plugins defined in the library.
+// The `lv2_descriptors` macro creates the entry point to the plugin library. It takes structs that
+// implement `Plugin` and exposes them. The host will load the library and call a generated
+// function to find all the plugins defined in the library.
 lv2_descriptors!(Amp);

From 808cfa60bf70e6f8b172a2b6c8fba5c7fd814c04 Mon Sep 17 00:00:00 2001
From: Yruama_Lairba <yruama_lairba@hotmail.com>
Date: Sun, 3 Jul 2022 02:42:53 +0200
Subject: [PATCH 17/18] require only minimal set of features

---
 docs/amp/Cargo.toml | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/docs/amp/Cargo.toml b/docs/amp/Cargo.toml
index 9a716f0b..9d3f304f 100644
--- a/docs/amp/Cargo.toml
+++ b/docs/amp/Cargo.toml
@@ -16,7 +16,10 @@ crate-type = ["cdylib"]
 # However, most plugins don't need to deal with them directly. Instead, they use the re-export crate
 # simply called `lv2`. It has an optional dependency to every sub-crate, which can be enabled via crate features.
 # 
-# The default feature set includes everything to create a simple plugin for audio and MIDI processing.
-# Therefore, we don't need to enable extra features here.
-[dependencies]
-lv2 = "0.6.0"
\ No newline at end of file
+# The 'minimal_plugin' feature enable minimum set of features required to
+# create a plugin. This minimum set allow audio processing so, we don't need to
+# enable additional features here.
+[dependencies.lv2]
+version = "0.6.0"
+default-features = false
+features = ["minimal_plugin"]

From 603e1741ad371afffa2036b652ceefe8031a3460 Mon Sep 17 00:00:00 2001
From: Yruama_Lairba <yruama_lairba@hotmail.com>
Date: Sun, 3 Jul 2022 02:43:42 +0200
Subject: [PATCH 18/18] remove inplacebroken since this plug now use inplace
 ports

---
 docs/amp/eg-amp-rs.lv2/amp.ttl | 2 --
 1 file changed, 2 deletions(-)

diff --git a/docs/amp/eg-amp-rs.lv2/amp.ttl b/docs/amp/eg-amp-rs.lv2/amp.ttl
index af6fdb60..145d314d 100644
--- a/docs/amp/eg-amp-rs.lv2/amp.ttl
+++ b/docs/amp/eg-amp-rs.lv2/amp.ttl
@@ -23,8 +23,6 @@
 # Every plugin must have a name, described with the doap:name property.
         doap:name "Simple Amplifier (Rust Version)" ;
         doap:license <http://opensource.org/licenses/isc> ;
-# This tells the host that this plugin can not work "in-place"; The input and output buffers may not be the same. This plugin could technically work "in-place", but it would mean that the plugin would receive a mutable and an immutable reference to the same place in memory, which obviously isn't allowed in Rust.
-        lv2:requiredFeature lv2:inPlaceBroken ;
         lv2:optionalFeature lv2:hardRTCapable ;
         lv2:port [
 # Every port must have at least two types, one that specifies direction