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;