1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
use crate::{Input, Message, Output, Signal};
use alloc::vec::Vec;

/// To implement [`Source`] means something can be a source of sound/voltage,
///
/// Two things are required by the trait:
///
/// 1) keeping track of what the source is using an unique `usize` id
/// 2) using the sample method to fill one or multiple [`Signal`] buffers with f32 data.
///
/// A very basic example might be to implement a DC offset module
///
/// ```
/// use screech::traits::{Tracker, Source};
/// use screech::{Screech, Input, Output};
///
/// struct Offset {
///     id: usize,
///     input: Input,
///     output: Output,
///     offset: f32,
/// }
///
/// impl Offset {
///     fn new(screech: &mut Screech, offset: f32) -> Self {
///         // obtain a unique identifier from the main sreech instance
///         let id = screech.create_source_id();
///
///         Offset {
///             id,
///             // initialize a new input to keep track of input connected to our source
///             input: screech.init_input(&id, "signal_in"),
///             // initialize a new output [`Signal`] buffer for our id and name
///             output: screech.init_output(&id, "signal_out"),
///             offset,
///         }
///     }
/// }
///
/// impl Source for Offset {
///     fn sample(&mut self, tracker: &mut dyn Tracker, sample_rate: usize) {
///         for i in 0..*tracker.get_buffer_size() {
///             // set offset as initial value
///             let mut signal = self.offset;
///
///             // add all inputs to the signal
///             for input in tracker.get_input(&self.input).unwrap().into_iter() {
///                 if let Some(s) = tracker.get_output(&input).and_then(|o| o.samples.get(i)) {
///                     signal += s;
///                 }
///             }
///
///             // add signal to the final output
///             let output = tracker.get_mut_output(&self.output).unwrap();
///             output.samples[i] = signal;
///         }
///     }
///
///     fn get_source_id(&self) -> &usize {
///         &self.id
///     }
/// }
/// ```
pub trait Source<MessageData = ()>: Send {
    /// function that gets called by [`crate::Screech`] during sampling.
    ///
    /// use the reference to the tracker to update relevant [`Signal`]s
    fn sample(&mut self, tracker: &mut dyn Tracker<MessageData>, sample_rate: usize);

    /// get reference to the id for the source,
    /// this is used to uniquely identify this source when sampling [`Signal`]s
    fn get_source_id(&self) -> &usize;
}

/// Tracker trait to keep track of buffers and connections between [`Output`]s and [`Input`]s
///
/// for implementation examples see [`crate::BasicTracker`] or [`crate::DynamicTracker`]
pub trait Tracker<MessageData = ()> {
    /// return the buffer size
    fn get_buffer_size(&self) -> &usize;

    /// resize internal buffers
    fn resize_buffers(&mut self, buffer_size: usize);

    /// Return a unique ID for keeping track of [`Source`]es
    fn create_source_id(&mut self) -> usize;

    /// clear source id and associated buffers
    fn clear_source(&mut self, id: usize);

    /// get all source ids required for a given source id
    fn get_sources(&self, id: &usize) -> Vec<usize>;

    /// get a reference to an output's [`Signal`]
    fn get_output(&self, output: &Output) -> Option<&Signal>;

    /// get a mutable reference to an output's [`Signal`]
    fn get_mut_output(&mut self, output: &Output) -> Option<&mut Signal>;

    /// initialize empty [`Signal`] for output
    fn init_output(&mut self, output: &Output);

    /// initialize input for tracking outputs connected to it
    fn init_input(&mut self, input: &Input);

    /// return a reference to a list of outputs for a given input
    fn get_input(&self, e: &Input) -> Option<&[Output]>;

    /// connect an [`Output`] to an [`Input`]
    fn connect_signal(&mut self, output: &Output, input: &Input);

    /// clear [`Output`] connection from an [`Input`]
    fn clear_connection(&mut self, output: &Output, input: &Input);

    /// send message to source id
    fn send_message(&mut self, id: &usize, message: Message<MessageData>);

    /// get all messages for given source id
    fn get_messages(&self, id: &usize) -> Option<&[Message<MessageData>]>;

    /// clear all messages for all sources
    fn clear_messages(&mut self);
}

/// Trait to implement conversion from a slice of sized types to a generic
pub trait FromPoints<T: Sized, U> {
    /// Create new instance based on sequence of points
    fn from_points(points: Vec<T>) -> U;
}