Update of /cvsroot/pure-data/abstractions/footils/sssad/doc/saving-tutorial
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv19310/doc/saving-tutorial
Added Files:
anystore.pd saving-01-intro.pd saving-02-abstraction.pd
saving-03-wrong.pd saving-04-no-message-box.pd
saving-05-one-send-to-rule-them-all.pd
saving-06-remotecontrol.pd saving-07-admin.pd
saving-08-collect-all.pd saving-09-textfile.pd
saving-10-mmadsssad.pd state.txt store-collect-delayed.pd
store-collect-tag.pd store-collect.pd store-save-tag.pd
store-save.pd store.pd tagged-del.pd tagged.pd wrong.pd
Log Message:
doc gui and more added
--- NEW FILE: saving-09-textfile.pd ---
#N canvas 376 15 549 684 10;
#X floatatom 53 88 5 0 0 0 - - -;
#X obj 53 191 bng 15 250 50 0 empty empty save 0 -6 0 8 -262144 -1
-1;
#X obj 75 287 s SAVING-ADMIN;
#X obj 100 88 store-collect-delayed more1;
#X floatatom 53 114 5 0 0 0 - - -;
#X obj 100 114 store-collect-delayed more2;
#X floatatom 54 141 5 0 0 0 - - -;
#X obj 101 141 store-collect-delayed more3;
#X text 45 21 Instead of saving to a message box you can also save
to a [textfile] which has the advantage \, that you can load different
textfiles to use with the same patch.;
#X obj 209 296 textfile;
#X msg 97 242 clear;
#X obj 209 207 r SAVING-SEND;
#X obj 209 234 list prepend add;
#X obj 209 255 list trim;
#X obj 53 214 t b b b;
#X obj 56 527 textfile;
#X obj 56 443 t b b;
#X obj 56 493 until;
#X obj 56 561 s SAVING-REC;
#X obj 56 423 bng 15 250 50 0 empty empty reload 0 -6 0 8 -262144 -1
-1;
#X text 52 384 Restoring from a file works like this:;
#X msg 53 321 print \, write state.txt;
#X text 326 494 Don't forget to rewind!;
#X text 52 603 By reading from SAVING-SEND and sending to SAVING-REC
you can also store your state in other ways \, for example to a [pool]
object or send it over a [netsend] or [sendOSC] network connection.
;
#X obj 344 85 tagged-del more4;
#X obj 345 129 tagged-del more5;
#X msg 106 493 read state.txt \, print \, rewind;
#X connect 0 0 3 0;
#X connect 1 0 14 0;
#X connect 3 0 0 0;
#X connect 4 0 5 0;
#X connect 5 0 4 0;
#X connect 6 0 7 0;
#X connect 7 0 6 0;
#X connect 10 0 9 0;
#X connect 11 0 12 0;
#X connect 12 0 13 0;
#X connect 13 0 9 0;
#X connect 14 0 21 0;
#X connect 14 1 2 0;
#X connect 14 2 10 0;
#X connect 15 0 18 0;
#X connect 15 1 17 1;
#X connect 16 0 17 0;
#X connect 16 1 26 0;
#X connect 17 0 15 0;
#X connect 19 0 16 0;
#X connect 21 0 9 0;
#X connect 26 0 15 0;
--- NEW FILE: saving-05-one-send-to-rule-them-all.pd ---
#N canvas 439 5 549 726 10;
#X floatatom 45 227 5 0 0 0 - - -;
#X obj 45 261 list prepend TAG;
#X obj 45 195 route TAG;
#X obj 45 285 s SAVING-SEND;
#X obj 45 133 r SAVING-REC;
#X text 126 196 filter by TAG;
#X text 166 263 add TAG;
#X obj 313 134 r SAVING-SEND;
#X obj 313 295 s SAVING-REC;
#X msg 313 231 43;
#X obj 421 214 loadbang;
#X text 26 91 Here's the basic principle in action:;
#X text 31 432 Again we can make abstractions out of this for easier
use. Now the first argument should be the tag to use for a certain
value.;
#X obj 81 489 store-collect-tag mytag1;
#X obj 322 489 store-save-tag mytag1;
#X msg 287 489 10;
#X floatatom 38 490 5 0 0 0 - - -;
#X msg 313 204 set \$1;
#X obj 313 177 route TAG;
#X obj 313 265 list prepend TAG;
#X text 434 267 add TAG;
#X text 393 178 filter by TAG;
#X msg 287 534 45;
#X floatatom 37 534 5 0 0 0 - - -;
#X text 32 322 [list prepend TAG] will generate a message "list TAG
number". This gets sent over to our message box saver \, where it is
filtered out with route \, so only messages with the correct tag get
accepted.;
#X text 31 386 Restoring works the same: We again prepend a tag \,
and filter by tag on the number box side.;
#X text 23 17 So lets reduce the number of sends and receives used
in our saving system to a single pair now. We will do this by "tagging"
our state variables with a name tag and then filter out only the values
with certain tags.;
#X obj 313 156 list trim;
#X obj 45 170 list trim;
#X obj 80 533 store-collect-tag mytag2;
#X obj 321 533 store-save-tag mytag2;
#X obj 39 606 tagged a;
#X msg 112 613 100;
#X obj 147 613 store-save-tag a/tag;
#X msg 209 651 24;
#X obj 136 644 tagged b;
#X obj 244 651 store-save-tag b/tag;
#X text 36 567 You can now even use this in abstractions through "tagging
with \$1" as shown here:;
#X connect 0 0 1 0;
#X connect 1 0 3 0;
#X connect 2 0 0 0;
#X connect 4 0 28 0;
#X connect 7 0 27 0;
#X connect 9 0 19 0;
#X connect 10 0 9 0;
#X connect 13 0 16 0;
#X connect 14 0 15 0;
#X connect 15 0 14 0;
#X connect 16 0 13 0;
#X connect 17 0 9 0;
#X connect 18 0 17 0;
#X connect 19 0 8 0;
#X connect 22 0 30 0;
#X connect 23 0 29 0;
#X connect 27 0 18 0;
#X connect 28 0 2 0;
#X connect 29 0 23 0;
#X connect 30 0 22 0;
#X connect 32 0 33 0;
#X connect 33 0 32 0;
#X connect 34 0 36 0;
#X connect 36 0 34 0;
--- NEW FILE: saving-06-remotecontrol.pd ---
#N canvas 365 52 528 565 10;
#X msg 119 140 127;
#X msg 119 199 12;
#X obj 46 133 tagged x;
#X obj 154 140 store-save-tag x/tag;
#X obj 154 199 store-save-tag y/tag;
#X obj 46 192 tagged y;
#X text 33 25 Now let me point out one very useful side effect of our
current system: It is possible to remote control all "watched" GUI
elements by sending tagged messages to the global saving receiver.
;
#X obj 48 362 s SAVING-REC;
#X msg 48 295 x/tag 1 \, y/tag 2;
#X text 40 257 Then we can make presets using static messages like
this:;
#X text 38 91 Assume this is our setup:;
#X msg 48 316 x/tag 10 \, y/tag 100;
#X msg 48 338 x/tag 127 \, y/tag 12;
#N canvas 0 0 478 198 sidenote 0;
#X obj 145 104 hsl 128 15 0 127 0 0 empty empty empty -2 -6 0 8 -262144
-1 -1 1000 1;
#X obj 36 125 s SAVING-REC;
#X text 35 33 Note that the remote control even works without having
a saver-abstraction:;
#X msg 36 78 myfoo 60;
#X msg 36 99 myfoo 10;
#X obj 142 125 store-collect-tag myfoo;
#X connect 0 0 5 0;
#X connect 3 0 1 0;
#X connect 4 0 1 0;
#X connect 5 0 0 0;
#X restore 326 320 pd sidenote;
#X text 45 409 Wouldn't it be nice to be able to automatically generate
such messages that describe the complete state of our patch and without
even knowing the tag-names of all our variables in advance? Read on.
;
#X connect 0 0 3 0;
#X connect 1 0 4 0;
#X connect 3 0 0 0;
#X connect 4 0 1 0;
#X connect 8 0 7 0;
#X connect 11 0 7 0;
#X connect 12 0 7 0;
--- NEW FILE: state.txt ---
more5/tag 41;
more4/tag -28;
more3 -29;
more2 27;
more1 37;
--- NEW FILE: saving-03-wrong.pd ---
#N canvas 274 79 534 578 10;
#X obj 49 137 wrong;
#X obj 182 137 wrong;
#X text 22 26 But first lets think about another problem: What happens
\, if we want to use our state saving enabled patch itself as an abstraction
and we want to use this abstraction several times \, each time with
its own state. wrong.pd shows \, that this won't work: For one \, we
cannot save this abstraction without opening it \, and second: We can
still only save one set of state variables:;
#X text 33 280 As soon as you save one of the "wrong" instances \,
the other one will take over its values.;
#X text 32 328 Now we could again move out our message boxes \, place
them in the parent patch connected through an inlet and outlet \, but
this would just be a temporary fix: As soon as we wanted to use the
parent as an abstraction again \, we would face the same issue again!
;
#X text 31 415 So we need a different strategy. Read on.;
--- NEW FILE: saving-08-collect-all.pd ---
#N canvas 373 10 570 698 10;
#X floatatom 169 56 5 0 0 0 - - -;
#X obj 51 56 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
-1;
#X obj 51 76 s SAVING-ADMIN;
#X floatatom 169 75 5 0 0 0 - - -;
#X obj 216 56 store-collect-delayed many1;
#X obj 216 78 store-collect-delayed many2;
#X floatatom 169 94 5 0 0 0 - - -;
#X obj 216 100 store-collect-delayed many3;
#X obj 52 191 r SAVING-SEND;
#X obj 52 211 print SAVING-SEND;
#X text 53 252 You get three lists containing things like "list many2
129". We can store all these into a message box by first resetting
the message box and then "add"ing the lists.;
#X obj 59 442 s SAVING-ADMIN;
#X msg 335 425;
#X obj 335 397 list trim;
#X obj 335 324 r SAVING-SEND;
#X msg 89 384 set;
#X obj 59 331 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
-1;
#X text 122 386 first empty the msg.box ...;
#X text 41 464 ... and then collect the state variables;
#X text 51 22 Lets say we have this setup:;
#X msg 278 626 \; SAVING-REC many3 15 \; SAVING-REC many2 169 \; SAVING-REC
many1 141 \;;
#X obj 278 598 list trim;
#X obj 278 535 r SAVING-SEND;
#X obj 278 579 list prepend add SAVING-REC;
#X obj 335 377 list prepend add;
#X text 55 499 However the saver-messagebox doesn't have the correct
format yet to restore the state. Thankfully the fix is easy:;
#X text 108 635 Press this to restore:;
#X msg 103 583 set \, addsemi;
#X obj 335 353 spigot;
#X obj 384 354 tgl 15 0 empty empty open-to-test 20 8 0 8 -262144 -1
-1 0 1;
#X obj 278 559 spigot;
#X obj 327 560 tgl 15 0 empty empty open-to-test 20 8 0 8 -262144 -1
-1 0 1;
#X obj 59 354 t b b;
#X obj 73 661 s SAVING-ADMIN;
#X obj 73 538 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
-1;
#X obj 73 561 t b b;
#X text 49 139 Now watch closely what gets send over our SAVING-SEND
lines in the console if you press the saving-bang \, after you have
played with the number boxes above:;
#X connect 0 0 4 0;
#X connect 1 0 2 0;
#X connect 3 0 5 0;
#X connect 4 0 0 0;
#X connect 5 0 3 0;
#X connect 6 0 7 0;
#X connect 7 0 6 0;
#X connect 8 0 9 0;
#X connect 13 0 12 0;
#X connect 14 0 28 0;
#X connect 15 0 12 0;
#X connect 16 0 32 0;
#X connect 21 0 20 0;
#X connect 22 0 30 0;
#X connect 23 0 21 0;
#X connect 24 0 13 0;
#X connect 27 0 20 0;
#X connect 28 0 24 0;
#X connect 29 0 28 1;
#X connect 30 0 23 0;
#X connect 31 0 30 1;
#X connect 32 0 11 0;
#X connect 32 1 15 0;
#X connect 34 0 35 0;
#X connect 35 0 33 0;
#X connect 35 1 27 0;
--- NEW FILE: store.pd ---
#N canvas 0 0 412 280 10;
#X msg 101 116 set \$1;
#X obj 153 117 loadbang;
#X obj 101 89 inlet;
#X obj 101 146 outlet;
#X connect 0 0 3 0;
#X connect 1 0 3 0;
#X connect 2 0 0 0;
--- NEW FILE: saving-01-intro.pd ---
#N canvas 296 70 583 730 10;
#X obj 105 254 hsl 128 15 0 127 0 1 empty empty empty -2 -6 0 8 -262144
-1 -1 5600 1;
#X text 78 200 This slider will recall the value it had when this patch
was saved:;
#X floatatom 82 327 5 0 0 0 - - -;
#X msg 125 348 set \$1;
#X msg 125 369 5;
#X obj 177 349 loadbang;
#X text 82 410 Here you already see a typical "idiom" to state saving:
We kind of eavesdrop the messages flowing along connections and store
this somewhere (a message box in this case) \, and we have a feedback
connection going back to the number box. This kind of cross-connection
is something we will see all the time later on.;
#X obj 95 577 phasor~;
#X obj 157 628 bp~;
#X floatatom 95 556 5 0 0 2 freq - -;
#X floatatom 165 591 5 0 0 2 cutoff - -;
#X floatatom 293 588 5 0 0 2 Q - -;
#N canvas 0 0 242 205 store 0;
#X msg 28 69 set \$1;
#X msg 77 105 5;
#X obj 77 43 loadbang;
#X obj 28 45 inlet;
#X obj 77 128 outlet;
#X connect 0 0 1 0;
#X connect 1 0 4 0;
#X connect 2 0 1 0;
#X connect 3 0 0 0;
#X restore 293 611 pd store;
#N canvas 0 0 242 205 store 0;
#X msg 28 69 set \$1;
#X msg 77 105 18;
#X obj 77 43 loadbang;
#X obj 28 45 inlet;
#X obj 77 128 outlet;
#X connect 0 0 1 0;
#X connect 1 0 4 0;
#X connect 2 0 1 0;
#X connect 3 0 0 0;
#X restore 212 589 pd store;
#N canvas 0 0 242 205 store 0;
#X msg 28 69 set \$1;
#X msg 77 105 174;
#X obj 77 43 loadbang;
#X obj 28 45 inlet;
#X obj 77 128 outlet;
#X connect 0 0 1 0;
#X connect 1 0 4 0;
#X connect 2 0 1 0;
#X connect 3 0 0 0;
#X restore 139 556 pd store;
#X text 80 496 Next is a real-life example: The set/loadbang construct
is inside the [pd store] subpatches:;
#X text 78 55 Saving the state of a patch in Pd can be done in various
ways. First lets think a bit about what should be saved. A natural
candidate for this is the current state of GUI elements like number
boxes or sliders \, though later we will see \, that we may want to
save different things as well.;
#X text 78 145 Sliders have a button labeled "init" in their Properties
dialog \, which is like a builtin "loadbang" and makes them recall
the last value they had \, when the patch was saved.;
#X text 79 292 Standard number boxes lack this feature \, but it is
easily built by hand using two message boxes and loadbangs:;
#X connect 2 0 3 0;
#X connect 3 0 4 0;
#X connect 4 0 2 0;
#X connect 5 0 4 0;
#X connect 7 0 8 0;
#X connect 9 0 7 0;
#X connect 9 0 14 0;
#X connect 10 0 8 1;
#X connect 10 0 13 0;
#X connect 11 0 8 2;
#X connect 11 0 12 0;
#X connect 12 0 11 0;
#X connect 13 0 10 0;
#X connect 14 0 9 0;
--- NEW FILE: store-save.pd ---
#N canvas 0 0 450 300 10;
#X msg 99 109 set \$1;
#X obj 99 82 r \$1-s;
#X obj 159 109 loadbang;
#X obj 99 138 outlet;
#X obj 99 167 inlet;
#X obj 99 193 s \$1-r;
#X connect 0 0 3 0;
#X connect 1 0 0 0;
#X connect 2 0 3 0;
#X connect 4 0 5 0;
--- NEW FILE: tagged.pd ---
#N canvas 0 0 493 304 10;
#X floatatom 125 122 5 0 0 0 tag - -;
#X obj 195 119 store-collect-tag \$1/tag;
#X connect 0 0 1 0;
#X connect 1 0 0 0;
#X coords 0 -1 1 1 65 40 1 100 100;
--- NEW FILE: saving-04-no-message-box.pd ---
#N canvas 443 27 545 640 10;
#X floatatom 49 156 5 0 0 0 - - -;
#X msg 96 155 set \$1;
#X msg 96 177 12;
#X text 47 133 Old;
#X floatatom 48 256 5 0 0 0 - - -;
#X msg 160 252 set \$1;
#X msg 160 274 33;
#X text 47 207 Better:;
#X obj 48 232 r myvalue-r;
#X obj 48 299 s myvalue-s;
#X obj 160 231 r myvalue-s;
#X obj 160 299 s myvalue-r;
#X obj 217 257 loadbang;
#X obj 102 417 store-collect myvalue2;
#X floatatom 48 419 5 0 0 0 - - -;
#X obj 308 419 store-save myvalue2;
#X msg 277 418 17;
#X text 44 495 BUT: This still has serious problems: For one we would
need to know all the send and receive names used this way in every
abstraction - even in those \, we didn't build ourselves or those we
did build \, but months ago.;
#X text 43 564 Additionally we would need to make sure that no receiver
names are used more than once \, as otherwise a receiver may receive
values not intended for it.;
#X floatatom 48 443 5 0 0 0 - - -;
#X msg 277 442 -33;
#X obj 102 441 store-collect myvalue3;
#X obj 308 443 store-save myvalue3;
#X text 41 33 The main problem we had so far is \, that we cannot really
tell \, where the message boxes to store our state will be located
\, because this highly depends on how our abstractions are using each
other. So the first thing to do is move away the message boxes and
use sends and receives instead:;
#X text 44 341 Now we could put the right side of the construct above
everywhere we want. We can even put this into two abstractions: store-collect.pd
and store-save.pd which use the send and receive names taken from the
\$1 argument:;
#X connect 0 0 1 0;
#X connect 1 0 2 0;
#X connect 2 0 0 0;
#X connect 4 0 9 0;
#X connect 5 0 6 0;
#X connect 6 0 11 0;
#X connect 8 0 4 0;
#X connect 10 0 5 0;
#X connect 12 0 6 0;
#X connect 13 0 14 0;
#X connect 14 0 13 0;
#X connect 15 0 16 0;
#X connect 16 0 15 0;
#X connect 19 0 21 0;
#X connect 20 0 22 0;
#X connect 21 0 19 0;
#X connect 22 0 20 0;
--- NEW FILE: store-collect-tag.pd ---
#N canvas 0 0 450 300 10;
#X obj 88 222 s SAVING-SEND;
#X obj 88 40 r SAVING-REC;
#X text 169 89 filter by TAG;
#X text 209 200 add TAG;
#X obj 88 119 outlet;
#X obj 88 172 inlet;
#X obj 88 88 route \$1;
#X obj 88 198 list prepend \$1;
#X obj 88 64 list trim;
#X connect 1 0 8 0;
#X connect 5 0 7 0;
#X connect 6 0 4 0;
#X connect 7 0 0 0;
#X connect 8 0 6 0;
--- NEW FILE: anystore.pd ---
#N canvas 0 0 412 280 10;
#X obj 153 117 loadbang;
#X obj 105 38 inlet;
#X obj 105 146 outlet;
#X obj 105 64 list prepend set;
#X obj 105 88 list trim;
#X connect 0 0 2 0;
#X connect 1 0 3 0;
#X connect 3 0 4 0;
#X connect 4 0 2 0;
--- NEW FILE: tagged-del.pd ---
#N canvas 0 0 493 304 10;
#X floatatom 125 122 5 0 0 0 tag - -;
#X obj 195 119 store-collect-delayed \$1/tag;
#X connect 0 0 1 0;
#X connect 1 0 0 0;
#X coords 0 -1 1 1 65 40 1 100 100;
--- NEW FILE: saving-02-abstraction.pd ---
#N canvas 269 73 557 780 10;
#X text 31 29 Now you may want to make the [pd store] subpatch into
an abstraction \, to make it easier to reuse it many times \, but then
you have a problem. First: Abstractions don't get saved again \, if
you save their parent patch. And even then \, you would only be able
to save a single value into the *single* abstraction file "store.pd".
This is useless.;
#X obj 80 178 store;
#X msg 80 198 9;
#X floatatom 39 179 5 0 0 0 - - -;
#X obj 186 223 phasor~;
#X obj 248 314 bp~;
#X floatatom 186 182 5 0 0 2 freq - -;
#X floatatom 256 237 5 0 0 2 cutoff - -;
#X floatatom 384 234 5 0 0 2 Q - -;
#X obj 230 182 store;
#X obj 303 235 store;
#X obj 384 257 store;
#X msg 384 279 9;
#X msg 303 255 25;
#X msg 230 202 179;
#X text 31 122 One way out would be to remove the storing message box
from store.pd and connect that to an outlet of store.pd as shown here:
;
#X msg 110 451 27 27 18;
#X obj 110 431 anystore;
#X obj 100 408 pack 1 2 3;
#X obj 100 475 unpack 1 2 3;
#X floatatom 50 387 5 0 0 0 - - -;
#X floatatom 90 387 5 0 0 0 - - -;
#X floatatom 132 387 5 0 0 0 - - -;
#X text 42 341 With a little change inside our abstraction we can also
store lists instead of just a single value:;
#X msg 419 497 35 27 18;
#X obj 419 477 anystore;
#X obj 409 454 pack 1 2 3;
#X obj 409 521 unpack 1 2 3;
#X obj 215 554 phasor~;
#X obj 277 605 bp~;
#X floatatom 215 513 5 0 0 2 freq - -;
#X floatatom 285 568 5 0 0 2 cutoff - -;
#X floatatom 413 565 5 0 0 2 Q - -;
#X text 39 692 But now it gets ugly \, which should be enough motivation
to think of possible improvements. Ugly always is wrong.;
#X connect 1 0 2 0;
#X connect 2 0 3 0;
#X connect 3 0 1 0;
#X connect 4 0 5 0;
#X connect 6 0 4 0;
#X connect 6 0 9 0;
#X connect 7 0 5 1;
#X connect 7 0 10 0;
#X connect 8 0 11 0;
#X connect 8 0 5 2;
#X connect 9 0 14 0;
#X connect 10 0 13 0;
#X connect 11 0 12 0;
#X connect 12 0 8 0;
#X connect 13 0 7 0;
#X connect 14 0 6 0;
#X connect 16 0 19 0;
#X connect 17 0 16 0;
#X connect 18 0 17 0;
#X connect 19 0 20 0;
#X connect 19 1 21 0;
#X connect 19 2 22 0;
#X connect 20 0 18 0;
#X connect 21 0 18 1;
#X connect 22 0 18 2;
#X connect 24 0 27 0;
#X connect 25 0 24 0;
#X connect 26 0 25 0;
#X connect 27 0 30 0;
#X connect 27 1 31 0;
#X connect 27 2 32 0;
#X connect 28 0 29 0;
#X connect 30 0 28 0;
#X connect 30 0 26 0;
#X connect 31 0 29 1;
#X connect 31 0 26 1;
#X connect 32 0 29 2;
#X connect 32 0 26 2;
--- NEW FILE: store-save-tag.pd ---
#N canvas 0 0 450 300 10;
#X obj 61 43 r SAVING-SEND;
#X obj 61 224 s SAVING-REC;
#X obj 153 118 loadbang;
#X msg 61 123 set \$1;
#X text 182 203 add TAG;
#X text 141 97 filter by TAG;
#X obj 61 96 route \$1;
#X obj 61 201 list prepend \$1;
#X obj 61 146 outlet;
#X obj 61 178 inlet;
#X obj 61 71 list trim;
#X connect 0 0 10 0;
#X connect 2 0 8 0;
#X connect 3 0 8 0;
#X connect 6 0 3 0;
#X connect 7 0 1 0;
#X connect 9 0 7 0;
#X connect 10 0 6 0;
--- NEW FILE: saving-10-mmadsssad.pd ---
#N canvas 385 54 503 659 10;
#X text 41 25 SSSAD and MMMAD;
#X obj 51 444 mmmad mmmany1;
#X obj 214 444 mmmad mmmany2;
#X obj 50 493 sssad mmmany3;
#X obj 213 493 sssad mmmany4;
#X obj 140 425 hsl 128 15 0 127 0 0 empty empty empty -2 -6 0 8 -262144
-1 -1 0 1;
#X obj 303 425 hsl 128 15 0 127 0 0 empty empty empty -2 -6 0 8 -262144
-1 -1 0 1;
#X obj 139 471 hsl 128 15 0 127 0 0 empty empty empty -2 -6 0 8 -262144
-1 -1 0 1;
#X obj 302 471 hsl 128 15 0 127 0 0 empty empty empty -2 -6 0 8 -262144
-1 -1 0 1;
#X obj 45 568 cnv 15 150 40 empty empty empty 20 12 0 14 -233017 -66577
0;
#N canvas 657 130 430 629 state-saving 0;
#X obj 13 315 cnv 15 400 300 empty empty Restore 300 12 0 14 -233017
-123526 0;
#X obj 13 12 cnv 15 400 300 empty empty Save 300 12 0 14 -233017 -123526
0;
#X obj 239 237 textfile;
#X msg 128 138 clear;
#X msg 313 220 print;
#X obj 239 161 list prepend add;
#X obj 239 187 list trim;
#X obj 86 520 textfile;
#X obj 86 550 s SSSAD;
#X obj 86 462 until;
#X msg 86 441 100;
#X msg 30 503 print;
#X text 81 572 also received inside sssad;
#X obj 106 238 s SSSAD_ADMIN;
#X obj 239 93 r SSSAD_ADMIN;
#X obj 239 137 route persist;
#X obj 239 115 list trim;
#X msg 106 172 save;
#X msg 120 211 set;
#X obj 154 547 s SSSAD_ADMIN;
#X msg 154 522 set;
#X obj 84 59 savepanel;
#X obj 84 102 t a b b;
#X msg 84 285 write \$1;
#X obj 84 31 bng 24 250 50 0 empty empty save 0 -6 0 8 -262144 -1 -1
;
#X obj 86 418 t b a;
#X msg 133 463 read \$1 \, rewind;
#X obj 86 337 bng 24 250 50 0 empty empty load 0 -6 0 8 -262144 -1
-1;
#X obj 86 365 openpanel;
#X text 118 441 Avoid loops. A bang normally also works.;
#X obj 84 81 symbol;
#X msg 27 63 bang;
#X text 25 43 again;
#X obj 86 395 symbol;
#X msg 29 378 bang;
#X text 27 358 again;
#X text 40 597 Hint: get creative with the [OSCroute] external!;
#X connect 3 0 2 0;
#X connect 4 0 2 0;
#X connect 5 0 6 0;
#X connect 6 0 2 0;
#X connect 7 0 8 0;
#X connect 7 1 9 1;
#X connect 7 1 20 0;
#X connect 9 0 7 0;
#X connect 10 0 9 0;
#X connect 11 0 7 0;
#X connect 14 0 16 0;
#X connect 15 0 5 0;
#X connect 16 0 15 0;
#X connect 17 0 13 0;
#X connect 18 0 13 0;
#X connect 20 0 19 0;
#X connect 21 0 30 0;
#X connect 22 0 23 0;
#X connect 22 1 17 0;
#X connect 22 2 3 0;
#X connect 23 0 2 0;
#X connect 24 0 21 0;
#X connect 25 0 10 0;
#X connect 25 1 26 0;
#X connect 26 0 7 0;
#X connect 27 0 28 0;
#X connect 28 0 33 0;
#X connect 30 0 22 0;
#X connect 31 0 30 0;
#X connect 33 0 25 0;
#X connect 34 0 33 0;
#X restore 59 580 pd state-saving;
#X text 47 544 State saving with mmmad/sssad is shown in this subpatch
;
#X text 45 246 "set" will update all state variables to the value that
was last loaded into memory \, and "save" is equivalent to the "bang"
we used before. It will make all state variables output their current
values prepended with the word "persist" to SSSAD_ADMIN.;
#X text 48 320 Also the connections have to be made to the second \,
cold inlet of [mmmad] rsp. [sssad]. The hot inlet accepts a "bang"
to send out the stored value to the outlet of mmmad/sssad. This way
you can use the same tag more than once without generating feedback
loops \, which is handy for polyphony.;
#N canvas 395 78 519 576 why 0;
#X text 38 45 You may wonder what's the difference between [mmmad]
and [sssad]?;
#X text 38 91 If you use two [mmmad] objects sharing the same tag \,
they will generate two persist messages:;
#X obj 48 166 mmmad double;
#X floatatom 143 166 5 0 0 0 - - -;
#X obj 203 166 mmmad double;
#X floatatom 298 166 5 0 0 0 - - -;
#X obj 47 223 s SSSAD_ADMIN;
#X obj 202 198 r SSSAD_ADMIN;
#X obj 202 220 print SSSAD_ADMIN;
#X msg 47 201 save;
#X text 199 244 "double NUM" will be printed twice!;
#X text 49 288 [sssad] however uses a singleton inside which will only
generate one persist message even when the same tag is used twice:
;
#X floatatom 165 353 5 0 0 0 - - -;
#X obj 54 352 sssad nodouble;
#X floatatom 331 352 5 0 0 0 - - -;
#X obj 220 351 sssad nodouble;
#X text 50 394 This is useful for adding values to a message box \,
because then they won't show up twice or more in the message box or
in the textfile.;
#X text 50 461 The disadvantage is \, that if you delete the first
[sssad nodouble] here \, the second won't get saved at all anymore
\, until you reload the patch. Just try it. Delete the left [sssad
nodouble] and press save again: Now nodouble is missing...;
#X connect 2 0 3 0;
#X connect 3 0 2 1;
#X connect 4 0 5 0;
#X connect 5 0 4 1;
#X connect 7 0 8 0;
#X connect 9 0 6 0;
#X connect 12 0 13 1;
#X connect 13 0 12 0;
#X connect 14 0 15 1;
#X connect 15 0 14 0;
#X restore 57 622 pd why mmmad and sssad?;
#X text 43 60 [sssad] and [mmmad] are ready-made objects that use the
principles you have learned in this tutorial to make state saving as
simple as cross-connecting what you want to save using tagged [sssad]
or [mmmad] objects.;
#X text 43 140 Instead of three receivers SAVING-REC \, SAVING-SEND
and SAVING-ADMIN only two are used. They are called SSSAD and SSSAD_ADMIN.
The admin-receiver SSAD_ADMIN instead of a simple "bang" message accepts
"set" and "save" messages and it also functions as the collector for
state values. These are prepended with the word "persist" \, so you
need one additional [route persist] object when saving.;
#X connect 1 0 5 0;
#X connect 2 0 6 0;
#X connect 3 0 7 0;
#X connect 4 0 8 0;
#X connect 5 0 1 1;
#X connect 6 0 2 1;
#X connect 7 0 3 1;
#X connect 8 0 4 1;
--- NEW FILE: store-collect-delayed.pd ---
#N canvas 0 0 459 430 10;
#X obj 65 304 s SAVING-SEND;
#X obj 88 40 r SAVING-REC;
#X text 169 89 filter by TAG;
#X text 209 200 add TAG;
#X obj 88 119 outlet;
#X obj 88 172 inlet;
#X obj 88 88 route \$1;
#X obj 88 198 list prepend \$1;
#X obj 88 64 list trim;
#X obj 65 278 list;
#X obj 65 247 r SAVING-ADMIN;
#X text 175 247 this expects a bang;
#X connect 1 0 8 0;
#X connect 5 0 7 0;
#X connect 6 0 4 0;
#X connect 7 0 9 1;
#X connect 8 0 6 0;
#X connect 9 0 0 0;
#X connect 10 0 9 0;
--- NEW FILE: store-collect.pd ---
#N canvas 0 0 450 300 10;
#X obj 99 69 r \$1-r;
#X obj 99 120 inlet;
#X obj 99 96 outlet;
#X obj 99 149 s \$1-s;
#X connect 0 0 2 0;
#X connect 1 0 3 0;
--- NEW FILE: saving-07-admin.pd ---
#N canvas 329 6 532 662 10;
#X floatatom 106 194 5 0 0 0 - - -;
#X obj 106 100 r SAVING-REC;
#X obj 106 137 list trim;
#X text 47 21 We need to find a way to make all tagged variables output
their current values on demand. We will do this by delaying the sending
of a state variable through a temporary storage using the cold inlet
of an additional [list] object:;
#X text 54 377 Now we have to bang the final list object to make the
change of the number box visible in our storage message box.;
#X obj 55 290 cnv 15 350 80 empty empty empty 20 12 0 14 -233017 -66577
0;
#X obj 83 351 s SAVING-SEND;
#X obj 83 326 list;
#X obj 83 295 r SAVING-ADMIN;
#X obj 245 312 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
-1;
#X obj 245 333 s SAVING-ADMIN;
#X obj 292 102 r SAVING-SEND;
#X obj 292 263 s SAVING-REC;
#X msg 292 199 142;
#X obj 400 182 loadbang;
#X msg 292 172 set \$1;
#X obj 292 124 list trim;
#X floatatom 181 481 5 0 0 0 - - -;
#X obj 106 162 route TAG2;
#X obj 106 218 list prepend TAG2;
#X obj 292 145 route TAG2;
#X obj 292 233 list prepend TAG2;
#X text 419 234 add TAG2;
#X text 372 146 filter by TAG2;
#X text 187 163 filter by TAG2;
#X text 230 220 add TAG2;
#X obj 228 480 store-collect-delayed deltag1;
#X obj 213 505 store-save-tag deltag1;
#X msg 181 505 166;
#X obj 70 480 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
-1;
#X obj 70 507 s SAVING-ADMIN;
#X floatatom 182 531 5 0 0 0 - - -;
#X msg 182 555 121;
#X obj 229 530 store-collect-delayed deltag2;
#X obj 214 555 store-save-tag deltag2;
#X text 54 418 Instead of directly connecting the GUI bang we will
use another global receiver. By this \, we can put all the stuff on
the left side into another abstraction again.;
#X text 57 598 The next step will be to remove the need for different
[store-save-tag TAG] objects for every variable.;
#X connect 0 0 19 0;
#X connect 1 0 2 0;
#X connect 2 0 18 0;
#X connect 7 0 6 0;
#X connect 8 0 7 0;
#X connect 9 0 10 0;
#X connect 11 0 16 0;
#X connect 13 0 21 0;
#X connect 14 0 13 0;
#X connect 15 0 13 0;
#X connect 16 0 20 0;
#X connect 17 0 26 0;
#X connect 18 0 0 0;
#X connect 19 0 7 1;
#X connect 20 0 15 0;
#X connect 21 0 12 0;
#X connect 26 0 17 0;
#X connect 27 0 28 0;
#X connect 28 0 27 0;
#X connect 29 0 30 0;
#X connect 31 0 33 0;
#X connect 32 0 34 0;
#X connect 33 0 31 0;
#X connect 34 0 32 0;
--- NEW FILE: wrong.pd ---
#N canvas 0 0 790 626 10;
#X obj 120 287 phasor~;
#X obj 139 363 bp~;
#X floatatom 119 131 5 0 0 2 freq - -;
#X floatatom 134 162 5 0 0 2 cutoff - -;
#X floatatom 156 197 5 0 0 2 Q - -;
#X obj 316 109 store;
#X obj 320 164 store;
#X obj 314 210 store;
#X msg 314 232 -16;
#X msg 320 184 47;
#X msg 316 129 149;
#X connect 0 0 1 0;
#X connect 2 0 0 0;
#X connect 2 0 5 0;
#X connect 3 0 1 1;
#X connect 3 0 6 0;
#X connect 4 0 7 0;
#X connect 4 0 1 2;
#X connect 5 0 10 0;
#X connect 6 0 9 0;
#X connect 7 0 8 0;
#X connect 8 0 4 0;
#X connect 9 0 3 0;
#X connect 10 0 2 0;
#X coords 0 -1 1 1 125 120 1 100 100;