11use caw_builder_proc_macros:: builder;
22use caw_core:: { Buf , Sig , SigCtx , SigT } ;
3- use caw_persist:: Persist ;
3+ use caw_persist:: PersistData ;
44use itertools:: izip;
55use serde:: { Deserialize , Serialize } ;
66
@@ -42,40 +42,45 @@ impl<T> Sequence<T> {
4242 }
4343}
4444
45- const KEY_LOOPER_PERSIST : & ' static str = "key_looper" ;
45+ impl < T > PersistData for Sequence < Option < T > >
46+ where
47+ T : Serialize + for < ' a > Deserialize < ' a > ,
48+ {
49+ const NAME : & ' static str = "sequence" ;
50+ }
4651
4752/// Driver for saving and loading a sequence state to a file.
48- pub trait KeyLooperIo < T > {
53+ pub trait LooperIo < T > {
4954 fn load ( & self ) -> Sequence < Option < T > > ;
5055 fn save ( & self , sequence : & Sequence < Option < T > > ) ;
5156}
5257
53- /// Implementation of `KeyLooperIo ` which doesn't actually save or load any data.
54- pub struct KeyLooperIoNull ;
55- impl < T > KeyLooperIo < T > for KeyLooperIoNull {
58+ /// Implementation of `LooperIo ` which doesn't actually save or load any data.
59+ pub struct LooperIoNull ;
60+ impl < T > LooperIo < T > for LooperIoNull {
5661 fn load ( & self ) -> Sequence < Option < T > > {
5762 Sequence :: new_with ( 1 , || None )
5863 }
5964
6065 fn save ( & self , _sequence : & Sequence < Option < T > > ) { }
6166}
6267
63- /// Implementation of `KeyLooperIo ` which saves state into a file of a given name.
64- pub struct KeyLooperIoWithName ( pub String ) ;
65- impl < T > KeyLooperIo < T > for KeyLooperIoWithName
68+ /// Implementation of `LooperIo ` which saves state into a file of a given name.
69+ pub struct LooperIoWithName ( pub String ) ;
70+ impl < T > LooperIo < T > for LooperIoWithName
6671where
6772 T : Serialize + for < ' a > Deserialize < ' a > ,
6873{
6974 fn load ( & self ) -> Sequence < Option < T > > {
70- if let Some ( sequence) = KEY_LOOPER_PERSIST . load_ ( & self . 0 ) {
75+ if let Some ( sequence) = Sequence :: load_ ( & self . 0 ) {
7176 sequence
7277 } else {
7378 Sequence :: new_with ( 1 , || None )
7479 }
7580 }
7681
7782 fn save ( & self , sequence : & Sequence < Option < T > > ) {
78- KEY_LOOPER_PERSIST . save_ ( sequence , & self . 0 )
83+ sequence . save_ ( & self . 0 )
7984 }
8085}
8186
8691 T : SigT < Item = bool > ,
8792 C : SigT < Item = bool > ,
8893 N : SigT < Item = u32 > ,
89- I : KeyLooperIo < X > ,
94+ I : LooperIo < X > ,
9095{
9196 sig : S ,
9297 last_value : Option < X > ,
@@ -105,7 +110,7 @@ where
105110 T : SigT < Item = bool > ,
106111 C : SigT < Item = bool > ,
107112 N : SigT < Item = u32 > ,
108- I : KeyLooperIo < X > ,
113+ I : LooperIo < X > ,
109114{
110115 type Item = S :: Item ;
111116
@@ -154,7 +159,7 @@ where
154159 T : SigT < Item = bool > ,
155160 C : SigT < Item = bool > ,
156161 N : SigT < Item = u32 > ,
157- I : KeyLooperIo < X > ,
162+ I : LooperIo < X > ,
158163{
159164 fn new ( sig : S , tick : T , clearing : C , length : N , io : I ) -> Sig < Self > {
160165 Sig ( KeyLooper {
@@ -192,10 +197,10 @@ builder! {
192197 #[ generic_name = "N" ]
193198 #[ default = 16 ]
194199 length: u32 ,
195- #[ generic_with_constraint = "KeyLooperIo <V>" ]
196- #[ default = KeyLooperIoNull ]
200+ #[ generic_with_constraint = "LooperIo <V>" ]
201+ #[ default = LooperIoNull ]
197202 #[ generic_name = "I" ]
198- io: KeyLooperIoNull ,
203+ io: LooperIoNull ,
199204 }
200205}
201206
@@ -206,12 +211,12 @@ where
206211 T : SigT < Item = bool > ,
207212 C : SigT < Item = bool > ,
208213 N : SigT < Item = u32 > ,
209- I : KeyLooperIo < X > ,
214+ I : LooperIo < X > ,
210215{
211216 pub fn persist_with_name (
212217 self ,
213218 name : impl AsRef < str > ,
214- ) -> KeyLooperBuilder < X , S , T , C , N , KeyLooperIoWithName > {
219+ ) -> KeyLooperBuilder < X , S , T , C , N , LooperIoWithName > {
215220 let Self {
216221 sig,
217222 trig,
@@ -224,34 +229,37 @@ where
224229 trig,
225230 clearing,
226231 length,
227- io : KeyLooperIoWithName ( name. as_ref ( ) . to_string ( ) ) ,
232+ io : LooperIoWithName ( format ! ( "key_looper_{}" , name. as_ref( ) ) ) ,
228233 }
229234 }
230235}
231236
232- pub struct ValueLooper < S , T , R , N >
237+ pub struct ValueLooper < S , T , R , N , I >
233238where
234239 S : SigT ,
235240 S :: Item : Clone ,
236241 T : SigT < Item = bool > ,
237242 R : SigT < Item = bool > ,
238243 N : SigT < Item = u32 > ,
244+ I : LooperIo < S :: Item > ,
239245{
240246 sig : S ,
241247 tick : T ,
242248 recording : R ,
243249 length : N ,
244250 sequence : Sequence < Option < S :: Item > > ,
245251 buf : Vec < S :: Item > ,
252+ io : I ,
246253}
247254
248- impl < S , T , R , N > SigT for ValueLooper < S , T , R , N >
255+ impl < S , T , R , N , I > SigT for ValueLooper < S , T , R , N , I >
249256where
250257 S : SigT ,
251258 S :: Item : Clone ,
252259 T : SigT < Item = bool > ,
253260 R : SigT < Item = bool > ,
254261 N : SigT < Item = u32 > ,
262+ I : LooperIo < S :: Item > ,
255263{
256264 type Item = S :: Item ;
257265
@@ -261,6 +269,7 @@ where
261269 let tick = self . tick . sample ( ctx) ;
262270 let recording = self . recording . sample ( ctx) ;
263271 let length = self . length . sample ( ctx) ;
272+ let mut changed_this_frame = false ;
264273 for ( sample, tick, recording, length) in izip ! {
265274 sig. iter( ) ,
266275 tick. iter( ) ,
@@ -275,32 +284,39 @@ where
275284 let out = match ( recording, stored. clone ( ) ) {
276285 ( true , _) | ( _, None ) => {
277286 * stored = Some ( sample. clone ( ) ) ;
287+ changed_this_frame = true ;
278288 sample
279289 }
280290 ( _, Some ( stored) ) => stored,
281291 } ;
282292 self . buf . push ( out) ;
283293 }
294+ if changed_this_frame {
295+ self . io . save ( & self . sequence ) ;
296+ }
284297 & self . buf
285298 }
286299}
287300
288- impl < S , T , R , N > ValueLooper < S , T , R , N >
301+ impl < S , T , R , N , I > ValueLooper < S , T , R , N , I >
289302where
290303 S : SigT ,
291304 S :: Item : Clone ,
292305 T : SigT < Item = bool > ,
293306 R : SigT < Item = bool > ,
294307 N : SigT < Item = u32 > ,
308+ I : LooperIo < S :: Item > ,
295309{
296- fn new ( sig : S , tick : T , recording : R , length : N ) -> Sig < Self > {
310+ fn new ( sig : S , tick : T , recording : R , length : N , io : I ) -> Sig < Self > {
311+ let sequence = io. load ( ) ;
297312 Sig ( ValueLooper {
298313 sig,
299314 tick,
300315 recording,
301316 length,
302- sequence : Sequence :: new_with ( 1 , || None ) ,
317+ sequence,
303318 buf : Vec :: new ( ) ,
319+ io,
304320 } )
305321 }
306322}
@@ -310,7 +326,7 @@ builder! {
310326 #[ constructor_doc = "A looper for values such as knob positions" ]
311327 #[ generic_setter_type_name = "X" ]
312328 #[ build_fn = "ValueLooper::new" ]
313- #[ build_ty = "Sig<ValueLooper<S, T, R, N>>" ]
329+ #[ build_ty = "Sig<ValueLooper<S, T, R, N, I >>" ]
314330 pub struct ValueLooperBuilder {
315331 #[ generic_with_constraint = "SigT" ]
316332 #[ generic_name = "S" ]
@@ -325,5 +341,39 @@ builder! {
325341 #[ generic_name = "N" ]
326342 #[ default = 16 ]
327343 length: u32 ,
344+ #[ generic_with_constraint = "LooperIo<S::Item>" ]
345+ #[ default = LooperIoNull ]
346+ #[ generic_name = "I" ]
347+ io: LooperIoNull ,
348+ }
349+ }
350+
351+ impl < S , T , R , N , I > ValueLooperBuilder < S , T , R , N , I >
352+ where
353+ S : SigT < Item = f32 > ,
354+ S :: Item : Clone + Serialize + for < ' a > Deserialize < ' a > ,
355+ T : SigT < Item = bool > ,
356+ R : SigT < Item = bool > ,
357+ N : SigT < Item = u32 > ,
358+ I : LooperIo < S :: Item > ,
359+ {
360+ pub fn persist_with_name (
361+ self ,
362+ name : impl AsRef < str > ,
363+ ) -> ValueLooperBuilder < S , T , R , N , LooperIoWithName > {
364+ let Self {
365+ sig,
366+ trig,
367+ recording,
368+ length,
369+ ..
370+ } = self ;
371+ ValueLooperBuilder {
372+ sig,
373+ trig,
374+ recording,
375+ length,
376+ io : LooperIoWithName ( format ! ( "value_looper_{}" , name. as_ref( ) ) ) ,
377+ }
328378 }
329379}
0 commit comments