-
Notifications
You must be signed in to change notification settings - Fork 5
/
lib.rs
89 lines (78 loc) · 2.83 KB
/
lib.rs
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
use pd_ext::builder::ControlExternalBuilder;
use pd_ext::external::ControlExternal;
use pd_ext::outlet::{OutletSend, OutletType};
use pd_ext_macros::external;
//https://github.com/pure-data/externals-howto#a-complex-external-counter
external! {
pub struct Counter {
count: isize,
step: isize,
range: (isize, isize),
count_outlet: Box<dyn OutletSend>,
wrap_outlet: Box<dyn OutletSend>,
}
impl ControlExternal for Counter {
fn new(builder: &mut dyn ControlExternalBuilder<Self>) -> Result<Self, String> {
//parse the args
let mut step = 1;
let mut range = (0, 1);
let mut args = builder.creation_args().iter();
if let Some(atom) = args.next() {
range.0 = atom.get_int().unwrap_or(0) as isize;
if let Some(atom) = args.next() {
range.1 = atom.get_int().unwrap_or(1) as isize;
if let Some(atom) = args.next() {
step = atom.get_int().unwrap_or(1) as isize;
}
}
}
//reorder if needed
if range.0 > range.1 {
range = (range.1, range.0);
}
let count_outlet = builder.new_message_outlet(OutletType::Float);
let wrap_outlet = builder.new_message_outlet(OutletType::Bang);
Ok(Self { count: 0, step, range, count_outlet, wrap_outlet })
}
}
impl Counter {
#[bang]
pub fn bang(&mut self) {
let f = self.count as pd_sys::t_float;
self.count = self.count.wrapping_add(self.step);
if self.range.0 != self.range.1 {
//if we're stepping up
if self.step > 0 {
//and count has exceeded the upper range
if self.count > self.range.1 {
self.count = self.range.0; //set to lower
self.wrap_outlet.send_bang();
}
} else {
if self.count < self.range.0 {
self.count = self.range.1; //set to upper
self.wrap_outlet.send_bang();
}
}
}
self.count_outlet.send_float(f);
}
#[sel(defaults=1)]
pub fn set(&mut self, v: pd_sys::t_float) {
self.count = v as isize;
}
#[sel]
pub fn reset(&mut self) {
self.count = self.range.0;
}
#[sel(defaults=2)]
pub fn bound(&mut self, bottom: pd_sys::t_float, top: pd_sys::t_float) {
self.range =
if bottom > top {
(top as isize, bottom as isize)
} else {
(bottom as isize, top as isize)
};
}
}
}