diff --git a/pd/doc/5.reference/preset_hub-help.pd b/pd/doc/5.reference/preset_hub-help.pd index bd13dc4064bc2a22b8108a471285d24013e2db7d..de352cdb619daf4e5a9f2688dd38da07057072c0 100644 --- a/pd/doc/5.reference/preset_hub-help.pd +++ b/pd/doc/5.reference/preset_hub-help.pd @@ -1,9 +1,9 @@ -#N canvas 138 24 553 616 10; +#N canvas 138 24 553 651 10; #X obj 109 282 cnv 15 60 37 empty empty empty 20 12 0 14 -261234 -66577 0; #X obj 183 294 cnv 15 44 27 empty empty empty 20 12 0 14 -204280 -66577 0; -#X obj 0 595 cnv 15 552 21 empty \$0-pddp.cnv.footer empty 20 12 0 +#X obj 0 1041 cnv 15 552 21 empty \$0-pddp.cnv.footer empty 20 12 0 14 -228856 -66577 0; #X obj 0 0 cnv 15 552 40 empty \$0-pddp.cnv.header preset_hub 3 12 0 18 -204280 -1 0; @@ -18,34 +18,31 @@ to conform to the PDDP template for Pd version 0.42.; #X text 12 85 OUTLET_0 anything; #X text 12 105 AUTHOR Ivica Ico Bukvic (c) 2012 <ico@vt.edu>; #X text 12 65 INLET_0 clear purge recall reset store; -#X restore 500 597 pd META; -#X obj 0 463 cnv 3 550 3 empty \$0-pddp.cnv.outlets outlets 8 12 0 +#X restore 500 1043 pd META; +#X obj 0 563 cnv 3 550 3 empty \$0-pddp.cnv.outlets outlets 8 12 0 13 -228856 -1 0; -#X obj 0 498 cnv 3 550 3 empty \$0-pddp.cnv.argument arguments 8 12 +#X obj 0 608 cnv 3 550 3 empty \$0-pddp.cnv.argument arguments 8 12 0 13 -228856 -1 0; -#X obj 0 538 cnv 3 550 3 empty \$0-pddp.cnv.more_info more_info 8 12 +#X obj 0 778 cnv 3 550 3 empty \$0-pddp.cnv.more_info more_info 8 12 0 13 -228856 -1 0; -#X obj 78 357 cnv 17 3 100 empty \$0-pddp.cnv.let.0 0 5 9 0 16 -228856 +#X obj 78 357 cnv 17 3 200 empty \$0-pddp.cnv.let.0 0 5 9 0 16 -228856 -162280 0; #N canvas 102 481 428 108 Related_objects 0; #X obj 1 1 cnv 15 425 20 empty \$0-pddp.cnv.subheading empty 3 12 0 14 -204280 -1 0; #X obj 22 36 preset_node; #X text 7 1 [preset_hub] Related Objects; -#X restore 101 597 pd Related_objects; -#X obj 78 472 cnv 17 3 17 empty \$0-pddp.cnv.let.0 0 5 9 0 16 -228856 +#X restore 101 1043 pd Related_objects; +#X obj 78 572 cnv 17 3 17 empty \$0-pddp.cnv.let.0 0 5 9 0 16 -228856 -162280 0; -#X obj 4 597 pddp/pddplink all_about_help_patches.pd -text Usage Guide +#X obj 4 1043 pddp/pddplink all_about_help_patches.pd -text Usage Guide ; #X text 11 20 universal preset system for pd-l2ork; -#X obj 20 202 preset_hub test %hidden% %node% 1 2 %preset% 1 30 %preset% -0 15 %node% 1 10 %preset% 1 2.24 nlah 1 %preset% 0 a b c 4 3 2 1 %node% -3 13 0 0 %preset% 1 1.02 %preset% 0 0.01 %node% 2 20 0 %preset% 1 two -%preset% 0 zero %node% 1 25 %node% 2 44 0 %node% 1 48 %node% 3 73 0 -0 %node% 2 54 0 %node% 1 21 %preset% 1 99 %preset% 2 23 %preset% 3 -1001 %preset% 0 3 %node% 2 31 1 %preset% 1 problems %preset% 2 skidoo -%preset% 3 nights %preset% 0 stooges %node% 1 33 %node% 2 39 0 %node% -1 64; +#X obj 20 202 preset_hub test %hidden% %node% 2 31 1 %preset% 1 problems +%preset% 2 skidoo %preset% 3 nights %preset% 0 stooges %node% 1 33 +%preset% 0 aaa 32 1 %preset% 1 2.24 nlah 1 %preset% 2 1 2 3 4 %node% +2 39 0 %preset% 0 1 %preset% 1 5 %preset% 2 9 %node% 1 61 %preset% +0 22.1 %preset% 1 0.5 %preset% 2 3.14; #X msg 80 125 store \$1; #X msg 80 74 recall \$1; #X msg 30 73 purge; @@ -61,11 +58,9 @@ to conform to the PDDP template for Pd version 0.42.; #X msg 386 60 reset; #X msg 447 190 clear \$1; #X floatatom 447 166 5 0 0 0 - - -; -#X obj 386 217 preset_hub another %hidden% %node% 2 23 10 %node% 2 -24 0 %node% 1 26 %node% 3 14 0 3 %preset% 0 -17 %preset% 1 382 %preset% -2 1234 %node% 1 25 %preset% 0 -4 %preset% 1 54 %preset% 2 -999 %node% -3 2 0 3 %node% 1 6 %node% 3 1 0 3 %node% 1 5 %node% 1 23 %node% 1 45 -%node% 3 73 0 3 %node% 2 54 2 %node% 1 32 %node% 2 39 2; +#X obj 386 217 preset_hub another %hidden% %node% 1 32 %preset% 0 99 +%preset% 1 65 %preset% 2 123 %preset% 3 0 %node% 2 39 2 %preset% 0 +19 %preset% 1 0.23 %preset% 2 999; #X obj 386 244 print hub_another_says; #X obj 20 268 hub_node_abs; #X obj 386 270 preset_node another; @@ -75,7 +70,7 @@ to conform to the PDDP template for Pd version 0.42.; #X msg 236 91 2.24 nlah 1; #X obj 188 157 print ----result----; #X msg 241 111 list 1 2 3 4; -#N canvas 0 0 404 229 sub 0; +#N canvas 444 419 404 229 sub 0; #X obj 237 69 preset_node test; #X floatatom 237 92 5 0 0 0 - - -; #X obj 113 69 preset_node another; @@ -84,14 +79,14 @@ to conform to the PDDP template for Pd version 0.42.; #X connect 0 0 1 0; #X connect 2 0 3 0; #X restore 119 292 pd sub; -#X text 98 418 reset; -#X text 99 472 anything; +#X text 98 416 reset; +#X text 99 572 anything; #X obj 425 21 pddp/pddplink http://wiki.puredata.info/en/preset_hub -text pdpedia: preset_hub; -#X text 99 376 purge; -#X text 98 397 recall; -#X text 98 438 store; -#X text 81 515 1) symbol; +#X text 98 376 purge; +#X text 98 396 recall; +#X text 98 436 store; +#X text 81 625 1) symbol; #X obj 381 305 cnv 15 44 27 empty empty empty 20 12 0 14 -204280 -66577 0; #X floatatom 386 310 5 0 0 0 - - -; @@ -101,12 +96,50 @@ to conform to the PDDP template for Pd version 0.42.; #X floatatom 80 151 5 0 0 0 - - -; #X obj 447 58 hradio 15 1 0 4 empty empty empty 0 -8 0 10 -262144 -1 -1 0; -#X obj 98 573 pddp/pddplink preset_node-help.pd; -#X text 168 397 - recall the values stored at index n; -#X text 168 438 - store the current state at index n; -#X text 169 472 - print message in response to input; -#X text 98 545 Scope- [preset_hub foo] is local to its patch and all +#X obj 98 813 pddp/pddplink preset_node-help.pd; +#X text 168 396 - recall the values stored at index n; +#X text 168 436 - store the current state at index n; +#X text 98 785 Scope- [preset_hub foo] is local to its patch and all of that patch's children (i.e. \, subpatches and abstractions).; +#X text 168 376 - purge all orphaned/unused nodes; +#X text 98 356 clear; +#X text 168 356 - clears preset n for all nodes; +#X obj 479 3 preset_hub %hidden% %node% 2 10 1; +#X obj 189 271 preset_node test; +#X floatatom 189 299 5 0 0 0 - - -; +#X msg 198 211 purge; +#X msg 189 189 reset; +#X msg 249 210 clearall \$1; +#X floatatom 249 189 5 0 0 0 - - -; +#X obj 233 300 print middle_node; +#X msg 232 244 set another; +#X msg 311 244 set test; +#X text 171 625 - OPTIONAL scope for this preset (defaults to null +or ""); +#X text 168 416 - reset all preset node data (wipes hub clean); +#X text 98 456 read; +#X text 169 572 - print message in response to input followed by 1 +for successful and 0 for failed operation; +#X text 81 645 2) symbol file; +#X text 81 735 3) float; +#X text 171 645 - OPTIONAL literal "file" argument instructs hub not +to embed its preset data into the patch but rather assumes that the +user will save this data into an external file (see read \, write \, +readpreset \, and writepreset message above)--this also means that +changes to the preset will not trigger "patch dirty" message; +#X text 171 735 - OPTIONAL argument used exclusively in the K12 mode +that renders preset_hub invisible to GUI operations; +#X text 98 476 write; +#X text 98 496 readpreset; +#X text 168 476 - write all presets to a file named in the second argument +; +#X text 168 456 - reads all presets from a file named in the second +argument; +#X text 168 496 - read one preset (optional 3rd argumemnt \, otherwise +preset 0) from a file named in the second argument; +#X text 98 526 writepreset; +#X text 168 526 - write one preset (optional 3rd argumemnt \, otherwise +preset 0) to a file named in the second argument; #N canvas 186 348 428 292 More_info 0; #X obj 30 165 cnv 15 349 98 empty \$0-pddp.cnv.subheading empty 3 12 0 14 -191407 -1 0; @@ -127,23 +160,71 @@ same canvas as the abstraction:; #X text 168 205 inside it.; #X text 40 171 [preset_hub foo] <-- this won't apply to [bar] because ; -#X restore 461 551 pd More_info; -#X text 168 376 - purge all orphaned/unused nodes; -#X text 168 418 - reset all preset node data; -#X text 98 356 clear; -#X text 168 356 - clears preset n for all nodes; -#X obj 479 3 preset_hub %hidden% %node% 2 10 1; -#X obj 189 271 preset_node test; -#X floatatom 189 299 5 0 0 0 - - -; -#X msg 198 211 purge; -#X msg 189 189 reset; -#X msg 249 210 clearall \$1; -#X floatatom 249 189 5 0 0 0 - - -; -#X obj 233 300 print middle_node; -#X msg 232 244 set another; -#X msg 311 244 set test; -#X text 171 515 - OPTIONAL scope for this preset (defaults to null -or ""); +#X restore 461 791 pd More_info; +#N canvas 512 381 640 292 More_info 0; +#X obj -9 -1 cnv 15 639 20 empty \$0-pddp.cnv.subheading empty 3 12 +0 14 -204280 -1 0; +#X text -3 -1 [preset_hub] More info on reading/writing operations +; +#X obj 9 192 preset_hub another file %hidden%; +#X obj 19 139 hradio 15 1 0 4 empty empty empty 0 -8 0 10 -262144 -1 +-1 0; +#X msg 19 159 recall \$1; +#X obj 85 139 hradio 15 1 0 4 empty empty empty 0 -8 0 10 -262144 -1 +-1 0; +#X msg 85 159 store \$1; +#X obj 10 238 preset_node another; +#X floatatom 10 260 5 0 0 0 - - -; +#X obj 135 238 preset_node another; +#X symbolatom 135 260 10 0 0 0 - - -; +#X text 263 24 First \, click on read to read all presets stored in +a separate file. Try recalling presets 0 and 1 Note how storing a new +preset does not make the patch dirty due to use of the "file" flag. +; +#X msg 151 165 reset; +#X text 263 82 Now reset the hub by clicking on the "reset" message. +The hub should be now clear of any presets. Now read a single preset +by clicking on readpreset message on the left. Notice how only preset +1 has any data (in this case identical to that found in all presets +file we loaded using the read call above.; +#X text 263 166 Loading a preset into a hub that already has data will +automatically result in a merge. As you experiment with mixing and +merging various presets \, notice how nodes in a preset that do not +have the right match in the current patch will be silently discarded +to minimize clutter among presets.; +#X msg 9 28 read preset_hub_all.preset; +#X msg 9 83 readpreset preset_hub_one.preset; +#X msg 9 104 writepreset /tmp/preset_hub_one.preset 1; +#X msg 9 49 write /tmp/preset_hub_all.preset; +#X obj 9 213 print preset_hub_another_says; +#X text 263 250 NB: check for write permissions before trying to save +files into specific folders.; +#X connect 2 0 19 0; +#X connect 3 0 4 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 9 0 10 0; +#X connect 12 0 2 0; +#X connect 15 0 2 0; +#X connect 16 0 2 0; +#X connect 17 0 2 0; +#X connect 18 0 2 0; +#X restore 461 841 pd More_info; +#X text 98 833 Writing to and reading from a file- preset_hub can also +write to an external file and read from it. More so \, the optional +2nd creation argument (literal symbol "file") prevents preset_hub from +trying to save itself into the patch. Hub can read/write all preset +states (read/write) or a select preset (readpreset/writepreset). Resetting +of hub's previously stored data must be done manually by the user. +Otherwise \, loaded data will be merged with the data already found +in the hub. Only valid nodes will be imported. Node data that does +not have a valid node in the existing patch will be silently dropped. +Reading a single preset will automatically recall it as soon as the +preset has been loaded.; +#X text 98 1007 Default values- messages when supplied no argument +default to 0 or empty string; #X connect 14 0 20 0; #X connect 15 0 14 0; #X connect 16 0 14 0; @@ -168,11 +249,11 @@ or ""); #X connect 50 0 15 0; #X connect 51 0 19 0; #X connect 52 0 23 0; -#X connect 64 0 70 0; -#X connect 64 0 65 0; -#X connect 66 0 64 0; -#X connect 67 0 64 0; -#X connect 68 0 64 0; -#X connect 69 0 68 0; -#X connect 71 0 64 0; -#X connect 72 0 64 0; +#X connect 61 0 67 0; +#X connect 61 0 62 0; +#X connect 63 0 61 0; +#X connect 64 0 61 0; +#X connect 65 0 61 0; +#X connect 66 0 65 0; +#X connect 68 0 61 0; +#X connect 69 0 61 0; diff --git a/pd/doc/5.reference/preset_node-help.pd b/pd/doc/5.reference/preset_node-help.pd index 157e1012d4243661d091bd27bc51863ae659fa4e..e785cd806b0c6c0e934be65aed721ead5beb132c 100644 --- a/pd/doc/5.reference/preset_node-help.pd +++ b/pd/doc/5.reference/preset_node-help.pd @@ -1,9 +1,9 @@ -#N canvas 357 24 555 678 10; -#X obj 178 291 cnv 15 44 27 empty empty empty 20 12 0 14 -204280 -66577 +#N canvas 135 24 553 653 10; +#X obj 180 291 cnv 15 44 27 empty empty empty 20 12 0 14 -204280 -66577 0; #X obj 105 279 cnv 15 60 37 empty empty empty 20 12 0 14 -261234 -66577 0; -#X obj -2 655 cnv 15 552 21 empty \$0-pddp.cnv.footer empty 20 12 0 +#X obj -2 865 cnv 15 552 21 empty \$0-pddp.cnv.footer empty 20 12 0 14 -228856 -66577 0; #X obj -2 0 cnv 15 552 40 empty \$0-pddp.cnv.header preset_node 3 12 0 18 -204280 -1 0; @@ -18,35 +18,34 @@ to conform to the PDDP template for Pd version 0.42.; #X text 12 65 INLET_0 anything; #X text 12 85 OUTLET_0 anything; #X text 12 105 AUTHOR Ivica Ico Bukvic (c) 2012 <ico@vt.edu>; -#X restore 498 657 pd META; -#X obj -2 493 cnv 3 550 3 empty \$0-pddp.cnv.outlets outlets 8 12 0 +#X restore 498 867 pd META; +#X obj -2 633 cnv 3 550 3 empty \$0-pddp.cnv.outlets outlets 8 12 0 13 -228856 -1 0; -#X obj -2 548 cnv 3 550 3 empty \$0-pddp.cnv.argument arguments 8 12 +#X obj -2 688 cnv 3 550 3 empty \$0-pddp.cnv.argument arguments 8 12 0 13 -228856 -1 0; -#X obj -2 598 cnv 3 550 3 empty \$0-pddp.cnv.more_info more_info 8 +#X obj -2 738 cnv 3 550 3 empty \$0-pddp.cnv.more_info more_info 8 12 0 13 -228856 -1 0; -#X obj 76 347 cnv 17 3 140 empty \$0-pddp.cnv.let.0 0 5 9 0 16 -228856 +#X obj 76 347 cnv 17 3 280 empty \$0-pddp.cnv.let.0 0 5 9 0 16 -228856 -162280 0; #N canvas 102 481 428 108 Related_objects 0; #X obj 1 1 cnv 15 425 20 empty \$0-pddp.cnv.subheading empty 3 12 0 14 -204280 -1 0; #X text 7 1 [preset_node] Related Objects; #X obj 22 36 preset_hub default %hidden%; -#X restore 99 657 pd Related_objects; -#X obj 76 502 cnv 17 3 17 empty \$0-pddp.cnv.let.0 0 5 9 0 16 -228856 +#X restore 99 867 pd Related_objects; +#X obj 76 642 cnv 17 3 17 empty \$0-pddp.cnv.let.0 0 5 9 0 16 -228856 -162280 0; -#X obj 2 657 pddp/pddplink all_about_help_patches.pd -text Usage Guide +#X obj 2 867 pddp/pddplink all_about_help_patches.pd -text Usage Guide ; #X text 9 20 universal preset system for pd-l2ork; #X obj 472 3 preset_node; #X obj 418 21 pddp/pddplink http://wiki.puredata.info/en/preset_node -text pdpedia: preset_node; -#X obj 18 202 preset_hub test %hidden% %node% 1 2 %preset% 1 30 %preset% -0 15 %node% 1 10 %preset% 1 2.24 nlah 1 %preset% 0 a b c 4 3 2 1 %node% -3 13 0 0 %preset% 1 1.02 %preset% 0 0.01 %node% 2 20 0 %preset% 1 two -%preset% 0 zero %node% 1 27 %node% 2 46 0 %node% 1 48 %node% 3 73 0 -0 %node% 2 54 0 %node% 2 44 1 %node% 1 26 %node% 2 43 1 %node% 1 46 -%node% 2 52 0; +#X obj 18 202 preset_hub test %hidden% %node% 1 26 %preset% 1 55.2 +%preset% 2 21.4 %preset% 0 123 %node% 2 43 1 %preset% 0 zero %preset% +1 one %preset% 2 two %node% 1 46 %preset% 0 aaa 32 1 %preset% 1 2.24 +nlah 1 %preset% 2 1 2 3 4 %node% 2 52 0 %preset% 0 0 %preset% 1 1 %preset% +2 2; #X msg 78 74 store \$1; #X msg 78 124 recall \$1; #X floatatom 78 50 5 0 0 0 - - -; @@ -56,38 +55,36 @@ to conform to the PDDP template for Pd version 0.42.; #X msg 79 174 clear \$1; #X floatatom 79 150 5 0 0 0 - - -; #X obj 18 231 print hub_test_says; -#X obj 184 267 preset_node test; -#X floatatom 184 295 5 0 0 0 - - -; -#X msg 193 213 purge; -#X msg 184 191 reset; -#X msg 244 212 clearall \$1; -#X floatatom 244 191 5 0 0 0 - - -; -#X obj 374 50 cnv 15 156 279 empty empty empty 20 12 0 14 -233017 -66577 +#X obj 186 267 preset_node test; +#X floatatom 186 295 5 0 0 0 - - -; +#X msg 195 213 purge; +#X msg 143 190 reset; +#X msg 246 212 clearall \$1; +#X floatatom 246 191 5 0 0 0 - - -; +#X obj 377 50 cnv 15 156 279 empty empty empty 20 12 0 14 -233017 -66577 0; -#X msg 445 83 store \$1; -#X msg 445 134 recall \$1; -#X floatatom 445 59 5 0 0 0 - - -; -#X floatatom 445 110 5 0 0 0 - - -; -#X msg 393 82 purge; -#X msg 384 60 reset; -#X msg 445 184 clear \$1; -#X floatatom 445 160 5 0 0 0 - - -; -#X obj 384 217 preset_hub another %hidden% %node% 2 23 10 %node% 2 -24 0 %node% 1 26 %node% 3 14 0 3 %preset% 0 -17 %preset% 1 382 %preset% -2 1234 %node% 1 25 %preset% 0 -4 %preset% 1 54 %preset% 2 -999 %node% -3 2 0 3 %node% 1 6 %node% 3 1 0 3 %node% 1 5 %node% 1 23 %node% 1 45 -%node% 3 73 0 3 %node% 2 54 2 %node% 1 44 %node% 2 52 2; -#X obj 384 244 print hub_another_says; +#X msg 448 83 store \$1; +#X msg 448 134 recall \$1; +#X floatatom 448 59 5 0 0 0 - - -; +#X floatatom 448 110 5 0 0 0 - - -; +#X msg 396 82 purge; +#X msg 387 60 reset; +#X msg 448 184 clear \$1; +#X floatatom 448 160 5 0 0 0 - - -; +#X obj 387 217 preset_hub another %hidden% %node% 1 44 %preset% 0 -5.1 +%preset% 1 22 %preset% 2 1.001 %node% 2 52 2 %preset% 0 41 %preset% +1 101 %preset% 2 7.13; +#X obj 387 244 print hub_another_says; #X obj 18 263 hub_node_abs; -#X obj 384 270 preset_node another; -#X obj 229 295 print middle_node; -#X obj 183 55 preset_node test; -#X obj 183 139 list; -#X msg 221 75 aaa 32 1; -#X msg 231 95 2.24 nlah 1; -#X obj 183 161 print ----result----; -#X msg 236 115 list 1 2 3 4; -#N canvas 0 0 404 229 sub 0; +#X obj 387 270 preset_node another; +#X obj 231 295 print middle_node; +#X obj 185 55 preset_node test; +#X obj 185 139 list; +#X msg 223 75 aaa 32 1; +#X msg 233 95 2.24 nlah 1; +#X obj 185 161 print ----result----; +#X msg 238 115 list 1 2 3 4; +#N canvas 523 458 404 229 sub 0; #X obj 237 69 preset_node test; #X floatatom 237 92 5 0 0 0 - - -; #X obj 113 69 preset_node another; @@ -97,15 +94,15 @@ to conform to the PDDP template for Pd version 0.42.; #X connect 2 0 3 0; #X restore 115 289 pd sub; #X text 96 366 clearall; -#X text 97 386 purge; -#X text 97 502 anything; -#X text 167 502 - [preset_node] makes an invisible connection from +#X text 96 386 purge; +#X text 97 642 anything; +#X text 167 642 - [preset_node] makes an invisible connection from the object below it back to its inlet. It can recall whatever type of message the connected object can output.; -#X text 79 565 1) symbol; -#X text 96 605 Scope- [preset_hub foo] is local to its patch and all +#X text 79 705 1) symbol; +#X text 96 745 Scope- [preset_hub foo] is local to its patch and all of that patch's children (i.e. \, subpatches and abstractions).; -#X obj 96 633 pddp/pddplink preset_hub-help.pd; +#X obj 96 773 pddp/pddplink preset_hub-help.pd; #N canvas 411 177 428 483 More_info 0; #X obj 271 378 cnv 15 39 23 empty empty empty 20 12 0 14 -261234 -66577 0; @@ -157,7 +154,7 @@ hub.; #X connect 17 0 20 0; #X connect 18 0 19 0; #X connect 19 0 21 0; -#X restore 457 610 pd More_info; +#X restore 457 750 pd More_info; #X text 166 386 - purge all orphaned/unused nodes (forwarded to hub) ; #X text 96 427 reset; @@ -175,13 +172,33 @@ hub); ; #X text 96 447 set; #X text 166 447 - change context (hub) node is paired with; -#X msg 227 242 set another; -#X msg 306 242 set test; -#X obj 378 293 cnv 15 44 27 empty empty empty 20 12 0 14 -204280 -66577 +#X msg 229 242 set another; +#X msg 308 242 set test; +#X obj 381 293 cnv 15 44 27 empty empty empty 20 12 0 14 -204280 -66577 0; -#X floatatom 384 298 5 0 0 0 - - -; -#X text 169 565 - OPTIONAL scope for this preset (defaults to null +#X floatatom 387 298 5 0 0 0 - - -; +#X text 169 705 - OPTIONAL scope for this preset (defaults to null or ""); +#X text 96 486 read; +#X text 96 516 write; +#X text 96 546 readpreset; +#X text 96 586 writepreset; +#X text 166 486 - reads all presets from a file named in the second +argument (forwarded to hub); +#X text 166 516 - write all presets to a file named in the second argument +(forwarded to hub); +#X text 166 546 - read one preset (optional 3rd argumemnt \, otherwise +preset 0) from a file named in the second argument (forwarded to hub) +; +#X text 166 586 - write one preset (optional 3rd argumemnt \, otherwise +preset 0) to a file named in the second argument (forwarded to hub) +; +#X text 96 795 Reading and writing- see preset_hub-help.pd for more +info.; +#X obj 96 809 pddp/pddplink preset_hub-help.pd; +#X msg 186 190 clear 0; +#X text 96 827 Default values- messages when supplied no argument default +to 0 or empty string; #X connect 16 0 25 0; #X connect 17 0 16 0; #X connect 18 0 16 0; @@ -214,3 +231,4 @@ or ""); #X connect 51 0 47 0; #X connect 73 0 26 0; #X connect 74 0 26 0; +#X connect 88 0 26 0; diff --git a/pd/src/m_pd.h b/pd/src/m_pd.h index 1bb8c9b984c008eb6a63e7c2de889082fa415a95..94a19562d3a309f051264c12576a8522d514207f 100644 --- a/pd/src/m_pd.h +++ b/pd/src/m_pd.h @@ -11,7 +11,7 @@ extern "C" { #define PD_MAJOR_VERSION 0 #define PD_MINOR_VERSION 42 #define PD_BUGFIX_VERSION 7 -#define PD_TEST_VERSION "20130126" +#define PD_TEST_VERSION "20130523" #define PDL2ORK /* old name for "MSW" flag -- we have to take it for the sake of many old diff --git a/pd/src/x_preset.c b/pd/src/x_preset.c index 5bfa69f917273ad3e0c39d0de5ddaf9008270601..353e4dae1088123972562624bee85d23aef1e1d6 100644 --- a/pd/src/x_preset.c +++ b/pd/src/x_preset.c @@ -46,13 +46,16 @@ void preset_hub_add_a_node(t_preset_hub *h, t_preset_node *x); void preset_hub_recall(t_preset_hub *h, t_float f); void preset_hub_store(t_preset_hub *h, t_float f); -void preset_hub_add_a_node(t_preset_hub *h, t_preset_node *x); void preset_hub_delete_a_node(t_preset_hub *h, t_preset_node *x); void preset_node_seek_hub(t_preset_node *x); int preset_hub_compare_loc(int *h_loc, int h_loc_length, int *n_loc, int n_loc_length); void preset_hub_reset(t_preset_hub *h); void preset_hub_purge(t_preset_hub *h); void preset_hub_clear(t_preset_hub *x, t_float f); +void preset_hub_read(t_preset_hub *x, t_symbol *filename); +void preset_hub_write(t_preset_hub *x, t_symbol *filename); +void preset_hub_readpreset(t_preset_hub *x, t_symbol *filename); +void preset_hub_writepreset(t_preset_hub *x, t_symbol *filename, float preset); static int preset_node_location_changed(t_preset_node *x); static void preset_node_update_my_glist_location(t_preset_node *x); @@ -452,6 +455,30 @@ void preset_node_request_hub_store(t_preset_node *x, t_float f) preset_hub_store(x->pn_hub, f); } +void preset_node_request_hub_read(t_preset_node *x, t_symbol *filename) +{ + if (x->pn_hub) + preset_hub_read(x->pn_hub, filename); +} + +void preset_node_request_hub_write(t_preset_node *x, t_symbol *filename) +{ + if (x->pn_hub) + preset_hub_write(x->pn_hub, filename); +} + +void preset_node_request_hub_readpreset(t_preset_node *x, t_symbol *filename) +{ + if (x->pn_hub) + preset_hub_readpreset(x->pn_hub, filename); +} + +void preset_node_request_hub_writepreset(t_preset_node *x, t_symbol *filename, float preset) +{ + if (x->pn_hub) + preset_hub_writepreset(x->pn_hub, filename, preset); +} + void preset_node_set_and_output_value(t_preset_node *x, t_alist val) { if(PH_DEBUG) fprintf(stderr,"preset_node_set_and_output_value %lx\n", (t_int)x); @@ -518,11 +545,11 @@ void preset_node_clear(t_preset_node *x, t_float f) } } } - if (changed) canvas_dirty(x->pn_hub->ph_canvas, 1); + if (changed && !x->pn_hub->ph_extern_file) canvas_dirty(x->pn_hub->ph_canvas, 1); SETFLOAT(ap+0, f); SETFLOAT(ap+1, (t_float)changed); - outlet_anything(x->pn_outlet, gensym("node_clear"), 2, ap); + outlet_anything(x->pn_hub->ph_outlet, gensym("node_clear"), 2, ap); } @@ -647,6 +674,15 @@ void preset_node_setup(void) class_addmethod(preset_node_class, (t_method)preset_node_purge, gensym("purge"), A_NULL, 0); + class_addmethod(preset_node_class, (t_method)preset_node_request_hub_read, + gensym("read"), A_DEFSYM, 0); + class_addmethod(preset_node_class, (t_method)preset_node_request_hub_write, + gensym("write"), A_DEFSYM, 0); + class_addmethod(preset_node_class, (t_method)preset_node_request_hub_readpreset, + gensym("readpreset"), A_DEFSYM, A_DEFFLOAT, 0); + class_addmethod(preset_node_class, (t_method)preset_node_request_hub_writepreset, + gensym("writepreset"), A_DEFSYM, A_DEFFLOAT, 0); + // we use anything to cover virtually all presetable types of data class_addanything(preset_node_class, preset_node_anything); } @@ -668,7 +704,7 @@ typedef enum /* syntax for saving a preset hub (all in a single line, here it is separated for legibility sakes): - #X obj X Y preset_hub NAME %hidden% + #X obj X Y preset_hub NAME(optional) file(optional) 1(optional) %hidden% %node% LOCATION_ARRAY_LENGTH LOCATION_ARRAY_(INT) 1 2 3 etc. %preset% 1 data %preset% 2 4 @@ -681,6 +717,12 @@ typedef enum NB: %hidden% is used to hide optional arguments following that argument it can be used by any other object as well + + file(optional) arg is used to tell hub it will be dealing exclusively with + external files (this prevents dirty flag when storing new presets) + + 1(optional) arg is used for k12 mode to prevent copying and pasting + multiple hubs with same names */ void preset_hub_save(t_gobj *z, t_binbuf *b) @@ -696,41 +738,49 @@ void preset_hub_save(t_gobj *z, t_binbuf *b) binbuf_addv(b, "ssiiss", gensym("#X"), gensym("obj"), (int)x->ph_obj.te_xpix, (int)x->ph_obj.te_ypix, gensym("preset_hub"), x->ph_name); + if (x->ph_extern_file) + binbuf_addv(b, "s", gensym("file")); + if (x->ph_invis) binbuf_addv(b, "i", (int)x->ph_invis); binbuf_addv(b, "s", gensym("%hidden%")); - phd = x->ph_data; - while (phd) { - if(PH_DEBUG) fprintf(stderr," saving phd\n"); - // designate a node and state whether it is active or disabled - // (disabled nodes are ones that have presets saved but have been deleted since-- - // we keep these in the case of undo actions during the session that may go beyond - // saving something into a file) - binbuf_addv(b, "si", gensym("%node%"), phd->phd_pn_gl_loc_length); - - // gather info about the length of the node's location and store it - for (i = 0; i < phd->phd_pn_gl_loc_length; i++) { - binbuf_addv(b,"i", (int)phd->phd_pn_gl_loc[i]); - } + // save preset data with the patch only if we are not + // saving into an external file + if (!x->ph_extern_file) { + + phd = x->ph_data; + while (phd) { + if(PH_DEBUG) fprintf(stderr," saving phd\n"); + // designate a node and state whether it is active or disabled + // (disabled nodes are ones that have presets saved but have been deleted since-- + // we keep these in the case of undo actions during the session that may go beyond + // saving something into a file) + binbuf_addv(b, "si", gensym("%node%"), phd->phd_pn_gl_loc_length); + + // gather info about the length of the node's location and store it + for (i = 0; i < phd->phd_pn_gl_loc_length; i++) { + binbuf_addv(b,"i", (int)phd->phd_pn_gl_loc[i]); + } - // save preset data - np = phd->phd_npreset; - while (np) { - if (np->np_val.l_n > 0) { - binbuf_addv(b, "si", gensym("%preset%"), (int)np->np_preset); - for (i = 0; i < np->np_val.l_n; i++) { - if (np->np_val.l_vec[i].l_a.a_type == A_FLOAT) - binbuf_addv(b, "f", np->np_val.l_vec[i].l_a.a_w.w_float); - else if (np->np_val.l_vec[i].l_a.a_type == A_SYMBOL) - binbuf_addv(b, "s", np->np_val.l_vec[i].l_a.a_w.w_symbol); + // save preset data + np = phd->phd_npreset; + while (np) { + if (np->np_val.l_n > 0) { + binbuf_addv(b, "si", gensym("%preset%"), (int)np->np_preset); + for (i = 0; i < np->np_val.l_n; i++) { + if (np->np_val.l_vec[i].l_a.a_type == A_FLOAT) + binbuf_addv(b, "f", np->np_val.l_vec[i].l_a.a_w.w_float); + else if (np->np_val.l_vec[i].l_a.a_type == A_SYMBOL) + binbuf_addv(b, "s", np->np_val.l_vec[i].l_a.a_w.w_symbol); + } } + np = np->np_next; } - np = np->np_next; - } - phd = phd->phd_next; + phd = phd->phd_next; + } } if(PH_DEBUG) fprintf(stderr," done\n"); binbuf_addv(b, ";"); @@ -877,7 +927,7 @@ void preset_hub_store(t_preset_hub *h, t_float f) } canvas_resume_dsp(dspstate); - if (changed) canvas_dirty(h->ph_canvas, 1); + if (changed && !h->ph_extern_file) canvas_dirty(h->ph_canvas, 1); SETFLOAT(ap+0, f); outlet_anything(h->ph_outlet, gensym("store"), 1, ap); @@ -1031,7 +1081,7 @@ void preset_hub_reset(t_preset_hub *h) // and finally request pairing with nodes (since we deleted all our references) glob_preset_node_list_seek_hub(); - if (changed) canvas_dirty(h->ph_canvas, 1); + if (changed && !h->ph_extern_file) canvas_dirty(h->ph_canvas, 1); SETFLOAT(ap+0, (t_float)changed); outlet_anything(h->ph_outlet, gensym("reset"), 1, ap); @@ -1083,7 +1133,7 @@ void preset_hub_clear(t_preset_hub *h, t_float f) hd2 = hd2->phd_next; } } - if (changed) canvas_dirty(h->ph_canvas, 1); + if (changed && !h->ph_extern_file) canvas_dirty(h->ph_canvas, 1); SETFLOAT(ap+0, (t_float)changed); outlet_anything(h->ph_outlet, gensym("clear"), 1, ap); @@ -1136,12 +1186,581 @@ void preset_hub_purge(t_preset_hub *h) } } } - if (changed) canvas_dirty(h->ph_canvas, 1); + if (changed && !h->ph_extern_file) canvas_dirty(h->ph_canvas, 1); SETFLOAT(ap+0, (t_float)changed); outlet_anything(h->ph_outlet, gensym("purge"), 1, ap); } +void preset_hub_read(t_preset_hub *x, t_symbol *filename) +{ + if(PH_DEBUG) fprintf(stderr,"preset_hub_read\n"); + + t_atom ap[1]; + int result = 0; + int pos = 0; + t_atom *argv = NULL; + t_binbuf *b = NULL; + int natom = 0; + int i = 0; + + t_preset_hub_data *hd1, *hd2; + t_node_preset *np1, *np2; + t_hub_parser h_cur = H_NONE; + int loc_length = 0; + int *loc_data = NULL; + int loc_pos = 0; + int node_preset = -1; + int found_node = 0; + int found_preset = 0; + int ignore_entry = 0; + int data_count = 0; + + if (filename == &s_) { + pd_error(x, "no read filename given\n"); + goto preset_hub_read_fail; + } + + // we only try to do this if we have valid paired nodes + // otherwise, we'll be filling the hub with bunch of + // disabled nodes that are unlikely to be paired properly + if (x->ph_data) { + + b = binbuf_new(); + + if (binbuf_read_via_canvas(b, filename->s_name, x->ph_canvas, 1)) { + pd_error(x, "%s: read failed", filename->s_name); + } else { + hd1 = NULL; + hd2 = NULL; + np1 = NULL; + np2 = NULL; + ignore_entry = 0; + + // load the data from the buffer and add to the preset db + natom = binbuf_getnatom(b); + if (pos < natom && natom > 1) { + argv = binbuf_getvec(b); + if (argv->a_type != A_SYMBOL || strcmp(atom_getsymbol(argv)->s_name, "#hub")) { + pd_error(x, "%s: malformed file", filename->s_name); + goto preset_hub_read_fail; + } else { + // detected proper preset file format, let's continue + argv++; + for (pos = 1; pos < natom; pos++, argv++) { + if(PH_DEBUG) fprintf(stderr," atom\n"); + // SYMBOL ANALYSIS + if (argv->a_type == A_SYMBOL) { + if(PH_DEBUG) fprintf(stderr," data = %s\n", atom_getsymbol(argv)->s_name); + if (!strcmp(atom_getsymbol(argv)->s_name, "%node%")) { + // beginning of a new node + ignore_entry = 0; + if(PH_DEBUG) fprintf(stderr," new node\n"); + loc_length = 0; + h_cur = H_NODE; + } + else if (!strcmp(atom_getsymbol(argv)->s_name, "%preset%") && !ignore_entry) { + // beginning of a new preset + if(PH_DEBUG) fprintf(stderr," new preset\n"); + h_cur = H_PRESET; + } + } + // FLOAT ANALYSIS + else if (argv->a_type == A_FLOAT && !ignore_entry) { + if(PH_DEBUG) fprintf(stderr," data = %g\n", atom_getfloat(argv)); + if (h_cur == H_NODE) { + // node location length + loc_length = (int)atom_getfloat(argv); + // reconstruct the dynamic location array + if (!loc_data) + loc_data = (int*)calloc(loc_length, sizeof(loc_data)); + loc_data[loc_length-1] = (int)atom_getfloat(&argv[i]); + if(PH_DEBUG) fprintf(stderr," loc length = %d\n", loc_length); + loc_pos = 0; + h_cur = H_LOCATION; + } + else if (h_cur == H_LOCATION) { + // node location data + loc_data[loc_pos] = (int)atom_getfloat(argv); + if(PH_DEBUG) fprintf(stderr," loc = %d\n", loc_data[loc_pos]); + loc_pos++; + if (loc_pos == loc_length) { + //the location data has been collected, now check if such a node already exists + found_node = 0; + + hd1 = NULL; + hd2 = NULL; + + // we use hd1 to navigate and hd2 to populate + // first check for existing nodes and reenable them if they match location + hd1 = x->ph_data; + while (hd1) { + if (!preset_hub_compare_loc(hd1->phd_pn_gl_loc, hd1->phd_pn_gl_loc_length, + loc_data, loc_length)) + { + // if this hub node data's location matches that of the node + if(PH_DEBUG) fprintf(stderr," found matching node\n"); + found_node = 1; + break; + } + hd1 = hd1->phd_next; + } + + if (!found_node) { + // we failed locating matching ph_data so we ignore the said data + // as there is no way the user will be able to predictably recreate + // node locations even if they wanted to + if(PH_DEBUG) fprintf(stderr," failed to find matching node\n"); + ignore_entry = 1; + } + + if (found_node) { + hd2 = hd1; + } + + // free loc_data as we don't need it any more + free(loc_data); + loc_data = NULL; + } + } + else if (h_cur == H_PRESET) { + // preset number + if(PH_DEBUG) fprintf(stderr," preset %g\n", atom_getfloat(argv)); + node_preset = (int)atom_getfloat(argv); + + np1 = NULL; + np2 = NULL; + + // check if the preset already exists + np1 = hd2->phd_npreset; + while (np1 && np1->np_preset != node_preset) { + np1 = np1->np_next; + } + if (!np1) { + // we need to create a new preset for the node + np2 = (t_node_preset *)t_getbytes(sizeof(*np2)); + if (!hd2->phd_npreset) { + hd2->phd_npreset = np2; + } else { + np1 = hd2->phd_npreset; + while(np1->np_next) { + np1 = np1->np_next; + } + np1->np_next = np2; + } + np2->np_preset = node_preset; + } else { + // otherwise we simply make np2 point to np1 (which is our matching preset) + np2 = np1; + // clear old preset data + if (np2->np_val.l_n) + alist_clear(&np2->np_val); + } + + data_count = 0; + argv++; + + // figure out how long of variable data list follows the preset descriptor + while (data_count < natom && strcmp(atom_getsymbol(argv+data_count)->s_name, "%preset%") && strcmp(atom_getsymbol(argv+data_count)->s_name, "%node%")) { + data_count++; + } + if(PH_DEBUG) fprintf(stderr," found preset? %d found node? %d\n", !strcmp(atom_getsymbol(argv+data_count)->s_name, "%preset%"), !strcmp(atom_getsymbol(argv+data_count)->s_name, "%node%")); + if(PH_DEBUG) fprintf(stderr," data_count = %d starting @ %d out of %d\n", data_count, pos+1, natom); + alist_init(&np2->np_val); + alist_list(&np2->np_val, 0, data_count, argv); + + if(PH_DEBUG) { + if ((argv)->a_type == A_SYMBOL) + fprintf(stderr," 1st_element = %s\n", atom_getsymbol(argv)->s_name); + else if ((argv)->a_type == A_FLOAT) + fprintf(stderr," 1st_element = %f\n", atom_getfloat(argv)); + else fprintf(stderr," 1st_element = unknown format\n"); + } + + pos = pos + data_count; + // we already incremented it above before figuring out + // how long data list is so we do one less + argv = argv + data_count - 1; + h_cur = H_PRESET_DATA; + } + } + } + } + } else { + pd_error(x, "%s: malformed/incomplete file", filename->s_name); + goto preset_hub_read_fail; + } + } + result = 1; + } + + preset_hub_read_fail: + if (b) binbuf_free(b); + SETFLOAT(ap+0, (t_float)result); + outlet_anything(x->ph_outlet, gensym("read"), 1, ap); +} + +void preset_hub_write(t_preset_hub *x, t_symbol *filename) +{ + if(PH_DEBUG) fprintf(stderr,"preset_hub_write\n"); + + t_atom ap[1]; + int result = 0; + t_atom *outv; + int i; + t_preset_hub_data *phd; + t_node_preset *np; + t_binbuf *b = binbuf_new(); + + if (filename == &s_) { + pd_error(x, "no write filename given\n"); + goto preset_hub_write_fail; + } + + phd = x->ph_data; + if (phd) { + binbuf_addv(b, "s", gensym("#hub")); + while (phd) { + if(PH_DEBUG) fprintf(stderr," saving phd\n"); + // designate a node and state whether it is active or disabled + // (disabled nodes are ones that have presets saved but have been deleted since-- + // we keep these in the case of undo actions during the session that may go beyond + // saving something into a file) + binbuf_addv(b, "si", gensym("%node%"), phd->phd_pn_gl_loc_length); + + // gather info about the length of the node's location and store it + for (i = 0; i < phd->phd_pn_gl_loc_length; i++) { + binbuf_addv(b,"i", (int)phd->phd_pn_gl_loc[i]); + } + + // save preset data + np = phd->phd_npreset; + while (np) { + if (np->np_val.l_n > 0) { + binbuf_addv(b, "si", gensym("%preset%"), (int)np->np_preset); + for (i = 0; i < np->np_val.l_n; i++) { + if (np->np_val.l_vec[i].l_a.a_type == A_FLOAT) + binbuf_addv(b, "f", np->np_val.l_vec[i].l_a.a_w.w_float); + else if (np->np_val.l_vec[i].l_a.a_type == A_SYMBOL) + binbuf_addv(b, "s", np->np_val.l_vec[i].l_a.a_w.w_symbol); + } + } + np = np->np_next; + } + + phd = phd->phd_next; + } + binbuf_addv(b, ";"); + result = 1; + } + if(PH_DEBUG) fprintf(stderr," done creating binbuf\n"); + + char buf[MAXPDSTRING]; + canvas_makefilename(x->ph_canvas, filename->s_name, + buf, MAXPDSTRING); + if (binbuf_write(b, buf, "", 1)) { + pd_error(x, "%s: write failed", filename->s_name); + result = 0; + } + + preset_hub_write_fail: + if (b) binbuf_free(b); + if(PH_DEBUG) fprintf(stderr," done saving file\n"); + + SETFLOAT(ap+0, (t_float)result); + outlet_anything(x->ph_outlet, gensym("write"), 1, ap); +} + +void preset_hub_readpreset(t_preset_hub *x, t_symbol *filename) +{ + if(PH_DEBUG) fprintf(stderr,"preset_hub_readpreset\n"); + + t_atom ap[1]; + int result = 0; + int pos = 0; + t_atom *argv = NULL; + t_binbuf *b = NULL; + int natom = 0; + int i = 0; + + t_preset_hub_data *hd1, *hd2; + t_node_preset *np1, *np2; + t_hub_parser h_cur = H_NONE; + int loc_length = 0; + int *loc_data = NULL; + int loc_pos = 0; + int node_preset = -1; + int found_node = 0; + int found_preset = 0; + int ignore_entry = 0; + int data_count = 0; + + int recall_preset = -1; + + if (filename == &s_) { + pd_error(x, "no readpreset filename given\n"); + goto preset_hub_readpreset_fail; + } + + // we only try to do this if we have valid paired nodes + // otherwise, we'll be filling the hub with bunch of + // disabled nodes that are unlikely to be paired properly + if (x->ph_data) { + + b = binbuf_new(); + + if (binbuf_read_via_canvas(b, filename->s_name, x->ph_canvas, 1)) { + pd_error(x, "%s: read failed", filename->s_name); + } else { + hd1 = NULL; + hd2 = NULL; + np1 = NULL; + np2 = NULL; + ignore_entry = 0; + + // load the data from the buffer and add to the preset db + natom = binbuf_getnatom(b); + if (pos < natom && natom > 1) { + argv = binbuf_getvec(b); + if (argv->a_type != A_SYMBOL || strcmp(atom_getsymbol(argv)->s_name, "#hubpreset")) { + pd_error(x, "%s: malformed file", filename->s_name); + goto preset_hub_readpreset_fail; + } else { + // detected proper preset file format, let's continue + argv++; + // read preset we need to recall as soon as we're done reading + if (argv->a_type != A_FLOAT) { + pd_error(x, "%s: malformed file", filename->s_name); + goto preset_hub_readpreset_fail; + } else { + recall_preset = (int)atom_getfloat(argv); + } + argv++; + for (pos = 1; pos < natom; pos++, argv++) { + if(PH_DEBUG) fprintf(stderr," atom\n"); + // SYMBOL ANALYSIS + if (argv->a_type == A_SYMBOL) { + if(PH_DEBUG) fprintf(stderr," data = %s\n", atom_getsymbol(argv)->s_name); + if (!strcmp(atom_getsymbol(argv)->s_name, "%node%")) { + // beginning of a new node + ignore_entry = 0; + if(PH_DEBUG) fprintf(stderr," new node\n"); + loc_length = 0; + h_cur = H_NODE; + } + else if (!strcmp(atom_getsymbol(argv)->s_name, "%preset%") && !ignore_entry) { + // beginning of a new preset + if(PH_DEBUG) fprintf(stderr," new preset\n"); + h_cur = H_PRESET; + } + } + // FLOAT ANALYSIS + else if (argv->a_type == A_FLOAT && !ignore_entry) { + if(PH_DEBUG) fprintf(stderr," data = %g\n", atom_getfloat(argv)); + if (h_cur == H_NODE) { + // node location length + loc_length = (int)atom_getfloat(argv); + // reconstruct the dynamic location array + if (!loc_data) + loc_data = (int*)calloc(loc_length, sizeof(loc_data)); + loc_data[loc_length-1] = (int)atom_getfloat(&argv[i]); + if(PH_DEBUG) fprintf(stderr," loc length = %d\n", loc_length); + loc_pos = 0; + h_cur = H_LOCATION; + } + else if (h_cur == H_LOCATION) { + // node location data + loc_data[loc_pos] = (int)atom_getfloat(argv); + if(PH_DEBUG) fprintf(stderr," loc = %d\n", loc_data[loc_pos]); + loc_pos++; + if (loc_pos == loc_length) { + //the location data has been collected, now check if such a node already exists + found_node = 0; + + hd1 = NULL; + hd2 = NULL; + + // we use hd1 to navigate and hd2 to populate + // first check for existing nodes and reenable them if they match location + hd1 = x->ph_data; + while (hd1) { + if (!preset_hub_compare_loc(hd1->phd_pn_gl_loc, hd1->phd_pn_gl_loc_length, + loc_data, loc_length)) + { + // if this hub node data's location matches that of the node + if(PH_DEBUG) fprintf(stderr," found matching node\n"); + found_node = 1; + break; + } + hd1 = hd1->phd_next; + } + + if (!found_node) { + // we failed locating matching ph_data so we ignore the said data + // as there is no way the user will be able to predictably recreate + // node locations even if they wanted to + if(PH_DEBUG) fprintf(stderr," failed to find matching node\n"); + ignore_entry = 1; + } + + if (found_node) { + hd2 = hd1; + } + + // free loc_data as we don't need it any more + free(loc_data); + loc_data = NULL; + } + } + else if (h_cur == H_PRESET) { + // preset number + if(PH_DEBUG) fprintf(stderr," preset %g\n", atom_getfloat(argv)); + node_preset = (int)atom_getfloat(argv); + + np1 = NULL; + np2 = NULL; + + // check if the preset already exists + np1 = hd2->phd_npreset; + while (np1 && np1->np_preset != node_preset) { + np1 = np1->np_next; + } + if (!np1) { + // we need to create a new preset for the node + np2 = (t_node_preset *)t_getbytes(sizeof(*np2)); + if (!hd2->phd_npreset) { + hd2->phd_npreset = np2; + } else { + np1 = hd2->phd_npreset; + while(np1->np_next) { + np1 = np1->np_next; + } + np1->np_next = np2; + } + np2->np_preset = node_preset; + } else { + // otherwise we simply make np2 point to np1 (which is our matching preset) + np2 = np1; + // clear old preset data + if (np2->np_val.l_n) + alist_clear(&np2->np_val); + } + + data_count = 0; + argv++; + + // figure out how long of variable data list follows the preset descriptor + while (data_count < natom && strcmp(atom_getsymbol(argv+data_count)->s_name, "%preset%") && strcmp(atom_getsymbol(argv+data_count)->s_name, "%node%")) { + data_count++; + } + if(PH_DEBUG) fprintf(stderr," found preset? %d found node? %d\n", !strcmp(atom_getsymbol(argv+data_count)->s_name, "%preset%"), !strcmp(atom_getsymbol(argv+data_count)->s_name, "%node%")); + if(PH_DEBUG) fprintf(stderr," data_count = %d starting @ %d out of %d\n", data_count, pos+1, natom); + alist_init(&np2->np_val); + alist_list(&np2->np_val, 0, data_count, argv); + + if(PH_DEBUG) { + if ((argv)->a_type == A_SYMBOL) + fprintf(stderr," 1st_element = %s\n", atom_getsymbol(argv)->s_name); + else if ((argv)->a_type == A_FLOAT) + fprintf(stderr," 1st_element = %f\n", atom_getfloat(argv)); + else fprintf(stderr," 1st_element = unknown format\n"); + } + + pos = pos + data_count; + // we already incremented it above before figuring out + // how long data list is so we do one less + argv = argv + data_count - 1; + h_cur = H_PRESET_DATA; + } + } + } + } + } else { + pd_error(x, "%s: malformed/incomplete file", filename->s_name); + goto preset_hub_readpreset_fail; + } + } + result = 1; + } + + preset_hub_readpreset_fail: + if (b) binbuf_free(b); + SETFLOAT(ap+0, (t_float)result); + outlet_anything(x->ph_outlet, gensym("readpreset"), 1, ap); + preset_hub_recall(x, recall_preset); +} + +void preset_hub_writepreset(t_preset_hub *x, t_symbol *filename, float preset) +{ + if(PH_DEBUG) fprintf(stderr,"preset_hub_writepreset\n"); + + t_atom ap[1]; + int result = 0; + t_atom *outv; + int i; + t_preset_hub_data *phd; + t_node_preset *np; + t_binbuf *b = binbuf_new(); + + if (filename == &s_) { + pd_error(x, "no writepreset filename given\n"); + goto preset_hub_writepreset_fail; + } + + phd = x->ph_data; + if (phd) { + binbuf_addv(b, "si", gensym("#hubpreset"), (int)preset); + while (phd) { + if(PH_DEBUG) fprintf(stderr," saving phd\n"); + // designate a node and state whether it is active or disabled + // (disabled nodes are ones that have presets saved but have been deleted since-- + // we keep these in the case of undo actions during the session that may go beyond + // saving something into a file) + binbuf_addv(b, "si", gensym("%node%"), phd->phd_pn_gl_loc_length); + + // gather info about the length of the node's location and store it + for (i = 0; i < phd->phd_pn_gl_loc_length; i++) { + binbuf_addv(b,"i", (int)phd->phd_pn_gl_loc[i]); + } + + // save preset data + np = phd->phd_npreset; + while (np) { + // only store preset if it matches requested preset number + if (np->np_val.l_n > 0 && np->np_preset == preset) { + binbuf_addv(b, "si", gensym("%preset%"), (int)np->np_preset); + for (i = 0; i < np->np_val.l_n; i++) { + if (np->np_val.l_vec[i].l_a.a_type == A_FLOAT) + binbuf_addv(b, "f", np->np_val.l_vec[i].l_a.a_w.w_float); + else if (np->np_val.l_vec[i].l_a.a_type == A_SYMBOL) + binbuf_addv(b, "s", np->np_val.l_vec[i].l_a.a_w.w_symbol); + } + } + np = np->np_next; + } + + phd = phd->phd_next; + } + binbuf_addv(b, ";"); + result = 1; + } + if(PH_DEBUG) fprintf(stderr," done creating binbuf\n"); + + char buf[MAXPDSTRING]; + canvas_makefilename(x->ph_canvas, filename->s_name, + buf, MAXPDSTRING); + if (binbuf_write(b, buf, "", 1)) { + pd_error(x, "%s: write failed", filename->s_name); + result = 0; + } + if(PH_DEBUG) fprintf(stderr," done saving file\n"); + + preset_hub_writepreset_fail: + if (b) binbuf_free(b); + SETFLOAT(ap+0, (t_float)result); + outlet_anything(x->ph_outlet, gensym("writepreset"), 1, ap); +} + static void *preset_hub_new(t_symbol *s, int argc, t_atom *argv) { if(PH_DEBUG) fprintf(stderr,"===preset_hub_new===\n"); @@ -1164,7 +1783,7 @@ static void *preset_hub_new(t_symbol *s, int argc, t_atom *argv) // read creation arguments and substitute default for objects without optional arguments if (!(argc > 0 && argv[0].a_type == A_SYMBOL) || (argc > 0 && argv[0].a_type == A_SYMBOL && !strcmp(atom_getsymbol(&argv[0])->s_name, "%hidden%"))) { - pos--; // we subtract one position as we are essentially missing one argument + pos--; // we subtract one position as we are essentially missing one argument (to counter pos++; call below that is called without checks) name = &s_; } else { @@ -1185,11 +1804,18 @@ static void *preset_hub_new(t_symbol *s, int argc, t_atom *argv) x = (t_preset_hub *)pd_new(preset_hub_class); x->ph_invis = 0; + x->ph_extern_file = 0; // read basic creation arguments x->ph_name = name; pos++; - if (argc > 1 && argv[1].a_type == A_FLOAT) { + // saving into external file + if (argc > pos && argv[pos].a_type == A_SYMBOL && !strcmp(atom_getsymbol(&argv[pos])->s_name, "file")) { + x->ph_extern_file = 1; + pos++; + } + // are we invisible (used by k12 mode) + if (argc > pos && argv[pos].a_type == A_FLOAT) { x->ph_invis = (int)atom_getfloat(&argv[1]); if (x->ph_invis < 0) x->ph_invis = 0; /*level = x->ph_level; @@ -1199,7 +1825,7 @@ static void *preset_hub_new(t_symbol *s, int argc, t_atom *argv) }*/ pos++; } - if(PH_DEBUG) fprintf(stderr,"hub name %s invis %d\n", x->ph_name->s_name, (int)x->ph_invis); + if(PH_DEBUG) fprintf(stderr,"hub name %s file %d invis %d\n", x->ph_name->s_name, x->ph_extern_file, x->ph_invis); pos++; // one more time to move ahead of the %hidden% tag @@ -1280,7 +1906,7 @@ static void *preset_hub_new(t_symbol *s, int argc, t_atom *argv) // reconstruct the dynamic location array if (!hd2->phd_pn_gl_loc) hd2->phd_pn_gl_loc = (int*)calloc(hd2->phd_pn_gl_loc_length, sizeof(hd2->phd_pn_gl_loc)); - hd2->phd_pn_gl_loc[hd2->phd_pn_gl_loc_length-1] = (int)atom_getfloat(&argv[i]); + hd2->phd_pn_gl_loc[hd2->phd_pn_gl_loc_length-1] = (int)atom_getfloat(&argv[i]); //WHY IS THIS HERE? if(PH_DEBUG) fprintf(stderr," loc length = %d\n", hd2->phd_pn_gl_loc_length); loc_pos = 0; h_cur = H_LOCATION; @@ -1300,9 +1926,9 @@ static void *preset_hub_new(t_symbol *s, int argc, t_atom *argv) while (data_count < argc && strcmp(atom_getsymbol(&argv[data_count])->s_name, "%preset%") && strcmp(atom_getsymbol(&argv[data_count])->s_name, "%node%")) { data_count++; } - if(PH_DEBUG) fprintf(stderr," found preset? %d found node? %d\n", strcmp(atom_getsymbol(&argv[data_count])->s_name, "%preset%"), strcmp(atom_getsymbol(&argv[data_count])->s_name, "%node%")); + if(PH_DEBUG) fprintf(stderr," found preset? %d found node? %d\n", !strcmp(atom_getsymbol(&argv[data_count])->s_name, "%preset%"), !strcmp(atom_getsymbol(&argv[data_count])->s_name, "%node%")); data_count = data_count - (i+1); - if(PH_DEBUG) fprintf(stderr," data_count = %d staring @ %d out of %d\n", data_count, i+1, argc); + if(PH_DEBUG) fprintf(stderr," data_count = %d starting @ %d out of %d\n", data_count, i+1, argc); alist_init(&np2->np_val); alist_list(&np2->np_val, 0, data_count, argv+(i+1)); i = i + data_count; @@ -1388,6 +2014,7 @@ static void preset_hub_free(t_preset_hub* x) } } hd2 = hd1->phd_next; + free(hd1->phd_pn_gl_loc); freebytes(hd1, sizeof(*hd1)); hd1 = hd2; } @@ -1419,6 +2046,15 @@ void preset_hub_setup(void) class_addmethod(preset_hub_class, (t_method)preset_hub_purge, gensym("purge"), A_NULL, 0); + class_addmethod(preset_hub_class, (t_method)preset_hub_read, + gensym("read"), A_DEFSYM, 0); + class_addmethod(preset_hub_class, (t_method)preset_hub_write, + gensym("write"), A_DEFSYM, 0); + class_addmethod(preset_hub_class, (t_method)preset_hub_readpreset, + gensym("readpreset"), A_DEFSYM, A_DEFFLOAT, 0); + class_addmethod(preset_hub_class, (t_method)preset_hub_writepreset, + gensym("writepreset"), A_DEFSYM, A_DEFFLOAT, 0); + class_addbang(preset_hub_class, preset_hub_bang); // we'll use this to output current preset class_setsavefn(preset_hub_class, preset_hub_save); } diff --git a/pd/src/x_preset.h b/pd/src/x_preset.h index 277b1ecbb1886f5950da2e19fd52777e98fe7db6..8f9c4f5745a39a5b80137d37208c7c8f5b654a4d 100644 --- a/pd/src/x_preset.h +++ b/pd/src/x_preset.h @@ -55,6 +55,10 @@ struct _preset_hub int ph_invis; // make it invisible (only for the k12 mode) int ph_preset; // last enabled preset (-1 at init time) + int ph_extern_file; // are we reading/writing from/to a file + // 0 = standard mode (saving with patch) + // 1 = saving into external file + t_canvas *ph_canvas; struct _preset_hub *ph_next; // next hub on the same canvas