aboutsummaryrefslogtreecommitdiff
path: root/externals
diff options
context:
space:
mode:
authorN.N. <matju@users.sourceforge.net>2009-11-06 18:37:00 +0000
committerN.N. <matju@users.sourceforge.net>2009-11-06 18:37:00 +0000
commit5a6bee4fe076e06514c6e4e538590dd3a2a5cdc3 (patch)
treeecf543b363457a0c861bfb187080a45fdeffc349 /externals
parent5e6bb4f4786dd39158ffe02913590cc3dea21ebd (diff)
upgrade gridflow
svn path=/trunk/; revision=12728
Diffstat (limited to 'externals')
-rw-r--r--externals/gridflow/COPYING340
-rw-r--r--externals/gridflow/ChangeLog704
-rw-r--r--externals/gridflow/LICENSE341
-rw-r--r--externals/gridflow/Makefile132
-rw-r--r--externals/gridflow/README131
-rw-r--r--externals/gridflow/TODO305
-rw-r--r--externals/gridflow/abstractions/#apply_colormap_channelwise.pd12
-rw-r--r--externals/gridflow/abstractions/#background_model.pd93
-rw-r--r--externals/gridflow/abstractions/#camera.pd353
-rw-r--r--externals/gridflow/abstractions/#change.pd22
-rw-r--r--externals/gridflow/abstractions/#checkers.pd18
-rw-r--r--externals/gridflow/abstractions/#clip.pd16
-rw-r--r--externals/gridflow/abstractions/#color.pd72
-rw-r--r--externals/gridflow/abstractions/#contrast.pd23
-rw-r--r--externals/gridflow/abstractions/#draw_hpgl.pd86
-rw-r--r--externals/gridflow/abstractions/#draw_rect.pd39
-rw-r--r--externals/gridflow/abstractions/#draw_slider.pd57
-rw-r--r--externals/gridflow/abstractions/#edit_polygon.pd64
-rw-r--r--externals/gridflow/abstractions/#extract_diagonal.pd22
-rw-r--r--externals/gridflow/abstractions/#fade.pd35
-rw-r--r--externals/gridflow/abstractions/#fade_lin.pd27
-rw-r--r--externals/gridflow/abstractions/#fastblur.pd89
-rw-r--r--externals/gridflow/abstractions/#gamma.pd21
-rw-r--r--externals/gridflow/abstractions/#greyscale_to_rgb.pd6
-rw-r--r--externals/gridflow/abstractions/#hello.pd28
-rw-r--r--externals/gridflow/abstractions/#hueshift.pd29
-rw-r--r--externals/gridflow/abstractions/#in.pd59
-rw-r--r--externals/gridflow/abstractions/#line_to_polygon.pd44
-rw-r--r--externals/gridflow/abstractions/#make_cross.pd30
-rw-r--r--externals/gridflow/abstractions/#moment_polar.pd54
-rw-r--r--externals/gridflow/abstractions/#motion_detection.pd142
-rw-r--r--externals/gridflow/abstractions/#mouse.pd93
-rw-r--r--externals/gridflow/abstractions/#out.pd51
-rw-r--r--externals/gridflow/abstractions/#polygon_area.pd19
-rw-r--r--externals/gridflow/abstractions/#polygon_comparator.pd99
-rw-r--r--externals/gridflow/abstractions/#polygon_each_edge.pd24
-rw-r--r--externals/gridflow/abstractions/#polygon_moment.pd65
-rw-r--r--externals/gridflow/abstractions/#polygon_perimetre.pd18
-rw-r--r--externals/gridflow/abstractions/#polygon_radial_map.pd184
-rw-r--r--externals/gridflow/abstractions/#posterize.pd19
-rw-r--r--externals/gridflow/abstractions/#ravel.pd15
-rw-r--r--externals/gridflow/abstractions/#record.pd72
-rw-r--r--externals/gridflow/abstractions/#reinterval.pd34
-rw-r--r--externals/gridflow/abstractions/#remap_image.pd23
-rw-r--r--externals/gridflow/abstractions/#rgb_to_greyscale.pd8
-rw-r--r--externals/gridflow/abstractions/#rgb_to_rgba.pd6
-rw-r--r--externals/gridflow/abstractions/#rgb_to_yuv.pd10
-rw-r--r--externals/gridflow/abstractions/#rgba_to_rgb.pd6
-rw-r--r--externals/gridflow/abstractions/#rotate.pd24
-rw-r--r--externals/gridflow/abstractions/#saturation.pd35
-rw-r--r--externals/gridflow/abstractions/#scale_to.pd29
-rw-r--r--externals/gridflow/abstractions/#seq_fold.pd31
-rw-r--r--externals/gridflow/abstractions/#slice.pd39
-rw-r--r--externals/gridflow/abstractions/#solarize.pd12
-rw-r--r--externals/gridflow/abstractions/#sort.pd13
-rw-r--r--externals/gridflow/abstractions/#spread.pd26
-rw-r--r--externals/gridflow/abstractions/#swap.pd16
-rw-r--r--externals/gridflow/abstractions/#t.pd16
-rw-r--r--externals/gridflow/abstractions/#text_to_image.pd41
-rw-r--r--externals/gridflow/abstractions/#to_literal.pd41
-rwxr-xr-xexternals/gridflow/abstractions/#window.pd28
-rw-r--r--externals/gridflow/abstractions/#yuv_to_rgb.pd10
-rw-r--r--externals/gridflow/abstractions/ascii.pd12
-rw-r--r--externals/gridflow/abstractions/ascii_to_f.pd71
-rw-r--r--externals/gridflow/abstractions/doc_add.pd55
-rw-r--r--externals/gridflow/abstractions/doc_also.pd56
-rw-r--r--externals/gridflow/abstractions/doc_below.pd42
-rw-r--r--externals/gridflow/abstractions/doc_bottom.pd70
-rw-r--r--externals/gridflow/abstractions/doc_c.pd25
-rw-r--r--externals/gridflow/abstractions/doc_cc.pd38
-rw-r--r--externals/gridflow/abstractions/doc_editmode.pd56
-rw-r--r--externals/gridflow/abstractions/doc_exist.pd30
-rw-r--r--externals/gridflow/abstractions/doc_f.pd12
-rw-r--r--externals/gridflow/abstractions/doc_h.pd212
-rw-r--r--externals/gridflow/abstractions/doc_i.pd28
-rw-r--r--externals/gridflow/abstractions/doc_ii.pd41
-rw-r--r--externals/gridflow/abstractions/doc_layout.pd178
-rw-r--r--externals/gridflow/abstractions/doc_m.pd166
-rw-r--r--externals/gridflow/abstractions/doc_make.pd35
-rw-r--r--externals/gridflow/abstractions/doc_o.pd28
-rw-r--r--externals/gridflow/abstractions/doc_oo.pd38
-rw-r--r--externals/gridflow/abstractions/expect.pd11
-rw-r--r--externals/gridflow/abstractions/for.pd37
-rw-r--r--externals/gridflow/abstractions/fps.pd210
-rw-r--r--externals/gridflow/abstractions/gf.io_generate.pd81
-rw-r--r--externals/gridflow/abstractions/gf.nbxhsl.pd32
-rw-r--r--externals/gridflow/abstractions/gf.not_open.pd10
-rw-r--r--externals/gridflow/abstractions/gf.oneshot.pd20
-rw-r--r--externals/gridflow/abstractions/hpgl_find_bbox.pd49
-rw-r--r--externals/gridflow/abstractions/hpgl_font_render.pd205
-rw-r--r--externals/gridflow/abstractions/hpgl_op.pd32
-rw-r--r--externals/gridflow/abstractions/hpgl_track_position.pd28
-rw-r--r--externals/gridflow/abstractions/interval_overlap.pd14
-rw-r--r--externals/gridflow/abstractions/inv0x2a.pd11
-rw-r--r--externals/gridflow/abstractions/inv0x2b.pd11
-rw-r--r--externals/gridflow/abstractions/norecurse.pd14
-rw-r--r--externals/gridflow/abstractions/pingpong.pd27
-rw-r--r--externals/gridflow/abstractions/plotter_control.pd119
-rw-r--r--externals/gridflow/abstractions/plotter_parser.pd78
-rw-r--r--externals/gridflow/abstractions/seq_fold.pd31
-rw-r--r--externals/gridflow/abstractions/var.#.pd16
-rwxr-xr-xexternals/gridflow/bin/backtrace18
-rwxr-xr-xexternals/gridflow/bin/check-help-version49
-rwxr-xr-xexternals/gridflow/bin/hpgl_move19
-rwxr-xr-xexternals/gridflow/bin/make-compose-makefile30
-rw-r--r--externals/gridflow/bin/pd-tools.tcl37
-rwxr-xr-xexternals/gridflow/bin/pdnonegative66
-rwxr-xr-xexternals/gridflow/bin/plusminus39
-rwxr-xr-xexternals/gridflow/bin/svn-mv5
-rwxr-xr-xexternals/gridflow/bin/valg5
-rw-r--r--externals/gridflow/bundled/g_canvas.h646
-rw-r--r--externals/gridflow/bundled/m_imp.h82
-rwxr-xr-xexternals/gridflow/configure822
-rw-r--r--externals/gridflow/deprecated/0x40!.pd28
-rw-r--r--externals/gridflow/deprecated/0x40complex_sq.pd11
-rw-r--r--externals/gridflow/deprecated/0x40convolve.pd23
-rw-r--r--externals/gridflow/deprecated/0x40fold.pd15
-rw-r--r--externals/gridflow/deprecated/0x40inner.pd23
-rw-r--r--externals/gridflow/deprecated/0x40scan.pd15
-rw-r--r--externals/gridflow/deprecated/fork.pd8
-rw-r--r--externals/gridflow/deprecated/listappend.pd10
-rw-r--r--externals/gridflow/deprecated/listelement.pd15
-rw-r--r--externals/gridflow/deprecated/listlength.pd6
-rw-r--r--externals/gridflow/deprecated/listprepend.pd10
-rw-r--r--externals/gridflow/deprecated/listsublist.pd12
-rw-r--r--externals/gridflow/deprecated/messageappend.pd12
-rw-r--r--externals/gridflow/deprecated/messageprepend.pd12
-rw-r--r--externals/gridflow/doc/Makefile7
-rw-r--r--externals/gridflow/doc/about.pd31
-rw-r--r--externals/gridflow/doc/find_missing.rb40
-rw-r--r--externals/gridflow/doc/flow_classes/#-help.pd55
-rw-r--r--externals/gridflow/doc/flow_classes/#apply_colormap_channelwise-help.pd55
-rw-r--r--externals/gridflow/doc/flow_classes/#background_model-help.pd90
-rw-r--r--externals/gridflow/doc/flow_classes/#border-help.pd44
-rw-r--r--externals/gridflow/doc/flow_classes/#camera-help.pd49
-rw-r--r--externals/gridflow/doc/flow_classes/#cast-help.pd67
-rw-r--r--externals/gridflow/doc/flow_classes/#centroid-help.pd29
-rw-r--r--externals/gridflow/doc/flow_classes/#change-help.pd35
-rw-r--r--externals/gridflow/doc/flow_classes/#checkers-help.pd26
-rw-r--r--externals/gridflow/doc/flow_classes/#clip-help.pd70
-rw-r--r--externals/gridflow/doc/flow_classes/#cluster_avg-help.pd22
-rw-r--r--externals/gridflow/doc/flow_classes/#color-help.pd44
-rw-r--r--externals/gridflow/doc/flow_classes/#contrast-help.pd72
-rw-r--r--externals/gridflow/doc/flow_classes/#convolve-help.pd67
-rw-r--r--externals/gridflow/doc/flow_classes/#dim-help.pd39
-rw-r--r--externals/gridflow/doc/flow_classes/#downscale_by-help.pd63
-rw-r--r--externals/gridflow/doc/flow_classes/#draw_hpgl-help.pd35
-rw-r--r--externals/gridflow/doc/flow_classes/#draw_image-help.pd102
-rw-r--r--externals/gridflow/doc/flow_classes/#draw_points-help.pd56
-rw-r--r--externals/gridflow/doc/flow_classes/#draw_polygon-help.pd116
-rw-r--r--externals/gridflow/doc/flow_classes/#draw_rect-help.pd40
-rw-r--r--externals/gridflow/doc/flow_classes/#draw_slider-help.pd56
-rw-r--r--externals/gridflow/doc/flow_classes/#edit_polygon-help.pd42
-rw-r--r--externals/gridflow/doc/flow_classes/#extract_diagonal-help.pd32
-rw-r--r--externals/gridflow/doc/flow_classes/#fade-help.pd57
-rw-r--r--externals/gridflow/doc/flow_classes/#fade_lin-help.pd36
-rw-r--r--externals/gridflow/doc/flow_classes/#fastblur-help.pd90
-rw-r--r--externals/gridflow/doc/flow_classes/#fft-help.pd73
-rw-r--r--externals/gridflow/doc/flow_classes/#finished-help.pd54
-rw-r--r--externals/gridflow/doc/flow_classes/#fold-help.pd80
-rw-r--r--externals/gridflow/doc/flow_classes/#for-help.pd83
-rw-r--r--externals/gridflow/doc/flow_classes/#from_pix-help.pd89
-rw-r--r--externals/gridflow/doc/flow_classes/#gamma-help.pd29
-rw-r--r--externals/gridflow/doc/flow_classes/#grade-help.pd45
-rw-r--r--externals/gridflow/doc/flow_classes/#greyscale_to_rgb-help.pd26
-rw-r--r--externals/gridflow/doc/flow_classes/#hello-help.pd23
-rw-r--r--externals/gridflow/doc/flow_classes/#hueshift-help.pd20
-rw-r--r--externals/gridflow/doc/flow_classes/#import-help.pd88
-rw-r--r--externals/gridflow/doc/flow_classes/#in-help.pd236
-rw-r--r--externals/gridflow/doc/flow_classes/#inner-help.pd56
-rw-r--r--externals/gridflow/doc/flow_classes/#io.aalib-help.pd45
-rw-r--r--externals/gridflow/doc/flow_classes/#io.grid-help.pd44
-rw-r--r--externals/gridflow/doc/flow_classes/#io.jpeg-help.pd16
-rw-r--r--externals/gridflow/doc/flow_classes/#io.png-help.pd18
-rw-r--r--externals/gridflow/doc/flow_classes/#io.quicktime-help.pd69
-rw-r--r--externals/gridflow/doc/flow_classes/#io.videodev-help.pd77
-rw-r--r--externals/gridflow/doc/flow_classes/#io.x11-help.pd150
-rw-r--r--externals/gridflow/doc/flow_classes/#join-help.pd72
-rw-r--r--externals/gridflow/doc/flow_classes/#labelling-help.pd55
-rw-r--r--externals/gridflow/doc/flow_classes/#layer-help.pd47
-rw-r--r--externals/gridflow/doc/flow_classes/#line_to_polygon-help.pd40
-rw-r--r--externals/gridflow/doc/flow_classes/#make_arrow-help.pd20
-rw-r--r--externals/gridflow/doc/flow_classes/#make_cross-help.pd47
-rw-r--r--externals/gridflow/doc/flow_classes/#moment-help.pd164
-rw-r--r--externals/gridflow/doc/flow_classes/#moment_polar-help.pd25
-rw-r--r--externals/gridflow/doc/flow_classes/#motion_detection-help.pd83
-rw-r--r--externals/gridflow/doc/flow_classes/#mouse-help.pd99
-rw-r--r--externals/gridflow/doc/flow_classes/#noise_gate_yuvs-help.pd26
-rw-r--r--externals/gridflow/doc/flow_classes/#out-help.pd139
-rw-r--r--externals/gridflow/doc/flow_classes/#outer-help.pd105
-rw-r--r--externals/gridflow/doc/flow_classes/#pack-help.pd46
-rw-r--r--externals/gridflow/doc/flow_classes/#perspective-help.pd49
-rw-r--r--externals/gridflow/doc/flow_classes/#polygon_area-help.pd28
-rw-r--r--externals/gridflow/doc/flow_classes/#polygon_comparator-help.pd85
-rw-r--r--externals/gridflow/doc/flow_classes/#polygon_each_edge-help.pd22
-rw-r--r--externals/gridflow/doc/flow_classes/#polygon_moment-help.pd64
-rw-r--r--externals/gridflow/doc/flow_classes/#polygon_perimetre-help.pd23
-rw-r--r--externals/gridflow/doc/flow_classes/#polygon_radial_map-help.pd55
-rw-r--r--externals/gridflow/doc/flow_classes/#posterize-help.pd63
-rw-r--r--externals/gridflow/doc/flow_classes/#print-help.pd73
-rw-r--r--externals/gridflow/doc/flow_classes/#ravel-help.pd42
-rw-r--r--externals/gridflow/doc/flow_classes/#record-help.pd53
-rw-r--r--externals/gridflow/doc/flow_classes/#redim-help.pd59
-rw-r--r--externals/gridflow/doc/flow_classes/#reinterval-help.pd33
-rw-r--r--externals/gridflow/doc/flow_classes/#remap_image-help.pd53
-rw-r--r--externals/gridflow/doc/flow_classes/#reverse-help.pd65
-rw-r--r--externals/gridflow/doc/flow_classes/#rgb_to_greyscale-help.pd27
-rw-r--r--externals/gridflow/doc/flow_classes/#rgb_to_yuv-help.pd30
-rw-r--r--externals/gridflow/doc/flow_classes/#rotate-help.pd49
-rw-r--r--externals/gridflow/doc/flow_classes/#rotatificator-help.pd50
-rw-r--r--externals/gridflow/doc/flow_classes/#saturation-help.pd52
-rw-r--r--externals/gridflow/doc/flow_classes/#scale_by-help.pd57
-rw-r--r--externals/gridflow/doc/flow_classes/#scale_to-help.pd66
-rw-r--r--externals/gridflow/doc/flow_classes/#scan-help.pd48
-rw-r--r--externals/gridflow/doc/flow_classes/#seq_fold-help.pd55
-rw-r--r--externals/gridflow/doc/flow_classes/#slice-help.pd47
-rw-r--r--externals/gridflow/doc/flow_classes/#solarize-help.pd39
-rw-r--r--externals/gridflow/doc/flow_classes/#sort-help.pd45
-rw-r--r--externals/gridflow/doc/flow_classes/#spread-help.pd79
-rw-r--r--externals/gridflow/doc/flow_classes/#store-help.pd111
-rw-r--r--externals/gridflow/doc/flow_classes/#swap-help.pd25
-rw-r--r--externals/gridflow/doc/flow_classes/#t-help.pd58
-rw-r--r--externals/gridflow/doc/flow_classes/#text_to_image-help.pd24
-rw-r--r--externals/gridflow/doc/flow_classes/#to_float-help.pd29
-rw-r--r--externals/gridflow/doc/flow_classes/#to_list-help.pd31
-rw-r--r--externals/gridflow/doc/flow_classes/#to_literal-help.pd34
-rw-r--r--externals/gridflow/doc/flow_classes/#to_pix-help.pd107
-rw-r--r--externals/gridflow/doc/flow_classes/#to_symbol-help.pd52
-rw-r--r--externals/gridflow/doc/flow_classes/#transpose-help.pd37
-rw-r--r--externals/gridflow/doc/flow_classes/#type-help.pd26
-rw-r--r--externals/gridflow/doc/flow_classes/#unpack-help.pd28
-rw-r--r--externals/gridflow/doc/flow_classes/#window-help.pd33
-rw-r--r--externals/gridflow/doc/flow_classes/0x40complex_sq-help.pd52
-rw-r--r--externals/gridflow/doc/flow_classes/args-demo.pd27
-rw-r--r--externals/gridflow/doc/flow_classes/args-help.pd50
-rw-r--r--externals/gridflow/doc/flow_classes/ascii-help.pd25
-rw-r--r--externals/gridflow/doc/flow_classes/ascii_to_f-help.pd31
-rw-r--r--externals/gridflow/doc/flow_classes/cv/#CornerHarris-help.pd14
-rw-r--r--externals/gridflow/doc/flow_classes/cv/#Ellipse-help.pd24
-rw-r--r--externals/gridflow/doc/flow_classes/cv/#Invert-help.pd32
-rw-r--r--externals/gridflow/doc/flow_classes/cv/#KMeans-help.pd29
-rw-r--r--externals/gridflow/doc/flow_classes/cv/#SVD-help.pd44
-rw-r--r--externals/gridflow/doc/flow_classes/cv/#numop-help.pd60
-rw-r--r--externals/gridflow/doc/flow_classes/display-help.pd24
-rw-r--r--externals/gridflow/doc/flow_classes/doc_add-help.pd23
-rw-r--r--externals/gridflow/doc/flow_classes/doc_also-help.pd18
-rw-r--r--externals/gridflow/doc/flow_classes/doc_below-help.pd40
-rw-r--r--externals/gridflow/doc/flow_classes/doc_bottom-help.pd27
-rw-r--r--externals/gridflow/doc/flow_classes/doc_c-help.pd17
-rw-r--r--externals/gridflow/doc/flow_classes/doc_cc-help.pd15
-rw-r--r--externals/gridflow/doc/flow_classes/doc_editmode-help.pd16
-rw-r--r--externals/gridflow/doc/flow_classes/doc_exist-help.pd26
-rw-r--r--externals/gridflow/doc/flow_classes/doc_f-help.pd7
-rw-r--r--externals/gridflow/doc/flow_classes/doc_h-help.pd13
-rw-r--r--externals/gridflow/doc/flow_classes/doc_i-help.pd10
-rw-r--r--externals/gridflow/doc/flow_classes/doc_ii-help.pd15
-rw-r--r--externals/gridflow/doc/flow_classes/doc_layout-help.pd46
-rw-r--r--externals/gridflow/doc/flow_classes/doc_m-help.pd78
-rw-r--r--externals/gridflow/doc/flow_classes/doc_make-help.pd25
-rw-r--r--externals/gridflow/doc/flow_classes/doc_o-help.pd11
-rw-r--r--externals/gridflow/doc/flow_classes/doc_oo-help.pd15
-rw-r--r--externals/gridflow/doc/flow_classes/for-help.pd56
-rw-r--r--externals/gridflow/doc/flow_classes/foreach-help.pd19
-rw-r--r--externals/gridflow/doc/flow_classes/fps-help.pd71
-rw-r--r--externals/gridflow/doc/flow_classes/gf.oneshot-help.pd42
-rw-r--r--externals/gridflow/doc/flow_classes/hpgl_find_bbox-help.pd21
-rw-r--r--externals/gridflow/doc/flow_classes/hpgl_font_render-help.pd178
-rw-r--r--externals/gridflow/doc/flow_classes/hpgl_op-help.pd30
-rw-r--r--externals/gridflow/doc/flow_classes/hpgl_track_position-help.pd21
-rw-r--r--externals/gridflow/doc/flow_classes/interval_overlap-help.pd46
-rw-r--r--externals/gridflow/doc/flow_classes/inv0x2a-help.pd78
-rw-r--r--externals/gridflow/doc/flow_classes/inv0x2b-help.pd75
-rw-r--r--externals/gridflow/doc/flow_classes/list.==-help.pd23
-rw-r--r--externals/gridflow/doc/flow_classes/listappend-help.pd49
-rw-r--r--externals/gridflow/doc/flow_classes/listelement-help.pd39
-rw-r--r--externals/gridflow/doc/flow_classes/listfind-help.pd32
-rw-r--r--externals/gridflow/doc/flow_classes/listflatten-help.pd39
-rw-r--r--externals/gridflow/doc/flow_classes/listlength-help.pd41
-rw-r--r--externals/gridflow/doc/flow_classes/listprepend-help.pd51
-rw-r--r--externals/gridflow/doc/flow_classes/listread-help.pd40
-rw-r--r--externals/gridflow/doc/flow_classes/listreverse-help.pd13
-rw-r--r--externals/gridflow/doc/flow_classes/listsublist-help.pd60
-rw-r--r--externals/gridflow/doc/flow_classes/norecurse-help.pd16
-rw-r--r--externals/gridflow/doc/flow_classes/parallel_port-help.pd96
-rw-r--r--externals/gridflow/doc/flow_classes/pingpong-help.pd27
-rw-r--r--externals/gridflow/doc/flow_classes/plotter_control-help.pd79
-rw-r--r--externals/gridflow/doc/flow_classes/plotter_parser-help.pd116
-rw-r--r--externals/gridflow/doc/flow_classes/range-help.pd28
-rw-r--r--externals/gridflow/doc/flow_classes/receives-help.pd38
-rw-r--r--externals/gridflow/doc/flow_classes/route2-help.pd33
-rw-r--r--externals/gridflow/doc/flow_classes/seq_fold-help.pd46
-rw-r--r--externals/gridflow/doc/flow_classes/shunt-help.pd70
-rw-r--r--externals/gridflow/doc/flow_classes/systemtime-help.pd33
-rw-r--r--externals/gridflow/doc/flow_classes/tsctime-help.pd50
-rw-r--r--externals/gridflow/doc/flow_classes/unix_time-help.pd50
-rw-r--r--externals/gridflow/doc/flow_classes/usertime-help.pd33
-rw-r--r--externals/gridflow/doc/flow_classes/var.#-help.pd21
-rw-r--r--externals/gridflow/doc/index.pd329
-rw-r--r--externals/gridflow/doc/locale/english.tcl210
-rw-r--r--externals/gridflow/doc/make_index.tcl29
-rw-r--r--externals/gridflow/doc/moulinette.tcl215
-rw-r--r--externals/gridflow/doc/numop.pd327
-rw-r--r--externals/gridflow/doc/numtype.pd56
-rw-r--r--externals/gridflow/doc/stuff.txt144
-rw-r--r--externals/gridflow/doc/tutorials/gf_sampling_quantization.pd57
-rw-r--r--externals/gridflow/doc/tutorials/gf_tutorial_grid_1.pd25
-rw-r--r--externals/gridflow/doc/tutorials/gf_tutorial_grid_2.pd64
-rw-r--r--externals/gridflow/doc/tutorials/gf_tutorial_grid_3.pd30
-rw-r--r--externals/gridflow/doc/tutorials/gf_tutorial_image_1.pd65
-rw-r--r--externals/gridflow/doc/tutorials/gf_tutorial_image_2.pd63
-rw-r--r--externals/gridflow/doc/tutorials/gf_tutorial_image_3.pd84
-rw-r--r--externals/gridflow/doc/tutorials/gf_tutorial_image_4.pd49
-rw-r--r--externals/gridflow/doc/tutorials/gf_tutorial_image_5.pd52
-rw-r--r--externals/gridflow/doc/tutorials/gf_tutorial_image_6.pd66
-rw-r--r--externals/gridflow/doc/tutorials/gf_tutorial_image_7.pd36
-rw-r--r--externals/gridflow/doc/tutorials/gf_tutorial_image_8.pd61
-rw-r--r--externals/gridflow/doc/tutorials/gf_tutorial_image_9.pd65
-rw-r--r--externals/gridflow/doc/tutorials/gf_tutorial_intro.pd86
-rw-r--r--externals/gridflow/doc/tutorials/grid-intro.pd10
-rw-r--r--externals/gridflow/doc/tutorials/pure-data-1.pd71
-rw-r--r--externals/gridflow/doc/tutorials/pure-data-2.pd73
-rw-r--r--externals/gridflow/doc/tutorials/pure-data-3.pd70
-rw-r--r--externals/gridflow/doc/tutorials/pure-data-4.pd87
-rw-r--r--externals/gridflow/doc/tutorials/pure-data-5.pd108
-rw-r--r--externals/gridflow/doc/tutorials/pure-data-6.pd92
-rw-r--r--externals/gridflow/doc/tutorials/pure-data-7.pd106
-rw-r--r--externals/gridflow/doc/tutorials/pure-data-8.pd89
-rw-r--r--externals/gridflow/doc/tutorials/pure-data-9.pd43
-rw-r--r--externals/gridflow/examples/binary_operations.pd73
-rw-r--r--externals/gridflow/examples/blob.pd106
-rw-r--r--externals/gridflow/examples/bounce.pd32
-rw-r--r--externals/gridflow/examples/cellular_1d.pd170
-rw-r--r--externals/gridflow/examples/color_correction.pd151
-rw-r--r--externals/gridflow/examples/color_detect.pd218
-rw-r--r--externals/gridflow/examples/convolve.pd90
-rw-r--r--externals/gridflow/examples/cross_fade.pd76
-rw-r--r--externals/gridflow/examples/doodle.pd51
-rw-r--r--externals/gridflow/examples/drag_rectangle.pd106
-rw-r--r--externals/gridflow/examples/eclipse.pd77
-rw-r--r--externals/gridflow/examples/epicycloid.pd125
-rw-r--r--externals/gridflow/examples/feedback_fractal.pd147
-rw-r--r--externals/gridflow/examples/fire.pd300
-rw-r--r--externals/gridflow/examples/frequency_mask.pd160
-rw-r--r--externals/gridflow/examples/game_of_life.pd92
-rw-r--r--externals/gridflow/examples/game_of_life_gem.pd291
-rw-r--r--externals/gridflow/examples/heat.pd173
-rw-r--r--externals/gridflow/examples/hello-world.pd39
-rw-r--r--externals/gridflow/examples/image_stats.pd62
-rw-r--r--externals/gridflow/examples/instant_blur.pd142
-rw-r--r--externals/gridflow/examples/linear_transform.pd225
-rw-r--r--externals/gridflow/examples/markov.pd133
-rw-r--r--externals/gridflow/examples/mechanics.pd121
-rw-r--r--externals/gridflow/examples/motion_detect.pd44
-rw-r--r--externals/gridflow/examples/multiblob.pd205
-rw-r--r--externals/gridflow/examples/nervous_video.pd163
-rw-r--r--externals/gridflow/examples/operator_spectrum.pd102
-rw-r--r--externals/gridflow/examples/photo_pianoroll.pd158
-rw-r--r--externals/gridflow/examples/pinwheel.pd108
-rw-r--r--externals/gridflow/examples/play_video.pd44
-rw-r--r--externals/gridflow/examples/plot.pd73
-rw-r--r--externals/gridflow/examples/polar.pd57
-rw-r--r--externals/gridflow/examples/polygon.pd123
-rw-r--r--externals/gridflow/examples/polygon_editor.pd23
-rw-r--r--externals/gridflow/examples/postdigital.pd67
-rw-r--r--externals/gridflow/examples/radial_blur.pd102
-rw-r--r--externals/gridflow/examples/ripple.pd184
-rw-r--r--externals/gridflow/examples/sand.pd392
-rw-r--r--externals/gridflow/examples/scratch_video.pd43
-rw-r--r--externals/gridflow/examples/slitscanning.pd54
-rw-r--r--externals/gridflow/examples/spectrogram.pd108
-rw-r--r--externals/gridflow/examples/surface_tension.pd138
-rw-r--r--externals/gridflow/examples/threshold.pd78
-rw-r--r--externals/gridflow/examples/transform.pd61
-rw-r--r--externals/gridflow/examples/translation_tracker.pd162
-rw-r--r--externals/gridflow/examples/translation_tracker2.pd126
-rw-r--r--externals/gridflow/examples/videodev_effects.pd264
-rw-r--r--externals/gridflow/examples/wave_1d.pd173
-rw-r--r--externals/gridflow/examples/waves.pd429
-rw-r--r--externals/gridflow/examples/wobble.pd56
-rw-r--r--externals/gridflow/images/README81
-rw-r--r--externals/gridflow/images/b001.jpgbin0 -> 29530 bytes
-rw-r--r--externals/gridflow/images/babbage.jpgbin0 -> 41468 bytes
-rw-r--r--externals/gridflow/images/bluemarble.jpgbin0 -> 29054 bytes
-rw-r--r--externals/gridflow/images/compose-8859-1.pdd28
-rw-r--r--externals/gridflow/images/david.jpgbin0 -> 86663 bytes
-rw-r--r--externals/gridflow/images/etch_a_sketch.jpgbin0 -> 341652 bytes
-rw-r--r--externals/gridflow/images/g001.jpgbin0 -> 53775 bytes
-rw-r--r--externals/gridflow/images/hello.hpgl3
-rw-r--r--externals/gridflow/images/hershey-latin-1/168.hpgl4
-rw-r--r--externals/gridflow/images/hershey-latin-1/180.hpgl2
-rw-r--r--externals/gridflow/images/hershey-latin-1/94.hpgl2
-rw-r--r--externals/gridflow/images/hershey-latin-1/96.hpgl2
-rw-r--r--externals/gridflow/images/lada.jpgbin0 -> 121288 bytes
-rw-r--r--externals/gridflow/images/lena.jpgbin0 -> 69363 bytes
-rw-r--r--externals/gridflow/images/lite_brite_1.jpgbin0 -> 271948 bytes
-rw-r--r--externals/gridflow/images/lite_brite_code.jpgbin0 -> 63224 bytes
-rw-r--r--externals/gridflow/images/litmus.jpgbin0 -> 371 bytes
-rw-r--r--externals/gridflow/images/lots_of_text.hpgl2
-rw-r--r--externals/gridflow/images/lucida-typewriter-12.gridbin0 -> 23320 bytes
-rw-r--r--externals/gridflow/images/opensource.pngbin0 -> 76504 bytes
-rw-r--r--externals/gridflow/images/plotter_parser_old.pd.hpgl341
-rw-r--r--externals/gridflow/images/pmask.pngbin0 -> 8237 bytes
-rw-r--r--externals/gridflow/images/pure-data.jpgbin0 -> 11166 bytes
-rw-r--r--externals/gridflow/images/r001.jpgbin0 -> 25505 bytes
-rw-r--r--externals/gridflow/images/rose.jpgbin0 -> 5756 bytes
-rw-r--r--externals/gridflow/images/scissors.jpgbin0 -> 244706 bytes
-rw-r--r--externals/gridflow/images/sewing.jpgbin0 -> 208559 bytes
-rw-r--r--externals/gridflow/images/teapot.pngbin0 -> 34407 bytes
-rw-r--r--externals/gridflow/images/test.mpegbin0 -> 345 bytes
-rw-r--r--externals/gridflow/images/tux.tga.gzbin0 -> 20629 bytes
-rw-r--r--externals/gridflow/images/violoncelle.movbin0 -> 1679651 bytes
-rw-r--r--externals/gridflow/images/working.jpgbin0 -> 399383 bytes
-rw-r--r--externals/gridflow/src/aalib.cxx144
-rw-r--r--externals/gridflow/src/classes1.cxx2342
-rw-r--r--externals/gridflow/src/classes2.cxx1183
-rw-r--r--externals/gridflow/src/dc1394.cxx287
-rw-r--r--externals/gridflow/src/fftw.cxx114
-rw-r--r--externals/gridflow/src/formats.cxx266
-rw-r--r--externals/gridflow/src/gem.cxx202
-rw-r--r--externals/gridflow/src/grid.cxx295
-rw-r--r--externals/gridflow/src/gridflow.cxx961
-rw-r--r--externals/gridflow/src/gridflow.hxx911
-rw-r--r--externals/gridflow/src/jpeg.cxx118
-rw-r--r--externals/gridflow/src/mmx.rb219
-rw-r--r--externals/gridflow/src/mpeg3.cxx83
-rw-r--r--externals/gridflow/src/netpbm.cxx117
-rw-r--r--externals/gridflow/src/number.cxx446
-rw-r--r--externals/gridflow/src/opencv.cxx537
-rw-r--r--externals/gridflow/src/png.cxx143
-rw-r--r--externals/gridflow/src/pwc-ioctl.h292
-rw-r--r--externals/gridflow/src/quartz.m224
-rw-r--r--externals/gridflow/src/quicktimeapple.cxx456
-rw-r--r--externals/gridflow/src/quicktimehw.cxx246
-rw-r--r--externals/gridflow/src/sdl.cxx209
-rw-r--r--externals/gridflow/src/source_filter.rb311
-rw-r--r--externals/gridflow/src/videodev.cxx793
-rw-r--r--externals/gridflow/src/x11.cxx664
-rw-r--r--externals/gridflow/tests/#ann_som-test.pd107
-rw-r--r--externals/gridflow/tests/#inner-test2.pd11
-rw-r--r--externals/gridflow/tests/#print-test.pd30
-rw-r--r--externals/gridflow/tests/Makefile7
-rw-r--r--externals/gridflow/tests/args-2-test.pd17
-rw-r--r--externals/gridflow/tests/args-test.pd23
-rw-r--r--externals/gridflow/tests/cv.SVD-test.pd37
-rw-r--r--externals/gridflow/tests/foreach-test.pd8
-rw-r--r--externals/gridflow/tests/fps-test.pd75
-rw-r--r--externals/gridflow/tests/gf.error-2-test.pd6
-rw-r--r--externals/gridflow/tests/gf.error-test.pd4
-rw-r--r--externals/gridflow/tests/listflatten-test.pd16
-rw-r--r--externals/gridflow/tests/malloc-test.c36
-rw-r--r--externals/gridflow/tests/opencv-test1.pd72
-rw-r--r--externals/gridflow/tests/opencv-test2.pd49
-rw-r--r--externals/gridflow/tests/plotter_control-test.pd51
-rw-r--r--externals/gridflow/tests/plotter_parser-test.pd73
-rw-r--r--externals/gridflow/tests/range-test.pd39
-rw-r--r--externals/gridflow/tests/suppressions.valg3201
456 files changed, 39633 insertions, 0 deletions
diff --git a/externals/gridflow/COPYING b/externals/gridflow/COPYING
new file mode 100644
index 00000000..eeb586b3
--- /dev/null
+++ b/externals/gridflow/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/externals/gridflow/ChangeLog b/externals/gridflow/ChangeLog
new file mode 100644
index 00000000..1b43583b
--- /dev/null
+++ b/externals/gridflow/ChangeLog
@@ -0,0 +1,704 @@
+/* $Id: ChangeLog 4755 2009-11-05 04:24:29Z matju $ */
+
+version 0.9.7 (...):
+
+version 0.9.6 (2009.11.02):
+
+ * MAJOR revision of the manual (no more xml nor html: all helpfiles)
+ * documented several dozen undocumented classes
+ * revised all documentation content
+ * installation instructions are now in ./README instead of doc/install.html
+ * added [gf/canvas_filename] [gf/string_replace] [gf/canvas_count]
+ * added [gf/canvas_getpos] [gf/canvas_setpos] [gf/canvas_edit_mode]
+ * added [gf/canvas_setgop] [gf/canvas_xid] [gf/canvas_loadbang] etc
+ * added [doc_h] [doc_c] [doc_cc] [doc_i] [doc_ii] [doc_o] [doc_oo]
+ * added [doc_m] [doc_also] [doc_editmodebang] [doc_pos]
+ * added examples/pinwheel.pd, examples/radial_blur.pd
+ * added examples/operator_spectrum.pd
+ * [#change]: now takes an argument just like [change]
+ * [#in x11]: fixed some bugs and set out_size to a sensible default.
+ * removed [#camera_control], [#camera_old], [#centroid_in_pd]
+ * removed [count], [condition]
+ * [#window]: added outlet
+ * [#swap]: added optional argument
+ * [var.#]: added optional argument
+ * [#spread]: added optional argument
+ * [#to_literal]: write numbertype
+ * [#fade_lin]: accept grid args
+ * [#posterize]: made the optional argument really optional...
+ * renamed source files
+ * rewrote GEM support without using GEM headers
+ * removed --gem-include
+ * removed bundled/Base (was a copy of GEM 0.91 include files)
+ * [#from_pix]: much faster
+ * [#to_pix]: support 3-channel rgb input
+ * [#out x11]: some video modes are now much faster than before
+ * [args]: don't [loadbang] it anymore: it's automatic now.
+ * [args]: removed attribute outlet: it's automatic now.
+ * removed [send39] : GridFlow requires PureData 0.40 these days.
+ * added GridFlow About in Help menu
+ * GridFlow menu items available in all windows instead of just the main
+
+version 0.9.5 (2009.10.18):
+
+ * added [gf.print] (aliased to [print])
+ * added [cv/#Ellipse], [cv/#HarrisCorner], [cv/#KMeans]
+ * renamed goop.pd to surface_tension.pd
+ * [#in quicktime]: "get" also produces messages "framerate", "height",
+ "width", "depth", "codec".
+ * added [#draw_hpgl], [#reinterval], [#cluster_avg]
+ * added [norecurse], [gf.error]
+ * [#color]: added bang
+ * [#inner]: fixed infinite loop bug with large right-inlet grids.
+ * [#transpose]: fixed crash with zero-sized grids.
+ * [receives]: "empty" prefix automatically turned into "" (no prefix).
+ * [#in grid] and [#out grid]: fixed several bugs
+ * [#make_cross] can make rectangular crosses
+ * [demux] alias removed (please use [shunt])
+ * renamed every [cv.Something] to [cv/#Something] to avoid any future
+ nameclashes with Loïc's library.
+ * automatically removes artificial stacksize limits of the OS that may
+ have caused segfaults in the last year or so, if you didn't use
+ ulimit -s unlimited or somesuch
+ * added [# c2p] and [# p2c] (polar transforms)
+ * added new examples: polar.pd, radial_blur.pd
+ * fixed more OSX bugs
+ * fixed [#grade] bug (thanks to mescalinum)
+ * removed support for gem 0.89 and some 0.90 versions
+ * renamed [#labeling] to [#labelling] (kept an alias)
+
+version 0.9.4 (2008.07.04):
+
+ * [#convolve] takes more RAM but gets faster on OSX
+ * added [listread], [receives], [ascii_to_f], [plotter_parser], [list.==]
+ * added [cv.Invert], [cv.SVD], [expect], [#hello]
+ * [plotter_control] supports most other commands and uppercase selectors
+ * added [#in dc1394]
+ * added [#window] (a shortcut for a [spigot] and a [#out window])
+ * rewrote [listflatten] (was removed in 0.9.2)
+ * [#camera] greys out unavailable options and supports dc1394
+ * added "GridFlow index" in Help menu (like Pd's right-click on blank)
+ * made arguments optional in [#border] [#draw_image] [#draw_polygon]
+ * [#draw_polygon]: added attribute "draw" (fill, line)
+ * [#draw_polygon]: added attribute "omit" (none, last, odd)
+ * support whitespace in symbols again (after bug in 0.9.2)
+ * fixed ppm loader
+ * [#fft]: added attribute "real"
+ * added example frequency_mask.pd
+
+version 0.9.3 (2008.06.06):
+
+ * fixed bugs introduced in 0.9.2 relative to: [#in] loop, [#in] initbang,
+ [display] selector, [#out] initbang, [#print], [#labeling], [#out window]
+ * added example patches instant_blur.pd game_of_life_gem.pd
+ * added [class_exists]
+ * added [#in quicktimecamera]
+ * fixed some example patches
+ * fixed some recent OSX compilation problems
+ * fixed OSX QuickTime decoding on Intel (endianness problem)
+ * fixed existing GEM 0.89 and 0.90 support
+ * added GEM 0.91 support (GemBase::isRunnable)
+ * --gem-source renamed to --gem-include
+ * --gem-include=bundled can compile gem support without gem source code
+ * swapped outlets of [#import_pix]
+ * added SDL mouse position event report (but buttonup does not work)
+ * added SDL key report
+ * added some SDL options: title, hidecursor, partial setcursor
+ * added SDL fullscreen (use key f, F11 or Escape)
+ * x11: replaced method "transfer" by method "shared_memory".
+
+version 0.9.2 (2008.05.02):
+
+ * removed libruby dependency
+
+version 0.9.1 (2008.04.16):
+
+ * switched from CVS to SVN
+ * removed LTIlib support
+ * x11: added "warp" method for moving mouse cursor around
+ * removed all Ruby code (rewritten in C++ or Pd)
+ * rewrote PPM support. now relies on libnetpbm.
+ (apt-get install libnetpbm10-dev)
+ * removed broken Targa support
+ * removed timelog feature in [#in]/[#out] (redundant)
+ * removed [joystick_port], [SoundMixer], [pd_netsocket], [rubyarray], [ls],
+ [system], [exec], [regsub], [memstat], [#edit], [peephole], [listmake],
+ [gridflow]/[#global], [sendgui], [realtimer], [bindpatcher], [renamefile]
+ (contact me if you need any of them)
+ * added [gf.error], [usertime], [systemtime], [tsctime]
+ * added method to_ascii in [#import]
+ * [display] word-wrap
+ * [#import] defaults to per_message mode
+ * removed support for ~/.gridflow_startup and GridFlow.data_path
+ (contact me if you need them)
+
+version 0.9.0 (2007.11.20):
+
+ * new object classes: [#slice], [#sort], [#line_to_polygon].
+ * rewrote some object classes from Ruby to Pd.
+ * split compilation of the LTIlib support allows to compile
+ it with reasonable amounts of RAM.
+ * new classes: [seq_fold], [#seq_fold], [#.var], [#noise_gate_yuvs]
+ * updated [#camera]
+ * added PWC-specific options: framerate white_mode white_red white_blue
+ white_speed white_delay auto_gain compression noise_reduction
+ * added "pwc" option in [#camera], for enabling PWC-specific options.
+ * colorspace conversion directly in [#in videodev] (faster)
+ * grid messages no longer contain dim and numbertype (just a pointer)
+ * GridOutlet: added set_chunk (so set_factor is obsolete)
+ * removed GridFlow menu
+ * faster [#inner] for small matrix sizes
+ * GridFlow won't work in plain Ruby anymore (without Pd)
+ * removed [pd_netsend] [jmax_udpsend] [jmax4_udpsend] [pd_netreceive]
+ [jmax_udpreceive] [jmax4_udpreceive] [printargs] [rubyprint]
+ * removed Type.rb and Contract.rb and their use in videodev.c
+ * [#in quicktime]: added workaround for jpeg_quality problem
+ * [#in quicktime]: added method "get", that produces message "frames"
+ that gives the number of frames in a video
+ * [#out]: added method "autoclose"
+ * removed old documentation: *-icon.png
+ * renamed [#export] to [#to_float]
+ * renamed [#export_list] to [#to_list]
+ * renamed [#export_symbol] to [#to_symbol]
+ * renamed [#export_pix] to [#to_pix]
+ * fixed 256MB limit bug
+ * fixed reassign bug
+
+version 0.8.4 (2006.10.12):
+
+ * resuming support for Ruby 1.8 !
+ * added compatibility with more recent versions of Ruby 1.9
+ * added compatibility with more recent versions of GCC 4.x
+ * much more LTIlib support! (a few dozen more object classes)
+ * [#camera]: improved
+ * rblti supports ltilib 1.9.15 and gcc 4
+ * new object classes: [route2], [#polygon_each_edge],
+ [#polygon_moment], [#polygon_radial_map], [#polygon_comparator],
+ [#moment_polar].
+ * new float-only numops: sin cos tanh exp log atan2
+ * new float-only vecops: C.sin C.cos C.tanh C.exp C.log
+ * [#fft] can do RGB (per channel)
+ * can show added inlets/outlets at runtime.
+ * can remove inlets/outlets at runtime (and erase them from screen).
+ * much faster videodev !!!
+
+ (also unfinished [#edit_polygon] and [#draw_rect]).
+
+version 0.8.3 (2006.04.02):
+
+ * added Makefile rules for downloading+installing ruby 1.9
+ * new numops: weight rol ror
+ * new vecops concept helps with complex numbers
+ * new vecops: C.* C.*conj C./ C./conj C.sq- C.abs-
+ * [#convolve]: added attr "wrap", "anti"
+ * [#inner]: faster!
+ * [#shunt]: added attr index,mode,lo,hi
+ * now also works with older (non-CVS) versions of GEM
+ * new object classes: [#fastblur], [#t], [#rgb_to_rgba], [#rgba_to_rgb],
+ [#change], [#swap], [#polygon_perimetre], [#polygon_area], [args],
+ [#gamma], [#saturation]
+ * now autodetects the .gz suffix (goes with ppm/targa/grid formats)
+ * moved the rest of pd_help/ to doc/flow_classes/
+ * automatic attribute generator for Ruby
+
+version 0.8.2 (2006.03.17):
+
+ * Ruby 1.9 required
+ * removed jmax2pd
+ * fixes of various compilation problems
+ * new object classes: [realtimer], [#export_pix], [#import_pix],
+ [#border], [#fft]
+ * beginning support for LTIlib. new object classes:
+ [lti], [lti.meanShiftSegmentation], etc.
+ * added "load" method in [gridflow]. (thanks Claude)
+ * automatic attribute generator for C++
+ * added "help" and "get" methods to *all* classes (!!!)
+ * no more "make install"
+ * not using mkmf.rb (ruby's makefile generator) anymore
+ * removed --debug-harder (use "valgrind" instead)
+
+version 0.8.1 (2006.02.20):
+
+ * [ls] now supports wildcards: ? [] * **
+ * [#color] has new method: delegate
+ * added [regsub], [memstat], [listfind], [sendgui]
+ * x11: removed methods: draw,autodraw; added: use_shm,title
+ * examples : added markov.pd, bounce.pd, doodle.pd, mechanics.pd
+ * [#pack],[#unpack] now default to 2 values
+ * new numops: clip+,clip-
+ * fix for shared memory bug in [#out x11]
+ * added [#out tk]
+ * added [#out opengl] (using GLUT, hackishly)
+ * [unix_time] behaviour changed. (see manual)
+
+version 0.8.0 (2005.06.06):
+
+ * removed support for jMax 2.5 and jMax 4.1
+ * added GCC 3.4 support
+ * added AMD64 support
+ * added support for puredata "datastructure" pointers (aka gpointer)
+ * changing the @-prefix for a #-prefix, where the old prefix still works
+ (the old syntax is backwards-compatible,
+ the new syntax is forwards-compatible)
+ * 13 object-classes rewritten from Ruby to Pd abstractions
+ * merged [@],[@!] -> [#] and added message "op"
+ * removed all one-input ops (see next...)
+ * new two-input ops: abs- sq- avg hypot sqrt rand
+ * [#fold],[#scan]: removed seed arg and right outlet; added msgs "op" and "seed"
+ * [#inner],[#convolve] : added msgs "op" and "seed"
+ * [#inner],[#convolve] : removed three first args (usually * + 0)
+ * [#inner] : removed middle inlet
+ * major changes to the bridge API (Ruby<->PureData)
+ * project "Linux Devices For Ruby" got merged in, as devices4ruby/
+ * source code cleanup
+ * internals: split Grid into Grid+GridPtr
+ * internals: GridObject no longer manages GridOutlet
+ * internals: added classes P,PtrGrid,...
+ * internals: beginning to use C++'s Standard Template Library (sometimes)
+ * [gridflow] now has "formats" msg (to list available formats)
+ * [#store] added msg "op"
+ * [#out x11] removed flag "verbose"
+ * some spaces may now be omitted in gf-lists. e.g.:
+ ( ( 2 1 ) ( ) ) ( 3 4 ( 5 ) ) can be shortened to: ((2 1) ()) (3 4 (5))
+ * new object classes:
+ [display], [#reverse], [#unpack], [#centroid2], [ls], [renamefile], [unix_time],
+ [exec], [plotter_control], [#text_to_image], [#hueshift], [rubyarray]
+ * in pd_examples added Alx's epicycloid.pd, scratch_video.pd, threshold.pd
+ and Matju's goop.pd
+ * some new/updated help files by St�hanie Brodeur & Darsha Hewitt
+
+version 0.7.7 (2004.08.24):
+
+ * GridFlow runs on MacOS 10.2 with PureData 0.37
+ * updated drag_rectangle.pd, nervous_video.pd, fire.pd, color_correction.pd
+ * updated feedback_fractal.pd (added morphing)
+ * added pd_examples/waves.pd, pd_examples/sand.pd
+ * added pd_examples/color_detect.pd (supersedes chroma_key.pd)
+ * added pd_examples/spectrogram.pd, pd_examples/photo_pianoroll.pd
+ * removed [rtmetro] (obsolete)
+ * [@store]: added methods: put_at, reassign
+ * [pingpong]: added $1
+ * [demux] renamed to [shunt] and extra optional arg added (for initial value)
+ * new object classes:
+ [range], [#mouse], [#pack], [#color], [bindpatcher],
+ [#camera], [#fade_lin], [#peephole]
+ * videodev: added method "get"
+ * [@out quartz] now works properly
+ * [@downscale_by] accepts any number of channels
+ * [@inner2] removed; instead use [@transpose] with [@inner]
+ * videodev: "transfer" message allows to change the queue's length
+ * quicktime(hw): added messages "parameter", "framerate", "size"
+ * quicktime(hw): fixed encoding bug
+ * png: fixed memory leak
+ * ./configure --lite disables float32 float64 int64
+ * ./configure --verbose prints useless details
+ * doc: rewrote installation instructions
+ * x11: fixed memory leak in resizing window
+ * on MacOS 10 [@out window] now defaults to [@out quartz]
+ * doc: added credits section
+
+version 0.7.6 (2004.03.22):
+
+ * GridFlow runs on MacOS 10.2 (only with jMax 2.5)
+ * [@out quartz] makes a native MacOS (Cocoa+Quartz) window (warning: very buggy)
+ * support for Apple QuickTime movie decoding (format/quicktimeapple.c)
+ * file suffix detector is now extensible
+ * added: Ruby interface for libUSB (base/usb.c)
+ * x11: now emits "keypress" and "keyrelease" messages
+ * [@downscale_by] now supports 4 channels (therefore [peephole] does too)
+ * fixed bugs in: x11, @draw_image, @import, @export, ...
+ * "open x11" now allows any DISPLAY spec
+ * now includes the pictures used in the examples
+ (not a separate download anymore)
+ * [@out x11 here override_redirect] (override window manager; be careful with this)
+ * [pd_netsocket] does like [netsend]/[netreceive] but two-way
+ (warning: not complete yet)
+ * support for nested lists in incoming messages
+ * new object classes:
+ [delcom_usb]: support for Delcom USB I/O controller
+ [joystick_port]: support for linux joystick drivers
+ [foreach], [rubysprintf], [listflatten]
+ [messageprepend], [messageappend], [@transpose]
+ [@fade], [@centroid]
+ jMax emulation: [listmake], [listlength], [listelement], [listsublist]
+ jMax emulation: [listprepend], [listappend], [listreverse], [oneshot]
+ jMax emulation: [inv+], [inv*]
+ * Pd main window: adding GridFlow menu, Ruby/Tcl evaluators (with command-history)
+ * added bin/jmax2pd (converts .jmax files to .pd files)
+ * ported all .jmax examples to .pd (using jmax2pd) (20 out of 20)
+ * support for variable number of inlets/outlets (only with PureData)
+
+version 0.7.5 (2003.09.28):
+
+ * type aliases: int32,i32,i; int16,i16,s; uint8,u8,b; float32,f32,f
+ * added support for float64 (alias f64, d)
+ * added support for int64 (alias i64, l)
+ * doc: added number type table
+ * @convolve: supports even-sized grids
+ * fixed bug: puredata gf clock ran way too fast
+ * rewrote the profiler subsystem (and removed bugs)
+ * @scale_by: now works with any number of channels
+ * renamed samples/ to jmax_examples/
+ * Algebraic Properties Descriptions (internal, used for accelerations)
+ * @convolve,@outer,@for,@inner,@draw_polygon: much faster
+ * quicktime: support for pluggable codecs (eg: dv, divx, rpza, ...)
+ * quicktime: fixed more bugs
+ * quicktime: major speed increase
+ * quicktime: added "colorspace" option
+ * videodev: fixed bugs
+ * videodev: removed obsolete option "noinit"
+ * videodev: added option "colormodel" (especially because of new camera drivers)
+ * sdl: added automatic resizing of window
+ * png: read support
+ * jMax bridge: more stable than ever
+ * PureData bridge: *much* more stable than ever
+ * Operator1, Operator2 renamed to Numop1, Numop2
+ * x11: now also called "window", so you can write "@out window", "open window"
+ * new object classes:
+ @draw_image: picture-in-picture, with alpha blending, etc
+ jmax4_udpsend: send to a jMax 4.0.x system via UDP
+ jmax4_udpreceive: receive from a jMax 4.0.x system via UDP
+ pd_netsend: send to a pd system via UDP
+ pd_netreceive: receive from a pd system via UDP
+ @eight: (like @four, but with eight of them ;-)
+ peephole: like [@out x11] but as inset of a patcher (jMax 2.5 only)
+ * support for upcoming jMax 4.1
+ * "open file" autodetects how to handle a file, by filename suffix
+
+version 0.7.2 (2003.04.24):
+
+ * fixed bugs in: make install, jpeg reading
+ * added support for float32
+ * added direct .jmax decoding
+ * added direct .pd encoding
+ * pd examples moved to separate directory
+ * ported some .jmax examples to .pd (automated) (8 out of 20)
+ * added motion_detect.pd
+ * new classes: demux, and more jmax emulations
+ * @in,@out: keyword "option" may be omitted
+ * configure: added --ruby-prefix
+ * adding custom C++ pre-preprocessor
+ * better type checking of message arguments (better error reporting too)
+ * @print supports 3 dimensions, and msg "base" with arg 2,8,10,16
+ * can now write loadbang-messages into an object box using the comma
+ * major cleanup of the source code
+ * added operator *>>8 (multiplication by value then division by 256)
+ * new classes: @rgb_to_yuv, @yuv_to_rgb
+ * @rotate now works with multiple axis (can work on 3D points, etc)
+
+version 0.7.1 (2003.03.24):
+
+ * fixed important bugs (crashes and such)
+ * @store,@ can now receive in inlet 1 while sending from outlet 0.
+ * @, when inlet 1 grid size is small but not 1, is now much faster.
+ * added memcpy() usage logging (see profiler_dump)
+ * added examples: drag_rectangle.jmax, plot.jmax, eclipse.jmax
+ * added example: cellular_1d.pd
+ * added classes: fork, jmax_udpsend, jmax_udpreceive
+ * added classes: @rotate, @remap_image, @type
+ * added operators: gcd,lcm (common divisors/multiples)
+ * quicktime: added encoding, added seek, fixed bugs
+ * @in inlet 1 tells frame number (int), end-of-file (bang)
+ * @in: added: set, option loop (controlling auto-rewind)
+ * updated cross_fade.jmax (much faster)
+ * @two,@three,@four allow inlet 0 bang trigger
+ * configure: simpler config for jMax 2.5
+ * PD help patches (by Uli Berthold)
+ * PD: "make install" takes care of help patches and library
+ * CVS web interface on artengine.ca (thanks to Alex)
+
+version 0.7.0 (2003.02.01):
+
+ * new classes: @cast, @join, @ravel, @grade, @perspective
+ * new grid protocol supports several number types (added uint8,int16)
+ * added number type support in most classes
+ * added "option cast" for @in in some formats
+ * can now specify number types in grid literals
+ * added some MMX support (accelerates by 0%..40%)
+ * @import: added optional 2nd arg specifying type.
+ * @import: can convert symbols to grids of their ascii codes.
+ * new [@import per_message] yields one grid per incoming message
+ * [fps]: added options "user" "system" "cpu" for selecting clock
+ * aalib: added options autodraw, draw, dump
+ * aalib: added raw input (two channels: characters, attributes)
+ * x11: added support for 256-color mode using a private colormap.
+ * x11: added "use_stripes" for alternate 256-color rendering.
+ * fixed problems with earlier versions of Ruby (like 1.6.2)
+ * new samples: polygon.jmax
+ * videodev_effects.jmax: added sort-effects, centre-of-gravity-tracking
+ * the time profiler is back to working !!!
+ * @scale_by, @downscale_by: added right inlet, for configuration
+ * @store is a bit faster
+ * ppm: accelerated by large amount
+ * @outer,@inner,@inner2,@fold accelerated by obscene amount
+
+version 0.6.5 (2003.01.10):
+
+ * can now encode Targa-24, Targa-32, JPEG-24
+ * can now output through aalib (ascii art library)
+ * fixed problems with libruby.a
+ * tested with the new version of Ruby (1.8)
+ * new classes:
+ fps, @rgb_to_greyscale, @greyscale_to_rgb, @solarize,
+ @complex_sq, @export_symbol, @draw_polygon,
+ @apply_colormap_channelwise
+ * new class FPatcher, a ruby patcher/abstraction system
+ * @scale_to,@contrast,@spread,@posterize now available in
+ PureData & Ruby; they also now accept arguments.
+ * [@scale_to]: back to working; inlets "height" and "width" merged
+ * [route grid_begin] replaced by [route grid]
+ * [route grid_end] replaced by [@finished]
+ * Most everything is 10-50% faster
+ * changes in the internal transmission of grids
+ * new two-input operators: div, swapdiv, put, ignore
+ * compilable on MacOS 10
+
+version 0.6.4 (2002.12.23):
+
+ * can now decode JPEG (using libjpeg.so)
+ * many bugs fixed (especially in file formats)
+ * operators: log* added; tanh renamed to tanh*
+ * @two,@three,@four are no longer specific to the jMax side
+ * format grid: option headerless for reading any kind of file
+ * format grid: option headerful (revert to actual .grid format mode)
+ * fixed problems with GNU C++ version 3
+ * format ppm: accelerated writing
+ * format modifier gzfile: gzip support also works with [@out]
+ * format x11: the "here" specifier is now optional
+ * added @checkers
+ * [@scale_by {y x}] for different y,x scale factors
+ * [@in blah blah] means "open blah blah" -> [@in] (and same with @out)
+ * added @downscale_by with or without smoothing
+ * format targa: can now decode 32 bit RGBA
+ * @layer: combines RGBA foreground with RGB background, yielding RGB.
+ * format grid options: endian big, endian little, endian same
+ * formats ppm,grid: use 'option rewind' to overwrite same file
+ (by default, rewind is no longer done after each frame)
+ ('option rewind' also rewinds on reading)
+
+version 0.6.3 (2002.12.06):
+
+ * removing the custom leak detector ("Valgrind" program used instead)
+ * removed all (?) memory leaks
+ * videodev: new options: frequency, transfer [read|mmap], noinit
+ * profiler summary code rewritten
+ * profiler wrapper code removed
+ * x11: option setcursor <0-63>, option hidecursor
+ * x11: outlet 0 tells cursor position / button state
+ * more C++ification of the code
+ * many bugs fixed (especially crashes)
+
+version 0.6.2 (2002.09.17):
+
+ * jMax objects written in (or using) Ruby now can work in PureData too.
+ * new format: SDL (portable output to window)
+ * can now compile bridges without libruby.so
+ * changed grid-protocol: added direct object-to-object streaming.
+ * bug: gridflow's clock tick back to a decent value (sorry)
+ * all inlets supporting grids also convert int/float as 0-D grids
+ * @fold and @scan now accept grids in right inlet and constructor
+ * @convolve is 2-3 times faster
+ * %,swap% are now called rem,swaprem; new %,swap% is the true modulo.
+ * @for now allows vectorial from/to/step values
+ * @identity_transform removed, change to eg: [@for{0 0}{240 320}{1 1}]
+ * PD users: grid literals are written like:
+ [@for ( 0 0 ) ( 240 320 ) ( 1 1 )] with all those spaces
+ * @inner,@inner2,@convolve can take right inlet grid as 4th argument
+ * re-enabled and improved the memory leak detector (use --debug)
+ * fixed many bugs and leaks
+ * fixed bugs in @store
+ * added sample: zoom.pd
+
+version 0.6.1 (2002.08.29):
+
+ * now compiling GridFlow as C++ (replacing C)
+ * now you can use Ruby 1.7, which is faster
+ note: if you do so, make sure your version is dated 2002
+ * new objects: rubyprint, printargs, @print, @scan, @inner
+ * new format: apple quicktime (using libquicktime.so)
+ * @in gzip support (example: "open ppm gzfile teapot.ppm.gz")
+ also works with targa and grid
+ * BitPacking now supports 1 to 4 channels instead of just 3
+ * using mkmf.rb makefile generation; some MSWindows support thru Cygwin
+ * added geiger counter simulator in [rtmetro]
+ * libruby.so is only needed when using GridFlow through jMax
+ * now can do grid literals in @ and @outer, like [@ + {0 1}]
+ * syntax of @redim,@import changed from [@redim 2 3] to [@redim {2 3}]
+ * "3 3 # 1 0 0 1" into inlet does automatic @redim, for all objects
+ * grid literals accept {2 3 # 1 4 5} as an implicit [@redim {2 3}]
+ * objects rewritten in Ruby language: @in, @out
+ * updated samples, templates, documentation.
+ * fixed bugs
+
+version 0.6.0 (2002.07.31):
+
+ * THIS IS AN EXPERIMENTAL BRANCH (VERY BUGGY)
+ REAL PROJECTS SHOULD USE VERSION 0.5.0 INSTEAD
+ * GridFlow rewritten as a plugin for Ruby instead of jMax.
+ * GridFlow now includes a Ruby-for-jMax bridge.
+ * you need Ruby 1.6.6 (including libruby.so) or compatible
+ * you don't need GNU Bash anymore (configurator is now a Ruby program)
+ * format handlers for .ppm, .tga, .grid rewritten in Ruby
+ * merged all Makefiles together, etc.
+ * sources are in base/ and format/ instead of c/src/
+ * many bugs removed, many bugs added.
+ * will read ~/.gridflow_startup if it exists
+
+version 0.5.0 (2002.06.08):
+
+ * big changes to the internals (especially use of macros)
+ * can compile without X11; added --no-x11 in ./configure
+ * removed support for jMax 2.4
+ * auto-detects jMax 2.5 and jMax 3.0
+ * @inner renamed to @inner2 (new, proper @inner coming soon)
+ * faster unary operators
+ * added unary operator: sq (faster squaring)
+ * further separation of GridFlow from jMax
+ * major format API changes (added Stream class)
+ * format "grid" now supports 8 bits per value
+ * support for HeroineWarrior's LibMPEG3 (reading + seeking)
+ * libmpeg.so (Greg Ward's) now also looked up as "libwardsmpeg.so"
+ * added objects: rtmetro, pingpong
+ * Moved CVS repository from Hostname.2y.net to Artengine.ca
+ * updated samples
+
+version 0.4.1 (2002.01.02):
+
+ * cvs repository now has public access
+ * now can run configure without jmax/fts being present
+ * standalone version now works on Silicon Graphics and Corel Netwinder.
+ * MPEG format readonly (single file at a time; mpeg video layer only)
+ * grid TCP: non-blocking read
+ * fixed all known memory leaks
+ * X11 Shared Memory now disables itself properly on remote display
+ * updated help files
+ * updated help screenshots in the manual
+ * fixed profiler bugs
+ * fts emulation moved to c/src/ and tests moved to tests/
+
+version 0.4.0 (2001.11.28):
+
+ * package name changed from "video4jmax" to "gridflow"
+ * documentation *rewritten*, more precise, more structured
+ * documentation format is now XML (includes HTMLized version)
+ * can now compile without jmax/fts (if you need quicker testing...)
+ * added format "grid" for storing any kind of grid to disk.
+ * added TCP client/server socket support (with format "grid" only)
+ * added (timewise) profiler
+ * @convolve now takes up to three arguments
+ * Format API changes again
+ * "connect" merged into "open"
+ * "size" merged into "option"
+ * @video_out merged into @out
+ * format videodev can now do full framerate (instead of just half)
+ * added X11 Shared Memory support (faster image transfer locally)
+ * added @scale_by for quick scaling by integer factors.
+ * @identity_transform, @scale_to are much faster.
+ * many other accelerations
+
+version 0.3.0 (2001.11.04):
+
+ * reworked File Format API
+ * grid objects now all accept lists of integers (auto-convert to 1D grid)
+ * many accelerations (incl large speedup on chains of binary operations)
+ * transformed @video_out (X11) into a "File Format" (really) and:
+ * allows multiple displays
+ * auto-resizing window
+ * can set output as wallpaper
+ * can read from the screen (screenshot)
+ * @video_out now a backward-compatibility wrapper
+ * format videodev now uses double buffer mmap (somewhat faster)
+ * @video_in_file, @video_out_file renamed to @in, @out (with aliases)
+ * new objects:
+ @convolve, @inner, @for
+ * more samples: Fire, Ripple, Game of Life, Chroma Key, Convolve, Saturation
+ * much improved samples: Color Correction, Linear Transform.
+ * use [@store uint8] for low-ram storage of values 0-255.
+ * videodev: added option norm 0=pal 1=ntsc 2=secam 3=auto
+
+version 0.2.2 (2001.08.15):
+
+ * @video_out auto-updates on X11 ExposeEvent
+ * updated documentation and help
+ * fixed installation/config of help and summary
+ * split BitPacking module from @video_out
+ * added support for BTTV input (that is, using mmap() command)
+ * new videodev options: channel,tuner,contrast,hue,etc.
+ * now with 30 binary operators, and 3 unary operators
+ * added many new samples
+ * new objects:
+ @!, @fold, @outer, @dim, @redim,
+ @posterize, @contrast, @two, @three,
+ @identity_transform, @scale_to, @spread
+
+version 0.2.1 (2001.08.01):
+
+ * added private CVS repository on hostname.2y.net
+ * added configuration script (detects video4linux 1.x)
+ * added documentation in HTML format
+ * added File Format API
+ * format "ppm": PPM P6 RGB24 support read-write
+ * format "targa": Targa RGB24 support read-only
+ * format "videodev": Video4linux read (using read() command only)
+ * @store no longer slowing down its downstream
+ * many other accelerations
+ * Tuple changed to Dim; Index removed
+ * Grid element type is typedef Number
+ * @ supports grids in right inlet
+ * now there are 20 binary operators
+
+version 0.2.0 (2001.05.05):
+
+ * package name changed from "video" to "video4jmax"
+ * new kind of post() cancels repetitive log entries
+ * major modifications to existing objects
+ * new "grid transmission system"
+ (Tuple,Index,GridInlet,GridOutlet,GridObject)
+ * vout -> @video_out
+ * vin_file -> @video_in_file
+ * vout_file -> @video_out_file
+ * added @import, @export
+ * added @, @store
+
+version 0.1.1 (2001.04.03):
+
+ * removed vout's grab
+ * vout width and height parameters swapped
+ * vout_file class is mostly like vout but writes to a file in PPM format.
+
+version 0.1.0 (2001.03.14):
+
+ * fixed the bits_per_pixel bug
+ * merged in some other variations on the main sample
+ * included Christian's makefiles for jmax 2.5
+
+version 0.0.7 (2001.03.08):
+
+ * vout should support most types of RGB visuals now
+ * autodraw now works: 0=none; 1=page; 2=line; 3=pixel
+ * less global variables
+ * putting all of this under the GPL
+
+version 0.0.5 (2001.03.05):
+
+ * vout class, two params: width, height; 24-bit BGR only; refresh by
+finishing scanline or sending bang; "grab" (hack); "reset" for resetting
+the pixel pointer.
+
+
+
+a very short history of GridFlow:
+
+video4jmax 0.1 (mar 2001): sending int messages to a window in jMax
+video4jmax 0.2 (may 2001): grids
+GridFlow 0.4 (nov 2001): xml manual; can compile without jMax
+GridFlow 0.5 (jun 2002): mpeg; cvs goes to artengine.ca
+GridFlow 0.6 (aug 2002): ruby; c++; literals
+GridFlow 0.6.2 - 0.6.5 : pd; jpeg; big speedups; 1 grid = 1 message
+GridFlow 0.7.0 (feb 2003): number types; mmx; other big speedups
+GridFlow 0.7.2 - 0.7.5 : pd support gets stable; float grids; @draw_image; source_filter.rb
+GridFlow 0.7.6 to 7 (2004): permanently switching from jmax to pd; #pack, #color, #camera
+GridFlow 0.8 (2005): attributes; # prefix
+GridFlow 0.8.1 to 4 (2006): LTI; FFT; complex numbers; GEM pix compatibility
+GridFlow 0.9.0 (2008): removing Ruby, removing LTI, adding OpenCV
+GridFlow 2.0 : ...
diff --git a/externals/gridflow/LICENSE b/externals/gridflow/LICENSE
new file mode 100644
index 00000000..a52b16e4
--- /dev/null
+++ b/externals/gridflow/LICENSE
@@ -0,0 +1,341 @@
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/externals/gridflow/Makefile b/externals/gridflow/Makefile
new file mode 100644
index 00000000..565685ce
--- /dev/null
+++ b/externals/gridflow/Makefile
@@ -0,0 +1,132 @@
+#!/usr/bin/make
+# $Id: Makefile 4724 2009-11-03 20:57:34Z matju $
+
+include config.make
+COMMON_DEPS = config.make Makefile src/source_filter.rb
+COMMON_DEPS2 = $(COMMON_DEPS) src/gridflow.hxx.fcs
+RUBY = ruby
+
+#--------#
+
+SHELL = /bin/sh
+LDSHARED = $(CXX) $(PDBUNDLEFLAGS)
+RM = rm -f
+CFLAGS += -Wall -Wno-unused -Wunused-variable -g -fPIC -I.
+
+# LDFLAGS += ../gem-cvs/Gem/Gem.pd_linux
+
+LDSOFLAGS += -lm $(LIBS)
+OBJS2 = src/gridflow.o src/grid.o src/classes1.o src/classes2.o src/number.1.o src/number.2.o src/number.3.o src/number.4.o src/formats.o
+SYSTEM = $(shell uname -s | sed -e 's/^MINGW.*/NT/')
+FILT = $(RUBY) -w src/source_filter.rb
+ifeq ($(OS),darwin)
+ CFLAGS += -mmacosx-version-min=10.4
+ LDSOFLAGS += -headerpad_max_install_names
+ PDSUF = .pd_darwin
+ PDBUNDLEFLAGS = -bundle -flat_namespace -undefined suppress
+else
+ ifeq ($(OS),nt)
+ PDSUF = .dll
+ PDBUNDLEFLAGS = -shared
+ else
+ PDSUF = .pd_linux
+ PDBUNDLEFLAGS = -shared -rdynamic
+ endif
+endif
+PD_LIB = gridflow$(PDSUF)
+
+ifeq ($(CPLUS_INCLUDE_PATH),)
+ SNAFU =
+else
+ SNAFU = $(subst :, -I,:$(CPLUS_INCLUDE_PATH))
+endif
+
+all:: $(PD_LIB) aliases
+
+.SUFFIXES:
+
+CFLAGS += -DPDSUF=\"$(PDSUF)\"
+
+%.hxx.fcs: %.hxx $(COMMON_DEPS)
+ $(FILT) $< $@
+%.cxx.fcs: %.cxx $(COMMON_DEPS2)
+ $(FILT) $< $@
+%.c.fcs: %.c $(COMMON_DEPS2)
+ $(FILT) $< $@
+%.m.fcs: %.m $(COMMON_DEPS2)
+ $(FILT) $< $@
+%.o: %.c.fcs $(COMMON_DEPS2)
+ $(CXX) -xc++ $(CFLAGS) -c $< -o $@
+%.o: %.cxx.fcs $(COMMON_DEPS2)
+ $(CXX) -xc++ $(CFLAGS) -c $< -o $@
+%.1.o: %.cxx.fcs $(COMMON_DEPS2)
+ $(CXX) -xc++ $(CFLAGS) -DPASS1 -c $< -o $@
+%.2.o: %.cxx.fcs $(COMMON_DEPS2)
+ $(CXX) -xc++ $(CFLAGS) -DPASS2 -c $< -o $@
+%.3.o: %.cxx.fcs $(COMMON_DEPS2)
+ $(CXX) -xc++ $(CFLAGS) -DPASS3 -c $< -o $@
+%.4.o: %.cxx.fcs $(COMMON_DEPS2)
+ $(CXX) -xc++ $(CFLAGS) -DPASS4 -c $< -o $@
+%.o: %.m.fcs $(COMMON_DEPS2)
+ $(CXX) -xc++ $(CFLAGS) $(SNAFU) -xobjective-c++ -c $< -o $@
+
+%.s: %.cxx.fcs $(COMMON_DEPS2)
+ $(CXX) $(CFLAGS) -S $< -o $@
+%.e: %.cxx.fcs $(COMMON_DEPS2)
+ $(CXX) $(CFLAGS) -E $< -o $@
+
+.PRECIOUS: %.hxx.fcs %.cxx.fcs %.h.fcs %.c.fcs %.m.fcs
+
+src/mmx.asm src/mmx_loader.cxx: src/mmx.rb
+ $(RUBY) src/mmx.rb src/mmx.asm src/mmx_loader.cxx
+src/mmx.o: src/mmx.asm
+ nasm -f elf src/mmx.asm -o src/mmx.o
+
+$(PD_LIB): $(OBJS2) $(OBJS) $(H) $(COMMON_DEPS)
+ $(CXX) -DPDSUF=\"$(PDSUF)\" $(LDSOFLAGS) $(CFLAGS) $(PDBUNDLEFLAGS) $(LIBPATH) -xnone $(OBJS2) $(OBJS) -o $@
+
+beep::
+ @for z in 1 2 3 4 5; do echo -ne '\a'; sleep 1; done
+
+install::
+ @echo -e "\033[0;1;33;41m"
+ @echo -e "1. move this folder to lib/pd/extra or add the folder to -path"
+ @echo -e "2. delete the old gridflow.pd_linux if you have one (from years ago)"
+ @echo -e "3. and don't do \"make install\" anymore\033[0m\n"
+
+DEPRECATED = motion_detection color mouse fade scale_to \
+ apply_colormap_channelwise checkers contrast posterize ravel remap_image solarize spread \
+ rgb_to_greyscale greyscale_to_rgb rgb_to_yuv yuv_to_rgb rotate in out
+
+aliases:: deprecated/@fade.pd deprecated/@!.pd doc/flow_classes/@complex_sq-help.pd \
+ doc/flow_classes/inv+-help.pd abstractions/inv+.pd \
+ doc/flow_classes/inv\*-help.pd abstractions/inv\*.pd
+
+deprecated/@fade.pd: abstractions/\#fade.pd
+ for z in $(DEPRECATED); do cp abstractions/\#$$z.pd deprecated/\@$$z.pd; done
+
+deprecated/@!.pd: deprecated/0x40!.pd
+ for z in complex_sq convolve fold inner \! scan; do cp deprecated/0x40$$z.pd deprecated/@$$z.pd; done
+
+doc/flow_classes/@complex_sq-help.pd: doc/flow_classes/0x40complex_sq-help.pd
+ cp doc/flow_classes/0x40complex_sq-help.pd doc/flow_classes/@complex_sq-help.pd
+
+doc/flow_classes/inv+-help.pd: doc/flow_classes/inv0x2b-help.pd
+ cp doc/flow_classes/inv0x2b-help.pd doc/flow_classes/inv+-help.pd
+
+doc/flow_classes/inv\*-help.pd: doc/flow_classes/inv0x2a-help.pd
+ cp doc/flow_classes/inv0x2a-help.pd doc/flow_classes/inv\*-help.pd
+
+abstractions/inv+.pd: abstractions/inv0x2b.pd
+ cp abstractions/inv0x2b.pd abstractions/inv+.pd
+
+abstractions/inv\*.pd: abstractions/inv0x2a.pd
+ cp abstractions/inv0x2a.pd abstractions/inv\*.pd
+
+clean::
+ @-$(RM) gridflow.pd_linux *.o */*.o *.so
+ rm -f $(OBJS2) $(OBJS)src/*.fcs format/*.fcs $(patsubst %,deprecated/@%.pd,$(DEPRECATED))
+
+distclean:: clean
+ rm -f config.make config.log config.h
+ rm -rf tmp
diff --git a/externals/gridflow/README b/externals/gridflow/README
new file mode 100644
index 00000000..a1b61aff
--- /dev/null
+++ b/externals/gridflow/README
@@ -0,0 +1,131 @@
+,-o----o----o----o-.
+| GridFlow 0.9.6 |
+`-o--------------o-'
+ |
+.-o--------------------------------------------------------------
+| Hardware and Software you Probably Need
+
+Computer/Processor: GridFlow is mainly made on PC. This includes AMD K6/K7/K8 (Athlon/Opteron/etc), Intel P2/P3/P4 and other Pentiums, Intel CoreDuo, etc.; the absolute minimum is 386. However, it has also been built recently for Macintosh PowerPC (G3/G4/G5) recently.
+
+Operating System: GridFlow is mainly made on Ubuntu. We have also used Debian, SuSE, Mandrake, OSX. Microsoft Windows is not supported, but if you do want to try to add support for that, try CygWin and/or MinGW.
+
+Required Software:
+ Ruby 1.8 or 1.9
+ PureData 0.40 or later, or DesireData
+ GNU C++ Compiler (g++) version 3.x or 4.x
+ GNU Make
+ SVN
+ Developer CD (XCODE) (if using OSX)
+ FINK (if using OSX)
+
+Multimedia Components (optional):
+ libSDL (Simple Directmedia Layer)
+ libjpeg
+ libpng
+ libmpeg3 (.mpg reader, HeroineWarrior's)
+ libquicktime (.mov reader/writer, Burkhard Plaum's or HeroineWarrior's)
+ libmpeg (.mpg reader, Greg Ward's, old)
+ Apple QuickTime (.mov reader/writer and camera interface)
+ Ascii Art Library (aalib)
+ PCI video digitizer card (and Video4linux 1 driver)
+ USB camera (and Video4linux 1 driver)
+ FFTW3
+ OpenCV
+ NetPBM
+ OpenGL
+ Apple X11 (for 10.3: http://www.apple.com/support/downloads/x11formacosx.html
+ for 10.4: http://www.apple.com/support/downloads/x11update2006113.html )
+
+.-o--------------------------------------------------------------
+| Downloading from SVN
+
+The SVN has the absolute latest version of GridFlow, but it's not guaranteed to be working, whereas
+the actual releases are more tested.
+However you may have various reasons to use the SVN edition, so here's how:
+Make sure you have the svn program installed.
+
+cd pd/extra
+svn checkout http://gridflow.ca/svn/trunk
+mv trunk gridflow
+And the subsequent times, you only do this:
+cd pd/extra/gridflow
+svn update
+
+.-o--------------------------------------------------------------
+| Installation instructions (incl. compilation)
+ Install Ruby.
+ Download GridFlow from the website and uncompress it, or get it from the SVN server.
+ Run ./configure from the gridflow directory. Make sure it detects all the components
+ you want to use with GridFlow. In MacOS you would normally use FINK to install those extra components: ruby libjpeg libjpeg-shlibs libpng-shlibs libpng3 libpng3-shlibs libmpeg libmpeg-shlibs
+
+ In Debian (lenny) or Ubuntu (8.04), do
+ apt-get install libjpeg62-dev libpng12-dev libmpeg3-dev libquicktime-dev fftw3-dev \
+ libaa1-dev libsdl1.2-dev libnetpbm10-dev libx11-dev libxt-dev g++ \
+ ruby nasm libglib1.2-dev
+
+ At least with Ubuntu you can add those, but haven't tried with Debian yet:
+ apt-get install libcv-dev libdc1394-13-dev
+
+
+ Note: you may have to set CPLUS_INCLUDE_PATH and C_INCLUDE_PATH
+to indicate where to find *.h files, and you
+may have to set both LIBRARY_PATH and LD_LIBRARY_PATH to indicate where to find
+*.so or *.a or *.dylib or *.bundle or *.dll or *.lib files.
+ Note: you can do ./configure --help to get a list of supported
+options. You can use them to ignore the presence of troublesome libraries
+and select debugging level. With --use-compiler you should use a version of g++, not
+directly a version of gcc, else you get undefined symbol problems. Some versions of gcc/g++
+are troublesome.
+ Run make to produce the executables gridflow.so and gridflow.pd_linux or similar
+ Loading GridFlow:
+ PureData : With a text editor, modify or create ~/.pdrc and write -lib gridflow.
+ DesireData : In "Server Preferences", add gridflow to the list of libraries.
+Note that on MacOS the dot-files are invisible in the Finder but you do cd ~/Desktop; ln -s ../.pdrc "PureData Configuration" to make an alias on the Desktop.
+Note also that on Windows the dot-files are even more trouble.
+
+.-o--------------------------------------------------------------
+| Other Tips
+
+ you just did a SVN update and now the program does not compile, or
+crashes, or changes didn't go through.
+ When some kinds of changes have happened, you may have to rerun the configure
+ program before redoing make. If you had previously reconfigured with specific options,
+ don't forget to use them again in this case.
+ Maybe matju forgot to upload part of an important change. Tell him.
+ PureData Crashing:
+ run start Pd from within the debugger using gdb $(which pd) then run then cause the crash.
+ In GDB, after a crash, you can use the where to find out what Pd was doing at the moment
+ of the crash. If instead Pd is frozen, you can force it to crash using Ctrl+C in the terminal.
+ To quit GDB use the quit command.
+
+.-o--------------------------------------------------------------
+| Directory layout
+
+ ./abstractions ..... Pd object classes written in Pd
+ ./src ............. object classes written in C++
+ ./bin .............. programs startable as applications
+ ./bundled .......... files from other packages, bundled here for convenience
+ ./examples ......... more complex Pd programs showing off more practical uses.
+ ./doc .............. complete documentation in HTML, with XML source
+ ./doc/flow_classes . help files (.pd)
+ ./doc/tutorials .... tutorials
+ ./examples ......... more complex Pd programs showing off more practical uses.
+ (this will replace ./pd_examples in the future).
+ ./images ........... sample images used by ./examples, ./doc
+ ./tests ............ will contain Pd programs that test GridFlow itself.
+ (see also: the PureUnity project)
+
+.-o--------------------------------------------------------------
+| License Info
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ This program is free software; you can redistribute it and/or
+ Modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ See file COPYING for further informations on licensing terms.
diff --git a/externals/gridflow/TODO b/externals/gridflow/TODO
new file mode 100644
index 00000000..d220d98d
--- /dev/null
+++ b/externals/gridflow/TODO
@@ -0,0 +1,305 @@
+$Id: TODO 4755 2009-11-05 04:24:29Z matju $
+
+0.9.6
+[ ] go back in all help files and fill in whatever is missing
+[ ] quicktime PNG encoding: does it work?
+[ ] add missing to index.pd
+[ ] about.pd: link from help menu; add link to website, mention irc, etc.
+
+unsorted
+[ ] [doc_cc] [doc_ii] [doc_oo]'s $1 doesn't really accept symbol now.
+[ ] remove last outlet of [#] when it's irrelevant, and don't have a $2 in that case, and don't check type of r in that case.
+[ ] can't handle [args] that come out as grid literals and have to become setter messages.
+[ ] [pack] trigger_by (choose which inlets are hot)
+[ ] GF objects don't have default methods like bang and list, unlike pd itself.
+[ ] bug in line rendering causes one pixel to be off by one pixel at the end of many linesegments. ([#draw_polygon] with hpgl)
+[ ] put_at is lacking some checks for number-of-dims, causing segfault.
+[ ] strange problem with [#import] when input size doesn't match output size and object is recreated
+[ ] get rid of doc/stuff.txt and doc/install.html
+[ ] fix [nbx]<->[hsl] relationship in [#camera]
+[ ] #line_to_polygon is buggy
+[ ] #draw_polygon init_lines() not sufficiently called
+[ ] conversion from float to int is inconsistent: when to round and when to trunc?
+[ ] with pwc, 720x480 crashes
+[ ] WILL NOT go through all the new [gf/...] to "clean things up" now; will not make help files of them right now either.
+[ ] what to do with [#motion_detection] ?
+[ ] [#saturation] is a linear colorspace transform: therefore it could be accelerated just like [#hueshift] could.
+[ ] try [# C.sq-] on chroma
+
+0.9.7
+[ ] listflatten-help.pd : [display] bug
+[ ] GridFlow Index dans toutes les fenêtres
+[ ] <mescalinum> matju: anyway, in #-help.pd, object [doc/numop] is still error
+[ ] [#reinterval] takes no argument
+[ ] [#draw_rect] doesn't support op, etc... what do we do about attributes?
+[ ] [doc_m] boxes are too big
+[ ] [#make_arrow] (fix and help)
+[ ] [#interval_overlap]
+
+Later
+[ ] [#in libv4l] and/or [#in unicap] and/or [#in videojack]
+<matju> oof -> error: [#io.quicktime in gf_spirals_and_moire.avi]: unknown colorspace 'yuv' (supported: rgb, rgba, bgr, bgrn, yuv, yuva)
+[ ] doc attributes: [doc_a] [doc_aa] ?
+[ ] [doc_ii] links to [doc_cc]
+[ ] regularise Grid[a,b] vs Grid Dim[a,b] vs Dim[a,b] vs a grid of size (a,b) or (a b)... big mess
+[ ] distinguish messages vs atoms in this manual
+ e.g. [doc_aa] would contain something like [doc_m]
+ but wouldn't have [doc_m] as a subnode.
+[ ] [print], [gf.print] bugs
+[ ] [gf/canvas_loadbang]: is it buggy? (see [doc_h] double-bang problem)
+[ ] probably a problem with loadbang: when making a new helppatch, it's better to save it and reload immediately,
+ to prevent a lot of redraw bugs.
+[ ] support "get" in abstractions... automatically, through [args] ?
+[ ] bugs/bugfixes from roman, claude, federico, etc
+[ ] [fps]: translate into pd: "publish if fps>0.001" (to remove outliers)
+[ ] reimplement negative indices in [listelement] and [listsublist]
+[ ] fix SDL modifiers
+[ ] fix quoting in [display]
+[ ] [args] have to be connected to a [t a] in common with first inlet... (BUT: this has an impact on float vs list distinction)
+ (why not make this automatic, by making [args] contact whichever inlet is first?)
+[ ] [#to_pix] newimage=0 to save CPU time and/or bus time?
+[ ] what to do with GridFlow version numbering?
+[ ] use [args] everywhere it should be used: e.g. [#background_model] but also many more
+[ ] reintroduce set_mode(0)
+[ ] [#fold] is slowwww
+[ ] [route3] is like [route] but doesn't trim.
+[ ] #out x11 doesn't accept 0-sized grids
+[ ] #inner doesnt support seeds of size>1, and isn't vecop-compatible, and ...
+[ ] #inner could optimise permutation matrices?
+[ ] claude wants http://en.wikipedia.org/wiki/Graham_scan
+[ ] make [#draw_points] [#edit_polygon]
+[ ] distinguish between C++ types Grid* and GridFlow*
+[ ] add [#out png]
+[ ] Accumulation of Background Statistics
+[ ] compenser pour les ajustements progressifs ou soudains de luminosité
+[ ] regular dc1394 options
+[ ] irregular dc1394 options: white_shading, white_balance; trigger_mode? trigger, trigger_delay
+
+OpenCV
+[ ] cvOpticalFlow
+[ ] [cv.split]
+[ ] cvEstimateRigidTransform
+[ ] cvApproxPoly pour un seul poly à la fois
+[ ] cvMeanShift, cvCamShift (?)
+ cvCamShift s'utilise presque comme MeanShift, sauf que ça requiert un autre type non-grid.
+ Celui-ci peut être représenté comme une grid de 5 éléments pour faire plus facile
+ (contrairement à cvHistogram, qui contient une grid ND mais a besoin de quelques fields de plus que ça).
+[ ] cvCalcBackProject (?)
+[ ] cvCalcHist, cvCreateHist.
+[ ] SnakeImage (what is the concept of 'energy', squared luminosity?)
+ J'aurais supposé que oui, mais c'est juste trois mesures reliées à trois forces qui "shapent" la courbe:
+ espacement égal des points, réduction des angles, et correspondance avec l'image même (qui doit normalement
+ être un edge-detect d'une image plus vieille).
+[ ] on doit aussi commencer à rajouter des types non-grid. Le premier sera CvHistogram et est requis pour tous les objets dont le nom contient "Hist".
+
+Common Video Framework
+[ ] a common library for all video IO (cameras, files, web), which is the project of Thomas H and Johannes.
+[ ] a six-way converter for GEM/PDP/GridFlow. There are already converters between GEM and PDP and between GEM and GridFlow
+ but there is none between PDP and GridFlow and then some things could be easier to install and run in a cross-platform way.
+[ ] a way to make GEM/PDP/GF conversions *implicitly* instead of having objects for that.
+[ ] threads for video?
+[ ] GEM geos vs 3DP: how do they compare?
+[ ] is there anything else deserving to be unified between the video plugins?
+[ ] look at camorama
+[ ] Generic Image Library: http://opensource.adobe.com/gil/html/giltutorial.html
+
+malloc alignment = 4 mod 8 (en utilisant valgrind)
+
+ClaudiusMaximus matju: feature request: [#store4], behaves like store but accepts grids
+of floats as coordinates and interpolate using 4-point interpolation, eg, right inlet ->
+(3 3 f # 0 0 0 1 1 1 2 4 8), left inlet -> (1 # 0.5) outputs (0.5 0.5 0.5)
+(or whatever the interpolation would really be), left inlet (2 # 1.5 1.5) outputs (3)
+
+http://oprofile.sourceforge.net/about/
+also: qprofile, amd profiler, opreport -cl --demangle=smart
+
+[ ] OpenCL
+[ ] look at the endian stuff that is most probably wrong... if I can run anything on a G4 or G5.
+[ ] -ftree-vectorizer-verbose
+[ ] try removing or modifying -falign on PPC/OSX
+[ ] encoding of quicktime RGBA (PNG) does not work at all!
+[ ] make example on separable convkernels
+[ ] add concepts of hot inlet and conf inlet at the code level
+[ ] [display] should use clocks to update tk less often
+[ ] deprecation warnings
+[ ] Add a video latency patch (in examples)
+[ ] Numop: warn on misalignment
+[ ] remove GridInlet* ?
+[ ] configure chokes if GCC3 doesn't have the C++ plugin
+[ ] [#import~] [#export~]
+[ ] [#expr]
+[ ] [#line]? [#pipe]? [#delay]?
+[ ] rewrite [#rgb_to_rgba] [#rgba_to_rgb] in C++ if I'm not going to rework [#inner] soon enough.
+[ ] #: option swap
+[ ] consider including [mysql] [renamefile] [ls] [shell]
+[ ] re-enable int64,float64
+[ ] add #matrix_solve, #slice
+[ ] Copy-on-Write (COW)
+[ ] internal grid protocol redesigned
+[ ] look into -ftree-vectorize
+[ ] look at Tetra Piccolo capture cards, as well as ImpactVCB (Hauppauge)
+[ ] some proper equivalent of [rubysprintf]... see also: [gf.error]
+[ ] small leak remaining in x11? may have to do with non-use of XDestroyImage?
+[ ] is [@convolve] actually cross-convolution? that is, convolves with a mirror image of the convolution matrix.
+[ ] #import with zero size crashes?
+[ ] numop ** can freeze GF
+[ ] osx: [#store] crash instead of raising
+[ ] MMX computations may be done misaligned, which may be bad.
+[ ] when file not found, mpeg error messages are wrong, they say the filename is "".
+[ ] osx: error: shmget failed (cannot allocate memory) in X11, for regular pictures
+[ ] "unsupported codec" bogus errors.
+[ ] format/mpeg3.c,quicktime.c might cause lockup on exit
+[ ] some seeds aren't typechecked
+[ ] GRID_FINISH triggered while backstore ???
+[ ] what would be a way to make GF work well with Pd's idea of a list?
+[ ] write unit tests about required functionality
+[ ] write unit tests about error checking
+[ ] make system to ensure everything is working before a release.
+[ ] it's possible to crash by sending data in two inlets of a same object at once
+
+Installation
+[ ] cross-compile: http://www.libsdl.org/extras/win32/cross/ http://rooster.stanford.edu/~ben/linux/cross.php
+
+Documentation
+[ ] document how to report bugs, basic troubleshooting
+[ ] document our distribution of the archives
+[ ] ascii conventions: [foo] vs "foo", etc.
+[ ] document internals
+[ ] describe indexmap in doc
+[ ] architecture: class->type/shape->use->role
+[ ] benchmarks (especially: simple video i/o)
+[ ] mimic [pdp_help_input] [pdp_help_output]: they are convenient
+
+Architecture
+[ ] reentrancy of objects (to allow true recursion)
+[ ] inlet-attrs (attrs associated to inlets) (see "same as arg" in help)
+[ ] eliminate the Dim class, replacing by Grid itself (?).
+[ ] pull mode (functional-style)
+[ ] bidirectional messages (constraint/relational-style)
+[ ] send-reply messages (imperative-style)
+[ ] add reflection (#global:classes, #global:methods, ...)
+[ ] transmitting grids by diffs?
+[ ] dispatch on _#{i}_-named methods (any selector one inlet)
+[ ] generalize the backstore
+[ ] Outlet#buffer should harmonise with the lcm of its corresponding Inlet#factor's.
+[ ] lazy grids: Grid#operator T* makes sure all the grid is received
+ and Grid#range(int start, int n, T bogus) makes sure the
+ specified part of the grid is received.
+[ ] accounting: grids messages packets numbers bytes copybytes
+[ ] memory profiling
+[ ] add a "query" class for debugging other objects? (would be able to extract extra info from each object/class)
+[ ] add a GridFlow::LaterException or something (which tells to retry later with the same packet because another
+ grid reception is not completed yet.)
+[ ] interpret nested lists as n-dimensional.
+[ ] MMX memcpy() ?
+[ ] MMX _runtime_ autodetection
+[ ] find a good profiler to use with GridFlow.
+
+Computation Objects
+[ ] #counter (similar to #for)
+[ ] zero option in #convolve (?)
+[ ] #conv (simpler #convolve) should allow n-D convolution
+[ ] #convolve rewritten as combination of #conv+#border ?
+[ ] #store: option zero (?)
+[ ] #import~, #export~
+[ ] #fold, #scan: option reverse (right-to-left)
+[ ] #join: option swap
+[ ] #matrix_solve, #replace_if, #random_select, #markov_chain, #splice
+[ ] #draw_polygon smoothly
+[ ] write a complete benchmark
+[ ] spatial biquads (ask Tom)
+[ ] string operations to compensate for the feebleness of PD in that area. this includes [#sprintf].
+[ ] see also APL/J/NArray/PDL/Aplus/Yorick/IPOW reference
+
+Effects
+[ ] #mosaic
+[ ] #gaussian_blur, #sobel, #pixelize, #despeckle (median)
+[ ] #dither, #draw_lines, #draw_points, #fire, #queue
+[ ] #chroma_key: i0=RGBpicture i1=RGBcolor i2=tolerance o0=RGBApicture
+ with fuzzy flag; (don't call it #chroma_key though)
+ maybe #mask...
+[ ] turtle (logo style)
+[ ] effectv
+[ ] create abstractions for usage patterns (eg: like #remap_image)
+[ ] see gimp for ideas
+[ ] multilinear interpolation a+(b-a)*x+(c-a)*y+(a-b-c+d)*x*y (#scale_by smoothly?)
+[ ] #scale_by/#downscale_by fractional values
+[ ] bicubic interpolation
+[ ] multilinear interpolation (n-dimensional?)
+[ ] #daltonism
+[ ] #perlin ?
+[ ] #moment could support more than 2 dimensions
+[ ] note in the helpfiles what is meant by YUV in gridflow (what colorspace that is)
+
+Input/Output
+[ ] a #store that is persistent (saved in .pd) ?
+[ ] Grid: support storage in all six types
+[ ] Grid: bpv 1,2,4 uint
+[ ] Grid: text version of the format
+[ ] Gimp, ffmpeg, xine, mplayer, PDP, OSC
+[ ] x11,sdl,aalib: use buffering to synchronise frames at a constant rate.
+[ ] x11: sync with the actual vsync of the monitor
+[ ] x11: double buffering using a Pixmap remote-object
+[ ] support for audio in the mpeg streams
+[ ] synchronized audio with the video when using mpeg1 & 2
+[ ] full screen mode (without the menu bars or frames)
+[ ] support for audio in cameras / videodev ... see field vcaps.audios
+
+Format
+[ ] remaining number type support in formats
+[ ] threaded [#in]/[#out]
+[ ] put_at/reassign in x11/sdl/quartz
+[ ] Generic SHM/MMAP Drivers
+[ ] "open grid pipe" and such.
+[ ] format grid: "headerless until 10" (text files)
+
+User Interface
+[ ] color picker
+[ ] #edit, grid edition dialog, etc.
+[ ] vector slider (n parallel sliders in one, Dim(n))
+[ ] 2d slider
+[ ] radial slider (angle chooser)
+[ ] drag-and-drop palette of object construction
+[ ] object construction menu specialized for each class (generated from class reflection/metadata)
+
+-mfpmath=sse2
+
+remember to check for volatile VALUEs if GC problems ever occur
+
+Tom Schouten wrote: «added demo/rawvideo.pf and some support scripts in bin/pf-rawvideo.*
+this is an example on how to use external programs for raw video input.
+rationale: mplayer is a very nice piece of software supporting virtually any input format/codec.
+since i'm not planning to waste time on integrating more input codecs in pf, the best alternative is to have mplayer
+(actually mencoder) or ffmpeg as a subprocess. the same will be done for recording later.»
+
+very old bookmarks:
+ http://pdl.perl.org/
+ http://www.opendragon.com/Pages/MaxObjects.shtml (not responding)
+ http://homepages.inf.ed.ac.uk/rbf/HIPR2/wksheets.htm
+ http://freej.dyne.org/
+
+FObject.subclass("memstat",1,1) {
+ def _0_bang; File.open("/proc/#{$$}/stat") {|f| send_out 0, Float(f.gets.split(" ")[22]) / 1024.0 } end
+ # lookup process stats for the currently running pd and figure out how much RAM it uses.
+ # virtual size of RAM in kilobytes (includes swapped out and shared memory)
+}
+
+there are bugs with abstractions that use [route]->[list] instead of [route2] because they fail when $1="list".
+
+svn propset svn:mime-type text/pure-data *.pd
+
+Benchmarks on a Pentium M 1733 (with #out x11):
+(fps) 0.9.0 0.9.3 0.9.4
+waves.pd rain 41.1 49.5 50.5
+game_of_life.pd 162 183 188
+sand.pd 18.7 20.5 20.1
+cellular_1d.pd 115 130.1 130
+wave_1d.pd 63.0 81.7 81.7
+
+Benchmarks on a Pentium M 1733 (without window):
+(fps) 0.9.0 0.9.3 0.9.4
+waves.pd rain 50.1 63.0
+game_of_life.pd 397 507
+sand.pd 27 30
+cellular_1d.pd 475 730
+wave_1d.pd 107 173
diff --git a/externals/gridflow/abstractions/#apply_colormap_channelwise.pd b/externals/gridflow/abstractions/#apply_colormap_channelwise.pd
new file mode 100644
index 00000000..c63a7651
--- /dev/null
+++ b/externals/gridflow/abstractions/#apply_colormap_channelwise.pd
@@ -0,0 +1,12 @@
+#N canvas 0 0 450 300 10;
+#X obj 17 17 inlet;
+#X obj 17 77 #store;
+#X obj 17 97 outlet;
+#X obj 67 17 inlet;
+#X obj 17 57 # + (3 2 # 0 0 0 1 0 2);
+#X obj 17 37 #outer & (-1 0);
+#X connect 0 0 5 0;
+#X connect 1 0 2 0;
+#X connect 3 0 1 1;
+#X connect 4 0 1 0;
+#X connect 5 0 4 0;
diff --git a/externals/gridflow/abstractions/#background_model.pd b/externals/gridflow/abstractions/#background_model.pd
new file mode 100644
index 00000000..07db6465
--- /dev/null
+++ b/externals/gridflow/abstractions/#background_model.pd
@@ -0,0 +1,93 @@
+#N canvas 563 12 770 687 10;
+#X text 415 -1 sliding buffer;
+#X obj 104 302 # sq-;
+#X obj 104 370 # /;
+#X text 57 293 input;
+#X obj 104 393 #fold +;
+#X text 171 302 <-- (input-mean)exp2;
+#X text 170 287 mean;
+#X text 369 -28 takes a grid as input;
+#X text 569 557 getModel;
+#X text 569 577 clearModel;
+#X obj 183 544 tgl 15 0 empty empty binaryFlag 0 -6 0 8 -24198 -1 -1
+1 1;
+#X text 568 534 adaptBackground (const image src \, const channel8
+mask);
+#X obj 104 578 shunt;
+#X text 195 194 <-- output is an average;
+#X text 201 215 <-- recentre les coordonnees selon la moyenne;
+#X obj 103 -136 inlet;
+#X obj 104 659 outlet;
+#X obj 190 512 inlet binary_flag;
+#X obj 282 -22 t a b;
+#X floatatom 312 20 5 0 0 0 - - -;
+#X msg 312 37 put_at ( \$1 0 0 0 );
+#X text 314 66 <-- this \$1 corresponds to the first argument given
+to the abstraction. The \$1 in the "put_at" message box is simply the
+indice from the counter.;
+#X text 282 145 <-- the number of frames that will establish the backgroundModel
+;
+#X obj 103 -95 t a b a;
+#X obj 126 121 #t;
+#X text 260 262 variance = standard deviation \, squared;
+#X text 523 210 (X - EX)squared;
+#X text 146 344 <-- variance;
+#X text 145 368 <-- squeeze;
+#X text 173 390 <-- applies the pythagore theorem;
+#X text 158 316 <-- fudge factor because we are not in float \, could
+try as float throughout instead;
+#X obj 250 566 inlet output_threshold;
+#X text 254 608 <-- checks to see if the value is within 0-255;
+#X text 158 660 <-- output is greyscale (channel8 in lti parlance)
+;
+#X text 124 468 <-- "malanowis distance" of each pixel to the background
+;
+#X text 297 -50 ------------ addBackground ----------;
+#X obj 104 416 #redim ( \$2 \$3 1);
+#X obj 126 69 #store ( \$1 \$2 \$3 \$4 #);
+#X obj 147 -56 spigot;
+#X obj 190 -83 inlet addBackground;
+#X text 242 416 <-- adds a channel;
+#X obj 217 283 outlet variance;
+#X obj 265 177 outlet Mean;
+#X obj 312 0 count 0 \$1;
+#X obj 126 200 # sq-;
+#X obj 176 119 #fold + \, seed ( \$2 \$3 \$4 #);
+#X obj 176 147 # / \$1;
+#X obj 127 235 #fold + \, seed ( \$2 \$3 \$4 #);
+#X obj 165 260 # / \$1;
+#X obj 135 607 # > 128;
+#X obj 134 628 # * 255;
+#X connect 1 0 2 0;
+#X connect 2 0 4 0;
+#X connect 4 0 36 0;
+#X connect 10 0 12 1;
+#X connect 12 0 16 0;
+#X connect 12 1 49 0;
+#X connect 15 0 23 0;
+#X connect 17 0 10 0;
+#X connect 18 0 37 1;
+#X connect 18 1 43 0;
+#X connect 19 0 20 0;
+#X connect 20 0 37 1;
+#X connect 23 0 1 0;
+#X connect 23 1 37 0;
+#X connect 23 2 38 0;
+#X connect 24 0 44 0;
+#X connect 24 1 45 0;
+#X connect 31 0 49 1;
+#X connect 36 0 12 0;
+#X connect 37 0 24 0;
+#X connect 38 0 18 0;
+#X connect 39 0 38 1;
+#X connect 43 0 19 0;
+#X connect 44 0 47 0;
+#X connect 45 0 46 0;
+#X connect 46 0 1 1;
+#X connect 46 0 42 0;
+#X connect 46 0 44 1;
+#X connect 47 0 48 0;
+#X connect 48 0 2 1;
+#X connect 48 0 41 0;
+#X connect 49 0 50 0;
+#X connect 50 0 16 0;
diff --git a/externals/gridflow/abstractions/#camera.pd b/externals/gridflow/abstractions/#camera.pd
new file mode 100644
index 00000000..4c55283d
--- /dev/null
+++ b/externals/gridflow/abstractions/#camera.pd
@@ -0,0 +1,353 @@
+#N canvas 599 0 421 345 10;
+#X obj 81 31 cnv 15 184 68 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X obj 143 34 hradio 12 1 0 4 \$0-s_channel \$0-channel _0_1_2_3 -2
+7 1 10 -233017 -195568 -195568 0;
+#N canvas 275 0 906 659 camera 0;
+#X obj 310 510 outlet;
+#X obj 51 9 inlet;
+#X obj 63 198 t a;
+#X msg 700 458 open videodev \$1 \, get;
+#X msg 673 309 size \$1 \$2;
+#X obj 598 8 r \$0-size0;
+#X msg 673 8 120 160;
+#X msg 673 27 120 180;
+#X obj 598 27 r \$0-size1;
+#X msg 673 46 240 320;
+#X msg 673 65 240 360;
+#X obj 598 46 r \$0-size2;
+#X obj 598 65 r \$0-size3;
+#X obj 598 84 r \$0-size4;
+#X obj 598 103 r \$0-size5;
+#X msg 673 84 480 640;
+#X msg 673 103 480 720;
+#X obj 598 122 r \$0-size6;
+#X obj 598 141 r \$0-size7;
+#X msg 673 122 576 720;
+#X msg 673 141 288 352;
+#X obj 673 204 unpack 0 0;
+#X obj 768 223 s \$0-width;
+#X obj 673 223 s \$0-height;
+#X obj 673 271 #pack;
+#X obj 673 290 #to_list;
+#X obj 700 439 makefilename /dev/video%d;
+#X obj 85 419 spigot;
+#X obj 308 579 args (device a -1);
+#X obj 308 560 loadbang;
+#X obj 308 617 s \$0-device;
+#X obj 85 441 route pwc;
+#X msg 85 460 pwc \$1 \, get;
+#X obj 51 28 list split 1;
+#X obj 51 47 makefilename \$0-%s;
+#X obj 51 104 s;
+#X obj 51 85 list;
+#X obj 51 66 t b s;
+#X msg 684 482 open dc1394 \, get;
+#X obj 391 287 listfind y yuv rgb magic;
+#X obj 391 344 listread y yuv rgb magic;
+#X msg 391 363 colorspace \$1;
+#X obj 181 66 list prepend;
+#X obj 181 85 list trim;
+#X obj 174 174 foreach;
+#X obj 174 193 makefilename \$0-%s;
+#X msg 174 212 \; \$1 color 10 20 20;
+#X msg 179 559 \; \$1 color 18 17 22;
+#X obj 122 381 t b a b b;
+#X obj 391 306 s \$0-colorspace_e;
+#X obj 391 325 r \$0-s_colorspace_e;
+#X obj 673 243 r \$0-s_height;
+#X obj 768 243 r \$0-s_width;
+#X obj 656 368 r \$0-s_device;
+#X obj 580 186 r \$0-size;
+#X msg 180 400 0;
+#X msg 122 400 1;
+#X obj 580 205 route2 color;
+#X obj 580 224 s \$0-sizec;
+#X obj 571 243 s \$0-width;
+#X obj 561 263 s \$0-height;
+#X obj 371 265 route2 color;
+#X obj 371 246 r \$0-colorspace;
+#X obj 635 538 s \$0-title;
+#X msg 635 519 label \$1;
+#X obj 563 481 r \$0-name;
+#X obj 563 500 route color;
+#X msg 490 591 close;
+#X msg 490 612 label No_camera_selected;
+#X msg 339 181 label Unknown_camera;
+#X obj 339 200 s \$0-title;
+#X obj 731 8 r \$0-minsize;
+#X obj 731 46 unpack 0 0;
+#X obj 796 65 s \$0-minwidth;
+#X obj 731 84 s \$0-minheight;
+#X obj 731 141 unpack 0 0;
+#X obj 731 103 r \$0-maxsize;
+#X obj 731 179 s \$0-maxheight;
+#X obj 796 160 s \$0-maxwidth;
+#X obj 731 27 route list;
+#X obj 731 122 route list;
+#X obj 393 522 s \$0-minsize;
+#X msg 393 501 0 0;
+#X obj 403 542 s \$0-maxsize;
+#X obj 656 387 t a b;
+#X obj 67 482 r \$0-palette;
+#X obj 139 539 s \$0-palette2;
+#X msg 139 520 label \$1;
+#X obj 25 563 route minsize maxsize;
+#X obj 67 501 route color;
+#X obj 181 8 receives \$0-s_ channel tuner frequency brightness contrast
+colour hue whiteness white_mode white_red white_blue white_speed white_delay
+auto_gain framerate noise_reduction compression pwc size colorspace
+norm transfer;
+#X msg 174 116 list channel tuner frequency brightness contrast colour
+hue whiteness white_mode white_red white_blue white_speed white_delay
+auto_gain framerate noise_reduction compression pwc size colorspace
+norm transfer;
+#X obj 714 505 r \$0-transfer;
+#X obj 754 544 listfind read mmap;
+#X obj 744 563 s \$0-transfer_e;
+#X obj 744 582 r \$0-s_transfer_e;
+#X obj 744 601 listread read mmap;
+#X msg 744 620 transfer \$1;
+#X obj 714 524 route2 color;
+#X obj 308 598 mod 11;
+#X obj 656 417 range 8 9 10;
+#X msg 434 399 open quicktimecamera \, get;
+#X connect 1 0 33 0;
+#X connect 2 0 27 0;
+#X connect 3 0 48 0;
+#X connect 4 0 0 0;
+#X connect 5 0 6 0;
+#X connect 6 0 21 0;
+#X connect 7 0 21 0;
+#X connect 8 0 7 0;
+#X connect 9 0 21 0;
+#X connect 10 0 21 0;
+#X connect 11 0 9 0;
+#X connect 12 0 10 0;
+#X connect 13 0 15 0;
+#X connect 14 0 16 0;
+#X connect 15 0 21 0;
+#X connect 16 0 21 0;
+#X connect 17 0 19 0;
+#X connect 18 0 20 0;
+#X connect 19 0 21 0;
+#X connect 20 0 21 0;
+#X connect 21 0 23 0;
+#X connect 21 1 22 0;
+#X connect 24 0 25 0;
+#X connect 25 0 4 0;
+#X connect 26 0 3 0;
+#X connect 27 0 31 0;
+#X connect 28 0 99 0;
+#X connect 29 0 28 0;
+#X connect 31 0 32 0;
+#X connect 31 1 0 0;
+#X connect 32 0 48 0;
+#X connect 33 0 34 0;
+#X connect 33 1 36 1;
+#X connect 34 0 37 0;
+#X connect 34 0 88 0;
+#X connect 36 0 35 0;
+#X connect 37 0 36 0;
+#X connect 37 1 35 1;
+#X connect 38 0 48 0;
+#X connect 39 0 49 0;
+#X connect 40 0 41 0;
+#X connect 41 0 2 0;
+#X connect 42 0 43 0;
+#X connect 43 0 2 0;
+#X connect 44 0 45 0;
+#X connect 45 0 46 0;
+#X connect 48 0 56 0;
+#X connect 48 1 0 0;
+#X connect 48 2 69 0;
+#X connect 48 2 91 0;
+#X connect 48 3 55 0;
+#X connect 50 0 40 0;
+#X connect 51 0 24 0;
+#X connect 52 0 24 1;
+#X connect 53 0 84 0;
+#X connect 54 0 57 0;
+#X connect 55 0 27 1;
+#X connect 56 0 27 1;
+#X connect 57 0 58 0;
+#X connect 57 0 59 0;
+#X connect 57 0 60 0;
+#X connect 57 1 21 0;
+#X connect 61 0 49 0;
+#X connect 61 1 39 0;
+#X connect 62 0 61 0;
+#X connect 64 0 63 0;
+#X connect 65 0 66 0;
+#X connect 66 1 64 0;
+#X connect 67 0 48 0;
+#X connect 67 0 68 0;
+#X connect 67 0 82 0;
+#X connect 68 0 63 0;
+#X connect 69 0 70 0;
+#X connect 71 0 79 0;
+#X connect 72 0 74 0;
+#X connect 72 1 73 0;
+#X connect 75 0 77 0;
+#X connect 75 1 78 0;
+#X connect 76 0 80 0;
+#X connect 79 0 72 0;
+#X connect 80 0 75 0;
+#X connect 82 0 81 0;
+#X connect 82 0 83 0;
+#X connect 84 0 100 0;
+#X connect 84 1 82 0;
+#X connect 85 0 89 0;
+#X connect 87 0 86 0;
+#X connect 88 2 47 0;
+#X connect 89 1 87 0;
+#X connect 90 0 42 0;
+#X connect 90 1 42 1;
+#X connect 91 0 44 0;
+#X connect 92 0 98 0;
+#X connect 93 0 94 0;
+#X connect 95 0 96 0;
+#X connect 96 0 97 0;
+#X connect 97 0 2 0;
+#X connect 98 0 94 0;
+#X connect 98 1 93 0;
+#X connect 99 0 30 0;
+#X connect 100 0 26 0;
+#X connect 100 1 38 0;
+#X connect 100 2 101 0;
+#X connect 100 3 67 0;
+#X connect 101 0 48 0;
+#X restore 34 390 pd camera;
+#X obj 7 409 outlet image;
+#X obj 7 352 inlet;
+#X obj 143 46 hradio 12 1 0 4 \$0-s_tuner \$0-tuner _0_1_2_3 -2 7 1
+10 -233017 -195568 -195568 0;
+#X obj 46 352 r \$0-o;
+#X text 84 35 channel:;
+#X text 98 47 tuner:;
+#X obj 6 31 cnv 15 70 216 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X text 9 32 device:;
+#X obj 11 50 vradio 15 1 0 11 \$0-s_device \$0-device empty 0 -6 0
+8 -241291 -1 -1 10;
+#X obj 81 105 cnv 15 184 172 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X obj 270 214 cnv 15 144 124 empty \$0-palette2 YUV420P 86 8 0 12
+-233017 -1 0;
+#X obj 270 31 cnv 15 144 178 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X obj 312 66 nbx 5 14 -1e+37 1e+37 0 0 \$0-s_height \$0-height empty
+0 -6 1 10 -233017 -195568 -195568 0 256;
+#X obj 360 66 nbx 5 14 -1e+37 1e+37 0 0 \$0-s_width \$0-width empty
+0 -6 1 10 -233017 -195568 -195568 0 256;
+#X text 275 65 size:;
+#X text 315 35 height;
+#X text 365 35 width;
+#X msg 291 315 transfer mmap 4;
+#X obj 291 352 s \$0-o;
+#X obj 329 124 bng 12 250 50 0 \$0-size0 \$0-sizec 120x160 -46 6 1
+10 -233017 -195568 -195568;
+#X obj 344 124 bng 12 250 50 0 \$0-size1 \$0-sizec 120x180 16 6 1 10
+-233017 -195568 -195568;
+#X obj 329 136 bng 12 250 50 0 \$0-size2 \$0-sizec 240x320 -46 6 1
+10 -233017 -195568 -195568;
+#X obj 344 136 bng 12 250 50 0 \$0-size3 \$0-sizec 240x360 16 6 1 10
+-233017 -195568 -195568;
+#X obj 329 148 bng 12 250 50 0 \$0-size4 \$0-sizec 480x640 -46 6 1
+10 -233017 -195568 -195568;
+#X obj 344 148 bng 12 250 50 0 \$0-size5 \$0-sizec 480x720 16 6 1 10
+-233017 -195568 -195568;
+#X obj 344 160 bng 12 250 50 0 \$0-size6 \$0-sizec 576x720 16 6 1 10
+-233017 -195568 -195568;
+#X obj 344 172 bng 12 250 50 0 \$0-size7 \$0-sizec 288x352 16 6 1 10
+-233017 -195568 -195568;
+#X obj 360 191 nbx 5 14 -1e+37 1e+37 0 0 \$0-s_framerate \$0-framerate
+empty 0 -6 1 10 -233017 -195568 -195568 0 256;
+#X obj 83 179 tgl 12 0 \$0-s_white_mode \$0-white_mode manual_white_balance
+20 7 1 10 -233017 -195568 -195568 0 1;
+#X text 27 50 #0;
+#X text 27 65 #1;
+#X text 27 80 #2;
+#X text 27 95 #3;
+#X text 27 110 #4;
+#X text 27 125 #5;
+#X text 27 140 #6;
+#X text 27 155 #7;
+#X text 317 106 presets:;
+#X text 90 167 ------- PWC ONLY: -------;
+#X obj 83 251 hradio 12 1 0 4 \$0-s_noise_reduction \$0-noise_reduction
+_0_1_2_3_noise_reduction -2 7 1 10 -233017 -195568 -195568 0;
+#X obj 83 263 hradio 12 1 0 4 \$0-s_compression \$0-compression _0_1_2_3_compression
+-2 7 1 10 -233017 -195568 -195568 0;
+#X obj 11 226 tgl 12 0 \$0-s_pwc \$0-pwc empty 20 7 1 10 -233017 -195568
+-195568 0 1;
+#X text 26 224 use PWC;
+#X text 28 170 DC1394;
+#X obj 356 232 vradio 12 1 0 4 \$0-s_colorspace_e \$0-colorspace_e
+empty 0 -8 0 10 -233017 -195568 -195568 0;
+#X text 370 229 y;
+#X text 370 241 yuv;
+#X text 370 254 rgb;
+#X text 370 266 magic;
+#X text 269 249 Colorspaces:;
+#N canvas 0 0 450 300 command_filtre 0;
+#X obj 22 24 inlet;
+#X obj 22 92 outlet;
+#X obj 22 43 route bang device;
+#X obj 79 122 s \$0-device;
+#X connect 0 0 2 0;
+#X connect 2 0 1 0;
+#X connect 2 1 3 0;
+#X connect 2 2 1 0;
+#X restore 7 371 pd command_filtre;
+#X text 287 191 framerate:;
+#X obj 201 34 vradio 12 1 0 4 \$0-s_norm \$0-norm empty 0 -8 0 10 -233017
+-195568 -195568 0;
+#X text 214 33 PAL;
+#X text 214 45 NTSC;
+#X text 213 57 SECAM;
+#X text 213 68 auto;
+#X obj 6 6 cnv 15 408 20 empty \$0-title No_camera_selected 4 10 1
+12 -1 -262144 0;
+#X obj 356 285 vradio 12 1 0 2 \$0-s_transfer_e \$0-transfer_e empty
+0 -8 0 10 -233017 -195568 -195568 0;
+#X text 291 289 Transfer:;
+#X text 370 283 read;
+#X text 371 295 mmap;
+#X obj 312 52 nbx 5 14 -1e+37 1e+37 0 0 empty \$0-minheight empty 0
+-6 1 10 -233017 -1 -195568 0 256;
+#X obj 360 52 nbx 5 14 -1e+37 1e+37 0 0 empty \$0-minwidth empty 0
+-6 1 10 -233017 -1 -195568 0 256;
+#X obj 312 80 nbx 5 14 -1e+37 1e+37 0 0 empty \$0-maxheight empty 0
+-6 1 10 -233017 -1 -195568 0 256;
+#X obj 360 80 nbx 5 14 -1e+37 1e+37 0 0 empty \$0-maxwidth empty 0
+-6 1 10 -233017 -1 -195568 0 256;
+#X text 275 79 max:;
+#X text 275 51 min:;
+#X text 297 214 Palette:;
+#X obj 45 53 cnv 1 3 1 empty empty empty 20 12 0 14 -1 -66577 0;
+#X obj 45 165 cnv 1 3 1 empty empty empty 20 12 0 14 -1 -66577 0;
+#X obj 48 55 cnv 1 1 53 empty empty empty 20 12 0 14 -1 -66577 0;
+#X obj 49 109 cnv 1 3 1 empty empty V4L1 6 0 0 10 -1 -66577 0;
+#X obj 48 111 cnv 1 1 53 empty empty empty 20 12 0 14 -1 -66577 0;
+#X text 27 200 OFF;
+#X text 27 185 MacOSX;
+#X obj 83 107 gf.nbxhsl \$0 contrast;
+#X obj 83 119 gf.nbxhsl \$0 brightness;
+#X obj 83 131 gf.nbxhsl \$0 colour;
+#X obj 83 143 gf.nbxhsl \$0 hue;
+#X obj 83 155 gf.nbxhsl \$0 whiteness;
+#X obj 82 191 gf.nbxhsl \$0 white_red;
+#X obj 82 203 gf.nbxhsl \$0 white_blue;
+#X obj 82 215 gf.nbxhsl \$0 white_speed;
+#X obj 82 227 gf.nbxhsl \$0 white_delay;
+#X obj 82 239 gf.nbxhsl \$0 auto_gain;
+#X obj 83 85 gf.nbxhsl \$0 frequency;
+#X obj 7 390 #in;
+#X connect 2 0 90 0;
+#X connect 4 0 53 0;
+#X connect 6 0 90 0;
+#X connect 20 0 21 0;
+#X connect 53 0 90 0;
+#X connect 90 0 3 0;
+#X connect 90 1 2 0;
diff --git a/externals/gridflow/abstractions/#change.pd b/externals/gridflow/abstractions/#change.pd
new file mode 100644
index 00000000..9a2a4ae7
--- /dev/null
+++ b/externals/gridflow/abstractions/#change.pd
@@ -0,0 +1,22 @@
+#N canvas 273 276 381 232 10;
+#X obj 64 38 inlet;
+#X obj 64 134 #fold |;
+#X obj 123 126 #store;
+#X obj 64 115 #ravel;
+#X obj 64 153 #to_float;
+#X obj 123 145 outlet;
+#X obj 64 57 t a a a;
+#X obj 64 172 sel 1;
+#X obj 158 22 args (initial a 0);
+#X obj 64 96 # !=;
+#X connect 0 0 6 0;
+#X connect 1 0 4 0;
+#X connect 2 0 5 0;
+#X connect 3 0 1 0;
+#X connect 4 0 7 0;
+#X connect 6 0 9 1;
+#X connect 6 1 9 0;
+#X connect 6 2 2 1;
+#X connect 7 0 2 0;
+#X connect 8 0 9 1;
+#X connect 9 0 3 0;
diff --git a/externals/gridflow/abstractions/#checkers.pd b/externals/gridflow/abstractions/#checkers.pd
new file mode 100644
index 00000000..5b0b8711
--- /dev/null
+++ b/externals/gridflow/abstractions/#checkers.pd
@@ -0,0 +1,18 @@
+#N canvas 0 0 450 300 10;
+#X obj 18 14 inlet;
+#X obj 18 34 # >> 3;
+#X obj 18 54 # & 1;
+#X obj 18 74 #fold ^;
+#X obj 18 94 # inv+;
+#X obj 18 114 # & 63;
+#X obj 18 134 # + 128;
+#X obj 18 174 outlet;
+#X obj 18 154 #outer ignore (3 #);
+#X connect 0 0 1 0;
+#X connect 1 0 2 0;
+#X connect 2 0 3 0;
+#X connect 3 0 4 0;
+#X connect 4 0 5 0;
+#X connect 5 0 6 0;
+#X connect 6 0 8 0;
+#X connect 8 0 7 0;
diff --git a/externals/gridflow/abstractions/#clip.pd b/externals/gridflow/abstractions/#clip.pd
new file mode 100644
index 00000000..5e0a4c11
--- /dev/null
+++ b/externals/gridflow/abstractions/#clip.pd
@@ -0,0 +1,16 @@
+#N canvas 531 259 649 265 10;
+#X obj 87 4 inlet;
+#X obj 87 230 outlet;
+#X obj 117 133 inlet;
+#X obj 117 58 inlet;
+#X obj 87 156 # min;
+#X obj 87 82 # max;
+#X obj 243 40 args (max a 0) (min a 255);
+#X text 439 40 <-- sets the initial values;
+#X connect 0 0 5 0;
+#X connect 2 0 4 1;
+#X connect 3 0 5 1;
+#X connect 4 0 1 0;
+#X connect 5 0 4 0;
+#X connect 6 0 5 1;
+#X connect 6 1 4 1;
diff --git a/externals/gridflow/abstractions/#color.pd b/externals/gridflow/abstractions/#color.pd
new file mode 100644
index 00000000..1a7957be
--- /dev/null
+++ b/externals/gridflow/abstractions/#color.pd
@@ -0,0 +1,72 @@
+#N canvas 184 193 450 373 10;
+#X obj 76 87 hsl 128 14 0 255 0 0 empty empty empty -2 -6 0 8 -225271
+-24198 -1 2300 1;
+#X obj 76 101 hsl 128 14 0 255 0 0 empty empty empty -2 -6 0 8 -228992
+-62784 -1 3100 1;
+#X obj 76 73 hsl 128 14 0 255 0 0 empty empty empty -2 -6 0 8 -261689
+-258699 -1 900 1;
+#X obj 10 166 #pack 3;
+#X obj 39 -6 inlet rgb_color;
+#X obj 15 188 outlet rgb_color;
+#X obj 122 62 cnv 10 60 10 empty \$0-cnv empty 20 12 0 14 -17104 -262144
+0;
+#X obj 10 343 s \$0-cnv;
+#X msg 10 324 color \$1;
+#X obj 10 267 #to_float;
+#X obj 10 248 # ^ -1;
+#X obj 10 229 #fold |;
+#X obj 216 123 loadbang;
+#X msg 216 199 range \$1 \$2;
+#X obj 216 180 #to_list;
+#X obj 64 267 loadbang;
+#X obj 64 305 - \$3;
+#X msg 64 286 1;
+#X obj 10 305 spigot;
+#X obj 166 32 #unpack 3;
+#X obj 216 161 # || (0 255);
+#X obj 10 210 # << (16 8 0);
+#X obj 216 142 #store ( \$1 \$2 );
+#X floatatom 50 73 3 0 255 0 - - -;
+#X floatatom 50 87 3 0 255 0 - - -;
+#X floatatom 50 101 3 0 255 0 - - -;
+#X obj 82 122 int;
+#X obj 82 141 int;
+#X obj 82 160 int;
+#X obj 38 13 route delegate bang;
+#X connect 0 0 27 0;
+#X connect 1 0 28 0;
+#X connect 2 0 26 0;
+#X connect 3 0 5 0;
+#X connect 3 0 21 0;
+#X connect 4 0 29 0;
+#X connect 8 0 7 0;
+#X connect 9 0 18 0;
+#X connect 10 0 9 0;
+#X connect 11 0 10 0;
+#X connect 12 0 22 0;
+#X connect 13 0 1 0;
+#X connect 13 0 0 0;
+#X connect 13 0 2 0;
+#X connect 14 0 13 0;
+#X connect 15 0 17 0;
+#X connect 16 0 18 1;
+#X connect 17 0 16 0;
+#X connect 18 0 8 0;
+#X connect 19 0 2 0;
+#X connect 19 1 0 0;
+#X connect 19 2 1 0;
+#X connect 20 0 14 0;
+#X connect 21 0 11 0;
+#X connect 22 0 20 0;
+#X connect 23 0 3 0;
+#X connect 24 0 3 1;
+#X connect 25 0 3 2;
+#X connect 26 0 23 0;
+#X connect 27 0 24 0;
+#X connect 28 0 25 0;
+#X connect 29 0 2 0;
+#X connect 29 0 0 0;
+#X connect 29 0 1 0;
+#X connect 29 1 2 0;
+#X connect 29 2 19 0;
+#X coords 0 -1 1 1 156 55 1 50 60;
diff --git a/externals/gridflow/abstractions/#contrast.pd b/externals/gridflow/abstractions/#contrast.pd
new file mode 100644
index 00000000..02ce80ed
--- /dev/null
+++ b/externals/gridflow/abstractions/#contrast.pd
@@ -0,0 +1,23 @@
+#N canvas 0 0 450 300 10;
+#X obj 14 14 inlet;
+#X obj 14 34 # inv+ 255;
+#X obj 14 54 # *>>8;
+#X obj 14 74 # inv+ 255;
+#X obj 14 94 # *>>8;
+#X obj 14 114 # min 255;
+#X obj 14 134 # max 0;
+#X obj 14 154 outlet;
+#X obj 54 14 inlet;
+#X obj 94 14 inlet;
+#X obj 163 43 args (span a 256) (white a 256);
+#X connect 0 0 1 0;
+#X connect 1 0 2 0;
+#X connect 2 0 3 0;
+#X connect 3 0 4 0;
+#X connect 4 0 5 0;
+#X connect 5 0 6 0;
+#X connect 6 0 7 0;
+#X connect 8 0 2 1;
+#X connect 9 0 4 1;
+#X connect 10 0 2 1;
+#X connect 10 1 4 1;
diff --git a/externals/gridflow/abstractions/#draw_hpgl.pd b/externals/gridflow/abstractions/#draw_hpgl.pd
new file mode 100644
index 00000000..763ff5ea
--- /dev/null
+++ b/externals/gridflow/abstractions/#draw_hpgl.pd
@@ -0,0 +1,86 @@
+#N canvas 413 192 510 430 10;
+#X obj 208 16 inlet command;
+#X obj 18 17 inlet image;
+#X obj 18 337 outlet image;
+#X obj 109 17 inlet colour;
+#X obj 142 36 loadbang;
+#X obj 107 318 spigot 1;
+#X text 167 319 pen;
+#X msg 231 109 0;
+#X msg 270 109 1;
+#X obj 201 80 t a b;
+#X obj 240 80 t a b;
+#X obj 279 69 route bang;
+#X obj 353 103 t a a;
+#X msg 142 55 2 2 # -1;
+#X obj 353 139 unpack;
+#X obj 399 139 unpack;
+#X obj 353 162 pack 0 0 0 0;
+#X obj 107 337 outlet time_to_draw;
+#X obj 353 200 t a a;
+#X obj 353 219 #finished;
+#X obj 40 55 #store;
+#X obj 62 74 #dim;
+#X obj 26 185 #reinterval;
+#X obj 18 36 t a b a;
+#X obj 353 239 inlet start;
+#X obj 367 278 inlet end;
+#X obj 62 93 #unpack 3;
+#X obj 26 204 #reverse -1;
+#X obj 18 290 #draw_polygon \, draw line;
+#X obj 353 84 #to_list;
+#X obj 208 35 route PU PD PA PR;
+#X obj 367 297 #cast f;
+#X obj 353 258 #cast f;
+#X obj 353 181 #import (2 2) f;
+#X obj 353 65 #import (2) f;
+#X obj 43 163 #pack 2 f;
+#X obj 112 163 #pack 2 f;
+#X obj 26 223 #cast i;
+#X connect 0 0 30 0;
+#X connect 1 0 23 0;
+#X connect 3 0 28 1;
+#X connect 4 0 13 0;
+#X connect 5 0 17 0;
+#X connect 7 0 5 1;
+#X connect 8 0 5 1;
+#X connect 9 0 11 0;
+#X connect 9 1 7 0;
+#X connect 10 0 11 0;
+#X connect 10 1 8 0;
+#X connect 11 1 34 0;
+#X connect 12 0 15 0;
+#X connect 12 1 14 0;
+#X connect 13 0 28 2;
+#X connect 14 0 16 0;
+#X connect 14 1 16 1;
+#X connect 15 0 16 2;
+#X connect 15 1 16 3;
+#X connect 16 0 33 0;
+#X connect 18 0 19 0;
+#X connect 18 1 20 1;
+#X connect 19 0 5 0;
+#X connect 20 0 22 0;
+#X connect 21 0 26 0;
+#X connect 22 0 27 0;
+#X connect 23 0 28 0;
+#X connect 23 1 20 0;
+#X connect 23 2 21 0;
+#X connect 24 0 32 0;
+#X connect 25 0 31 0;
+#X connect 26 0 35 1;
+#X connect 26 1 36 0;
+#X connect 27 0 37 0;
+#X connect 28 0 2 0;
+#X connect 29 0 12 0;
+#X connect 30 0 9 0;
+#X connect 30 1 10 0;
+#X connect 30 2 34 0;
+#X connect 30 3 34 0;
+#X connect 31 0 22 2;
+#X connect 32 0 22 1;
+#X connect 33 0 18 0;
+#X connect 34 0 29 0;
+#X connect 35 0 22 3;
+#X connect 36 0 22 4;
+#X connect 37 0 28 2;
diff --git a/externals/gridflow/abstractions/#draw_rect.pd b/externals/gridflow/abstractions/#draw_rect.pd
new file mode 100644
index 00000000..25dfea35
--- /dev/null
+++ b/externals/gridflow/abstractions/#draw_rect.pd
@@ -0,0 +1,39 @@
+#N canvas 371 309 473 313 10;
+#X obj 12 28 inlet;
+#X obj 98 250 outlet;
+#X obj 234 1 inlet;
+#X obj 221 157 #to_list;
+#X msg 221 176 4 2 # \$1 \$2 \$1 \$4 \$3 \$4 \$3 \$2;
+#X obj 72 28 inlet;
+#X msg 107 207 op \$1;
+#X obj 221 195 shunt 2;
+#X obj 12 110 route outline;
+#X obj 245 135 #store;
+#X obj 245 116 t b f;
+#X obj 269 214 #join 0;
+#X obj 269 195 t a a;
+#X obj 308 195 # + (1 1 1 1 -1 -1 -1 -1);
+#X obj 98 231 #draw_polygon put;
+#X obj 120 32 args op color (polygon a (2 2 #));
+#X connect 0 0 8 0;
+#X connect 2 0 9 1;
+#X connect 2 0 3 0;
+#X connect 3 0 4 0;
+#X connect 4 0 7 0;
+#X connect 5 0 14 1;
+#X connect 6 0 14 0;
+#X connect 7 0 14 2;
+#X connect 7 1 12 0;
+#X connect 8 0 10 0;
+#X connect 8 1 14 0;
+#X connect 9 0 3 0;
+#X connect 10 0 9 0;
+#X connect 10 1 7 1;
+#X connect 11 0 14 2;
+#X connect 12 0 11 0;
+#X connect 12 1 13 0;
+#X connect 13 0 11 1;
+#X connect 14 0 1 0;
+#X connect 15 0 6 0;
+#X connect 15 1 14 1;
+#X connect 15 2 3 0;
diff --git a/externals/gridflow/abstractions/#draw_slider.pd b/externals/gridflow/abstractions/#draw_slider.pd
new file mode 100644
index 00000000..94d9fffe
--- /dev/null
+++ b/externals/gridflow/abstractions/#draw_slider.pd
@@ -0,0 +1,57 @@
+#N canvas 330 0 950 464 10;
+#X obj 277 189 loadbang;
+#X msg 253 146 2 2 # 40 40 80 \$1;
+#X msg 277 286 40 40 80 300;
+#X obj 44 -5 inlet;
+#X obj 44 384 outlet;
+#X obj 87 91 inlet;
+#X msg 119 152 255 200 150;
+#X text 132 90 <-- colour;
+#X obj 253 -2 inlet;
+#X text 296 -3 <-- incoming values;
+#X obj 281 350 # + (10 2 # -1 -1 -1 1 1 1 1 -1 -1 -1 0 0 0 0 0 0 0
+0 0 0);
+#X msg 281 331 10 2 # \$1 \$2 \$1 \$4 \$3 \$4 \$3 \$2 \$1 \$2;
+#X obj 281 308 #to_list;
+#X obj 44 349 #draw_polygon \$1 (255 255 255);
+#X obj 470 28 args op insidecolour outsidecolour rect min max;
+#X obj 707 100 inv+;
+#X obj 253 45 -;
+#X obj 253 64 *;
+#X obj 387 283 -;
+#X obj 253 83 /;
+#X msg 387 264 \$4 \$2;
+#X obj 254 107 +;
+#X msg 442 265 \$2;
+#X obj 44 34 t a;
+#X obj 44 188 #draw_rect \$1;
+#X connect 0 0 6 0;
+#X connect 0 0 2 0;
+#X connect 1 0 24 2;
+#X connect 2 0 12 0;
+#X connect 3 0 23 0;
+#X connect 5 0 24 1;
+#X connect 6 0 24 1;
+#X connect 8 0 16 0;
+#X connect 10 0 13 2;
+#X connect 11 0 10 0;
+#X connect 12 0 11 0;
+#X connect 12 0 20 0;
+#X connect 12 0 22 0;
+#X connect 13 0 4 0;
+#X connect 14 1 24 1;
+#X connect 14 2 13 1;
+#X connect 14 3 12 0;
+#X connect 14 4 15 0;
+#X connect 14 4 16 1;
+#X connect 14 5 15 1;
+#X connect 15 0 19 1;
+#X connect 16 0 17 0;
+#X connect 17 0 19 0;
+#X connect 18 0 17 1;
+#X connect 19 0 21 0;
+#X connect 20 0 18 0;
+#X connect 21 0 1 0;
+#X connect 22 0 21 1;
+#X connect 23 0 24 0;
+#X connect 24 0 13 0;
diff --git a/externals/gridflow/abstractions/#edit_polygon.pd b/externals/gridflow/abstractions/#edit_polygon.pd
new file mode 100644
index 00000000..f1ec7e6e
--- /dev/null
+++ b/externals/gridflow/abstractions/#edit_polygon.pd
@@ -0,0 +1,64 @@
+#N canvas 210 217 686 442 10;
+#X obj 33 38 inlet;
+#X obj 33 398 outlet;
+#X obj 33 255 #draw_polygon \$1;
+#X obj 597 412 outlet attr;
+#X msg 41 208 op \$1;
+#X obj 95 232 inlet;
+#X obj 165 189 inlet;
+#X obj 41 189 args op color pos;
+#X obj 33 57 route2 grid position;
+#X obj 100 76 #mouse \, \, \, \,;
+#X obj 396 372 #transpose;
+#X obj 153 244 #store;
+#X obj 140 211 t a a;
+#X obj 123 106 t a;
+#X obj 206 105 print;
+#X obj 396 353 #outer + (-12 12);
+#X obj 284 97 # sqrt;
+#X obj 376 210 #fold |;
+#X obj 283 157 #grade;
+#X obj 284 178 #print GR;
+#X obj 361 153 #print DIST;
+#X obj 376 229 #to_float;
+#X obj 376 191 # < 16;
+#X obj 33 279 shunt 2;
+#X obj 284 78 #inner \, op sq-;
+#X obj 386 78 #transpose;
+#X obj 63 372 #draw_rect put (3 # 255 0 0) (2 2 #) \, outline 1;
+#X connect 0 0 8 0;
+#X connect 2 0 23 0;
+#X connect 4 0 2 0;
+#X connect 5 0 2 1;
+#X connect 6 0 12 0;
+#X connect 7 0 4 0;
+#X connect 7 1 2 1;
+#X connect 7 2 12 0;
+#X connect 8 0 2 0;
+#X connect 8 1 9 0;
+#X connect 8 2 1 0;
+#X connect 9 0 13 0;
+#X connect 9 1 13 0;
+#X connect 9 2 13 0;
+#X connect 9 3 13 0;
+#X connect 10 0 26 2;
+#X connect 11 0 2 2;
+#X connect 12 0 2 2;
+#X connect 12 1 11 1;
+#X connect 12 1 25 0;
+#X connect 13 0 14 0;
+#X connect 13 0 15 0;
+#X connect 13 0 24 0;
+#X connect 15 0 10 0;
+#X connect 16 0 18 0;
+#X connect 16 0 20 0;
+#X connect 16 0 22 0;
+#X connect 17 0 21 0;
+#X connect 18 0 19 0;
+#X connect 21 0 23 1;
+#X connect 22 0 17 0;
+#X connect 23 0 1 0;
+#X connect 23 1 26 0;
+#X connect 24 0 16 0;
+#X connect 25 0 24 1;
+#X connect 26 0 1 0;
diff --git a/externals/gridflow/abstractions/#extract_diagonal.pd b/externals/gridflow/abstractions/#extract_diagonal.pd
new file mode 100644
index 00000000..c40db2ef
--- /dev/null
+++ b/externals/gridflow/abstractions/#extract_diagonal.pd
@@ -0,0 +1,22 @@
+#N canvas 534 165 450 300 10;
+#X obj 19 20 inlet matrix;
+#X obj 19 206 outlet diagonal_vector;
+#X obj 85 39 #dim;
+#X obj 19 152 #store;
+#X obj 19 39 t a a;
+#X obj 19 58 #finished;
+#X obj 19 103 #for 0 0 1;
+#X obj 85 58 #to_list;
+#X msg 85 77 \$1;
+#X obj 19 122 #outer + (0 0);
+#X connect 0 0 4 0;
+#X connect 2 0 7 0;
+#X connect 3 0 1 0;
+#X connect 4 0 5 0;
+#X connect 4 1 2 0;
+#X connect 4 1 3 1;
+#X connect 5 0 6 0;
+#X connect 6 0 9 0;
+#X connect 7 0 8 0;
+#X connect 8 0 6 1;
+#X connect 9 0 3 0;
diff --git a/externals/gridflow/abstractions/#fade.pd b/externals/gridflow/abstractions/#fade.pd
new file mode 100644
index 00000000..007597f3
--- /dev/null
+++ b/externals/gridflow/abstractions/#fade.pd
@@ -0,0 +1,35 @@
+#N canvas 398 352 418 256 10;
+#X obj 21 65 inlet;
+#X obj 21 233 outlet;
+#X obj 21 147 # +;
+#X obj 37 128 # *;
+#X obj 156 64 inlet;
+#X text 20 7 new = (x-1)/x of old input + 1/x of new input;
+#X obj 53 109 # - 1;
+#X text 198 65 select fade rate;
+#X text 61 65 input;
+#X text 70 236 output;
+#X obj 21 166 # +;
+#X obj 46 166 # / 2;
+#X obj 156 86 t a;
+#X text 19 21 now rounds to closest;
+#X obj 21 187 # *>>8;
+#X obj 70 188 # inv* 256;
+#X obj 21 213 t a a;
+#X text 19 34 also faster (uses *>>8 instead of /);
+#X obj 190 107 args (slope a 1);
+#X connect 0 0 2 0;
+#X connect 2 0 10 0;
+#X connect 3 0 2 1;
+#X connect 4 0 12 0;
+#X connect 6 0 3 1;
+#X connect 10 0 14 0;
+#X connect 11 0 10 1;
+#X connect 12 0 11 0;
+#X connect 12 0 6 0;
+#X connect 12 0 15 0;
+#X connect 14 0 16 0;
+#X connect 15 0 14 1;
+#X connect 16 0 1 0;
+#X connect 16 1 3 0;
+#X connect 18 0 12 0;
diff --git a/externals/gridflow/abstractions/#fade_lin.pd b/externals/gridflow/abstractions/#fade_lin.pd
new file mode 100644
index 00000000..0a2916e9
--- /dev/null
+++ b/externals/gridflow/abstractions/#fade_lin.pd
@@ -0,0 +1,27 @@
+#N canvas 614 446 450 300 10;
+#X obj 68 16 inlet;
+#X obj 92 146 outlet;
+#X obj 95 61 # -;
+#X obj 155 16 inlet;
+#X obj 65 123 # +;
+#X obj 95 124 t a;
+#X obj 78 101 # max -1;
+#X obj 78 81 # min 1;
+#X obj 195 16 inlet;
+#X obj 132 101 # inv+ 0;
+#X obj 68 35 t a;
+#X obj 151 56 args (maxraise a 1) (maxdrop a 1);
+#X connect 0 0 10 0;
+#X connect 2 0 7 0;
+#X connect 3 0 7 1;
+#X connect 4 0 5 0;
+#X connect 5 0 4 1;
+#X connect 5 0 1 0;
+#X connect 5 0 2 1;
+#X connect 6 0 4 0;
+#X connect 7 0 6 0;
+#X connect 8 0 9 0;
+#X connect 9 0 6 1;
+#X connect 10 0 2 0;
+#X connect 11 0 7 1;
+#X connect 11 1 9 0;
diff --git a/externals/gridflow/abstractions/#fastblur.pd b/externals/gridflow/abstractions/#fastblur.pd
new file mode 100644
index 00000000..96156c03
--- /dev/null
+++ b/externals/gridflow/abstractions/#fastblur.pd
@@ -0,0 +1,89 @@
+#N canvas 330 194 632 389 10;
+#X obj 18 129 #border (0 0 0) (0 0 0);
+#X obj 48 226 #convolve (1 1 # 1) \, wrap 0;
+#X obj 96 110 # / 2;
+#X obj 18 55 inlet image;
+#X obj 18 349 outlet image;
+#X obj 196 50 inlet kernelSize;
+#X obj 334 171 # == 0;
+#X obj 65 311 # inv* 65536;
+#X obj 178 31 args kernelSize;
+#X obj 18 311 # *>>8;
+#X obj 18 330 # >> 8;
+#X obj 177 88 #join 0 (1);
+#X obj 153 311 #fold *;
+#X obj 334 94 #unpack 3;
+#X obj 48 284 #convolve (1 1 # 1) \, wrap 0;
+#X obj 334 133 t b l;
+#X obj 334 152 #for (0) (0) (1);
+#X obj 334 190 # inv+;
+#X obj 457 171 # == 0;
+#X obj 457 133 t b l;
+#X obj 457 152 #for (0) (0) (1);
+#X obj 457 190 # inv+;
+#X obj 18 148 shunt;
+#X obj 18 245 shunt;
+#X obj 457 228 #transpose;
+#X obj 183 129 # / 2;
+#X obj 334 209 #join 0 (1 1 # 1);
+#X obj 457 209 #join 0 (1 1 # 1);
+#X msg 146 44 3 3;
+#X obj 57 245 != 1;
+#X obj 57 148 != 1;
+#X obj 48 265 #scan + \, seed (3 #);
+#X obj 48 207 #scan + \, seed (0 3 #);
+#X msg 199 207 seed ( \$2 3 #);
+#X obj 87 167 #dim;
+#X obj 119 167 #to_list;
+#X obj 48 167 t a a;
+#X obj 182 69 # max (1 1);
+#X obj 96 91 # - 1;
+#X connect 0 0 22 0;
+#X connect 1 0 23 0;
+#X connect 2 0 0 1;
+#X connect 3 0 0 0;
+#X connect 5 0 37 0;
+#X connect 6 0 17 0;
+#X connect 7 0 9 1;
+#X connect 8 0 37 0;
+#X connect 9 0 10 0;
+#X connect 10 0 4 0;
+#X connect 11 0 12 0;
+#X connect 11 0 13 0;
+#X connect 11 0 25 0;
+#X connect 11 0 38 0;
+#X connect 12 0 7 0;
+#X connect 13 0 15 0;
+#X connect 13 0 30 0;
+#X connect 13 1 19 0;
+#X connect 13 1 29 0;
+#X connect 14 0 9 0;
+#X connect 15 0 16 0;
+#X connect 15 1 16 1;
+#X connect 16 0 6 0;
+#X connect 17 0 26 0;
+#X connect 18 0 21 0;
+#X connect 19 0 20 0;
+#X connect 19 1 20 1;
+#X connect 20 0 18 0;
+#X connect 21 0 27 0;
+#X connect 22 0 23 0;
+#X connect 22 1 36 0;
+#X connect 23 0 9 0;
+#X connect 23 1 31 0;
+#X connect 24 0 14 1;
+#X connect 25 0 0 2;
+#X connect 26 0 1 1;
+#X connect 27 0 24 0;
+#X connect 28 0 11 0;
+#X connect 29 0 23 1;
+#X connect 30 0 22 1;
+#X connect 31 0 14 0;
+#X connect 32 0 1 0;
+#X connect 33 0 32 0;
+#X connect 34 0 35 0;
+#X connect 35 0 33 0;
+#X connect 36 0 32 0;
+#X connect 36 1 34 0;
+#X connect 37 0 11 0;
+#X connect 38 0 2 0;
diff --git a/externals/gridflow/abstractions/#gamma.pd b/externals/gridflow/abstractions/#gamma.pd
new file mode 100644
index 00000000..8963260c
--- /dev/null
+++ b/externals/gridflow/abstractions/#gamma.pd
@@ -0,0 +1,21 @@
+#N canvas 0 0 450 300 10;
+#X obj 27 202 outlet image;
+#X obj 27 22 inlet image;
+#X obj 235 73 loadbang;
+#X obj 235 97 \$1;
+#X obj 263 97 inlet gamma;
+#X obj 235 136 #for 0 256 1;
+#X obj 235 162 # gamma;
+#X obj 27 115 #store;
+#X obj 27 82 #outer ignore (0);
+#X obj 235 117 t b f;
+#X connect 1 0 8 0;
+#X connect 2 0 3 0;
+#X connect 3 0 9 0;
+#X connect 4 0 3 0;
+#X connect 5 0 6 0;
+#X connect 6 0 7 1;
+#X connect 7 0 0 0;
+#X connect 8 0 7 0;
+#X connect 9 0 5 0;
+#X connect 9 1 6 1;
diff --git a/externals/gridflow/abstractions/#greyscale_to_rgb.pd b/externals/gridflow/abstractions/#greyscale_to_rgb.pd
new file mode 100644
index 00000000..47dfdd6e
--- /dev/null
+++ b/externals/gridflow/abstractions/#greyscale_to_rgb.pd
@@ -0,0 +1,6 @@
+#N canvas 550 233 335 174 10;
+#X obj 10 10 inlet;
+#X obj 10 48 outlet;
+#X obj 10 29 #inner (1 3 # 1 1 1);
+#X connect 0 0 2 0;
+#X connect 2 0 1 0;
diff --git a/externals/gridflow/abstractions/#hello.pd b/externals/gridflow/abstractions/#hello.pd
new file mode 100644
index 00000000..b094c9ff
--- /dev/null
+++ b/externals/gridflow/abstractions/#hello.pd
@@ -0,0 +1,28 @@
+#N canvas 165 50 305 255 10;
+#X obj -6 38 # / 320;
+#X obj -6 114 # * 255;
+#X obj -6 95 # != 0;
+#X obj -6 57 # inv+ 7;
+#X obj -6 19 # * 7;
+#X obj -6 76 #outer & (2 4 1);
+#X obj -6 -76 inlet;
+#X obj -6 -19 #for (0 0) (0 0) (1 1);
+#X obj -6 -57 t a a;
+#X obj -6 -38 #finished;
+#X obj -6 0 #inner (0 1);
+#X obj 184 -40 #inner (0 1);
+#X obj -6 133 outlet;
+#X connect 0 0 3 0;
+#X connect 1 0 12 0;
+#X connect 2 0 1 0;
+#X connect 3 0 5 0;
+#X connect 4 0 0 0;
+#X connect 5 0 2 0;
+#X connect 6 0 8 0;
+#X connect 7 0 10 0;
+#X connect 8 0 9 0;
+#X connect 8 1 7 1;
+#X connect 8 1 11 0;
+#X connect 9 0 7 0;
+#X connect 10 0 4 0;
+#X connect 11 0 0 1;
diff --git a/externals/gridflow/abstractions/#hueshift.pd b/externals/gridflow/abstractions/#hueshift.pd
new file mode 100644
index 00000000..13195952
--- /dev/null
+++ b/externals/gridflow/abstractions/#hueshift.pd
@@ -0,0 +1,29 @@
+#N canvas 581 130 450 278 10;
+#X obj 13 105 inlet;
+#X obj 13 162 outlet;
+#X obj 59 48 #rgb_to_yuv;
+#X obj 59 124 #yuv_to_rgb;
+#X obj 59 67 # - 128;
+#X obj 59 105 # + 128;
+#X obj 171 10 inlet;
+#X obj 59 86 #rotate \, axis 1 2 3;
+#X obj 59 7 loadbang;
+#X obj 171 29 t b f;
+#X obj 13 124 #inner;
+#X msg 59 29 3 3 # 256 0 0 0;
+#X obj 13 143 # >> 8;
+#X obj 212 29 args (rotate a 0);
+#X connect 0 0 10 0;
+#X connect 2 0 4 0;
+#X connect 3 0 10 1;
+#X connect 4 0 7 0;
+#X connect 5 0 3 0;
+#X connect 6 0 9 0;
+#X connect 7 0 5 0;
+#X connect 8 0 11 0;
+#X connect 9 0 11 0;
+#X connect 9 1 7 1;
+#X connect 10 0 12 0;
+#X connect 11 0 2 0;
+#X connect 12 0 1 0;
+#X connect 13 0 9 0;
diff --git a/externals/gridflow/abstractions/#in.pd b/externals/gridflow/abstractions/#in.pd
new file mode 100644
index 00000000..49459bce
--- /dev/null
+++ b/externals/gridflow/abstractions/#in.pd
@@ -0,0 +1,59 @@
+#N canvas 457 271 567 388 10;
+#X obj 19 20 inlet;
+#X obj 19 316 outlet;
+#X obj 163 297 outlet;
+#X obj 333 101 args *;
+#N canvas 116 23 450 300 \$0-placeholder 0;
+#X obj 0 0 r 1085-in;
+#X obj 0 40 s 1085-out;
+#X obj 0 20 gf.not_open;
+#X connect 0 0 2 0;
+#X connect 2 0 1 0;
+#X restore 19 239 pd \$0-placeholder;
+#X obj 19 220 s \$0-in;
+#X obj 19 258 r \$0-out;
+#X obj 19 170 route bang;
+#X msg 19 190 bang;
+#X text 53 191 hack.;
+#X obj 333 156 gf.io_generate \$0 in;
+#X msg 342 131 bang;
+#X msg 135 15 open \$1 \, bang \, close;
+#X obj 19 58 list;
+#X obj 113 58 list;
+#X obj 172 257 spigot 1;
+#X obj 172 238 route bang;
+#X msg 172 276 rewind \, bang;
+#X obj 19 39 route open close load loop set float;
+#X msg 183 149 seek \$1;
+#X msg 224 184 seek \$1 \, bang;
+#X obj 19 297 route2 grid not_open;
+#X msg 86 316 bang;
+#X obj 333 175 s pd-\$0-placeholder;
+#X connect 0 0 18 0;
+#X connect 3 0 10 0;
+#X connect 6 0 16 0;
+#X connect 6 0 21 0;
+#X connect 7 0 8 0;
+#X connect 7 1 5 0;
+#X connect 8 0 5 0;
+#X connect 10 0 23 0;
+#X connect 11 0 10 0;
+#X connect 12 0 18 0;
+#X connect 13 0 10 0;
+#X connect 14 0 12 0;
+#X connect 15 0 17 0;
+#X connect 16 0 15 0;
+#X connect 17 0 18 0;
+#X connect 18 0 13 0;
+#X connect 18 1 11 0;
+#X connect 18 2 14 0;
+#X connect 18 3 15 1;
+#X connect 18 4 19 0;
+#X connect 18 5 20 0;
+#X connect 18 6 7 0;
+#X connect 19 0 5 0;
+#X connect 20 0 5 0;
+#X connect 21 0 1 0;
+#X connect 21 1 22 0;
+#X connect 21 2 2 0;
+#X connect 22 0 2 0;
diff --git a/externals/gridflow/abstractions/#line_to_polygon.pd b/externals/gridflow/abstractions/#line_to_polygon.pd
new file mode 100644
index 00000000..3f85aaa0
--- /dev/null
+++ b/externals/gridflow/abstractions/#line_to_polygon.pd
@@ -0,0 +1,44 @@
+#N canvas 667 260 450 300 10;
+#X obj 45 57 inlet;
+#X obj 45 235 outlet;
+#X obj 170 75 #redim (2);
+#X obj 45 216 # +;
+#X obj 170 94 #rotate 9000;
+#X obj 170 176 # *;
+#X obj 170 199 # /;
+#X obj 170 113 #t;
+#X obj 205 114 # sq-;
+#X obj 205 133 #fold +;
+#X obj 205 152 # sqrt;
+#X obj 297 176 inlet;
+#X obj 265 176 f \$1;
+#X obj 265 157 loadbang;
+#X obj 61 95 #reverse;
+#X obj 45 76 #t;
+#X obj 45 126 #join 0;
+#X obj 75 216 #outer *;
+#X msg 75 197 -1 -1 1 1;
+#X obj 45 145 t a b;
+#X connect 0 0 15 0;
+#X connect 2 0 4 0;
+#X connect 3 0 1 0;
+#X connect 4 0 7 0;
+#X connect 5 0 6 0;
+#X connect 6 0 17 1;
+#X connect 7 0 5 0;
+#X connect 7 1 8 0;
+#X connect 8 0 9 0;
+#X connect 9 0 10 0;
+#X connect 10 0 6 1;
+#X connect 11 0 12 0;
+#X connect 12 0 5 1;
+#X connect 13 0 12 0;
+#X connect 14 0 16 1;
+#X connect 15 0 16 0;
+#X connect 15 1 2 0;
+#X connect 15 1 14 0;
+#X connect 16 0 19 0;
+#X connect 17 0 3 1;
+#X connect 18 0 17 0;
+#X connect 19 0 3 0;
+#X connect 19 1 18 0;
diff --git a/externals/gridflow/abstractions/#make_cross.pd b/externals/gridflow/abstractions/#make_cross.pd
new file mode 100644
index 00000000..016458c7
--- /dev/null
+++ b/externals/gridflow/abstractions/#make_cross.pd
@@ -0,0 +1,30 @@
+#N canvas 374 339 450 300 10;
+#X obj 27 247 outlet;
+#X obj 27 25 inlet point;
+#X obj 116 22 inlet size;
+#X obj 27 63 #finished;
+#X obj 27 180 #outer *;
+#X msg 27 161 1 -1;
+#X obj 27 199 #redim (12 2);
+#X obj 27 228 # +;
+#X obj 62 121 # + 1;
+#X obj 27 44 t a a b;
+#X obj 62 102 # * 16;
+#X obj 62 140 # * (6 2 # 1 1 1 1 1 1 -1 1 -1 1 -1 1);
+#X msg 62 83 6 2 # 1 0 0 0 0 1 0 1 0 0 1 0;
+#X obj 127 60 args (size a 16);
+#X connect 1 0 9 0;
+#X connect 2 0 10 1;
+#X connect 3 0 5 0;
+#X connect 4 0 6 0;
+#X connect 5 0 4 0;
+#X connect 6 0 7 0;
+#X connect 7 0 0 0;
+#X connect 8 0 11 0;
+#X connect 9 0 3 0;
+#X connect 9 1 7 1;
+#X connect 9 2 12 0;
+#X connect 10 0 8 0;
+#X connect 11 0 4 1;
+#X connect 12 0 10 0;
+#X connect 13 0 10 1;
diff --git a/externals/gridflow/abstractions/#moment_polar.pd b/externals/gridflow/abstractions/#moment_polar.pd
new file mode 100644
index 00000000..8aaa0393
--- /dev/null
+++ b/externals/gridflow/abstractions/#moment_polar.pd
@@ -0,0 +1,54 @@
+#N canvas 247 203 690 456 10;
+#X obj 21 20 inlet 2nd_moment_matrix;
+#X obj 21 419 outlet angle;
+#X obj 21 208 #grade;
+#X obj 53 88 #transpose;
+#X obj 21 285 #store;
+#X obj 21 189 # inv+ (f #);
+#X text 76 211 sort eigenvectors;
+#X text 76 223 by eigenvalues downwards;
+#X obj 21 266 #redim (1);
+#X obj 21 342 # atan;
+#X obj 21 304 #unpack;
+#X obj 74 304 #pack 1 f;
+#X obj 21 323 #pack 1 f;
+#X text 29 358 angle of (one of the two) longest radius;
+#X text 113 247 but pick only biggest;
+#X text 96 70 eigenvectors (axes of the ellipse);
+#X text 28 370 centidegrees 0..35999;
+#X text 27 148 squareroots of eigenvalues (radiuses of the ellipse)
+;
+#X obj 21 165 #t;
+#X obj 147 296 #store;
+#X text 185 21 (float);
+#X obj 21 132 # sqrt (f #);
+#X obj 21 45 #cast f;
+#X obj 21 396 #to_float;
+#X obj 21 238 #t;
+#X obj 147 277 #outer + (0);
+#X obj 134 420 outlet radiuses_sorted;
+#X obj 21 69 cv/#SVD;
+#X obj 21 112 #extract_diagonal;
+#X connect 0 0 22 0;
+#X connect 2 0 24 0;
+#X connect 3 0 4 1;
+#X connect 4 0 10 0;
+#X connect 5 0 2 0;
+#X connect 8 0 4 0;
+#X connect 9 0 23 0;
+#X connect 10 0 12 0;
+#X connect 10 1 11 0;
+#X connect 11 0 9 1;
+#X connect 12 0 9 0;
+#X connect 18 0 5 0;
+#X connect 18 1 19 1;
+#X connect 19 0 26 0;
+#X connect 21 0 18 0;
+#X connect 22 0 27 0;
+#X connect 23 0 1 0;
+#X connect 24 0 8 0;
+#X connect 24 1 25 0;
+#X connect 25 0 19 0;
+#X connect 27 0 28 0;
+#X connect 27 1 3 0;
+#X connect 28 0 21 0;
diff --git a/externals/gridflow/abstractions/#motion_detection.pd b/externals/gridflow/abstractions/#motion_detection.pd
new file mode 100644
index 00000000..c39953b8
--- /dev/null
+++ b/externals/gridflow/abstractions/#motion_detection.pd
@@ -0,0 +1,142 @@
+#N canvas 932 467 705 527 10;
+#X obj 53 -47 inlet camera_input;
+#X obj 183 -1 inlet motion_or_presence;
+#X obj 53 420 outlet to_window;
+#X obj 53 130 # max 0;
+#X obj 71 88 hsl 128 15 0 127 0 0 empty empty empty -2 -6 0 8 -260818
+-1 -1 0 1;
+#X obj 53 110 # -;
+#X text 107 130 noise reduction (on find-edges only);
+#X obj 108 11 vradio 15 1 0 2 empty empty empty 0 -6 0 8 -241291 -1
+-1 0;
+#X text 128 25 emboss;
+#X text 127 11 hilite;
+#N canvas 372 198 399 273 image 0;
+#X obj 15 113 # << 2;
+#X obj 15 162 # abs-;
+#X obj 15 9 inlet;
+#X obj 18 80 # -;
+#X obj 70 174 # + 128;
+#X obj 15 245 outlet;
+#X obj 15 204 # min 255;
+#X obj 15 224 # max 0;
+#X obj 70 155 # << 2;
+#X obj 15 35 t a a;
+#X obj 15 134 shunt 2;
+#X obj 70 133 inlet render;
+#X obj 155 54 inlet type;
+#X obj 15 54 shunt 2;
+#X connect 0 0 10 0;
+#X connect 1 0 6 0;
+#X connect 2 0 9 0;
+#X connect 3 0 0 0;
+#X connect 4 0 6 0;
+#X connect 6 0 7 0;
+#X connect 7 0 5 0;
+#X connect 8 0 4 0;
+#X connect 9 0 13 0;
+#X connect 9 1 3 0;
+#X connect 10 0 1 0;
+#X connect 10 1 8 0;
+#X connect 11 0 10 1;
+#X connect 12 0 13 1;
+#X connect 13 0 3 1;
+#X restore 53 52 pd image difference;
+#N canvas 52 305 399 248 motion 0;
+#X obj 60 49 inlet;
+#X obj 60 72 # +;
+#X obj 60 158 outlet;
+#X msg 108 51 0;
+#X obj 60 142 t a a;
+#X text 164 114 divide by 32 \, 16 \, 4;
+#X text 4 1 we do like #fade but faster (because of >>);
+#X text 4 15 feedback factors are 1/32 for red \, 1/16 for green \,
+1/8 for blue.;
+#X obj 175 85 # * (31 15 3);
+#X obj 60 114 # >> (5 4 2);
+#X connect 0 0 1 0;
+#X connect 1 0 9 0;
+#X connect 3 0 1 1;
+#X connect 4 0 2 0;
+#X connect 4 1 8 0;
+#X connect 8 0 1 1;
+#X connect 9 0 4 0;
+#X restore 80 206 pd motion fade;
+#X obj 398 91 tgl 15 0 empty empty empty 0 -6 0 8 -241291 -1 -1 0 1
+;
+#X obj 53 275 shunt 2;
+#X obj 173 298 #centroid;
+#X obj 168 342 #to_list;
+#X obj 163 370 unpack 0 0;
+#N canvas 547 147 477 267 crosshair 0;
+#X obj 12 224 outlet;
+#X obj 12 9 inlet;
+#X msg 21 125 12 2 # \$1 \$2 \$1 \$3 \$2 \$3 \$2 \$4 \$3 \$4 \$3 \$3
+\$4 \$3 \$4 \$2 \$3 \$2 \$3 \$1 \$2 \$1 \$2 \$2;
+#X obj 175 37 #fade 8;
+#X obj 175 18 inlet;
+#X obj 170 60 #finished;
+#X msg 54 95 -8 -1 1 8;
+#X obj 95 169 # + (120 160);
+#X obj 12 205 #draw_polygon + (0 170 0);
+#X connect 1 0 8 0;
+#X connect 2 0 7 0;
+#X connect 3 0 5 0;
+#X connect 3 0 7 1;
+#X connect 4 0 3 0;
+#X connect 5 0 6 0;
+#X connect 6 0 2 0;
+#X connect 7 0 8 2;
+#X connect 8 0 0 0;
+#X restore 92 320 pd crosshair;
+#X obj 53 373 t a;
+#X text 422 91 designed to work with "hilite" above;
+#X obj 170 274 #rgb_to_greyscale;
+#X obj 333 278 #fold +;
+#X obj 333 300 #fold +;
+#X obj 333 320 #fold +;
+#X obj 333 340 #to_float;
+#X obj 333 360 / 100;
+#X obj 398 66 inlet crosshair;
+#X obj 333 418 outlet displaced_pixels;
+#X obj 163 419 outlet;
+#X obj 220 419 outlet;
+#X obj 68 -25 inlet noise_reduction;
+#X obj 53 185 shunt;
+#X obj 111 152 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1
+1;
+#X obj 301 36 inlet fade;
+#X obj 53 150 t a a;
+#X connect 0 0 10 0;
+#X connect 1 0 10 2;
+#X connect 3 0 34 0;
+#X connect 4 0 5 1;
+#X connect 5 0 3 0;
+#X connect 7 0 10 1;
+#X connect 10 0 5 0;
+#X connect 11 0 13 0;
+#X connect 12 0 13 1;
+#X connect 13 0 18 0;
+#X connect 13 1 17 0;
+#X connect 13 1 20 0;
+#X connect 14 0 15 0;
+#X connect 14 0 17 1;
+#X connect 15 0 16 0;
+#X connect 16 0 28 0;
+#X connect 16 1 29 0;
+#X connect 17 0 18 0;
+#X connect 18 0 2 0;
+#X connect 20 0 14 0;
+#X connect 21 0 22 0;
+#X connect 22 0 23 0;
+#X connect 23 0 24 0;
+#X connect 24 0 25 0;
+#X connect 25 0 27 0;
+#X connect 26 0 12 0;
+#X connect 30 0 4 0;
+#X connect 31 0 13 0;
+#X connect 31 1 11 0;
+#X connect 32 0 31 1;
+#X connect 33 0 32 0;
+#X connect 34 0 31 0;
+#X connect 34 1 21 0;
diff --git a/externals/gridflow/abstractions/#mouse.pd b/externals/gridflow/abstractions/#mouse.pd
new file mode 100644
index 00000000..479f6e13
--- /dev/null
+++ b/externals/gridflow/abstractions/#mouse.pd
@@ -0,0 +1,93 @@
+#N canvas 313 211 690 428 10;
+#X obj 23 103 listsublist 0 2;
+#X obj 48 64 t a a;
+#X obj 126 181 t a a;
+#X text 153 149 is button pressed?;
+#X obj 129 209 -;
+#X obj 125 150 > 0;
+#X obj 183 86 listelement 2;
+#X obj 120 377 outlet;
+#X text 161 183 1=click \, 0=nochange \, -1=unclick;
+#X text 157 36 list (y \, x \, buttons);
+#X obj 49 8 inlet;
+#X obj 48 34 route position;
+#X text 93 8 compatible with output of [#out window];
+#X obj 142 246 inv+ 1;
+#X obj 98 397 outlet;
+#X obj 142 356 outlet;
+#X text 431 330 three toggle-compatible outputs;
+#X text 432 346 and one +1/0/-1 for the wheel;
+#X text 147 397 click;
+#X text 193 357 unclick;
+#X obj 468 60 listelement 2;
+#X obj 430 301 outlet;
+#X obj 480 301 outlet;
+#X obj 530 301 outlet;
+#X obj 580 301 outlet;
+#X obj 430 273 change;
+#X obj 108 63 t a a;
+#X obj 469 115 # & 1;
+#X obj 469 173 unpack 0 0 0 0 0;
+#X obj 549 241 inv+;
+#X obj 480 274 change;
+#X obj 530 275 change;
+#X obj 580 276 change;
+#X obj 469 145 #to_list;
+#X obj 163 335 outlet;
+#X text 172 378 drag;
+#X text 214 337 move;
+#X obj 163 275 inv+ 1;
+#X obj 389 16 inlet;
+#X text 433 9 list of 3 toggles;
+#X text 434 23 which buttons should be active;
+#X obj 345 107 #fold +;
+#X obj 345 131 #to_float;
+#X obj 125 126 &;
+#X text 151 126 check only wanted buttons;
+#X obj 305 33 loadbang;
+#X msg 305 57 1 1 1;
+#X obj 98 269 shunt 3;
+#X obj 120 302 shunt 2;
+#X obj 347 81 # << (8 9 10);
+#X obj 468 86 #outer >> (8 9 10 11 12);
+#X connect 0 0 47 0;
+#X connect 1 0 0 0;
+#X connect 1 1 6 0;
+#X connect 2 0 4 1;
+#X connect 2 1 4 0;
+#X connect 2 1 37 0;
+#X connect 4 0 13 0;
+#X connect 5 0 2 0;
+#X connect 6 0 43 0;
+#X connect 10 0 11 0;
+#X connect 11 0 26 0;
+#X connect 13 0 47 1;
+#X connect 20 0 50 0;
+#X connect 25 0 21 0;
+#X connect 26 0 1 0;
+#X connect 26 1 20 0;
+#X connect 27 0 33 0;
+#X connect 28 0 25 0;
+#X connect 28 1 30 0;
+#X connect 28 2 31 0;
+#X connect 28 3 29 0;
+#X connect 28 4 29 1;
+#X connect 29 0 32 0;
+#X connect 30 0 22 0;
+#X connect 31 0 23 0;
+#X connect 32 0 24 0;
+#X connect 33 0 28 0;
+#X connect 37 0 48 1;
+#X connect 38 0 49 0;
+#X connect 41 0 42 0;
+#X connect 42 0 43 1;
+#X connect 43 0 5 0;
+#X connect 45 0 46 0;
+#X connect 46 0 49 0;
+#X connect 47 0 14 0;
+#X connect 47 1 48 0;
+#X connect 47 2 15 0;
+#X connect 48 0 7 0;
+#X connect 48 1 34 0;
+#X connect 49 0 41 0;
+#X connect 50 0 27 0;
diff --git a/externals/gridflow/abstractions/#out.pd b/externals/gridflow/abstractions/#out.pd
new file mode 100644
index 00000000..a1957afc
--- /dev/null
+++ b/externals/gridflow/abstractions/#out.pd
@@ -0,0 +1,51 @@
+#N canvas 678 294 470 356 10;
+#X obj 99 10 inlet;
+#X obj 288 213 outlet;
+#X obj 320 18 args *;
+#N canvas 116 23 450 300 \$0-placeholder 0;
+#X obj 0 0 r 1090-in;
+#X obj 0 40 s 1090-out;
+#X obj 0 20 gf.not_open;
+#X connect 0 0 2 0;
+#X connect 2 0 1 0;
+#X restore 288 175 pd \$0-placeholder;
+#X obj 288 156 s \$0-in;
+#X obj 288 194 r \$0-out;
+#X obj 288 118 route bang;
+#X msg 288 137 bang;
+#X text 325 139 hack.;
+#X obj 99 59 route open close autoclose;
+#X obj 252 118 t a a;
+#X obj 99 283 spigot;
+#X obj 25 216 route bang;
+#X msg 25 236 1;
+#X obj 128 229 #finished;
+#X obj 128 184 route2 grid list float;
+#X msg 99 302 close;
+#X obj 320 60 gf.io_generate \$0 out;
+#X msg 150 78 bang;
+#X obj 320 79 s pd-\$0-placeholder;
+#X connect 0 0 9 0;
+#X connect 2 0 17 0;
+#X connect 5 0 1 0;
+#X connect 6 0 7 0;
+#X connect 6 1 4 0;
+#X connect 7 0 4 0;
+#X connect 9 0 17 0;
+#X connect 9 1 18 0;
+#X connect 9 2 12 0;
+#X connect 9 3 10 0;
+#X connect 10 0 15 0;
+#X connect 10 1 6 0;
+#X connect 11 0 16 0;
+#X connect 12 0 13 0;
+#X connect 12 1 11 1;
+#X connect 13 0 11 1;
+#X connect 14 0 11 0;
+#X connect 14 0 1 0;
+#X connect 15 0 14 0;
+#X connect 15 1 14 0;
+#X connect 15 2 14 0;
+#X connect 16 0 9 0;
+#X connect 17 0 19 0;
+#X connect 18 0 17 0;
diff --git a/externals/gridflow/abstractions/#polygon_area.pd b/externals/gridflow/abstractions/#polygon_area.pd
new file mode 100644
index 00000000..55daf54f
--- /dev/null
+++ b/externals/gridflow/abstractions/#polygon_area.pd
@@ -0,0 +1,19 @@
+#N canvas 44 398 450 214 10;
+#X obj 24 25 inlet;
+#X obj 24 63 #convolve (2 1 # 0 1);
+#X obj 24 82 #convolve (1 2 # 0 1);
+#X obj 24 101 # *;
+#X obj 24 44 #t;
+#X obj 24 120 #fold inv+;
+#X obj 24 139 #fold +;
+#X obj 24 177 outlet;
+#X obj 24 158 # / 2;
+#X connect 0 0 4 0;
+#X connect 1 0 2 0;
+#X connect 2 0 3 0;
+#X connect 3 0 5 0;
+#X connect 4 0 1 0;
+#X connect 4 1 3 1;
+#X connect 5 0 6 0;
+#X connect 6 0 8 0;
+#X connect 8 0 7 0;
diff --git a/externals/gridflow/abstractions/#polygon_comparator.pd b/externals/gridflow/abstractions/#polygon_comparator.pd
new file mode 100644
index 00000000..32da8e59
--- /dev/null
+++ b/externals/gridflow/abstractions/#polygon_comparator.pd
@@ -0,0 +1,99 @@
+#N canvas 415 302 865 491 10;
+#X obj 13 13 inlet left;
+#X obj 183 22 inlet right;
+#X obj 13 32 route2 precision;
+#X obj 33 383 outlet result;
+#X obj 183 109 #polygon_radial_map;
+#X obj 183 225 #fft;
+#X obj 33 225 #fft;
+#X obj 33 263 #fft \, sign -1;
+#N canvas 0 0 450 300 (subpatch) 0;
+#X array \$0-table 256 float 2;
+#X coords 0 1 256 0 200 140 1;
+#X restore 405 42 graph;
+#X obj 33 109 #polygon_radial_map;
+#X obj 33 168 #redim (1 256 1);
+#X obj 183 168 #redim (1 256 1);
+#X obj 33 206 #cast f;
+#X obj 33 187 #outer * (1 0);
+#X obj 183 187 #outer * (1 0);
+#X obj 183 206 #cast f;
+#X obj 33 329 #inner (2 f # 1 0) \, seed (f # 0);
+#X obj 33 348 #redim (256);
+#X obj 33 244 # C.*conj (2 f # 1 0);
+#X obj 33 128 #t;
+#X obj 183 128 #t;
+#X obj 208 129 # sq-;
+#X obj 247 129 #fold +;
+#X obj 58 129 # sq-;
+#X obj 97 129 #fold +;
+#X obj 224 237 # *;
+#X obj 247 148 #cast f;
+#X obj 97 148 #cast f;
+#X obj 224 256 # sqrt (f #);
+#X obj 33 301 # / (f # 1);
+#X obj 33 282 # / (f # 256);
+#X obj 183 59 #t;
+#X obj 208 59 #polygon_moment;
+#X obj 183 80 # -;
+#X obj 33 58 #t;
+#X obj 58 58 #polygon_moment;
+#X obj 33 79 # -;
+#X obj 330 437 f;
+#X obj 216 456 tabwrite \$0-table;
+#X obj 216 420 t f b;
+#X msg 346 418 0;
+#X obj 355 437 + 1;
+#X obj 216 373 t a b;
+#X obj 216 401 #to_float;
+#X connect 0 0 2 0;
+#X connect 1 0 31 0;
+#X connect 2 0 4 0;
+#X connect 2 0 9 0;
+#X connect 2 1 34 0;
+#X connect 4 0 20 0;
+#X connect 5 0 18 1;
+#X connect 6 0 18 0;
+#X connect 7 0 30 0;
+#X connect 9 0 19 0;
+#X connect 10 0 13 0;
+#X connect 11 0 14 0;
+#X connect 12 0 6 0;
+#X connect 13 0 12 0;
+#X connect 14 0 15 0;
+#X connect 15 0 5 0;
+#X connect 16 0 17 0;
+#X connect 17 0 3 0;
+#X connect 17 0 42 0;
+#X connect 18 0 7 0;
+#X connect 19 0 10 0;
+#X connect 19 1 23 0;
+#X connect 20 0 11 0;
+#X connect 20 1 21 0;
+#X connect 21 0 22 0;
+#X connect 22 0 26 0;
+#X connect 23 0 24 0;
+#X connect 24 0 27 0;
+#X connect 25 0 28 0;
+#X connect 26 0 25 1;
+#X connect 27 0 25 0;
+#X connect 28 0 29 1;
+#X connect 29 0 16 0;
+#X connect 30 0 29 0;
+#X connect 31 0 33 0;
+#X connect 31 1 32 0;
+#X connect 32 0 33 1;
+#X connect 33 0 4 0;
+#X connect 34 0 36 0;
+#X connect 34 1 35 0;
+#X connect 35 0 36 1;
+#X connect 36 0 9 0;
+#X connect 37 0 41 0;
+#X connect 37 0 38 1;
+#X connect 39 0 38 0;
+#X connect 39 1 37 0;
+#X connect 40 0 37 1;
+#X connect 41 0 37 1;
+#X connect 42 0 43 0;
+#X connect 42 1 40 0;
+#X connect 43 0 39 0;
diff --git a/externals/gridflow/abstractions/#polygon_each_edge.pd b/externals/gridflow/abstractions/#polygon_each_edge.pd
new file mode 100644
index 00000000..7d9757bd
--- /dev/null
+++ b/externals/gridflow/abstractions/#polygon_each_edge.pd
@@ -0,0 +1,24 @@
+#N canvas 574 358 450 300 10;
+#X obj 20 21 inlet;
+#X obj 19 214 outlet;
+#X obj 19 195 #store;
+#X obj 20 40 t a a;
+#X obj 20 59 #finished;
+#X obj 102 22 #dim;
+#X obj 102 41 #to_list;
+#X msg 102 60 \$1;
+#X obj 19 156 #outer + (2 1 # 0 1);
+#X obj 20 97 #for 0 0 1;
+#X obj 19 120 #to_float;
+#X connect 0 0 3 0;
+#X connect 2 0 1 0;
+#X connect 3 0 4 0;
+#X connect 3 1 2 1;
+#X connect 3 1 5 0;
+#X connect 4 0 9 0;
+#X connect 5 0 6 0;
+#X connect 6 0 7 0;
+#X connect 7 0 9 1;
+#X connect 8 0 2 0;
+#X connect 9 0 10 0;
+#X connect 10 0 8 0;
diff --git a/externals/gridflow/abstractions/#polygon_moment.pd b/externals/gridflow/abstractions/#polygon_moment.pd
new file mode 100644
index 00000000..7b3ad84b
--- /dev/null
+++ b/externals/gridflow/abstractions/#polygon_moment.pd
@@ -0,0 +1,65 @@
+#N canvas 127 192 736 402 10;
+#X obj 24 25 inlet;
+#X obj 24 182 # *;
+#X obj 24 144 #t;
+#X obj 24 201 #fold inv+;
+#X obj 24 349 outlet;
+#X obj 24 163 #convolve (2 2 # 0 0 0 1);
+#X obj 126 221 #convolve (2 1 # 1 1);
+#X obj 24 249 # *;
+#X obj 24 220 #outer + (2 #);
+#X obj 24 268 #fold + \, seed (2 #);
+#X obj 24 291 # /;
+#X obj 93 249 #polygon_area;
+#X obj 24 310 # / 6;
+#X obj 270 32 inlet;
+#X obj 24 49 # -;
+#X obj 24 68 shunt 3 \$1;
+#X obj 294 182 # *;
+#X obj 294 144 #t;
+#X obj 294 201 #fold inv+;
+#X obj 294 163 #convolve (2 2 # 0 0 0 1);
+#X obj 410 221 #convolve (2 1 # 1 1);
+#X obj 294 249 # *;
+#X obj 294 291 # /;
+#X obj 363 249 #polygon_area;
+#X obj 294 310 # / 6;
+#X obj 294 220 #outer + (2 2 #);
+#X text 416 208 what should the change to this box be?;
+#X text 368 117 Second order (covariance matrix);
+#X text 65 122 First order (centroid);
+#X obj 294 268 #fold + \, seed (2 2 #);
+#X text 411 134 NOT WORKING ?;
+#X connect 0 0 14 0;
+#X connect 1 0 3 0;
+#X connect 2 0 5 0;
+#X connect 2 1 1 1;
+#X connect 2 1 6 0;
+#X connect 2 1 11 0;
+#X connect 3 0 8 0;
+#X connect 5 0 1 0;
+#X connect 6 0 7 1;
+#X connect 7 0 9 0;
+#X connect 8 0 7 0;
+#X connect 9 0 10 0;
+#X connect 10 0 12 0;
+#X connect 11 0 10 1;
+#X connect 12 0 4 0;
+#X connect 13 0 14 1;
+#X connect 14 0 15 0;
+#X connect 15 1 2 0;
+#X connect 15 2 17 0;
+#X connect 16 0 18 0;
+#X connect 17 0 19 0;
+#X connect 17 1 16 1;
+#X connect 17 1 20 0;
+#X connect 17 1 23 0;
+#X connect 18 0 25 0;
+#X connect 19 0 16 0;
+#X connect 20 0 21 1;
+#X connect 21 0 29 0;
+#X connect 22 0 24 0;
+#X connect 23 0 22 1;
+#X connect 24 0 4 0;
+#X connect 25 0 21 0;
+#X connect 29 0 22 0;
diff --git a/externals/gridflow/abstractions/#polygon_perimetre.pd b/externals/gridflow/abstractions/#polygon_perimetre.pd
new file mode 100644
index 00000000..f23ef312
--- /dev/null
+++ b/externals/gridflow/abstractions/#polygon_perimetre.pd
@@ -0,0 +1,18 @@
+#N canvas 0 0 450 300 10;
+#X obj 37 39 inlet;
+#X obj 37 191 outlet;
+#X obj 37 58 #outer ignore (0);
+#X obj 37 96 #fold put;
+#X obj 37 115 # sq-;
+#X obj 37 134 #fold +;
+#X obj 37 153 # sqrt;
+#X obj 37 172 #fold +;
+#X obj 37 77 #convolve (2 1 # -1 1);
+#X connect 0 0 2 0;
+#X connect 2 0 8 0;
+#X connect 3 0 4 0;
+#X connect 4 0 5 0;
+#X connect 5 0 6 0;
+#X connect 6 0 7 0;
+#X connect 7 0 1 0;
+#X connect 8 0 3 0;
diff --git a/externals/gridflow/abstractions/#polygon_radial_map.pd b/externals/gridflow/abstractions/#polygon_radial_map.pd
new file mode 100644
index 00000000..ded6c88d
--- /dev/null
+++ b/externals/gridflow/abstractions/#polygon_radial_map.pd
@@ -0,0 +1,184 @@
+#N canvas 257 49 711 558 10;
+#X obj 10 15 inlet polygon;
+#X obj 22 92 f;
+#X obj 22 54 loadbang;
+#X obj 229 200 #polygon_each_edge;
+#X obj 229 219 #t;
+#X obj 47 92 s \$0-precision;
+#X obj 281 242 #unpack;
+#X obj 281 261 t f f;
+#X obj 281 366 f;
+#X obj 281 347 until;
+#X obj 205 325 sel;
+#X obj 205 344 s \$0-stop;
+#X obj 311 328 r \$0-stop;
+#X obj 331 366 mod;
+#X obj 356 366 r \$0-precision;
+#X obj 306 366 +;
+#X msg 281 328 666;
+#X obj 2 331 outlet radial_map;
+#X obj 260 437 tabread \$0-table;
+#X obj 221 493 pack;
+#X obj 221 512 s \$0-table;
+#X obj 253 493 +;
+#N canvas 0 0 450 238 directions-of-points 0;
+#X obj 20 25 inlet;
+#X obj 20 96 # atan;
+#X obj 20 115 # *;
+#X obj 45 115 r \$0-precision;
+#X obj 20 134 # / 36000;
+#X obj 45 153 r \$0-precision;
+#X obj 20 153 # %;
+#N canvas 480 317 313 169 #split 0;
+#X obj 34 28 inlet;
+#X obj 34 123 outlet;
+#X obj 50 85 outlet;
+#X obj 34 47 #t;
+#X text 58 48 split;
+#X obj 50 66 #inner (0 1);
+#X obj 34 104 #inner (1 0);
+#X connect 0 0 3 0;
+#X connect 3 0 6 0;
+#X connect 3 1 5 0;
+#X connect 5 0 2 0;
+#X connect 6 0 1 0;
+#X restore 20 44 pd #split 2;
+#X obj 20 172 outlet;
+#X connect 0 0 7 0;
+#X connect 1 0 2 0;
+#X connect 2 0 4 0;
+#X connect 3 0 2 1;
+#X connect 4 0 6 0;
+#X connect 5 0 6 1;
+#X connect 6 0 8 0;
+#X connect 7 0 1 0;
+#X connect 7 1 1 1;
+#X restore 281 223 pd directions-of-points;
+#N canvas 642 350 344 210 closest-turn 0;
+#X obj 27 23 inlet;
+#X obj 52 68 r \$0-precision;
+#X obj 27 144 outlet;
+#X obj 27 49 -;
+#X obj 27 68 mod;
+#X obj 52 87 / 2;
+#X obj 77 23 inlet;
+#X obj 27 106 * 2;
+#X obj 27 125 - 1;
+#X obj 27 87 >;
+#X text 25 3 figure out clockwise vs counterclockwise;
+#X connect 0 0 3 0;
+#X connect 1 0 4 1;
+#X connect 1 0 5 0;
+#X connect 3 0 4 0;
+#X connect 4 0 9 0;
+#X connect 5 0 9 1;
+#X connect 6 0 3 1;
+#X connect 7 0 8 0;
+#X connect 8 0 2 0;
+#X connect 9 0 7 0;
+#X restore 326 268 pd closest-turn;
+#X obj 260 414 /;
+#X obj 285 414 r \$0-precision;
+#N canvas 637 343 450 300 find-intersection 0;
+#X obj 21 20 inlet edge;
+#X obj 110 21 inlet direction;
+#X obj 21 259 outlet;
+#X text 109 4 float;
+#X text 20 4 2x2 matrix;
+#X obj 21 63 #rotate;
+#X obj 21 128 #ravel;
+#X obj 21 147 #unpack 4;
+#X obj 110 40 * -1;
+#X obj 21 240 expr $f2 - $f1*($f4-$f2)/($f3-$f1);
+#X connect 0 0 5 0;
+#X connect 1 0 8 0;
+#X connect 5 0 6 0;
+#X connect 6 0 7 0;
+#X connect 7 0 9 0;
+#X connect 7 1 9 1;
+#X connect 7 2 9 2;
+#X connect 7 3 9 3;
+#X connect 8 0 5 1;
+#X connect 9 0 2 0;
+#X restore 77 457 pd find-intersection;
+#X obj 77 438 #store;
+#X obj 260 395 * 36000;
+#X obj 22 130 s \$0-table;
+#X msg 22 111 resize \$1;
+#X obj 77 409 t b f;
+#X obj 221 395 t f f;
+#X obj 221 437 t f f;
+#X obj 2 255 for 0 0 1;
+#X obj 31 236 r \$0-precision;
+#X obj 83 293 r \$0-precision;
+#X obj 2 312 #import (1);
+#X msg 83 312 list \$1;
+#X obj 260 160 s \$0-table;
+#X msg 260 141 const 0;
+#X obj 2 274 tabread \$0-table;
+#X obj 207 141 t a a b;
+#X obj 13 181 #finished;
+#X msg 22 73 256;
+#N canvas 0 0 450 300 graph4 0;
+#X array \$0-table 256 float 2;
+#X coords 0 100 256 0 200 140 1;
+#X restore 475 29 graph;
+#X obj 75 509 *;
+#X obj 10 34 route precision;
+#X connect 0 0 47 0;
+#X connect 1 0 30 0;
+#X connect 1 0 5 0;
+#X connect 2 0 44 0;
+#X connect 3 0 4 0;
+#X connect 4 0 22 0;
+#X connect 4 1 27 1;
+#X connect 6 0 7 0;
+#X connect 6 1 10 1;
+#X connect 6 1 23 1;
+#X connect 7 0 16 0;
+#X connect 7 1 8 1;
+#X connect 7 1 23 0;
+#X connect 8 0 10 0;
+#X connect 8 0 15 0;
+#X connect 9 0 8 0;
+#X connect 10 0 11 0;
+#X connect 10 1 32 0;
+#X connect 12 0 9 1;
+#X connect 13 0 8 1;
+#X connect 14 0 13 1;
+#X connect 15 0 13 0;
+#X connect 16 0 9 0;
+#X connect 18 0 21 0;
+#X connect 19 0 20 0;
+#X connect 21 0 19 1;
+#X connect 22 0 6 0;
+#X connect 23 0 15 1;
+#X connect 23 0 46 1;
+#X connect 24 0 31 0;
+#X connect 25 0 24 1;
+#X connect 26 0 46 0;
+#X connect 27 0 26 0;
+#X connect 28 0 24 0;
+#X connect 30 0 29 0;
+#X connect 31 0 27 0;
+#X connect 31 1 26 1;
+#X connect 32 0 33 0;
+#X connect 32 1 28 0;
+#X connect 33 0 19 0;
+#X connect 33 1 18 0;
+#X connect 34 0 41 0;
+#X connect 35 0 34 1;
+#X connect 36 0 38 0;
+#X connect 37 0 17 0;
+#X connect 38 0 37 1;
+#X connect 40 0 39 0;
+#X connect 41 0 37 0;
+#X connect 42 0 43 0;
+#X connect 42 1 3 0;
+#X connect 42 2 40 0;
+#X connect 43 0 34 0;
+#X connect 44 0 1 0;
+#X connect 46 0 21 1;
+#X connect 47 0 1 0;
+#X connect 47 1 42 0;
+#X coords 0 0 1 1 85 60 0;
diff --git a/externals/gridflow/abstractions/#posterize.pd b/externals/gridflow/abstractions/#posterize.pd
new file mode 100644
index 00000000..e55ba796
--- /dev/null
+++ b/externals/gridflow/abstractions/#posterize.pd
@@ -0,0 +1,19 @@
+#N canvas 0 0 450 300 10;
+#X obj 13 11 inlet;
+#X obj 13 31 # *>>8;
+#X obj 13 51 # * 255;
+#X obj 13 71 # /;
+#X obj 92 49 # - 1;
+#X obj 13 91 outlet;
+#X obj 92 11 inlet;
+#X obj 92 30 t a;
+#X obj 150 42 args (n a 2);
+#X connect 0 0 1 0;
+#X connect 1 0 2 0;
+#X connect 2 0 3 0;
+#X connect 3 0 5 0;
+#X connect 4 0 3 1;
+#X connect 6 0 7 0;
+#X connect 7 0 1 1;
+#X connect 7 0 4 0;
+#X connect 8 0 7 0;
diff --git a/externals/gridflow/abstractions/#ravel.pd b/externals/gridflow/abstractions/#ravel.pd
new file mode 100644
index 00000000..35e7b775
--- /dev/null
+++ b/externals/gridflow/abstractions/#ravel.pd
@@ -0,0 +1,15 @@
+#N canvas 0 0 450 195 10;
+#X obj 14 15 inlet;
+#X obj 44 53 #dim;
+#X obj 14 34 t a a;
+#X obj 14 143 outlet;
+#X obj 44 91 #redim (1);
+#X obj 44 72 #fold *;
+#X obj 14 124 #redim (0);
+#X connect 0 0 2 0;
+#X connect 1 0 5 0;
+#X connect 2 0 6 0;
+#X connect 2 1 1 0;
+#X connect 4 0 6 1;
+#X connect 5 0 4 0;
+#X connect 6 0 3 0;
diff --git a/externals/gridflow/abstractions/#record.pd b/externals/gridflow/abstractions/#record.pd
new file mode 100644
index 00000000..101ae103
--- /dev/null
+++ b/externals/gridflow/abstractions/#record.pd
@@ -0,0 +1,72 @@
+#N canvas 1036 267 571 412 10;
+#X obj 235 302 #out;
+#X msg 235 190 close;
+#X obj 75 41 inlet filename;
+#X obj 205 44 inlet close;
+#X obj -32 41 inlet videoin;
+#X msg 75 100 open \$1;
+#X obj 75 77 savepanel;
+#X obj 75 124 print;
+#X obj 61 231 spigot;
+#X obj 123 194 inlet start;
+#X msg 123 218 1;
+#X msg 124 240 0;
+#X obj 205 106 t b b;
+#X obj 324 101 vradio 15 1 0 4 \$0-framerate \$0-framerate select_framerate
+0 -6 0 12 -241291 -258699 -1 2;
+#X text 350 99 10 fps;
+#X text 350 116 24 fps;
+#X text 350 132 25 fps;
+#X text 350 149 30 fps;
+#N canvas 691 426 273 271 framerate 0;
+#X obj 95 37 r \$0-framerate;
+#X floatatom 103 67 5 0 0 0 - - -;
+#X obj 107 225 outlet;
+#X msg 54 153 10;
+#X msg 85 153 24;
+#X msg 120 152 25;
+#X msg 153 152 30;
+#X msg 107 198 framerate \$1;
+#X obj 54 114 sel 0;
+#X obj 89 114 sel 1;
+#X obj 124 115 sel 2;
+#X obj 159 114 sel 3;
+#X connect 0 0 1 0;
+#X connect 1 0 8 0;
+#X connect 1 0 9 0;
+#X connect 1 0 10 0;
+#X connect 1 0 11 0;
+#X connect 3 0 7 0;
+#X connect 4 0 7 0;
+#X connect 5 0 7 0;
+#X connect 6 0 7 0;
+#X connect 7 0 2 0;
+#X connect 8 0 3 0;
+#X connect 9 0 4 0;
+#X connect 10 0 5 0;
+#X connect 11 0 6 0;
+#X restore 283 278 pd framerate;
+#X obj 75 149 s openfilename;
+#X msg 283 247 framerate 10;
+#X obj 284 305 r openfilename;
+#X text 108 335 I'd like to use [#peephole] to monitor what is being
+recorded but it's too buggy at the moment.;
+#X msg 283 221 codec jpeg;
+#X text 343 178 the framerate option;
+#X connect 1 0 0 0;
+#X connect 2 0 6 0;
+#X connect 3 0 12 0;
+#X connect 4 0 8 0;
+#X connect 5 0 7 0;
+#X connect 5 0 19 0;
+#X connect 6 0 5 0;
+#X connect 8 0 0 0;
+#X connect 9 0 10 0;
+#X connect 10 0 8 1;
+#X connect 11 0 8 1;
+#X connect 12 0 11 0;
+#X connect 12 1 1 0;
+#X connect 18 0 0 0;
+#X connect 20 0 0 0;
+#X connect 21 0 0 0;
+#X connect 23 0 0 0;
diff --git a/externals/gridflow/abstractions/#reinterval.pd b/externals/gridflow/abstractions/#reinterval.pd
new file mode 100644
index 00000000..ba8e6481
--- /dev/null
+++ b/externals/gridflow/abstractions/#reinterval.pd
@@ -0,0 +1,34 @@
+#N canvas 62 179 531 300 10;
+#X obj 15 18 inlet hot;
+#X obj 82 18 inlet oldstart;
+#X obj 184 18 inlet oldend;
+#X obj 272 18 inlet newstart;
+#X obj 374 18 inlet newend;
+#X obj 45 56 #store;
+#X obj 235 54 #store;
+#X obj 15 37 t a b;
+#X obj 45 75 # inv+;
+#X obj 235 73 # inv+;
+#X obj 15 139 # -;
+#X obj 15 160 # *;
+#X obj 15 179 # /;
+#X obj 15 198 # +;
+#X obj 15 217 outlet;
+#X connect 0 0 7 0;
+#X connect 1 0 5 1;
+#X connect 1 0 10 1;
+#X connect 2 0 8 1;
+#X connect 3 0 6 1;
+#X connect 3 0 13 1;
+#X connect 4 0 9 1;
+#X connect 5 0 8 0;
+#X connect 6 0 9 0;
+#X connect 7 0 10 0;
+#X connect 7 1 5 0;
+#X connect 7 1 6 0;
+#X connect 8 0 12 1;
+#X connect 9 0 11 1;
+#X connect 10 0 11 0;
+#X connect 11 0 12 0;
+#X connect 12 0 13 0;
+#X connect 13 0 14 0;
diff --git a/externals/gridflow/abstractions/#remap_image.pd b/externals/gridflow/abstractions/#remap_image.pd
new file mode 100644
index 00000000..bb3ea18c
--- /dev/null
+++ b/externals/gridflow/abstractions/#remap_image.pd
@@ -0,0 +1,23 @@
+#N canvas 0 0 450 300 10;
+#X obj 18 13 inlet;
+#X obj 168 163 inlet;
+#X obj 18 160 #store;
+#X obj 92 73 #dim;
+#X obj 18 33 t a a;
+#X obj 18 110 #finished;
+#X obj 18 191 outlet;
+#X obj 68 191 outlet;
+#X obj 18 130 #for (0 0) (0 0) (1 1);
+#X obj 92 92 #to_list;
+#X msg 92 111 \$1 \$2;
+#X connect 0 0 4 0;
+#X connect 1 0 2 0;
+#X connect 2 0 6 0;
+#X connect 3 0 9 0;
+#X connect 4 0 5 0;
+#X connect 4 1 3 0;
+#X connect 4 1 2 1;
+#X connect 5 0 8 0;
+#X connect 8 0 7 0;
+#X connect 9 0 10 0;
+#X connect 10 0 8 1;
diff --git a/externals/gridflow/abstractions/#rgb_to_greyscale.pd b/externals/gridflow/abstractions/#rgb_to_greyscale.pd
new file mode 100644
index 00000000..79842613
--- /dev/null
+++ b/externals/gridflow/abstractions/#rgb_to_greyscale.pd
@@ -0,0 +1,8 @@
+#N canvas 550 233 335 174 10;
+#X obj 10 10 inlet;
+#X obj 9 67 outlet;
+#X obj 9 29 #inner (3 1 # 77 151 28);
+#X obj 9 48 # >> 8;
+#X connect 0 0 2 0;
+#X connect 2 0 3 0;
+#X connect 3 0 1 0;
diff --git a/externals/gridflow/abstractions/#rgb_to_rgba.pd b/externals/gridflow/abstractions/#rgb_to_rgba.pd
new file mode 100644
index 00000000..850b2723
--- /dev/null
+++ b/externals/gridflow/abstractions/#rgb_to_rgba.pd
@@ -0,0 +1,6 @@
+#N canvas 209 229 409 113 10;
+#X obj 22 26 inlet rgb;
+#X obj 22 64 outlet rgba;
+#X obj 22 45 #inner (3 4 # 1 0 0 0 0 1 0 0 0 0 1 0);
+#X connect 0 0 2 0;
+#X connect 2 0 1 0;
diff --git a/externals/gridflow/abstractions/#rgb_to_yuv.pd b/externals/gridflow/abstractions/#rgb_to_yuv.pd
new file mode 100644
index 00000000..7e341ea0
--- /dev/null
+++ b/externals/gridflow/abstractions/#rgb_to_yuv.pd
@@ -0,0 +1,10 @@
+#N canvas 550 233 438 174 10;
+#X obj 10 10 inlet;
+#X obj 10 90 outlet;
+#X obj 10 50 # >> 8;
+#X obj 10 30 #inner (3 3 # 76 -44 128 150 -85 -108 29 128 -21);
+#X obj 10 70 # + (0 128 128);
+#X connect 0 0 3 0;
+#X connect 2 0 4 0;
+#X connect 3 0 2 0;
+#X connect 4 0 1 0;
diff --git a/externals/gridflow/abstractions/#rgba_to_rgb.pd b/externals/gridflow/abstractions/#rgba_to_rgb.pd
new file mode 100644
index 00000000..46d5ad0e
--- /dev/null
+++ b/externals/gridflow/abstractions/#rgba_to_rgb.pd
@@ -0,0 +1,6 @@
+#N canvas 0 0 450 300 10;
+#X obj 26 23 inlet rgba;
+#X obj 26 61 outlet rgb;
+#X obj 26 42 #inner (4 3 # 1 0 0 0 1 0 0 0 1 0 0 0);
+#X connect 0 0 2 0;
+#X connect 2 0 1 0;
diff --git a/externals/gridflow/abstractions/#rotate.pd b/externals/gridflow/abstractions/#rotate.pd
new file mode 100644
index 00000000..5de20071
--- /dev/null
+++ b/externals/gridflow/abstractions/#rotate.pd
@@ -0,0 +1,24 @@
+#N canvas 448 101 416 220 10;
+#X obj 11 12 inlet;
+#X obj 43 190 outlet;
+#X obj 171 57 t f;
+#X obj 171 28 args (angle f 0);
+#X obj 196 57 inlet angle;
+#X obj 99 121 #rotatificator;
+#X obj 11 61 route2 axis;
+#X obj 43 133 t a b;
+#X msg 99 100 256;
+#X obj 43 152 #inner;
+#X obj 43 171 # >> 8;
+#X connect 0 0 6 0;
+#X connect 2 0 5 1;
+#X connect 3 0 2 0;
+#X connect 4 0 2 0;
+#X connect 5 0 9 1;
+#X connect 6 0 5 0;
+#X connect 6 1 7 0;
+#X connect 7 0 9 0;
+#X connect 7 1 8 0;
+#X connect 8 0 5 0;
+#X connect 9 0 10 0;
+#X connect 10 0 1 0;
diff --git a/externals/gridflow/abstractions/#saturation.pd b/externals/gridflow/abstractions/#saturation.pd
new file mode 100644
index 00000000..289c2336
--- /dev/null
+++ b/externals/gridflow/abstractions/#saturation.pd
@@ -0,0 +1,35 @@
+#N canvas 0 0 450 300 10;
+#X obj 59 119 # inv+ 255;
+#X obj 8 169 # +;
+#X obj 33 28 #rgb_to_greyscale;
+#X obj 8 189 # >> 8;
+#X obj 106 91 loadbang;
+#X text 62 216 keep values inside visible range;
+#X obj 8 149 # *;
+#X obj 33 119 # *;
+#X obj 8 9 inlet image;
+#X obj 8 243 outlet image;
+#X obj 47 71 inlet saturation;
+#X text 170 75 0 = grey \; 256 = identity;
+#X text 34 172 mix the original picture with its greyed version;
+#X obj 33 48 #greyscale_to_rgb;
+#X obj 47 91 t a;
+#X obj 8 215 #clip;
+#X obj 8 28 #t;
+#X obj 74 91 f \$1;
+#X connect 0 0 7 1;
+#X connect 1 0 3 0;
+#X connect 2 0 13 0;
+#X connect 3 0 15 0;
+#X connect 4 0 17 0;
+#X connect 6 0 1 0;
+#X connect 7 0 1 1;
+#X connect 8 0 16 0;
+#X connect 10 0 14 0;
+#X connect 13 0 7 0;
+#X connect 14 0 6 1;
+#X connect 14 0 0 0;
+#X connect 15 0 9 0;
+#X connect 16 0 6 0;
+#X connect 16 1 2 0;
+#X connect 17 0 14 0;
diff --git a/externals/gridflow/abstractions/#scale_to.pd b/externals/gridflow/abstractions/#scale_to.pd
new file mode 100644
index 00000000..582e5963
--- /dev/null
+++ b/externals/gridflow/abstractions/#scale_to.pd
@@ -0,0 +1,29 @@
+#N canvas 0 0 450 300 10;
+#X obj 28 20 inlet;
+#X obj 28 201 outlet;
+#X obj 28 110 #for (0 0) (0 0) (1 1);
+#X obj 28 144 # *;
+#X obj 28 163 # /;
+#X obj 28 182 #store;
+#X obj 162 145 #dim;
+#X obj 162 164 #redim (2);
+#X obj 28 64 #finished;
+#X obj 28 39 t a a;
+#X obj 140 20 inlet;
+#X obj 185 51 args size;
+#X obj 113 68 t a;
+#X connect 0 0 9 0;
+#X connect 2 0 3 0;
+#X connect 3 0 4 0;
+#X connect 4 0 5 0;
+#X connect 5 0 1 0;
+#X connect 6 0 7 0;
+#X connect 7 0 3 1;
+#X connect 8 0 2 0;
+#X connect 9 0 8 0;
+#X connect 9 1 6 0;
+#X connect 9 1 5 1;
+#X connect 10 0 12 0;
+#X connect 11 0 12 0;
+#X connect 12 0 2 1;
+#X connect 12 0 4 1;
diff --git a/externals/gridflow/abstractions/#seq_fold.pd b/externals/gridflow/abstractions/#seq_fold.pd
new file mode 100644
index 00000000..cb2c8dc5
--- /dev/null
+++ b/externals/gridflow/abstractions/#seq_fold.pd
@@ -0,0 +1,31 @@
+#N canvas 728 111 450 473 10;
+#X obj 26 40 inlet end;
+#X obj 94 40 inlet elements;
+#X obj 26 294 outlet final;
+#X obj 115 294 outlet op_left;
+#X obj 217 294 outlet op_right;
+#X obj 112 75 t b b b;
+#X obj 180 218 shunt;
+#X msg 270 170 1;
+#X msg 241 170 0;
+#X obj 270 40 inlet op_result;
+#X obj 196 40 inlet seed;
+#X obj 196 170 var.#;
+#X obj 180 199 var.#;
+#X obj 94 199 t b a;
+#X connect 0 0 5 0;
+#X connect 1 0 13 0;
+#X connect 5 0 8 0;
+#X connect 5 0 11 0;
+#X connect 5 1 12 0;
+#X connect 5 2 7 0;
+#X connect 6 0 3 0;
+#X connect 6 1 2 0;
+#X connect 7 0 6 1;
+#X connect 8 0 6 1;
+#X connect 9 0 12 1;
+#X connect 10 0 11 0;
+#X connect 11 0 12 1;
+#X connect 12 0 6 0;
+#X connect 13 0 12 0;
+#X connect 13 1 4 0;
diff --git a/externals/gridflow/abstractions/#slice.pd b/externals/gridflow/abstractions/#slice.pd
new file mode 100644
index 00000000..03b8b30d
--- /dev/null
+++ b/externals/gridflow/abstractions/#slice.pd
@@ -0,0 +1,39 @@
+#N canvas 133 255 450 300 10;
+#X obj 13 24 inlet;
+#X obj 53 259 outlet;
+#X obj 53 240 #store;
+#X obj 93 24 inlet;
+#X obj 153 24 inlet;
+#X obj 181 98 # put 1;
+#X obj 64 217 #for 0 0 1;
+#X obj 93 98 #to_list;
+#X obj 13 56 t a a;
+#X obj 13 75 #finished;
+#X obj 129 198 #ravel;
+#X obj 99 178 #ravel;
+#X obj 198 26 args start end;
+#X obj 153 66 t a;
+#X obj 93 68 t a;
+#X obj 83 156 list trim;
+#X obj 83 137 list prepend set (;
+#X obj 83 118 list append );
+#X connect 0 0 8 0;
+#X connect 2 0 1 0;
+#X connect 3 0 14 0;
+#X connect 4 0 13 0;
+#X connect 5 0 10 0;
+#X connect 6 0 2 0;
+#X connect 7 0 17 0;
+#X connect 8 0 9 0;
+#X connect 8 1 2 1;
+#X connect 9 0 6 0;
+#X connect 10 0 6 2;
+#X connect 11 0 6 1;
+#X connect 12 0 14 0;
+#X connect 12 1 13 0;
+#X connect 13 0 5 0;
+#X connect 13 0 11 0;
+#X connect 14 0 7 0;
+#X connect 15 0 6 0;
+#X connect 16 0 15 0;
+#X connect 17 0 16 0;
diff --git a/externals/gridflow/abstractions/#solarize.pd b/externals/gridflow/abstractions/#solarize.pd
new file mode 100644
index 00000000..bcf7ecb4
--- /dev/null
+++ b/externals/gridflow/abstractions/#solarize.pd
@@ -0,0 +1,12 @@
+#N canvas 0 0 450 300 10;
+#X obj 15 14 inlet;
+#X obj 15 34 # & 255;
+#X obj 15 53 # << 1;
+#X obj 15 92 # inv+ 255;
+#X obj 15 112 outlet;
+#X obj 15 72 # abs- 255;
+#X connect 0 0 1 0;
+#X connect 1 0 2 0;
+#X connect 2 0 5 0;
+#X connect 3 0 4 0;
+#X connect 5 0 3 0;
diff --git a/externals/gridflow/abstractions/#sort.pd b/externals/gridflow/abstractions/#sort.pd
new file mode 100644
index 00000000..174e7a06
--- /dev/null
+++ b/externals/gridflow/abstractions/#sort.pd
@@ -0,0 +1,13 @@
+#N canvas 374 137 450 165 10;
+#X obj 28 30 inlet;
+#X obj 28 136 outlet;
+#X obj 28 73 #grade;
+#X obj 28 92 #outer + (0);
+#X obj 28 117 #store;
+#X obj 28 49 #t;
+#X connect 0 0 5 0;
+#X connect 2 0 3 0;
+#X connect 3 0 4 0;
+#X connect 4 0 1 0;
+#X connect 5 0 2 0;
+#X connect 5 1 4 1;
diff --git a/externals/gridflow/abstractions/#spread.pd b/externals/gridflow/abstractions/#spread.pd
new file mode 100644
index 00000000..e37c5beb
--- /dev/null
+++ b/externals/gridflow/abstractions/#spread.pd
@@ -0,0 +1,26 @@
+#N canvas 0 0 450 300 10;
+#X obj 17 12 inlet;
+#X obj 17 52 # & 0;
+#X obj 17 72 # + 5;
+#X obj 17 92 # rand;
+#X obj 17 112 # - 2;
+#X obj 137 162 # +;
+#X obj 124 88 # >> 1;
+#X obj 17 32 t a a;
+#X obj 137 182 outlet;
+#X obj 124 32 inlet;
+#X obj 220 36 args (r a 5);
+#X obj 124 59 t a;
+#X connect 0 0 7 0;
+#X connect 1 0 2 0;
+#X connect 2 0 3 0;
+#X connect 3 0 4 0;
+#X connect 4 0 5 0;
+#X connect 5 0 8 0;
+#X connect 6 0 4 1;
+#X connect 7 0 1 0;
+#X connect 7 1 5 1;
+#X connect 9 0 11 0;
+#X connect 10 0 11 0;
+#X connect 11 0 2 1;
+#X connect 11 0 6 0;
diff --git a/externals/gridflow/abstractions/#swap.pd b/externals/gridflow/abstractions/#swap.pd
new file mode 100644
index 00000000..c40a80f8
--- /dev/null
+++ b/externals/gridflow/abstractions/#swap.pd
@@ -0,0 +1,16 @@
+#N canvas 83 326 450 195 10;
+#X obj 24 35 inlet A;
+#X obj 89 102 inlet B;
+#X obj 24 136 outlet A;
+#X obj 84 136 outlet B;
+#X obj 24 102 #store;
+#X obj 24 54 t a a;
+#X obj 24 73 #finished;
+#X obj 72 54 args (my_grid a 0);
+#X connect 0 0 5 0;
+#X connect 1 0 4 1;
+#X connect 4 0 2 0;
+#X connect 5 0 6 0;
+#X connect 5 1 3 0;
+#X connect 6 0 4 0;
+#X connect 7 0 4 1;
diff --git a/externals/gridflow/abstractions/#t.pd b/externals/gridflow/abstractions/#t.pd
new file mode 100644
index 00000000..5b8fce67
--- /dev/null
+++ b/externals/gridflow/abstractions/#t.pd
@@ -0,0 +1,16 @@
+#N canvas 454 233 450 176 10;
+#X obj 26 29 inlet;
+#X obj 26 116 outlet;
+#X obj 72 116 outlet;
+#X obj 26 48 t a a;
+#X obj 26 67 #finished;
+#X obj 26 86 #store;
+#X text 120 22 This is for when [t a a] is not sufficient;
+#X text 121 36 Because GF doesn't fully follow ordering of;
+#X text 121 49 messages.;
+#X connect 0 0 3 0;
+#X connect 3 0 4 0;
+#X connect 3 1 5 1;
+#X connect 3 1 2 0;
+#X connect 4 0 5 0;
+#X connect 5 0 1 0;
diff --git a/externals/gridflow/abstractions/#text_to_image.pd b/externals/gridflow/abstractions/#text_to_image.pd
new file mode 100644
index 00000000..94fe4d52
--- /dev/null
+++ b/externals/gridflow/abstractions/#text_to_image.pd
@@ -0,0 +1,41 @@
+#N canvas 674 0 450 300 10;
+#X obj 16 14 inlet text;
+#X obj 16 265 outlet image;
+#X obj 291 132 inlet font;
+#X obj 16 155 #store;
+#X obj 203 38 inlet colors;
+#X text 203 2 0: background;
+#X text 203 18 1: foreground;
+#X obj 203 66 t a;
+#X obj 16 174 #store;
+#X obj 229 66 loadbang;
+#X text 67 157 font;
+#X text 68 174 palette;
+#X obj 16 212 t a a;
+#X obj 154 161 #dim;
+#X obj 154 180 #unpack 4;
+#X obj 174 200 *;
+#X obj 16 193 #transpose 0 1;
+#X obj 154 228 pack 0 0 0;
+#X msg 229 85 2 3 # 0 0 0 255 255 255;
+#X obj 16 33 #outer ignore (0);
+#X obj 16 238 #redim ();
+#X connect 0 0 19 0;
+#X connect 2 0 3 1;
+#X connect 3 0 8 0;
+#X connect 4 0 7 0;
+#X connect 8 0 16 0;
+#X connect 9 0 18 0;
+#X connect 12 0 20 0;
+#X connect 12 1 13 0;
+#X connect 13 0 14 0;
+#X connect 14 0 17 0;
+#X connect 14 1 15 0;
+#X connect 14 2 15 1;
+#X connect 14 3 17 2;
+#X connect 15 0 17 1;
+#X connect 16 0 12 0;
+#X connect 17 0 20 1;
+#X connect 18 0 8 1;
+#X connect 19 0 3 0;
+#X connect 20 0 1 0;
diff --git a/externals/gridflow/abstractions/#to_literal.pd b/externals/gridflow/abstractions/#to_literal.pd
new file mode 100644
index 00000000..feb07aef
--- /dev/null
+++ b/externals/gridflow/abstractions/#to_literal.pd
@@ -0,0 +1,41 @@
+#N canvas 0 0 513 171 10;
+#X obj 44 63 #to_list;
+#X obj 136 24 #dim;
+#X obj 136 43 #to_list;
+#X obj 44 82 list prepend;
+#X obj 136 132 list append #;
+#X obj 44 25 inlet;
+#X obj 44 101 outlet;
+#X obj 44 44 t a a a;
+#X obj 214 24 #type;
+#X obj 136 113 list append;
+#X obj 214 43 sel uint8 int16 int32 int64 float32 float64;
+#X msg 214 62 symbol b;
+#X msg 256 81 symbol s;
+#X msg 299 62 bang;
+#X msg 341 81 symbol l;
+#X msg 384 62 symbol f;
+#X msg 426 81 symbol d;
+#X connect 0 0 3 0;
+#X connect 1 0 2 0;
+#X connect 2 0 9 0;
+#X connect 3 0 6 0;
+#X connect 4 0 3 1;
+#X connect 5 0 7 0;
+#X connect 7 0 0 0;
+#X connect 7 1 1 0;
+#X connect 7 2 8 0;
+#X connect 8 0 10 0;
+#X connect 9 0 4 0;
+#X connect 10 0 11 0;
+#X connect 10 1 12 0;
+#X connect 10 2 13 0;
+#X connect 10 3 14 0;
+#X connect 10 4 15 0;
+#X connect 10 5 16 0;
+#X connect 11 0 9 1;
+#X connect 12 0 9 1;
+#X connect 13 0 9 1;
+#X connect 14 0 9 1;
+#X connect 15 0 9 1;
+#X connect 16 0 9 1;
diff --git a/externals/gridflow/abstractions/#window.pd b/externals/gridflow/abstractions/#window.pd
new file mode 100755
index 00000000..b5c2d647
--- /dev/null
+++ b/externals/gridflow/abstractions/#window.pd
@@ -0,0 +1,28 @@
+#N canvas 354 116 450 300 10;
+#X msg 65 140 close;
+#X obj 15 56 spigot;
+#X obj -48 9 inlet;
+#X msg 87 106 open window \, title \$1;
+#X obj 65 9 inlet;
+#X obj 87 83 symbol \$1;
+#X obj 65 61 sel 0 1;
+#X obj -95 162 args (title s untitled);
+#X obj -48 37 route state;
+#X obj 65 29 t a;
+#X obj 87 219 outlet;
+#X obj 87 200 #out;
+#X connect 0 0 11 0;
+#X connect 1 0 11 0;
+#X connect 2 0 8 0;
+#X connect 3 0 11 0;
+#X connect 4 0 9 0;
+#X connect 5 0 3 0;
+#X connect 6 0 0 0;
+#X connect 6 1 5 0;
+#X connect 7 0 5 1;
+#X connect 8 0 9 0;
+#X connect 8 1 1 0;
+#X connect 9 0 6 0;
+#X connect 9 0 1 1;
+#X connect 11 0 10 0;
+#X coords 0 0 1 1 24 24 0;
diff --git a/externals/gridflow/abstractions/#yuv_to_rgb.pd b/externals/gridflow/abstractions/#yuv_to_rgb.pd
new file mode 100644
index 00000000..df2f242f
--- /dev/null
+++ b/externals/gridflow/abstractions/#yuv_to_rgb.pd
@@ -0,0 +1,10 @@
+#N canvas 550 233 438 174 10;
+#X obj 10 10 inlet;
+#X obj 10 90 outlet;
+#X obj 10 70 # >> 8;
+#X obj 10 30 # - (0 128 128);
+#X obj 10 50 #inner (3 3 # 256 256 256 0 -88 454 358 -183 0);
+#X connect 0 0 3 0;
+#X connect 2 0 1 0;
+#X connect 3 0 4 0;
+#X connect 4 0 2 0;
diff --git a/externals/gridflow/abstractions/ascii.pd b/externals/gridflow/abstractions/ascii.pd
new file mode 100644
index 00000000..1daaa93d
--- /dev/null
+++ b/externals/gridflow/abstractions/ascii.pd
@@ -0,0 +1,12 @@
+#N canvas 310 286 450 300 10;
+#X obj 22 23 inlet;
+#X msg 22 61 to_ascii \$1;
+#X obj 22 118 outlet;
+#X obj 22 99 #to_float;
+#X obj 22 42 int;
+#X obj 22 80 #import;
+#X connect 0 0 4 0;
+#X connect 1 0 5 0;
+#X connect 3 0 2 0;
+#X connect 4 0 1 0;
+#X connect 5 0 3 0;
diff --git a/externals/gridflow/abstractions/ascii_to_f.pd b/externals/gridflow/abstractions/ascii_to_f.pd
new file mode 100644
index 00000000..02043a4c
--- /dev/null
+++ b/externals/gridflow/abstractions/ascii_to_f.pd
@@ -0,0 +1,71 @@
+#N canvas 230 221 450 387 10;
+#X obj 71 6 inlet;
+#X obj 71 44 range 48 58;
+#X obj 258 143 outlet other;
+#X obj 50 128 +;
+#X obj 34 147 f;
+#X obj 91 296 outlet parsed;
+#X obj 91 227 * 1;
+#X msg 156 183 -1;
+#X msg 130 183 1;
+#X obj 258 74 t f b b;
+#X msg 280 183 0;
+#X obj 50 109 - 48;
+#X obj 75 128 * 10;
+#X obj 170 74 sel 43 45 46;
+#X obj 91 277 / 1;
+#X obj 71 25 #to_float;
+#X obj 201 260 * 10;
+#X obj 176 260 f 1;
+#X msg 176 218 1;
+#X obj 206 237 spigot 0;
+#X msg 257 218 0;
+#X obj 279 14 t b;
+#X msg 206 218 bang;
+#X msg 266 237 1;
+#X obj 34 90 r \$0-fini;
+#X obj 302 112 s \$0-fini;
+#X text 96 261 denominator;
+#X text 87 207 sign;
+#X obj 302 93 gf.oneshot 0;
+#X connect 0 0 15 0;
+#X connect 1 0 13 0;
+#X connect 1 1 11 0;
+#X connect 1 1 21 0;
+#X connect 1 1 22 0;
+#X connect 1 2 13 0;
+#X connect 3 0 4 1;
+#X connect 3 0 12 0;
+#X connect 4 0 6 0;
+#X connect 6 0 14 0;
+#X connect 7 0 6 1;
+#X connect 8 0 6 1;
+#X connect 9 0 2 0;
+#X connect 9 1 8 0;
+#X connect 9 1 10 0;
+#X connect 9 1 20 0;
+#X connect 9 1 18 0;
+#X connect 9 2 28 0;
+#X connect 10 0 3 1;
+#X connect 11 0 3 0;
+#X connect 12 0 3 1;
+#X connect 13 0 8 0;
+#X connect 13 0 21 0;
+#X connect 13 1 7 0;
+#X connect 13 1 21 0;
+#X connect 13 2 21 0;
+#X connect 13 2 23 0;
+#X connect 13 3 9 0;
+#X connect 14 0 5 0;
+#X connect 15 0 1 0;
+#X connect 16 0 17 1;
+#X connect 17 0 16 0;
+#X connect 17 0 14 1;
+#X connect 18 0 17 0;
+#X connect 19 0 17 0;
+#X connect 20 0 19 1;
+#X connect 21 0 28 1;
+#X connect 22 0 19 0;
+#X connect 23 0 19 1;
+#X connect 24 0 4 0;
+#X connect 28 0 25 0;
diff --git a/externals/gridflow/abstractions/doc_add.pd b/externals/gridflow/abstractions/doc_add.pd
new file mode 100644
index 00000000..4d05c532
--- /dev/null
+++ b/externals/gridflow/abstractions/doc_add.pd
@@ -0,0 +1,55 @@
+#N canvas 448 372 578 428 10;
+#X obj 58 332 s;
+#X msg 149 230 symbol pd-\$1;
+#X obj 149 211 gf/canvas_filename 2;
+#X obj 98 27 inlet y;
+#X obj 11 17 inlet bang;
+#X obj 58 294 pack 0 s;
+#X obj 112 294 symbol \$1;
+#X obj 112 275 loadbang;
+#X msg 98 46 \$2;
+#X obj 98 65 - 20;
+#X msg 58 313 obj 100 \$1 doc_m \$2;
+#X obj 11 366 gf/canvas_loadbang 2;
+#X obj 11 112 t b b b b;
+#X obj 78 113 gf/canvas_count 2;
+#X obj 11 141 f;
+#X obj 11 82 f;
+#X obj 58 169 doc_bottom;
+#X obj 239 68 symbol \$1;
+#X obj 239 88 gf/string_replace c c/;
+#X obj 239 108 gf/string_replace i i/;
+#X obj 239 128 gf/string_replace o o/;
+#X obj 212 10 loadbang;
+#X obj 212 48 gf/canvas_dollarzero 2;
+#X obj 212 29 t b b;
+#X obj 212 152 pack 0 s;
+#X msg 212 171 symbol \$1/\$2;
+#X connect 1 0 0 1;
+#X connect 2 0 1 0;
+#X connect 3 0 8 0;
+#X connect 4 0 15 0;
+#X connect 5 0 10 0;
+#X connect 6 0 5 1;
+#X connect 7 0 6 0;
+#X connect 8 0 9 0;
+#X connect 9 0 15 1;
+#X connect 10 0 0 0;
+#X connect 12 0 14 0;
+#X connect 12 1 16 0;
+#X connect 12 2 2 0;
+#X connect 12 3 13 0;
+#X connect 13 0 14 1;
+#X connect 14 0 11 0;
+#X connect 15 0 12 0;
+#X connect 16 0 5 0;
+#X connect 17 0 18 0;
+#X connect 18 0 19 0;
+#X connect 19 0 20 0;
+#X connect 20 0 24 1;
+#X connect 21 0 23 0;
+#X connect 22 0 24 0;
+#X connect 23 0 22 0;
+#X connect 23 1 17 0;
+#X connect 24 0 25 0;
+#X connect 25 0 16 1;
diff --git a/externals/gridflow/abstractions/doc_also.pd b/externals/gridflow/abstractions/doc_also.pd
new file mode 100644
index 00000000..cfca1dd9
--- /dev/null
+++ b/externals/gridflow/abstractions/doc_also.pd
@@ -0,0 +1,56 @@
+#N canvas 49 157 658 459 10;
+#X obj 0 0 cnv 15 92 17 empty \$0-rect See also: 35 9 1 9 -88239
+-262144 0;
+#X obj 409 156 gf/canvas_setpos 0;
+#X obj 409 40 loadbang;
+#X obj 409 116 gf/canvas_getpos 0;
+#X msg 409 136 3 \$2;
+#X obj 212 49 doc_below o 1 10;
+#X obj 25 263 outlet dummy;
+#X obj 168 263 outlet to_child_nodes;
+#X obj 0 27 doc_layout s 92 20;
+#X obj 327 383 gf/lol 1;
+#X obj 327 307 gf/canvas_edit_mode 1;
+#X obj 327 326 sel 0 1;
+#X msg 327 364 wire_hide;
+#X obj 327 288 t b b;
+#X obj 442 212 gf/canvas_getpos 0;
+#X obj 442 231 unpack f f;
+#X obj 442 269 pack f f;
+#X obj 442 250 + 100;
+#X msg 442 288 box_align y \$1 \$2 8;
+#X obj 327 193 gf/canvas_dollarzero 1;
+#X msg 327 212 symbol \$1-clock;
+#X obj 327 174 loadbang;
+#X obj 327 231 receives;
+#X obj 409 59 gf/canvas_dollarzero 1;
+#X obj 409 97 receives;
+#X msg 409 78 symbol \$1-clock;
+#X msg 483 345 box_dotted 255 170 0;
+#X msg 346 345 wire_dotted 255 170 0;
+#X connect 2 0 23 0;
+#X connect 3 0 4 0;
+#X connect 4 0 1 0;
+#X connect 5 0 8 1;
+#X connect 8 2 5 0;
+#X connect 10 0 11 0;
+#X connect 11 0 12 0;
+#X connect 11 1 27 0;
+#X connect 12 0 9 0;
+#X connect 13 0 10 0;
+#X connect 13 1 14 0;
+#X connect 14 0 15 0;
+#X connect 15 0 17 0;
+#X connect 15 1 16 1;
+#X connect 16 0 18 0;
+#X connect 17 0 16 0;
+#X connect 18 0 9 0;
+#X connect 19 0 20 0;
+#X connect 20 0 22 0;
+#X connect 21 0 19 0;
+#X connect 22 0 13 0;
+#X connect 23 0 25 0;
+#X connect 24 0 3 0;
+#X connect 25 0 24 0;
+#X connect 27 0 9 0;
+#X coords 0 -1 1 1 92 16 2 0 0;
diff --git a/externals/gridflow/abstractions/doc_below.pd b/externals/gridflow/abstractions/doc_below.pd
new file mode 100644
index 00000000..68a6fa9d
--- /dev/null
+++ b/externals/gridflow/abstractions/doc_below.pd
@@ -0,0 +1,42 @@
+#N canvas 254 70 463 409 10;
+#X obj 45 28 inlet;
+#X obj 45 359 outlet;
+#X obj 64 66 gf/canvas_dollarzero 2;
+#X obj 85 85 symbol \$1;
+#X obj 117 231 r \$0-r;
+#X obj 45 231 unpack 0 0;
+#X obj 45 340 pack 0 0;
+#X obj 102 318 max;
+#X msg 117 280 \$4;
+#X obj 45 47 t a b b;
+#X obj 136 47 inlet;
+#X obj 64 112 pack 0 s \$0 \$2;
+#X msg 81 162 \; \$1/\$2 getbounds \$3-r \$4;
+#X obj 117 299 + \$3;
+#X obj 154 112 inlet;
+#X obj 62 133 t b a a;
+#X obj 266 149 receives;
+#X msg 266 130 list \$1/\$2;
+#X msg 245 109 list;
+#X text 279 109 prevent "no such object";
+#X connect 0 0 9 0;
+#X connect 2 0 11 0;
+#X connect 3 0 11 1;
+#X connect 4 0 8 0;
+#X connect 5 0 6 0;
+#X connect 5 1 7 0;
+#X connect 6 0 1 0;
+#X connect 7 0 6 1;
+#X connect 8 0 13 0;
+#X connect 9 0 5 0;
+#X connect 9 1 2 0;
+#X connect 9 2 3 0;
+#X connect 10 0 3 1;
+#X connect 11 0 15 0;
+#X connect 13 0 7 1;
+#X connect 14 0 11 3;
+#X connect 15 0 18 0;
+#X connect 15 1 12 0;
+#X connect 15 2 17 0;
+#X connect 17 0 16 0;
+#X connect 18 0 16 0;
diff --git a/externals/gridflow/abstractions/doc_bottom.pd b/externals/gridflow/abstractions/doc_bottom.pd
new file mode 100644
index 00000000..8f6de55a
--- /dev/null
+++ b/externals/gridflow/abstractions/doc_bottom.pd
@@ -0,0 +1,70 @@
+#N canvas 777 40 448 600 10;
+#X obj 33 151 pack f s;
+#X obj 33 113 \$0;
+#X msg 14 427 bang \, set;
+#X msg 23 488;
+#X obj 33 370 s;
+#X obj 33 332 \$0;
+#X msg 23 446 add2 \$1;
+#X obj 33 313 t b s;
+#X obj 33 233 r \$0-r1;
+#X msg 33 201 \; \$2/foreach_child symbol \$1-r1;
+#X obj 33 389 r \$0-r2;
+#X msg 33 408 \$4;
+#X obj 14 94 t b b f;
+#X msg 73 113 set \$1;
+#X obj 23 526 #fold max;
+#X obj 23 545 #to_float;
+#X obj 23 507 t a;
+#X text 45 506 HACK;
+#X obj 33 170 t a a;
+#X msg 122 150 symbol \$2/foreach_child;
+#X text 174 168 (dummy);
+#X text 120 182 to prevent "no such object";
+#X obj 14 15 inlet;
+#X obj 23 564 outlet;
+#X obj 78 16 inlet;
+#X msg 33 351 getbounds \$1-r2 1;
+#X obj 122 169 receives;
+#X obj 33 252 shunt 2 \$1;
+#X obj 99 271 spigot;
+#X obj 29 465 r \$0-zz;
+#X obj 73 132 s \$0-zz;
+#X obj 135 252 gf/string_<;
+#X obj 14 38 route2 before;
+#X msg 152 74 symbol \$1;
+#X obj 99 252 t s s;
+#X connect 0 0 18 0;
+#X connect 1 0 0 0;
+#X connect 2 0 3 0;
+#X connect 3 0 16 0;
+#X connect 5 0 25 0;
+#X connect 6 0 3 0;
+#X connect 7 0 5 0;
+#X connect 7 1 4 1;
+#X connect 8 0 27 0;
+#X connect 10 0 11 0;
+#X connect 11 0 6 0;
+#X connect 12 0 2 0;
+#X connect 12 1 1 0;
+#X connect 12 2 13 0;
+#X connect 13 0 30 0;
+#X connect 14 0 15 0;
+#X connect 15 0 23 0;
+#X connect 16 0 14 0;
+#X connect 18 0 9 0;
+#X connect 18 1 19 0;
+#X connect 19 0 26 0;
+#X connect 22 0 32 0;
+#X connect 24 0 0 1;
+#X connect 25 0 4 0;
+#X connect 27 0 7 0;
+#X connect 27 1 34 0;
+#X connect 28 0 7 0;
+#X connect 29 0 3 0;
+#X connect 31 0 28 1;
+#X connect 32 0 33 0;
+#X connect 32 1 12 0;
+#X connect 33 0 31 1;
+#X connect 34 0 28 0;
+#X connect 34 1 31 0;
diff --git a/externals/gridflow/abstractions/doc_c.pd b/externals/gridflow/abstractions/doc_c.pd
new file mode 100644
index 00000000..19a9042b
--- /dev/null
+++ b/externals/gridflow/abstractions/doc_c.pd
@@ -0,0 +1,25 @@
+#N canvas 437 169 573 492 10;
+#X obj 0 0 cnv 15 606 17 empty \$0-rect Creation arguments (0)
+200 8 1 9 -88239 -262144 0;
+#X obj 354 137 loadbang;
+#X obj 354 196 s \$0-rect;
+#X msg 414 38 3 \$2;
+#X msg 354 176 label Creation arguments (\$1);
+#X obj 354 156 list append \$1;
+#X obj 562 20 bng 12 250 50 0 empty \$0-create empty 17 7 0 10 -258048
+-1 -1;
+#X msg 377 89 \$2;
+#X obj 448 122 doc_make cc \$1;
+#X obj 414 57 doc_below h;
+#X obj 184 18 doc_layout c 574 30 - 1;
+#X obj 206 230 doc_editmode 562 1;
+#X connect 1 0 5 0;
+#X connect 3 0 9 0;
+#X connect 4 0 2 0;
+#X connect 5 0 4 0;
+#X connect 6 0 8 0;
+#X connect 7 0 8 1;
+#X connect 9 0 10 1;
+#X connect 10 2 3 0;
+#X connect 10 2 7 0;
+#X coords 0 -1 1 1 606 17 1 0 0;
diff --git a/externals/gridflow/abstractions/doc_cc.pd b/externals/gridflow/abstractions/doc_cc.pd
new file mode 100644
index 00000000..656f4212
--- /dev/null
+++ b/externals/gridflow/abstractions/doc_cc.pd
@@ -0,0 +1,38 @@
+#N canvas 91 65 567 335 10;
+#X obj 0 0 cnv 16 80 17 empty \$0-rect Argument 2: 4 9 1 9 -175159
+-1 0;
+#X obj 353 175 s \$0-rect;
+#X obj 353 135 list append \$1;
+#X msg 353 155 label Argument \$1:;
+#X msg 312 21 14 \$2;
+#X obj 353 116 loadbang;
+#X obj 68 20 bng 12 250 50 0 empty \$0-create empty 17 7 0 10 -262144
+-1 -1;
+#X obj 68 185 doc_add c\$1;
+#X obj 312 40 doc_below c;
+#X obj 384 2 loadbang;
+#X obj 384 21 float \$1;
+#X obj 384 40 moses 1;
+#X obj 432 40 - 1;
+#X obj 182 115 doc_editmode 68;
+#X obj 82 0 doc_layout c/\$1 80 20 c;
+#X msg 432 78 symbol c/\$1;
+#X obj 432 59 t a b;
+#X msg 468 59 1;
+#X connect 2 0 3 0;
+#X connect 3 0 1 0;
+#X connect 4 0 8 0;
+#X connect 5 0 2 0;
+#X connect 6 0 7 0;
+#X connect 8 0 14 1;
+#X connect 9 0 10 0;
+#X connect 10 0 11 0;
+#X connect 11 1 12 0;
+#X connect 12 0 16 0;
+#X connect 14 2 4 0;
+#X connect 14 2 7 1;
+#X connect 15 0 8 1;
+#X connect 16 0 15 0;
+#X connect 16 1 17 0;
+#X connect 17 0 8 2;
+#X coords 0 -1 1 1 80 17 2 0 0;
diff --git a/externals/gridflow/abstractions/doc_editmode.pd b/externals/gridflow/abstractions/doc_editmode.pd
new file mode 100644
index 00000000..e4615916
--- /dev/null
+++ b/externals/gridflow/abstractions/doc_editmode.pd
@@ -0,0 +1,56 @@
+#N canvas 0 0 450 431 10;
+#X obj 16 171 change 2;
+#X obj 16 7 loadbang;
+#X obj 33 278 + 20;
+#X obj 33 259 * -20;
+#X obj 16 335 t b b;
+#X obj 16 412 s;
+#X obj 16 152 gf/canvas_edit_mode 2;
+#X obj 123 207 gf/canvas_dollarzero 1;
+#X msg 144 327 symbol \$1-create;
+#X obj 120 327 s;
+#X obj 33 297 pack 0 \$1;
+#X msg 120 308 pos \$2 \$1;
+#X obj 43 354 gf/canvas_dollarzero 2;
+#X msg 43 373 symbol \$1-doc_h;
+#X msg 16 392 redraw;
+#X obj 261 264 s;
+#X msg 285 264 symbol \$1-rect;
+#X msg 261 245 pos 0 \$1;
+#X obj 16 190 t b a a b;
+#X obj 50 228 * 20;
+#X obj 50 209 spigot \$2;
+#X text 46 31 still something wrong with the loadbang? it's a mystery.
+;
+#X msg 16 114 symbol \$1-clock;
+#X obj 16 76 loadbang;
+#X obj 16 133 receives;
+#X msg 16 33 1;
+#X obj 16 95 gf/canvas_dollarzero 2;
+#X connect 0 0 18 0;
+#X connect 1 0 25 0;
+#X connect 2 0 10 0;
+#X connect 3 0 2 0;
+#X connect 4 0 14 0;
+#X connect 4 1 12 0;
+#X connect 6 0 0 0;
+#X connect 7 0 8 0;
+#X connect 7 0 16 0;
+#X connect 8 0 9 1;
+#X connect 10 0 11 0;
+#X connect 11 0 9 0;
+#X connect 12 0 13 0;
+#X connect 13 0 5 1;
+#X connect 14 0 5 0;
+#X connect 16 0 15 1;
+#X connect 17 0 15 0;
+#X connect 18 0 4 0;
+#X connect 18 1 3 0;
+#X connect 18 2 20 0;
+#X connect 18 3 7 0;
+#X connect 19 0 17 0;
+#X connect 20 0 19 0;
+#X connect 22 0 24 0;
+#X connect 23 0 26 0;
+#X connect 24 0 6 0;
+#X connect 26 0 22 0;
diff --git a/externals/gridflow/abstractions/doc_exist.pd b/externals/gridflow/abstractions/doc_exist.pd
new file mode 100644
index 00000000..1ae7b3cb
--- /dev/null
+++ b/externals/gridflow/abstractions/doc_exist.pd
@@ -0,0 +1,30 @@
+#N canvas 173 217 450 300 10;
+#X obj 20 20 inlet;
+#X obj 20 229 outlet;
+#X obj 87 58 gf/canvas_dollarzero 2;
+#X obj 108 77 symbol \$1;
+#X obj 87 104 pack 0 s \$0;
+#X obj 159 39 inlet;
+#X obj 68 39 t b b b;
+#X msg 87 123 \; \$1/\$2 ping \$3-r;
+#X obj 87 155 r \$0-r;
+#X msg 59 169 0;
+#X obj 20 39 t b b b;
+#X obj 20 210 f;
+#X obj 87 174 b;
+#X msg 87 193 1;
+#X connect 0 0 10 0;
+#X connect 2 0 4 0;
+#X connect 3 0 4 1;
+#X connect 4 0 7 0;
+#X connect 5 0 3 1;
+#X connect 6 1 2 0;
+#X connect 6 2 3 0;
+#X connect 8 0 12 0;
+#X connect 9 0 11 1;
+#X connect 10 0 11 0;
+#X connect 10 1 6 0;
+#X connect 10 2 9 0;
+#X connect 11 0 1 0;
+#X connect 12 0 13 0;
+#X connect 13 0 11 1;
diff --git a/externals/gridflow/abstractions/doc_f.pd b/externals/gridflow/abstractions/doc_f.pd
new file mode 100644
index 00000000..0ad12654
--- /dev/null
+++ b/externals/gridflow/abstractions/doc_f.pd
@@ -0,0 +1,12 @@
+#N canvas 110 0 620 482 10;
+#X obj 3 3 cnv 15 608 18 empty \$0-rect empty 2 9 1 13 -1 -262144 0
+;
+#X msg 417 38 0 \$2;
+#X obj 417 57 doc_below o 1 10;
+#X obj 417 77 doc_below s 1 0;
+#X obj 177 28 doc_layout f 582 24;
+#X connect 1 0 2 0;
+#X connect 2 0 3 0;
+#X connect 3 0 4 1;
+#X connect 4 2 1 0;
+#X coords 0 -1 1 1 614 24 2 0 0;
diff --git a/externals/gridflow/abstractions/doc_h.pd b/externals/gridflow/abstractions/doc_h.pd
new file mode 100644
index 00000000..79644105
--- /dev/null
+++ b/externals/gridflow/abstractions/doc_h.pd
@@ -0,0 +1,212 @@
+#N canvas 0 53 798 627 10;
+#X obj 3 3 cnv 15 608 18 empty \$0-rect ♯apply_colormap_channelwise
+2 9 1 13 -1 -262144 0;
+#X obj 6 28 loadbang;
+#X obj 61 30 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
+-1;
+#X symbolatom 6 68 20 0 0 0 - - -;
+#X obj 6 264 s \$0-rect;
+#X obj 6 48 gf/canvas_filename 1;
+#X obj 6 87 gf/string_replace # ♯;
+#X obj 6 166 gf/string_replace -help.pd;
+#X obj 510 3 cnv 15 100 18 empty \$0-rect2 GridFlow 1.0 2 9 1 12
+-1 -262144 0;
+#X obj 6 107 gf/string_replace 0x40 @;
+#X obj 6 127 gf/string_replace 0x2a *;
+#X obj 6 147 gf/string_replace 0x2b +;
+#X msg 390 47 0 0;
+#X obj 394 213 receives;
+#X obj 394 175 gf/canvas_dollarzero 1;
+#X obj 394 148 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 411 147 loadbang;
+#X msg 394 194 symbol \$1-doc_h;
+#X obj 394 232 route redraw;
+#X obj 420 308 gf/canvas_filename 1;
+#X obj 420 289 loadbang;
+#X obj 394 327 s;
+#X msg 420 327 symbol pd-\$1;
+#X msg 394 270 map 0 \, map 1;
+#X obj 394 251 delay 50;
+#X obj 27 512 #in;
+#X msg 27 493 open x11 here \$1 \, bang;
+#X obj 138 598 #out;
+#X obj 4 419 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
+-1;
+#X obj 138 541 gf/canvas_filename 1;
+#X obj 29 428 t b b;
+#X obj 27 531 t a a;
+#X obj 27 550 #finished;
+#X obj 28 405 route bang float;
+#X obj 74 443 delay;
+#X obj 74 424 t b f;
+#X obj 138 560 gf/string_replace -help.pd -help.ppm;
+#X obj 27 384 r justscreenshot;
+#X obj 27 569 t b b;
+#X msg 54 588 \; shoot end;
+#X msg 138 579 open png/\$1;
+#X obj 27 474 gf/canvas_xid 1;
+#X msg 29 451 bang;
+#X obj 536 580 gf/canvas_hehehe 1;
+#X obj 383 438 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 1
+1;
+#X obj 383 379 loadbang;
+#X obj 258 166 doc_exist c;
+#X obj 175 109 loadbang;
+#X msg 282 185 obj 0 0 doc_c;
+#X obj 258 185 sel;
+#X obj 242 223 sel;
+#X obj 242 204 doc_exist i;
+#X msg 266 223 obj 0 0 doc_i;
+#X obj 226 261 sel;
+#X msg 250 261 obj 0 0 doc_o;
+#X obj 226 242 doc_exist o;
+#X obj 211 299 sel;
+#X obj 211 280 doc_exist f;
+#X msg 235 299 obj 0 0 doc_f;
+#X text 234 127 _sorry_.;
+#X obj 175 147 t b b;
+#X msg 383 514 0 0;
+#X msg 383 552 \$2;
+#X obj 383 533 doc_below f;
+#X obj 383 571 + 5;
+#X obj 283 147 gf/canvas_count 1;
+#X floatatom 305 126 5 0 0 0 - - -;
+#X obj 211 147 t b b b b b;
+#X obj 175 318 gf/canvas_loadbang 1;
+#X obj 175 197 f;
+#X obj 533 72 t b b;
+#X obj 533 148 #in;
+#X msg 533 129 open x11 here \$1;
+#X obj 533 110 gf/canvas_xid 1;
+#X msg 560 91 open doc_anim.mov \, codec png;
+#X msg 587 169 close;
+#X obj 521 24 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
+-1;
+#X obj 560 192 #out;
+#X obj 536 24 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
+-1;
+#X obj 432 52 gf/canvas_dollarzero 1;
+#X obj 432 33 t b f;
+#X obj 492 4 tgl 15 0 empty empty empty 17 7 0 10 -4034 -1 -1 0 1;
+#X msg 432 109 \; \$1-pullup \$2;
+#X obj 477 71 * 8;
+#X obj 432 90 pack f f;
+#X obj 399 407 print doc_h_loadbang;
+#X text 293 416 URGHHH;
+#X obj 6 226 pack s s;
+#X obj 6 185 t a b;
+#X obj 33 204 symbol \$1;
+#X msg 6 245 label \$2\$1;
+#X obj 175 128 delay 400;
+#X obj 383 483 t b b;
+#X obj 454 445 gf/canvas_dollarzero 1;
+#X obj 439 483 s;
+#X msg 454 464 symbol \$1-clock;
+#X obj 454 426 loadbang;
+#X obj 383 456 metro 200;
+#X msg 341 416 1;
+#X obj 160 27 doc_layout h 582 24;
+#X obj 383 590 min 642;
+#X connect 1 0 5 0;
+#X connect 2 0 5 0;
+#X connect 3 0 6 0;
+#X connect 5 0 3 0;
+#X connect 6 0 9 0;
+#X connect 7 0 88 0;
+#X connect 9 0 10 0;
+#X connect 10 0 11 0;
+#X connect 11 0 7 0;
+#X connect 12 0 99 1;
+#X connect 13 0 18 0;
+#X connect 14 0 17 0;
+#X connect 15 0 14 0;
+#X connect 16 0 14 0;
+#X connect 17 0 13 0;
+#X connect 18 0 24 0;
+#X connect 19 0 22 0;
+#X connect 20 0 19 0;
+#X connect 22 0 21 1;
+#X connect 23 0 21 0;
+#X connect 24 0 23 0;
+#X connect 25 0 31 0;
+#X connect 26 0 25 0;
+#X connect 28 0 33 0;
+#X connect 29 0 36 0;
+#X connect 30 0 42 0;
+#X connect 30 1 29 0;
+#X connect 31 0 32 0;
+#X connect 31 1 27 0;
+#X connect 32 0 38 0;
+#X connect 33 0 30 0;
+#X connect 33 1 35 0;
+#X connect 34 0 30 0;
+#X connect 35 0 34 0;
+#X connect 35 1 34 1;
+#X connect 36 0 40 0;
+#X connect 37 0 33 0;
+#X connect 38 1 39 0;
+#X connect 40 0 27 0;
+#X connect 41 0 26 0;
+#X connect 42 0 41 0;
+#X connect 44 0 97 0;
+#X connect 45 0 85 0;
+#X connect 45 0 98 0;
+#X connect 46 0 49 0;
+#X connect 47 0 91 0;
+#X connect 48 0 21 0;
+#X connect 49 0 48 0;
+#X connect 50 0 52 0;
+#X connect 51 0 50 0;
+#X connect 52 0 21 0;
+#X connect 53 0 54 0;
+#X connect 54 0 21 0;
+#X connect 55 0 53 0;
+#X connect 56 0 58 0;
+#X connect 57 0 56 0;
+#X connect 58 0 21 0;
+#X connect 60 0 69 0;
+#X connect 60 1 67 0;
+#X connect 61 0 63 0;
+#X connect 62 0 64 0;
+#X connect 63 0 62 0;
+#X connect 64 0 100 0;
+#X connect 65 0 66 0;
+#X connect 65 0 69 1;
+#X connect 67 0 57 0;
+#X connect 67 1 55 0;
+#X connect 67 2 51 0;
+#X connect 67 3 46 0;
+#X connect 67 4 65 0;
+#X connect 69 0 68 0;
+#X connect 70 0 73 0;
+#X connect 70 1 74 0;
+#X connect 71 0 77 0;
+#X connect 72 0 71 0;
+#X connect 73 0 72 0;
+#X connect 74 0 77 0;
+#X connect 75 0 77 0;
+#X connect 76 0 70 0;
+#X connect 78 0 75 0;
+#X connect 79 0 84 0;
+#X connect 80 0 79 0;
+#X connect 80 1 83 0;
+#X connect 81 0 80 0;
+#X connect 83 0 84 1;
+#X connect 84 0 82 0;
+#X connect 87 0 90 0;
+#X connect 88 0 87 0;
+#X connect 88 1 89 0;
+#X connect 89 0 87 1;
+#X connect 90 0 4 0;
+#X connect 91 0 60 0;
+#X connect 92 0 61 0;
+#X connect 92 1 94 0;
+#X connect 93 0 95 0;
+#X connect 95 0 94 1;
+#X connect 96 0 93 0;
+#X connect 97 0 92 0;
+#X connect 98 0 44 0;
+#X connect 99 2 12 0;
+#X connect 100 0 43 0;
+#X coords 0 -1 1 1 614 24 2 0 0;
diff --git a/externals/gridflow/abstractions/doc_i.pd b/externals/gridflow/abstractions/doc_i.pd
new file mode 100644
index 00000000..d44e1b81
--- /dev/null
+++ b/externals/gridflow/abstractions/doc_i.pd
@@ -0,0 +1,28 @@
+#N canvas 110 0 573 469 10;
+#X obj 0 0 cnv 15 606 17 empty \$0-rect Inlets (2) 240 8 1 9 -88239
+-262144 0;
+#X obj 157 155 loadbang;
+#X obj 126 154 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 157 214 s \$0-rect;
+#X msg 399 38 3 \$2;
+#X obj 157 174 list append \$1;
+#X obj 562 20 bng 12 250 50 0 empty \$0-create empty 17 7 0 10 -262144
+-1 -1;
+#X msg 157 194 label Inlets (\$1);
+#X msg 362 89 \$2;
+#X obj 445 140 doc_make ii \$1;
+#X obj 399 57 doc_below c 1 10;
+#X obj 169 18 doc_layout i 574 30;
+#X obj 139 292 doc_editmode 562 1;
+#X connect 1 0 5 0;
+#X connect 2 0 5 0;
+#X connect 4 0 10 0;
+#X connect 5 0 7 0;
+#X connect 6 0 9 0;
+#X connect 7 0 3 0;
+#X connect 8 0 9 1;
+#X connect 10 0 11 1;
+#X connect 11 2 4 0;
+#X connect 11 2 8 0;
+#X coords 0 -1 1 1 606 17 1 0 0;
diff --git a/externals/gridflow/abstractions/doc_ii.pd b/externals/gridflow/abstractions/doc_ii.pd
new file mode 100644
index 00000000..8cfe43a3
--- /dev/null
+++ b/externals/gridflow/abstractions/doc_ii.pd
@@ -0,0 +1,41 @@
+#N canvas 143 119 573 310 10;
+#X obj 0 0 cnv 16 64 17 empty \$0-rect Inlet 2: 12 9 1 9 -175159
+-1 0;
+#X obj 328 103 loadbang;
+#X obj 309 120 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 328 163 s \$0-rect;
+#X obj 328 123 list append \$1;
+#X msg 328 143 label Inlet \$1:;
+#X msg 287 20 14 \$2;
+#X obj 52 0 bng 12 250 50 0 empty \$0-create empty 17 7 0 10 -262144
+-1 -1;
+#X obj 379 20 loadbang;
+#X obj 379 39 float \$1;
+#X obj 379 58 moses 1;
+#X obj 427 58 - 1;
+#X msg 427 96 symbol i/\$1;
+#X obj 98 76 doc_editmode 52;
+#X obj 287 39 doc_below i;
+#X obj 66 0 doc_layout i/\$1 80 20 i;
+#X obj 64 161 doc_add i\$1;
+#X obj 427 77 t a b;
+#X msg 463 77 1;
+#X connect 1 0 4 0;
+#X connect 2 0 4 0;
+#X connect 4 0 5 0;
+#X connect 5 0 3 0;
+#X connect 6 0 14 0;
+#X connect 7 0 16 0;
+#X connect 8 0 9 0;
+#X connect 9 0 10 0;
+#X connect 10 1 11 0;
+#X connect 11 0 17 0;
+#X connect 12 0 14 1;
+#X connect 14 0 15 1;
+#X connect 15 2 6 0;
+#X connect 15 2 16 1;
+#X connect 17 0 12 0;
+#X connect 17 1 18 0;
+#X connect 18 0 14 2;
+#X coords 0 -1 1 1 64 17 2 0 0;
diff --git a/externals/gridflow/abstractions/doc_layout.pd b/externals/gridflow/abstractions/doc_layout.pd
new file mode 100644
index 00000000..d1503c03
--- /dev/null
+++ b/externals/gridflow/abstractions/doc_layout.pd
@@ -0,0 +1,178 @@
+#N canvas 252 150 805 567 10;
+#X obj 6 368 outlet;
+#X obj 5 106 inlet;
+#X obj 5 87 outlet;
+#X obj 202 0 loadbang;
+#X obj 202 38 gf/canvas_dollarzero 2;
+#X msg 202 95 symbol \$1/\$2;
+#X obj 202 114 receives;
+#X obj 202 19 t b b;
+#X obj 256 76 symbol \$1;
+#X obj 202 76 pack 0 s;
+#X symbolatom 0 18 32 0 0 0 - - -;
+#X msg 5 144 symbol \$1;
+#X obj 5 163 t b s;
+#X obj 408 171 inlet;
+#X obj 408 152 outlet;
+#X obj 408 209 #to_list;
+#X obj 408 190 #change -99999;
+#X obj 408 228 gf/canvas_setpos 1;
+#X obj 408 75 gf/canvas_getpos 1;
+#X obj 408 133 t a a;
+#X floatatom 44 52 5 0 0 0 - - -;
+#X floatatom 84 52 5 0 0 0 - - -;
+#X floatatom 124 52 5 0 0 0 - - -;
+#X floatatom 164 52 5 0 0 0 - - -;
+#X obj 44 0 unpack;
+#X obj 97 74 + \$3;
+#X obj 677 291 gf/canvas_hohoho 2;
+#X obj 243 238 #pack 4;
+#X obj 243 276 #to_list;
+#X obj 67 74 + \$2;
+#X obj 152 390 list;
+#X obj 75 462 l2s;
+#X obj 75 481 gf.error unknown message '%s';
+#X obj 152 448 s;
+#X obj 152 251 t b a;
+#X obj 202 133 route2 getbounds ping;
+#X msg 263 152 symbol \$1;
+#X obj 280 372 t b a;
+#X obj 253 257 #change (4 # -99999);
+#X msg 202 152 list \$1 \$2;
+#X obj 202 171 unpack s f;
+#X obj 408 348 receives;
+#X obj 408 405 s;
+#X obj 408 367 t b s;
+#X obj 408 386 symbol;
+#X obj 152 270 shunt;
+#X obj 152 429 t a;
+#X obj 564 436 unpack f f f f;
+#X obj 566 456 pack f f f f;
+#X obj 408 251 loadbang;
+#X obj 182 394 list;
+#X text 3 350 (dummy);
+#X obj 677 272 list;
+#X obj 645 455 doc_bottom;
+#X obj 408 309 pack 0 s;
+#X obj 462 309 symbol \$4;
+#X obj 468 270 t b s;
+#X msg 468 251 symbol \$1;
+#X obj 408 270 t b b;
+#X obj 408 290 gf/canvas_dollarzero 2;
+#X msg 408 329 symbol \$1/\$2/foreach_child;
+#X msg 9 201 float \$1;
+#X obj 10 220 t b f;
+#X obj 123 305 t b b;
+#X obj 138 327 gf/canvas_getpos 1;
+#X obj 137 350 unpack f f;
+#X obj 408 94 unpack f f;
+#X obj 408 113 pack f f;
+#X obj 465 113 -;
+#X obj 5 125 route2 name parent height;
+#X obj 522 113 receives;
+#X obj 522 56 loadbang;
+#X msg 522 94 symbol \$1-pullup;
+#X obj 522 132 shunt 2 \$5;
+#X text 589 132 avoid pullup for c;
+#X obj 522 75 gf/canvas_dollarzero 2;
+#X obj 482 21 receives;
+#X msg 482 2 symbol \$1-clock;
+#X connect 1 0 69 0;
+#X connect 3 0 7 0;
+#X connect 4 0 9 0;
+#X connect 5 0 6 0;
+#X connect 5 0 10 0;
+#X connect 5 0 44 1;
+#X connect 5 0 53 1;
+#X connect 6 0 35 0;
+#X connect 7 0 4 0;
+#X connect 7 1 8 0;
+#X connect 8 0 9 1;
+#X connect 9 0 5 0;
+#X connect 11 0 12 0;
+#X connect 12 0 9 0;
+#X connect 12 1 8 0;
+#X connect 13 0 16 0;
+#X connect 15 0 17 0;
+#X connect 16 0 15 0;
+#X connect 18 0 24 0;
+#X connect 18 0 66 0;
+#X connect 19 0 14 0;
+#X connect 19 1 16 0;
+#X connect 20 0 27 0;
+#X connect 20 0 29 0;
+#X connect 21 0 25 0;
+#X connect 21 0 27 1;
+#X connect 22 0 27 2;
+#X connect 23 0 27 3;
+#X connect 24 0 20 0;
+#X connect 24 1 21 0;
+#X connect 25 0 23 0;
+#X connect 27 0 28 0;
+#X connect 28 0 30 1;
+#X connect 28 0 47 0;
+#X connect 29 0 22 0;
+#X connect 30 0 46 0;
+#X connect 31 0 32 0;
+#X connect 34 0 45 0;
+#X connect 34 1 33 1;
+#X connect 35 0 39 0;
+#X connect 35 1 36 0;
+#X connect 36 0 37 0;
+#X connect 37 0 33 0;
+#X connect 37 1 33 1;
+#X connect 38 0 28 0;
+#X connect 39 0 40 0;
+#X connect 40 0 34 0;
+#X connect 40 1 45 1;
+#X connect 41 0 43 0;
+#X connect 43 0 44 0;
+#X connect 43 1 42 1;
+#X connect 44 0 42 0;
+#X connect 45 0 63 0;
+#X connect 45 1 50 0;
+#X connect 46 0 33 0;
+#X connect 47 0 48 0;
+#X connect 47 1 48 1;
+#X connect 47 2 48 2;
+#X connect 47 3 53 0;
+#X connect 48 0 50 1;
+#X connect 48 0 52 1;
+#X connect 49 0 58 0;
+#X connect 50 0 46 0;
+#X connect 53 0 48 3;
+#X connect 54 0 60 0;
+#X connect 55 0 54 1;
+#X connect 56 0 54 0;
+#X connect 56 1 55 0;
+#X connect 57 0 56 0;
+#X connect 58 0 59 0;
+#X connect 58 1 55 0;
+#X connect 59 0 54 0;
+#X connect 60 0 41 0;
+#X connect 61 0 62 0;
+#X connect 62 0 25 0;
+#X connect 62 1 25 1;
+#X connect 63 0 30 0;
+#X connect 63 1 64 0;
+#X connect 64 0 65 0;
+#X connect 65 0 27 0;
+#X connect 65 1 27 1;
+#X connect 66 0 67 0;
+#X connect 66 1 68 0;
+#X connect 67 0 19 0;
+#X connect 68 0 67 1;
+#X connect 69 0 11 0;
+#X connect 69 1 57 0;
+#X connect 69 2 61 0;
+#X connect 69 3 31 0;
+#X connect 70 0 73 0;
+#X connect 71 0 75 0;
+#X connect 72 0 70 0;
+#X connect 73 0 68 1;
+#X connect 75 0 72 0;
+#X connect 75 0 77 0;
+#X connect 76 0 18 0;
+#X connect 76 0 52 0;
+#X connect 77 0 76 0;
+#X coords 0 -1 1 1 200 69 1 0 0;
diff --git a/externals/gridflow/abstractions/doc_m.pd b/externals/gridflow/abstractions/doc_m.pd
new file mode 100644
index 00000000..d5a2e81e
--- /dev/null
+++ b/externals/gridflow/abstractions/doc_m.pd
@@ -0,0 +1,166 @@
+#N canvas 90 97 836 502 10;
+#X obj 0 0 cnv 15 126 17 \$0-rect_s \$0-rect grid 4 9 1 9 -261615 -1
+0;
+#X obj 9 176 gf/string_replace c c/;
+#X obj 9 195 gf/string_replace i i/;
+#X obj 9 214 gf/string_replace o o/;
+#X obj 9 233 pack s s;
+#X obj 346 20 doc_below ??? 0 -20;
+#X msg 9 252 name \$1/\$2 \, parent \$1;
+#X msg 346 1 97 \$2;
+#X obj 35 458 outlet dummy;
+#X obj 317 478 outlet to_comment;
+#X obj 317 392 gf/lol 1;
+#X obj 650 193 loadbang;
+#X obj 317 297 gf/canvas_edit_mode 1;
+#X obj 317 335 sel 0 1;
+#X msg 317 373 wire_hide;
+#X obj 662 217 print doc_m:\$1:\$2;
+#X obj 317 278 t b b;
+#X obj 432 240 gf/canvas_getpos 0;
+#X msg 432 259 \$2;
+#X obj 317 430 change -242;
+#X msg 317 449 height \$1;
+#X obj 317 411 max 20;
+#X obj 403 158 max;
+#X obj 429 158 doc_bottom 1;
+#X obj 446 77 pack 0 s;
+#X msg 446 96 symbol \$1/\$2;
+#X obj 446 58 gf/canvas_dollarzero 1;
+#X obj 346 39 unpack f f;
+#X obj 358 65 pack f f;
+#X obj 446 115 pack s s;
+#X msg 446 134 before \$1/\$2;
+#X obj 412 39 t f f b b;
+#N canvas 0 0 468 230 fudgename 0;
+#X obj 7 12 inlet;
+#X obj 274 197 outlet;
+#X obj 7 31 sel bang float grid symbol pointer list <any>;
+#X obj 7 180 list;
+#X msg 7 50 0b;
+#X msg 45 50 0f;
+#X msg 83 50 0g;
+#X msg 121 50 0s;
+#X msg 159 50 1p;
+#X msg 197 50 2l;
+#X msg 235 50 ~a;
+#X connect 0 0 2 0;
+#X connect 2 0 4 0;
+#X connect 2 1 5 0;
+#X connect 2 2 6 0;
+#X connect 2 3 7 0;
+#X connect 2 4 8 0;
+#X connect 2 5 9 0;
+#X connect 2 6 10 0;
+#X connect 2 7 1 0;
+#X connect 3 0 1 0;
+#X connect 4 0 3 0;
+#X connect 5 0 3 0;
+#X connect 6 0 3 0;
+#X connect 7 0 3 0;
+#X connect 8 0 3 0;
+#X connect 9 0 3 0;
+#X connect 10 0 3 0;
+#X restore 72 233 pd fudgename;
+#X obj 501 115 symbol;
+#X obj 77 157 s \$0-rect;
+#X msg 77 138 label \$1;
+#X obj 9 116 args id (type a ~unspecified~) *;
+#X obj 9 157 symbol \$1;
+#X obj 635 127 doc_editmode 0 1;
+#X obj 75 293 gf/canvas_count 1;
+#X obj 29 293 t b b;
+#X obj 29 276 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
+-1;
+#X obj 29 312 f;
+#X obj 90 331 gf/canvas_filename 1;
+#X obj 90 312 loadbang;
+#X obj 29 412 s;
+#X msg 90 350 symbol pd-\$1;
+#X msg 29 393 obj \$2 200;
+#X text 96 411 we don't have our own object index;
+#X obj 93 372 +;
+#X obj 29 374 pack f f;
+#X obj 317 205 gf/canvas_dollarzero 1;
+#X msg 317 224 symbol \$1-clock;
+#X obj 317 186 loadbang;
+#X obj 317 243 receives;
+#X msg 336 354 wire_dotted 255 170 0;
+#X msg 484 335 box_dotted 255 170 0;
+#X obj 640 434 gf/canvas_setgop 0;
+#X obj 639 407 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 1
+1;
+#X obj 648 337 change 42;
+#X obj 637 363 inv+ 1;
+#X msg 432 278 box_align x 232 \$1 8;
+#X obj 130 1 doc_layout ~unspecified~ 126 20;
+#X connect 1 0 2 0;
+#X connect 2 0 3 0;
+#X connect 3 0 4 0;
+#X connect 3 0 5 1;
+#X connect 3 0 24 1;
+#X connect 4 0 6 0;
+#X connect 5 0 27 0;
+#X connect 6 0 62 0;
+#X connect 7 0 5 0;
+#X connect 10 0 21 0;
+#X connect 11 0 15 0;
+#X connect 12 0 13 0;
+#X connect 12 0 59 0;
+#X connect 13 0 14 0;
+#X connect 13 1 55 0;
+#X connect 14 0 10 0;
+#X connect 16 0 12 0;
+#X connect 16 1 17 0;
+#X connect 17 0 18 0;
+#X connect 18 0 61 0;
+#X connect 19 0 20 0;
+#X connect 19 0 49 1;
+#X connect 20 0 62 0;
+#X connect 21 0 19 0;
+#X connect 22 0 28 1;
+#X connect 23 0 22 1;
+#X connect 24 0 25 0;
+#X connect 25 0 23 1;
+#X connect 25 0 29 0;
+#X connect 26 0 24 0;
+#X connect 27 0 28 0;
+#X connect 27 1 31 0;
+#X connect 28 0 62 1;
+#X connect 29 0 30 0;
+#X connect 30 0 23 0;
+#X connect 31 0 22 0;
+#X connect 31 1 23 0;
+#X connect 31 2 26 0;
+#X connect 31 3 33 0;
+#X connect 32 0 4 1;
+#X connect 32 0 33 1;
+#X connect 33 0 29 1;
+#X connect 35 0 34 0;
+#X connect 36 0 37 0;
+#X connect 36 1 35 0;
+#X connect 36 1 32 0;
+#X connect 37 0 1 0;
+#X connect 39 0 42 1;
+#X connect 40 0 42 0;
+#X connect 40 1 39 0;
+#X connect 41 0 40 0;
+#X connect 42 0 50 0;
+#X connect 43 0 46 0;
+#X connect 44 0 43 0;
+#X connect 46 0 45 1;
+#X connect 47 0 45 0;
+#X connect 49 0 50 1;
+#X connect 50 0 47 0;
+#X connect 51 0 52 0;
+#X connect 52 0 54 0;
+#X connect 53 0 51 0;
+#X connect 54 0 16 0;
+#X connect 55 0 10 0;
+#X connect 58 0 57 0;
+#X connect 59 0 60 0;
+#X connect 60 0 58 0;
+#X connect 61 0 10 0;
+#X connect 62 2 7 0;
+#X connect 62 2 49 0;
+#X coords 0 -1 1 1 126 17 1 0 0;
diff --git a/externals/gridflow/abstractions/doc_make.pd b/externals/gridflow/abstractions/doc_make.pd
new file mode 100644
index 00000000..bbb79ffa
--- /dev/null
+++ b/externals/gridflow/abstractions/doc_make.pd
@@ -0,0 +1,35 @@
+#N canvas 198 167 463 440 10;
+#X obj 27 402 s;
+#X obj 27 252 * 24;
+#X obj 27 271 +;
+#X msg 54 146 symbol pd-\$1;
+#X obj 27 202 t f f;
+#X obj 27 226 + 1;
+#X obj 15 100 t b b b;
+#X msg 15 367 loadbang;
+#X obj 15 21 inlet;
+#X obj 54 127 gf/canvas_filename 2;
+#X msg 27 333 obj 3 \$1 \$2 \$3;
+#X obj 27 290 pack f s f;
+#X obj 117 258 symbol doc_\$1;
+#X obj 117 239 loadbang;
+#X obj 224 126 inlet y;
+#X obj 27 183 for 0 \$2 1;
+#X connect 1 0 2 0;
+#X connect 2 0 11 0;
+#X connect 3 0 0 1;
+#X connect 4 0 5 0;
+#X connect 4 1 11 2;
+#X connect 5 0 1 0;
+#X connect 6 0 7 0;
+#X connect 6 1 15 0;
+#X connect 6 2 9 0;
+#X connect 7 0 0 0;
+#X connect 8 0 6 0;
+#X connect 9 0 3 0;
+#X connect 10 0 0 0;
+#X connect 11 0 10 0;
+#X connect 12 0 11 1;
+#X connect 13 0 12 0;
+#X connect 14 0 2 1;
+#X connect 15 0 4 0;
diff --git a/externals/gridflow/abstractions/doc_o.pd b/externals/gridflow/abstractions/doc_o.pd
new file mode 100644
index 00000000..c036b816
--- /dev/null
+++ b/externals/gridflow/abstractions/doc_o.pd
@@ -0,0 +1,28 @@
+#N canvas 110 0 614 482 10;
+#X obj 0 0 cnv 15 606 16 empty \$0-rect Outlets (1) 240 8 1 9 -88239
+-262144 0;
+#X obj 59 221 loadbang;
+#X obj 28 239 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
+-1;
+#X obj 59 280 s \$0-rect;
+#X msg 407 38 3 \$2;
+#X obj 59 240 list append \$1;
+#X obj 562 20 bng 12 250 50 0 empty \$0-create empty 17 7 0 10 -262144
+-1 -1;
+#X msg 370 89 \$2;
+#X obj 448 141 doc_make oo \$1;
+#X msg 59 260 label Outlets (\$1);
+#X obj 407 57 doc_below i 1 10;
+#X obj 177 18 doc_layout o 574 30;
+#X obj 56 305 doc_editmode 562 1;
+#X connect 1 0 5 0;
+#X connect 2 0 5 0;
+#X connect 4 0 10 0;
+#X connect 5 0 9 0;
+#X connect 6 0 8 0;
+#X connect 7 0 8 1;
+#X connect 9 0 3 0;
+#X connect 10 0 11 1;
+#X connect 11 2 4 0;
+#X connect 11 2 7 0;
+#X coords 0 -1 1 1 606 17 1 0 0;
diff --git a/externals/gridflow/abstractions/doc_oo.pd b/externals/gridflow/abstractions/doc_oo.pd
new file mode 100644
index 00000000..61a69c7b
--- /dev/null
+++ b/externals/gridflow/abstractions/doc_oo.pd
@@ -0,0 +1,38 @@
+#N canvas 113 292 560 322 10;
+#X obj 0 0 cnv 16 64 17 empty \$0-rect Outlet 0: 8 9 1 9 -175159
+-1 0;
+#X obj 318 135 loadbang;
+#X obj 318 195 s \$0-rect;
+#X obj 318 155 list append \$1;
+#X msg 318 175 label Outlet \$1:;
+#X msg 287 22 14 \$2;
+#X obj 52 0 bng 12 250 50 0 empty \$0-create empty 17 7 0 10 -262144
+-1 -1;
+#X obj 52 133 doc_add o\$1;
+#X obj 287 41 doc_below o;
+#X obj 359 3 loadbang;
+#X obj 359 22 float \$1;
+#X obj 359 41 moses 1;
+#X obj 407 41 - 1;
+#X msg 407 90 symbol o/\$1;
+#X obj 152 71 doc_editmode 52;
+#X obj 66 0 doc_layout o/\$1 80 20 o;
+#X obj 407 69 t a b;
+#X msg 443 69 1;
+#X connect 1 0 3 0;
+#X connect 3 0 4 0;
+#X connect 4 0 2 0;
+#X connect 5 0 8 0;
+#X connect 6 0 7 0;
+#X connect 8 0 15 1;
+#X connect 9 0 10 0;
+#X connect 10 0 11 0;
+#X connect 11 1 12 0;
+#X connect 12 0 16 0;
+#X connect 13 0 8 1;
+#X connect 15 2 5 0;
+#X connect 15 2 7 1;
+#X connect 16 0 13 0;
+#X connect 16 1 17 0;
+#X connect 17 0 8 2;
+#X coords 0 -1 1 1 64 17 2 0 0;
diff --git a/externals/gridflow/abstractions/expect.pd b/externals/gridflow/abstractions/expect.pd
new file mode 100644
index 00000000..02df9edf
--- /dev/null
+++ b/externals/gridflow/abstractions/expect.pd
@@ -0,0 +1,11 @@
+#N canvas 531 173 450 300 10;
+#X obj 11 11 inlet;
+#X obj 150 30 args *;
+#X obj 11 150 outlet;
+#X obj 150 49 t a;
+#X obj 11 90 list.==;
+#X text 8 229 TODO: should do [gf.error expected %s but got %s];
+#X connect 0 0 4 0;
+#X connect 1 0 3 0;
+#X connect 3 0 4 1;
+#X connect 4 0 2 0;
diff --git a/externals/gridflow/abstractions/for.pd b/externals/gridflow/abstractions/for.pd
new file mode 100644
index 00000000..ed57b150
--- /dev/null
+++ b/externals/gridflow/abstractions/for.pd
@@ -0,0 +1,37 @@
+#N canvas 767 232 450 301 10;
+#X obj 30 56 inlet from;
+#X obj 190 56 inlet to;
+#X obj 250 56 inlet step;
+#X obj 55 239 outlet;
+#X obj 250 82 t f;
+#X obj 190 82 t f;
+#X obj 55 34 args from to step;
+#X obj 30 81 route set float bang;
+#X obj 55 170 until;
+#X obj 55 189 f;
+#X obj 80 189 +;
+#X obj 55 220 moses;
+#X obj 163 165 bang;
+#X obj 55 128 f;
+#X obj 55 150 t b f;
+#X connect 0 0 7 0;
+#X connect 1 0 5 0;
+#X connect 2 0 4 0;
+#X connect 4 0 10 1;
+#X connect 5 0 11 1;
+#X connect 6 0 13 1;
+#X connect 6 1 5 0;
+#X connect 6 2 4 0;
+#X connect 7 0 13 1;
+#X connect 7 1 13 0;
+#X connect 7 2 13 0;
+#X connect 8 0 9 0;
+#X connect 9 0 10 0;
+#X connect 9 0 11 0;
+#X connect 10 0 9 1;
+#X connect 11 0 3 0;
+#X connect 11 1 12 0;
+#X connect 12 0 8 1;
+#X connect 13 0 14 0;
+#X connect 14 0 8 0;
+#X connect 14 1 9 1;
diff --git a/externals/gridflow/abstractions/fps.pd b/externals/gridflow/abstractions/fps.pd
new file mode 100644
index 00000000..82921bc8
--- /dev/null
+++ b/externals/gridflow/abstractions/fps.pd
@@ -0,0 +1,210 @@
+#N canvas 0 0 660 613 10;
+#X obj 18 11 inlet;
+#X obj 113 543 outlet;
+#X obj 18 261 +;
+#X obj 43 261 t a;
+#X obj 18 280 moses 1000;
+#X obj 18 85 t a a b;
+#X msg 71 86 1;
+#X obj 71 105 +;
+#X obj 96 105 t a;
+#X obj 113 337 inv*;
+#X obj 113 318 / 1000;
+#X obj 83 299 t b a;
+#X msg 83 318 0;
+#X obj 126 49 symbol;
+#N canvas 173 324 450 300 timer 0;
+#X obj 18 32 inlet bang;
+#X obj 92 32 inlet mode;
+#X obj 92 51 listfind real user system cpu logical process;
+#X obj 18 175 realtime;
+#X obj 18 148 t b b;
+#X obj 304 156 t b b;
+#X obj 304 175 cputime;
+#X obj 265 175 timer;
+#X obj 265 156 t b b;
+#X obj 18 51 shunt 6;
+#X obj 78 148 t b b;
+#X obj 78 175 usertime;
+#X obj 138 152 t b b;
+#X obj 212 153 t b b;
+#X obj 212 175 tsctime;
+#X obj 138 175 systemtime;
+#X obj 18 236 outlet;
+#X connect 0 0 9 0;
+#X connect 1 0 2 0;
+#X connect 2 0 9 1;
+#X connect 3 0 16 0;
+#X connect 4 0 3 0;
+#X connect 4 1 3 1;
+#X connect 5 0 6 0;
+#X connect 5 1 6 1;
+#X connect 6 0 16 0;
+#X connect 7 0 16 0;
+#X connect 8 0 7 0;
+#X connect 8 1 7 1;
+#X connect 9 0 4 0;
+#X connect 9 1 10 0;
+#X connect 9 2 12 0;
+#X connect 9 4 8 0;
+#X connect 9 5 5 0;
+#X connect 10 0 11 0;
+#X connect 10 1 11 1;
+#X connect 11 0 16 0;
+#X connect 12 0 15 0;
+#X connect 12 1 15 1;
+#X connect 13 0 14 0;
+#X connect 13 1 14 1;
+#X connect 15 0 16 0;
+#X restore 18 66 pd timer;
+#X obj 256 40 args (detailed s terse);
+#X obj 256 59 listfind terse detailed;
+#X obj 280 251 shunt;
+#X msg 381 183 1;
+#X msg 342 183 0;
+#X obj 323 164 t b b b b;
+#X obj 113 367 shunt;
+#X obj 143 428 list append;
+#X obj 280 232 list prepend;
+#N canvas 207 253 585 366 min.med.max 0;
+#X obj 39 51 #sort;
+#X obj 39 32 #import per_message f;
+#X obj 39 70 t a a;
+#X obj 39 89 #finished;
+#X obj 106 56 #dim;
+#X obj 39 158 pack 0 0 0 0;
+#X obj 106 114 # / 2;
+#X obj 220 73 #to_float;
+#X obj 39 196 #store;
+#X obj 220 92 - 1;
+#X obj 39 215 #unpack 4;
+#X obj 60 235 +;
+#X obj 60 254 / 2;
+#X obj 35 275 pack 0 0 0;
+#X obj 106 133 #unpack;
+#X obj 39 13 inlet;
+#X obj 35 294 outlet;
+#X obj 39 177 #redim (4 1);
+#X obj 106 75 #redim (2);
+#X obj 106 94 # - (1 0);
+#X connect 0 0 2 0;
+#X connect 1 0 0 0;
+#X connect 2 0 3 0;
+#X connect 2 1 4 0;
+#X connect 2 1 8 1;
+#X connect 3 0 5 0;
+#X connect 4 0 7 0;
+#X connect 4 0 18 0;
+#X connect 5 0 17 0;
+#X connect 6 0 14 0;
+#X connect 7 0 9 0;
+#X connect 8 0 10 0;
+#X connect 9 0 5 3;
+#X connect 10 0 13 0;
+#X connect 10 1 11 0;
+#X connect 10 2 11 1;
+#X connect 10 3 13 2;
+#X connect 11 0 12 0;
+#X connect 12 0 13 1;
+#X connect 13 0 16 0;
+#X connect 14 0 5 1;
+#X connect 14 1 5 2;
+#X connect 15 0 1 0;
+#X connect 17 0 8 0;
+#X connect 18 0 19 0;
+#X connect 19 0 6 0;
+#X restore 310 310 pd min.med.max;
+#X text 169 371 weird;
+#X obj 143 390 f;
+#X obj 168 390 t b a;
+#X obj 143 479 list append;
+#X obj 215 460 inv* 1000;
+#N canvas 0 0 450 300 stdev 0;
+#X obj 16 -43 inlet values;
+#X obj 15 194 outlet stdev;
+#X obj 96 14 #fold +;
+#X obj 96 52 # /;
+#X obj 121 33 #dim;
+#X obj 96 -5 t a a;
+#X obj 16 -24 #import per_message f;
+#X obj 121 52 #cast f;
+#X obj 16 -5 #t;
+#X obj 16 95 # sq-;
+#X obj 15 171 #to_float;
+#X obj 16 114 #fold + \, seed (f #);
+#X obj 16 152 # sqrt (f #);
+#X obj 16 133 # /;
+#X connect 0 0 6 0;
+#X connect 2 0 3 0;
+#X connect 3 0 9 1;
+#X connect 4 0 7 0;
+#X connect 5 0 2 0;
+#X connect 5 1 4 0;
+#X connect 6 0 8 0;
+#X connect 7 0 3 1;
+#X connect 7 0 13 1;
+#X connect 8 0 9 0;
+#X connect 8 1 5 0;
+#X connect 9 0 11 0;
+#X connect 10 0 1 0;
+#X connect 11 0 13 0;
+#X connect 12 0 10 0;
+#X connect 13 0 12 0;
+#X restore 342 351 pd stdev;
+#X obj 143 509 list append;
+#X obj 310 281 t a a;
+#X obj 167 409 spigot;
+#X obj 18 30 route bang detailed mode period;
+#X obj 177 49 * 1000;
+#X connect 0 0 34 0;
+#X connect 2 0 3 0;
+#X connect 2 0 4 0;
+#X connect 3 0 2 1;
+#X connect 4 1 11 0;
+#X connect 5 0 2 0;
+#X connect 5 1 23 0;
+#X connect 5 2 6 0;
+#X connect 6 0 7 0;
+#X connect 7 0 8 0;
+#X connect 8 0 7 1;
+#X connect 8 0 9 1;
+#X connect 9 0 21 0;
+#X connect 9 0 29 0;
+#X connect 10 0 9 0;
+#X connect 11 0 12 0;
+#X connect 11 0 20 0;
+#X connect 11 1 10 0;
+#X connect 12 0 7 1;
+#X connect 12 0 2 1;
+#X connect 13 0 14 1;
+#X connect 14 0 5 0;
+#X connect 15 0 16 0;
+#X connect 16 0 21 1;
+#X connect 16 0 33 1;
+#X connect 17 0 23 1;
+#X connect 17 1 32 0;
+#X connect 18 0 17 1;
+#X connect 19 0 17 1;
+#X connect 20 0 23 1;
+#X connect 20 1 19 0;
+#X connect 20 2 23 0;
+#X connect 20 3 18 0;
+#X connect 21 0 1 0;
+#X connect 21 1 26 1;
+#X connect 22 0 28 0;
+#X connect 23 0 17 0;
+#X connect 24 0 27 0;
+#X connect 26 0 22 0;
+#X connect 27 0 33 0;
+#X connect 27 1 22 1;
+#X connect 28 0 31 0;
+#X connect 29 0 28 1;
+#X connect 30 0 31 1;
+#X connect 31 0 1 0;
+#X connect 32 0 24 0;
+#X connect 32 1 30 0;
+#X connect 33 0 26 0;
+#X connect 34 0 14 0;
+#X connect 34 2 13 0;
+#X connect 34 3 35 0;
+#X connect 35 0 4 1;
diff --git a/externals/gridflow/abstractions/gf.io_generate.pd b/externals/gridflow/abstractions/gf.io_generate.pd
new file mode 100644
index 00000000..43a6b475
--- /dev/null
+++ b/externals/gridflow/abstractions/gf.io_generate.pd
@@ -0,0 +1,81 @@
+#N canvas 491 139 789 550 10;
+#X msg 74 492 connect 0 0 2 0 \, connect 2 0 1 0;
+#X obj 96 353 list trim;
+#X obj 96 75 list split 1;
+#X obj 96 114 gf.suffix_lookup;
+#X obj 143 276 list append;
+#X obj 96 315 list prepend;
+#X obj 96 213 t b s;
+#X obj 96 94 t s s;
+#X obj 9 10 inlet;
+#X obj 322 65 \$1;
+#X obj 184 315 pack s s s;
+#X obj 251 292 symbol \$2;
+#X obj 251 273 loadbang;
+#X obj 74 518 outlet;
+#X obj 74 48 t b a b;
+#X obj 212 114 sel window;
+#X obj 143 257 list append \$2;
+#X obj 9 29 route bang;
+#X msg 322 443 clear \, obj 0 0 r \$1-in \, obj 0 40 s \$1-out;
+#X obj 96 334 list prepend obj 0 20;
+#X obj 9 313 \$1;
+#X obj 143 238 makefilename #io.%s;
+#X obj 213 157 class_exists;
+#X obj 213 176 sel 0 1;
+#X msg 213 138 symbol #io.quartz;
+#X msg 213 214 symbol x11;
+#X msg 231 195 symbol quartz;
+#X obj 96 142 route bang;
+#X obj 409 233 gf.error unknown suffix '%s';
+#X obj 409 214 list;
+#X msg 31 426 obj 0 20 gf.not_open;
+#X obj 9 332 t a a a;
+#X obj 96 380 t b a;
+#X msg 96 399 else obj 0 20 gf.not_open;
+#X connect 0 0 13 0;
+#X connect 1 0 32 0;
+#X connect 2 0 7 0;
+#X connect 2 1 4 1;
+#X connect 3 0 27 0;
+#X connect 3 1 29 1;
+#X connect 3 2 15 0;
+#X connect 4 0 19 0;
+#X connect 5 0 19 0;
+#X connect 6 0 5 0;
+#X connect 6 1 10 0;
+#X connect 7 0 3 0;
+#X connect 7 1 10 2;
+#X connect 8 0 17 0;
+#X connect 9 0 18 0;
+#X connect 10 0 5 1;
+#X connect 11 0 10 1;
+#X connect 12 0 11 0;
+#X connect 14 0 0 0;
+#X connect 14 1 2 0;
+#X connect 14 2 9 0;
+#X connect 15 0 24 0;
+#X connect 15 1 21 0;
+#X connect 16 0 4 0;
+#X connect 17 0 20 0;
+#X connect 17 1 14 0;
+#X connect 18 0 13 0;
+#X connect 19 0 1 0;
+#X connect 20 0 31 0;
+#X connect 21 0 16 0;
+#X connect 22 0 23 0;
+#X connect 23 0 25 0;
+#X connect 23 1 26 0;
+#X connect 24 0 22 0;
+#X connect 25 0 21 0;
+#X connect 26 0 21 0;
+#X connect 27 0 29 0;
+#X connect 27 1 6 0;
+#X connect 29 0 28 0;
+#X connect 30 0 13 0;
+#X connect 31 0 0 0;
+#X connect 31 1 30 0;
+#X connect 31 2 18 0;
+#X connect 32 0 33 0;
+#X connect 32 1 13 0;
+#X connect 33 0 13 0;
diff --git a/externals/gridflow/abstractions/gf.nbxhsl.pd b/externals/gridflow/abstractions/gf.nbxhsl.pd
new file mode 100644
index 00000000..088b6cdf
--- /dev/null
+++ b/externals/gridflow/abstractions/gf.nbxhsl.pd
@@ -0,0 +1,32 @@
+#N canvas 770 0 450 300 10;
+#X msg 290 89 label \$1;
+#X obj 237 89 t s s s;
+#X obj 237 184 t a;
+#X msg 237 165 receive \$1;
+#X msg 259 127 send \$1;
+#X obj 50 0 hsl 129 12 0 65535 0 0 1005-s_contrast 1005-contrast contrast
+4 7 1 10 -233017 -195568 -195568 0 0;
+#X obj 0 0 nbx 5 12 0 65535 0 0 1005-s_contrast 1005-contrast empty
+4 7 1 10 -233017 -195568 -195568 0 256;
+#X msg 47 75 set \$1;
+#X msg 0 75 set \$1;
+#X obj 173 60 args (self f) (name s);
+#X obj 237 146 makefilename \$1-%s;
+#X obj 259 108 makefilename \$1-s_%s;
+#X obj 312 60 gf.error where does this go?;
+#X connect 0 0 5 0;
+#X connect 1 0 10 0;
+#X connect 1 1 11 0;
+#X connect 1 2 0 0;
+#X connect 2 0 6 0;
+#X connect 2 0 5 0;
+#X connect 3 0 2 0;
+#X connect 4 0 2 0;
+#X connect 5 0 8 0;
+#X connect 6 0 7 0;
+#X connect 7 0 5 0;
+#X connect 8 0 6 0;
+#X connect 9 1 1 0;
+#X connect 10 0 3 0;
+#X connect 11 0 4 0;
+#X coords 0 -1 1 1 181 12 2 0 0;
diff --git a/externals/gridflow/abstractions/gf.not_open.pd b/externals/gridflow/abstractions/gf.not_open.pd
new file mode 100644
index 00000000..b311c621
--- /dev/null
+++ b/externals/gridflow/abstractions/gf.not_open.pd
@@ -0,0 +1,10 @@
+#N canvas 0 0 450 300 10;
+#X obj 16 16 inlet;
+#X obj 16 35 t b b;
+#X obj 16 73 outlet;
+#X obj 55 35 gf.error not open;
+#X msg 16 54 not_open;
+#X connect 0 0 1 0;
+#X connect 1 0 4 0;
+#X connect 1 1 3 0;
+#X connect 4 0 2 0;
diff --git a/externals/gridflow/abstractions/gf.oneshot.pd b/externals/gridflow/abstractions/gf.oneshot.pd
new file mode 100644
index 00000000..f2174f1f
--- /dev/null
+++ b/externals/gridflow/abstractions/gf.oneshot.pd
@@ -0,0 +1,20 @@
+#N canvas 520 225 450 300 10;
+#X obj 33 82 inlet;
+#X obj 33 139 outlet;
+#X obj 33 120 t a b;
+#X msg 84 82 0;
+#X obj 123 20 inlet;
+#X obj 123 39 route bang;
+#X msg 123 58 1;
+#X obj 39 39 args (x f 1);
+#X obj 33 101 spigot;
+#X connect 0 0 8 0;
+#X connect 2 0 1 0;
+#X connect 2 1 3 0;
+#X connect 3 0 8 1;
+#X connect 4 0 5 0;
+#X connect 5 0 6 0;
+#X connect 5 1 8 1;
+#X connect 6 0 8 1;
+#X connect 7 0 8 1;
+#X connect 8 0 2 0;
diff --git a/externals/gridflow/abstractions/hpgl_find_bbox.pd b/externals/gridflow/abstractions/hpgl_find_bbox.pd
new file mode 100644
index 00000000..7fb8855d
--- /dev/null
+++ b/externals/gridflow/abstractions/hpgl_find_bbox.pd
@@ -0,0 +1,49 @@
+#N canvas 507 388 450 300 10;
+#X obj 23 26 inlet hpgl;
+#X obj 23 45 route2 PA PD PU;
+#X obj 233 109 #import (2);
+#X obj 233 128 #to_list;
+#X obj 104 26 inlet end;
+#X obj 104 270 outlet report;
+#X obj 300 128 loadbang;
+#X obj 104 191 #seq_fold;
+#X obj 23 74 t a;
+#X obj 194 90 list split 1;
+#X obj 274 196 #seq_fold;
+#X obj 133 210 # min;
+#X obj 303 215 # max;
+#X obj 233 147 t a a;
+#X obj 104 125 t b b;
+#X obj 104 251 #join 0;
+#X obj 104 232 #redim (1 2);
+#X obj 274 234 #redim (1 2);
+#X msg 341 196 -999999 -999999;
+#X msg 171 191 999999 999999;
+#X connect 0 0 1 0;
+#X connect 1 0 8 0;
+#X connect 1 1 8 0;
+#X connect 1 2 8 0;
+#X connect 2 0 3 0;
+#X connect 3 0 13 0;
+#X connect 4 0 14 0;
+#X connect 6 0 19 0;
+#X connect 6 0 18 0;
+#X connect 7 0 16 0;
+#X connect 7 1 11 0;
+#X connect 7 2 11 1;
+#X connect 8 0 9 0;
+#X connect 9 1 2 0;
+#X connect 10 0 17 0;
+#X connect 10 1 12 0;
+#X connect 10 2 12 1;
+#X connect 11 0 7 3;
+#X connect 12 0 10 3;
+#X connect 13 0 7 1;
+#X connect 13 1 10 1;
+#X connect 14 0 7 0;
+#X connect 14 1 10 0;
+#X connect 15 0 5 0;
+#X connect 16 0 15 0;
+#X connect 17 0 15 1;
+#X connect 18 0 10 2;
+#X connect 19 0 7 2;
diff --git a/externals/gridflow/abstractions/hpgl_font_render.pd b/externals/gridflow/abstractions/hpgl_font_render.pd
new file mode 100644
index 00000000..bb31d888
--- /dev/null
+++ b/externals/gridflow/abstractions/hpgl_font_render.pd
@@ -0,0 +1,205 @@
+#N canvas 529 0 693 585 10;
+#X obj 11 11 inlet hpgl;
+#X obj 11 556 outlet hpgl;
+#X obj 85 11 inlet font_name;
+#X obj 85 30 symbol;
+#X obj 194 30 args font_name;
+#X msg 51 230 symbol \$1;
+#X obj 51 266 #import;
+#X obj 51 304 #to_float;
+#X obj 212 375 pack f s;
+#X obj 11 211 t a;
+#X obj 212 394 t a b;
+#X obj 492 96 hpgl_track_position;
+#X obj 242 486 f;
+#X obj 242 524 +;
+#X obj 242 543 +;
+#X obj 472 152 #unpack;
+#X obj 267 543 r \$0-char-width;
+#X obj 242 562 s \$0-char-pos;
+#X obj 72 155 s \$0-scaling;
+#X obj 334 96 route print_from_ascii;
+#X obj 267 96 route2 LB;
+#X obj 134 136 s \$0-rowheight;
+#X obj 535 189 f;
+#X obj 560 189 -;
+#X obj 585 189 r \$0-rowheight;
+#X obj 447 181 f;
+#X obj 11 96 route spacing scaling rowheight wrap;
+#X obj 196 117 s \$0-wrap;
+#X obj 51 364 t b;
+#X obj 57 343 r \$0-crlf;
+#X obj 242 505 shunt;
+#X msg 300 432 1;
+#X msg 261 432 0;
+#X obj 242 413 t b b b b;
+#X obj 51 383 f;
+#X obj 51 323 route 10 13;
+#X obj 132 323 t a a;
+#X obj 76 383 * -1;
+#X obj 531 215 s \$0-row-pos;
+#N canvas 418 66 489 534 draw_one_character 0;
+#X msg 132 58 open grid \$2/\$1.hpgl \, headerless \, type b;
+#X obj 51 137 until;
+#X obj 51 156 #in;
+#X obj 90 137 route bang;
+#X obj 82 296 hpgl_find_bbox;
+#X obj 51 58 t b b b b a;
+#X msg 300 125 1;
+#X msg 301 162 0;
+#X obj 52 277 shunt;
+#X msg 23 107 rewind;
+#X obj 110 455 #pack;
+#X obj 110 436 inv+;
+#X obj 82 357 inv+;
+#X obj 82 315 #redim (4);
+#X obj 52 194 route2 PA PU PD;
+#X obj 82 334 #unpack 4;
+#X obj 52 230 hpgl_op *;
+#X obj 52 474 hpgl_op +;
+#X obj 82 395 s \$0-char-width;
+#X obj 142 436 r \$0-char-pos;
+#X obj 119 230 r \$0-scaling;
+#X obj 82 376 max;
+#X obj 52 175 plotter_parser;
+#X obj 149 455 r \$0-row-pos;
+#X obj 51 39 inlet;
+#X obj 52 493 outlet;
+#X connect 0 0 2 0;
+#X connect 1 0 2 0;
+#X connect 2 0 22 0;
+#X connect 2 1 3 0;
+#X connect 3 0 1 1;
+#X connect 4 0 13 0;
+#X connect 5 0 1 0;
+#X connect 5 1 7 0;
+#X connect 5 1 9 0;
+#X connect 5 1 4 1;
+#X connect 5 2 1 0;
+#X connect 5 3 6 0;
+#X connect 5 4 0 0;
+#X connect 6 0 8 1;
+#X connect 7 0 8 1;
+#X connect 8 0 17 0;
+#X connect 8 1 4 0;
+#X connect 9 0 2 0;
+#X connect 10 0 17 1;
+#X connect 11 0 10 0;
+#X connect 12 0 21 0;
+#X connect 13 0 15 0;
+#X connect 14 0 16 0;
+#X connect 14 1 16 0;
+#X connect 14 2 16 0;
+#X connect 15 0 12 0;
+#X connect 15 0 11 0;
+#X connect 15 2 12 1;
+#X connect 16 0 8 0;
+#X connect 17 0 25 0;
+#X connect 19 0 11 1;
+#X connect 20 0 16 1;
+#X connect 21 0 18 0;
+#X connect 22 0 14 0;
+#X connect 23 0 10 1;
+#X connect 24 0 5 0;
+#X restore 62 533 pd draw_one_character;
+#N canvas 0 0 450 300 word-wrap 0;
+#X obj 27 125 -;
+#X obj 66 144 r \$0-wrap;
+#X obj 43 106 #unpack;
+#X obj 57 230 s \$0-crlf;
+#X obj 27 144 moses;
+#X obj 57 211 spigot;
+#X obj 103 211 == 32;
+#X obj 57 168 spigot 0;
+#X obj 117 168 !=;
+#X obj 103 192 inlet cur-char;
+#X obj 27 26 inlet cur-pos;
+#X obj 43 87 inlet orig-pos;
+#X connect 0 0 4 0;
+#X connect 1 0 4 1;
+#X connect 1 0 8 0;
+#X connect 2 0 0 1;
+#X connect 4 1 7 0;
+#X connect 5 0 3 0;
+#X connect 6 0 5 1;
+#X connect 7 0 5 0;
+#X connect 8 0 7 1;
+#X connect 9 0 6 0;
+#X connect 10 0 0 0;
+#X connect 11 0 2 0;
+#X restore 453 293 pd word-wrap;
+#X obj 447 152 t b;
+#X obj 51 402 s \$0-char-width;
+#X obj 246 179 t b;
+#X obj 223 254 s \$0-char-width;
+#X msg 223 235 0;
+#X obj 51 285 t a b;
+#X obj 85 49 s \$0-font-name;
+#X obj 263 356 r \$0-font-name;
+#X obj 267 524 r \$0-spacing;
+#X obj 11 174 s \$0-spacing;
+#X obj 76 364 r \$0-spacing;
+#X connect 0 0 26 0;
+#X connect 2 0 3 0;
+#X connect 3 0 47 0;
+#X connect 4 0 3 0;
+#X connect 5 0 6 0;
+#X connect 6 0 46 0;
+#X connect 7 0 35 0;
+#X connect 8 0 10 0;
+#X connect 9 0 1 0;
+#X connect 10 0 39 0;
+#X connect 10 1 33 0;
+#X connect 11 0 15 0;
+#X connect 11 0 40 1;
+#X connect 12 0 30 0;
+#X connect 13 0 14 0;
+#X connect 14 0 12 1;
+#X connect 14 0 17 0;
+#X connect 15 0 25 0;
+#X connect 15 1 22 1;
+#X connect 15 1 38 0;
+#X connect 16 0 14 1;
+#X connect 19 0 6 0;
+#X connect 19 1 11 0;
+#X connect 19 1 9 0;
+#X connect 20 0 5 0;
+#X connect 20 1 19 0;
+#X connect 22 0 23 0;
+#X connect 23 0 22 1;
+#X connect 23 0 38 0;
+#X connect 24 0 23 1;
+#X connect 25 0 12 1;
+#X connect 26 0 50 0;
+#X connect 26 1 18 0;
+#X connect 26 2 21 0;
+#X connect 26 3 27 0;
+#X connect 26 4 20 0;
+#X connect 28 0 34 0;
+#X connect 28 0 41 0;
+#X connect 29 0 28 0;
+#X connect 30 0 13 0;
+#X connect 30 1 40 0;
+#X connect 31 0 30 1;
+#X connect 32 0 30 1;
+#X connect 33 0 12 0;
+#X connect 33 1 32 0;
+#X connect 33 2 12 0;
+#X connect 33 3 31 0;
+#X connect 34 0 42 0;
+#X connect 35 0 28 0;
+#X connect 35 2 36 0;
+#X connect 36 0 8 0;
+#X connect 36 1 40 2;
+#X connect 37 0 34 1;
+#X connect 39 0 1 0;
+#X connect 41 0 25 0;
+#X connect 41 0 22 0;
+#X connect 43 0 11 1;
+#X connect 43 0 45 0;
+#X connect 45 0 44 0;
+#X connect 46 0 7 0;
+#X connect 46 1 43 0;
+#X connect 48 0 8 1;
+#X connect 49 0 13 1;
+#X connect 51 0 37 0;
diff --git a/externals/gridflow/abstractions/hpgl_op.pd b/externals/gridflow/abstractions/hpgl_op.pd
new file mode 100644
index 00000000..caf81f74
--- /dev/null
+++ b/externals/gridflow/abstractions/hpgl_op.pd
@@ -0,0 +1,32 @@
+#N canvas 348 192 474 256 10;
+#X obj -43 19 inlet;
+#X obj 13 213 outlet;
+#X obj 134 20 inlet offset;
+#X obj 37 112 list split 1;
+#X obj 37 188 list trim;
+#X obj 71 150 # +;
+#X obj 71 169 #to_list;
+#X obj 37 169 list;
+#X obj 71 131 #import \, cast f;
+#X obj 224 40 args op (offset a (0 0));
+#X msg 92 82 op \$1;
+#X obj -43 38 route2 PU PD PA op;
+#X obj 95 150 #import \, cast f;
+#X connect 0 0 11 0;
+#X connect 2 0 12 0;
+#X connect 3 0 7 0;
+#X connect 3 1 8 0;
+#X connect 4 0 1 0;
+#X connect 5 0 6 0;
+#X connect 6 0 7 1;
+#X connect 7 0 4 0;
+#X connect 8 0 5 0;
+#X connect 9 0 10 0;
+#X connect 9 1 12 0;
+#X connect 10 0 5 0;
+#X connect 11 0 3 0;
+#X connect 11 1 3 0;
+#X connect 11 2 3 0;
+#X connect 11 3 10 0;
+#X connect 11 4 1 0;
+#X connect 12 0 5 1;
diff --git a/externals/gridflow/abstractions/hpgl_track_position.pd b/externals/gridflow/abstractions/hpgl_track_position.pd
new file mode 100644
index 00000000..f18e1259
--- /dev/null
+++ b/externals/gridflow/abstractions/hpgl_track_position.pd
@@ -0,0 +1,28 @@
+#N canvas 733 333 450 300 10;
+#X obj 15 15 inlet;
+#X obj 219 74 b;
+#X obj 15 34 route2 get PA PD PU;
+#X obj 64 76 t a;
+#X obj 227 93 list split 1;
+#X obj 296 131 list length;
+#X obj 266 112 t a a;
+#X obj 231 169 list split;
+#X obj 296 150 - 2;
+#X obj 219 225 outlet;
+#X obj 219 14 inlet;
+#X obj 219 206 list 0 0;
+#X connect 0 0 2 0;
+#X connect 1 0 11 0;
+#X connect 2 0 1 0;
+#X connect 2 1 3 0;
+#X connect 2 2 3 0;
+#X connect 2 3 3 0;
+#X connect 3 0 4 0;
+#X connect 4 1 6 0;
+#X connect 5 0 8 0;
+#X connect 6 0 7 0;
+#X connect 6 1 5 0;
+#X connect 7 1 11 1;
+#X connect 8 0 7 1;
+#X connect 10 0 1 0;
+#X connect 11 0 9 0;
diff --git a/externals/gridflow/abstractions/interval_overlap.pd b/externals/gridflow/abstractions/interval_overlap.pd
new file mode 100644
index 00000000..cf0525f0
--- /dev/null
+++ b/externals/gridflow/abstractions/interval_overlap.pd
@@ -0,0 +1,14 @@
+#N canvas 599 0 574 300 10;
+#X obj 25 165 outlet;
+#X obj 25 51 inlet start1;
+#X obj 142 51 inlet end1;
+#X obj 259 51 inlet start2;
+#X obj 377 51 inlet end2;
+#X obj 25 90 expr ($f1>=$f3 && $f1<$f4) || ($f2>=$f3 && $f2<$f4);
+#X text 20 19 There's some bug with the endpoints (see dd's proc overlap)
+;
+#X connect 1 0 5 0;
+#X connect 2 0 5 1;
+#X connect 3 0 5 2;
+#X connect 4 0 5 3;
+#X connect 5 0 0 0;
diff --git a/externals/gridflow/abstractions/inv0x2a.pd b/externals/gridflow/abstractions/inv0x2a.pd
new file mode 100644
index 00000000..fb3b9189
--- /dev/null
+++ b/externals/gridflow/abstractions/inv0x2a.pd
@@ -0,0 +1,11 @@
+#N canvas 0 0 450 300 10;
+#X obj 20 -35 inlet;
+#X obj 60 -35 inlet;
+#X obj 20 39 outlet;
+#X obj 20 20 /;
+#X obj 20 -1 swap \$1;
+#X connect 0 0 4 0;
+#X connect 1 0 4 1;
+#X connect 3 0 2 0;
+#X connect 4 0 3 0;
+#X connect 4 1 3 1;
diff --git a/externals/gridflow/abstractions/inv0x2b.pd b/externals/gridflow/abstractions/inv0x2b.pd
new file mode 100644
index 00000000..1aab4c34
--- /dev/null
+++ b/externals/gridflow/abstractions/inv0x2b.pd
@@ -0,0 +1,11 @@
+#N canvas 0 0 450 300 10;
+#X obj 20 -35 inlet;
+#X obj 60 -35 inlet;
+#X obj 20 39 outlet;
+#X obj 20 20 -;
+#X obj 20 -1 swap \$1;
+#X connect 0 0 4 0;
+#X connect 1 0 4 1;
+#X connect 3 0 2 0;
+#X connect 4 0 3 0;
+#X connect 4 1 3 1;
diff --git a/externals/gridflow/abstractions/norecurse.pd b/externals/gridflow/abstractions/norecurse.pd
new file mode 100644
index 00000000..1d3b77d3
--- /dev/null
+++ b/externals/gridflow/abstractions/norecurse.pd
@@ -0,0 +1,14 @@
+#N canvas 442 212 450 300 10;
+#X obj 20 22 inlet;
+#X obj 52 108 outlet;
+#X obj 20 48 spigot 1;
+#X obj 20 67 t b a b;
+#X msg 89 59 0;
+#X msg 17 90 1;
+#X connect 0 0 2 0;
+#X connect 2 0 3 0;
+#X connect 3 0 5 0;
+#X connect 3 1 1 0;
+#X connect 3 2 4 0;
+#X connect 4 0 2 1;
+#X connect 5 0 2 1;
diff --git a/externals/gridflow/abstractions/pingpong.pd b/externals/gridflow/abstractions/pingpong.pd
new file mode 100644
index 00000000..406c9d16
--- /dev/null
+++ b/externals/gridflow/abstractions/pingpong.pd
@@ -0,0 +1,27 @@
+#N canvas 0 0 450 270 10;
+#X text 50 11 counter;
+#X obj 67 40 inlet;
+#X obj 67 83 %;
+#X obj 67 103 -;
+#X obj 164 49 inlet;
+#X text 163 32 maxvalue;
+#X obj 83 62 * 2;
+#X obj 67 124 abs;
+#X obj 67 185 outlet;
+#X text 123 184 values from 0 to maxvalue;
+#X obj 67 145 -;
+#X obj 67 165 * -1;
+#X obj 164 70 float \$1;
+#X obj 206 49 loadbang;
+#X connect 1 0 2 0;
+#X connect 2 0 3 0;
+#X connect 3 0 7 0;
+#X connect 4 0 12 0;
+#X connect 6 0 2 1;
+#X connect 7 0 10 0;
+#X connect 10 0 11 0;
+#X connect 11 0 8 0;
+#X connect 12 0 6 0;
+#X connect 12 0 10 1;
+#X connect 12 0 3 1;
+#X connect 13 0 12 0;
diff --git a/externals/gridflow/abstractions/plotter_control.pd b/externals/gridflow/abstractions/plotter_control.pd
new file mode 100644
index 00000000..3bca76d9
--- /dev/null
+++ b/externals/gridflow/abstractions/plotter_control.pd
@@ -0,0 +1,119 @@
+#N canvas 474 0 746 530 10;
+#X obj 8 4 inlet;
+#X obj 8 503 outlet;
+#X msg 8 463 59 10;
+#X text 52 463 comma+newline;
+#X obj 201 443 #import;
+#X msg 201 424 to_ascii \$1;
+#X obj 201 462 #to_float;
+#X msg 54 443 44;
+#X msg 373 102 list IP;
+#X obj 320 102 t b a b;
+#X obj 316 362 foreach;
+#X obj 316 338 t a b;
+#X msg 355 338 0;
+#X msg 320 121 end;
+#X obj 368 381 spigot;
+#X msg 435 412 1;
+#X obj 315 381 t b a b;
+#X obj 337 465 t a;
+#X obj 8 172 list split 1;
+#X obj 30 210 list;
+#X obj 297 208 #import;
+#X obj 297 227 # & -33;
+#X text 352 226 turns to uppercase if content is only letters;
+#X obj 297 246 #to_symbol;
+#X msg 100 443 32;
+#X obj 17 49 list;
+#X msg 70 68 list LB;
+#X obj 17 68 t b l b;
+#X msg 146 443 3;
+#X msg 17 87 break \, end;
+#X obj 126 49 t b l b;
+#X msg 179 49 list LB;
+#X obj 148 68 #to_symbol;
+#X msg 126 87 break \, end;
+#X obj 8 23 route other print print_from_ascii;
+#X obj 8 191 t b b s;
+#X obj 104 369 t a b;
+#X obj 316 305 t a b;
+#X obj 343 425 symbol;
+#X msg 381 305 symbol space;
+#X msg 143 369 symbol comma;
+#X obj 8 424 route end comma space break;
+#X obj 343 444 list trim;
+#X obj 17 106 s \$0-e;
+#X obj 8 405 r \$0-e;
+#X obj 320 148 s \$0-e;
+#X obj 337 484 s \$0-e;
+#X obj 126 106 s \$0-e;
+#X obj 297 265 s \$0-e;
+#X obj 320 40 route ip IP;
+#X obj 8 272 s \$0-e;
+#X msg 8 253 end;
+#X connect 0 0 34 0;
+#X connect 2 0 1 0;
+#X connect 4 0 6 0;
+#X connect 5 0 4 0;
+#X connect 6 0 1 0;
+#X connect 7 0 1 0;
+#X connect 8 0 45 0;
+#X connect 9 0 13 0;
+#X connect 9 1 36 0;
+#X connect 9 2 8 0;
+#X connect 10 0 16 0;
+#X connect 11 0 10 0;
+#X connect 11 1 12 0;
+#X connect 12 0 14 1;
+#X connect 13 0 45 0;
+#X connect 14 0 38 0;
+#X connect 15 0 14 1;
+#X connect 16 0 15 0;
+#X connect 16 1 17 0;
+#X connect 16 2 14 0;
+#X connect 17 0 46 0;
+#X connect 18 0 35 0;
+#X connect 18 1 19 1;
+#X connect 19 0 36 0;
+#X connect 20 0 21 0;
+#X connect 21 0 23 0;
+#X connect 23 0 48 0;
+#X connect 24 0 1 0;
+#X connect 25 0 27 0;
+#X connect 26 0 43 0;
+#X connect 27 0 29 0;
+#X connect 27 1 37 0;
+#X connect 27 2 26 0;
+#X connect 28 0 1 0;
+#X connect 29 0 43 0;
+#X connect 30 0 33 0;
+#X connect 30 1 32 0;
+#X connect 30 2 31 0;
+#X connect 31 0 47 0;
+#X connect 32 0 47 0;
+#X connect 33 0 47 0;
+#X connect 34 0 18 0;
+#X connect 34 1 25 0;
+#X connect 34 2 30 0;
+#X connect 34 3 49 0;
+#X connect 35 0 51 0;
+#X connect 35 1 19 0;
+#X connect 35 2 20 0;
+#X connect 36 0 11 0;
+#X connect 36 1 40 0;
+#X connect 37 0 11 0;
+#X connect 37 1 39 0;
+#X connect 38 0 42 0;
+#X connect 39 0 38 1;
+#X connect 40 0 38 1;
+#X connect 41 0 2 0;
+#X connect 41 1 7 0;
+#X connect 41 2 24 0;
+#X connect 41 3 28 0;
+#X connect 41 4 5 0;
+#X connect 42 0 17 0;
+#X connect 44 0 41 0;
+#X connect 49 0 9 0;
+#X connect 49 1 9 0;
+#X connect 49 2 18 0;
+#X connect 51 0 50 0;
diff --git a/externals/gridflow/abstractions/plotter_parser.pd b/externals/gridflow/abstractions/plotter_parser.pd
new file mode 100644
index 00000000..80547693
--- /dev/null
+++ b/externals/gridflow/abstractions/plotter_parser.pd
@@ -0,0 +1,78 @@
+#N canvas 738 220 450 377 10;
+#X obj 156 11 inlet;
+#X obj 320 117 - 32;
+#X obj 290 184 #to_symbol;
+#X obj 156 30 #to_float;
+#X obj 156 49 shunt;
+#X obj 186 68 sel 3;
+#X msg 205 49 0;
+#X obj 112 140 sel 10 44 59;
+#X obj 230 88 range 65 91 97 123;
+#X obj 149 268 t l l;
+#X obj 149 249 list prepend;
+#X obj 126 287 list;
+#X obj 127 220 t b b;
+#X obj 290 165 #import (2);
+#X obj 126 306 list prepend;
+#X obj 126 325 list trim;
+#X obj 126 344 outlet hpgl;
+#X obj 200 140 outlet other;
+#X text 103 49 strings;
+#X text 110 88 floats;
+#X text 31 140 punctuation;
+#X text 360 89 letters;
+#X msg 201 201 1;
+#X msg 248 165 reset;
+#X obj 290 205 sel LB;
+#X msg 235 49 1;
+#X obj 302 33 list prepend;
+#X obj 390 33 t a;
+#X obj 279 66 list;
+#X obj 127 201 gf.oneshot;
+#X obj 156 88 ascii_to_f;
+#X msg 290 224 print_from_ascii;
+#X connect 0 0 3 0;
+#X connect 1 0 13 0;
+#X connect 2 0 22 0;
+#X connect 2 0 24 0;
+#X connect 3 0 4 0;
+#X connect 4 0 30 0;
+#X connect 4 1 5 0;
+#X connect 5 0 6 0;
+#X connect 5 0 28 0;
+#X connect 5 0 26 1;
+#X connect 5 1 26 0;
+#X connect 6 0 4 1;
+#X connect 7 0 29 0;
+#X connect 7 2 29 0;
+#X connect 7 3 17 0;
+#X connect 8 0 7 0;
+#X connect 8 1 13 0;
+#X connect 8 2 7 0;
+#X connect 8 3 1 0;
+#X connect 8 4 7 0;
+#X connect 9 0 11 1;
+#X connect 9 1 10 1;
+#X connect 10 0 9 0;
+#X connect 11 0 14 0;
+#X connect 12 0 11 1;
+#X connect 12 0 10 1;
+#X connect 12 1 11 0;
+#X connect 12 1 23 0;
+#X connect 13 0 2 0;
+#X connect 14 0 15 0;
+#X connect 15 0 16 0;
+#X connect 22 0 29 1;
+#X connect 23 0 13 0;
+#X connect 24 0 25 0;
+#X connect 24 0 31 0;
+#X connect 24 1 14 1;
+#X connect 25 0 4 1;
+#X connect 26 0 27 0;
+#X connect 26 0 28 1;
+#X connect 27 0 26 1;
+#X connect 28 0 10 0;
+#X connect 29 0 12 0;
+#X connect 30 0 10 0;
+#X connect 30 1 8 0;
+#X connect 31 0 14 1;
diff --git a/externals/gridflow/abstractions/seq_fold.pd b/externals/gridflow/abstractions/seq_fold.pd
new file mode 100644
index 00000000..5be24887
--- /dev/null
+++ b/externals/gridflow/abstractions/seq_fold.pd
@@ -0,0 +1,31 @@
+#N canvas 512 144 450 473 10;
+#X obj 26 40 inlet end;
+#X obj 94 40 inlet elements;
+#X obj 180 199 f;
+#X obj 26 294 outlet final;
+#X obj 115 294 outlet op_left;
+#X obj 217 294 outlet op_right;
+#X obj 94 199 t b f;
+#X obj 112 75 t b b b;
+#X obj 180 218 shunt;
+#X msg 270 170 1;
+#X msg 241 170 0;
+#X obj 270 40 inlet op_result;
+#X obj 196 40 inlet seed;
+#X obj 196 180 f;
+#X connect 0 0 7 0;
+#X connect 1 0 6 0;
+#X connect 2 0 8 0;
+#X connect 6 0 2 0;
+#X connect 6 1 5 0;
+#X connect 7 0 10 0;
+#X connect 7 0 13 0;
+#X connect 7 1 2 0;
+#X connect 7 2 9 0;
+#X connect 8 0 4 0;
+#X connect 8 1 3 0;
+#X connect 9 0 8 1;
+#X connect 10 0 8 1;
+#X connect 11 0 2 1;
+#X connect 12 0 13 0;
+#X connect 13 0 2 1;
diff --git a/externals/gridflow/abstractions/var.#.pd b/externals/gridflow/abstractions/var.#.pd
new file mode 100644
index 00000000..85402ebf
--- /dev/null
+++ b/externals/gridflow/abstractions/var.#.pd
@@ -0,0 +1,16 @@
+#N canvas 373 266 450 300 10;
+#X obj 15 120 #store;
+#X obj 15 21 inlet;
+#X obj 214 22 inlet;
+#X obj 15 139 outlet;
+#X obj 15 46 route bang;
+#X obj 89 46 t a a;
+#X obj 89 65 #finished;
+#X connect 0 0 3 0;
+#X connect 1 0 4 0;
+#X connect 2 0 0 1;
+#X connect 4 0 0 0;
+#X connect 4 1 5 0;
+#X connect 5 0 6 0;
+#X connect 5 1 0 1;
+#X connect 6 0 0 0;
diff --git a/externals/gridflow/bin/backtrace b/externals/gridflow/bin/backtrace
new file mode 100755
index 00000000..ac1358af
--- /dev/null
+++ b/externals/gridflow/bin/backtrace
@@ -0,0 +1,18 @@
+#!/usr/bin/env ruby
+if ARGV.length != 1
+ puts "usage: core.rb <corefile>"
+ exit 1
+end
+qfile=ARGV[0].gsub /'/, "\\\\'"
+x=`gdb --batch -c '#{qfile}'`.split"\n"
+m=/`([^']+)/.match x[0]
+f=File.open("/tmp/backtrace_#{$$}.gdb","w")
+f.puts"bt"
+f.puts"quit"
+f.close
+cmd="gdb #{m[1]} #{qfile} --command=/tmp/backtrace_#{$$}.gdb"
+x=`#{cmd}`.split("\n")
+i=nil
+x.each_with_index {|line,i| break if /^#0/ =~ line }
+x[0..i]=[]
+puts x
diff --git a/externals/gridflow/bin/check-help-version b/externals/gridflow/bin/check-help-version
new file mode 100755
index 00000000..cb067154
--- /dev/null
+++ b/externals/gridflow/bin/check-help-version
@@ -0,0 +1,49 @@
+#!/usr/bin/tclsh
+
+set argh0 [file normalize [file join [pwd] $argv0]]
+source [file dirname $argh0]/pd-tools.tcl
+
+set report {}
+
+proc find_version_strings {lines i} {
+ global filename report
+ lappend toplefts [list patate poil] ;# temporary dummy value so that subpatches are represented in the correct order
+ set j $i
+ set versions {}
+ while {$i < [llength $lines]} {
+ set list [split [lindex $lines $i] " "]
+ switch -- [lindex $list 1] {
+ text {
+ set comment [join [lrange $list 4 end] " "]
+ if {[regexp {^GridFlow (\d\.\d\.\d)} $comment v0 v1]} {
+ lappend versions $v1
+ }
+ }
+ connect {incr i; continue}
+ restore {break}
+ }
+ # recurse into subpatches (disabled because not necessary; can treat the file as one flat patch anyway)
+ ### if {[string compare [lindex $list 0] "#N"]==0} {set i [find_version_strings $lines [expr $i+1]]}
+ incr i
+ }
+ lappend report [list $filename [lsort $versions]]
+ return $i
+}
+
+foreach filename $argv {
+ set lines [pd_read_file $filename]
+ find_version_strings $lines 1
+}
+
+set env(PRINT_CLASS_LIST) yes
+set f [open "| pd -nogui -send {pd quit} 2&>1" r+]
+while {![eof $f]} {
+ if {[regexp {^class_new (.*)} [gets $f] m0 m1]} {
+ puts $m1
+ }
+}
+
+foreach line [lsort -decreasing -index 1 $report] {
+ foreach {filename versions} $line {}
+ puts [format "%40s: %s" $filename $versions]
+}
diff --git a/externals/gridflow/bin/hpgl_move b/externals/gridflow/bin/hpgl_move
new file mode 100755
index 00000000..f4bf0534
--- /dev/null
+++ b/externals/gridflow/bin/hpgl_move
@@ -0,0 +1,19 @@
+#!/usr/bin/env ruby
+# Copyright (c) 2009 by Mathieu Bouchard
+
+x = Float ARGV[0]
+y = Float ARGV[1]
+
+puts STDIN.read.split(/\s*;\s*/).map {|m|
+ h = m.slice!(0,2)
+ d = m.split(",")
+ case h
+ when "PA","PD","PU"
+ (0...d.length).each {|i|
+ off = if i%2==0 then x else y end
+ v = Float(d[i])+off
+ d[i] = if v==v.to_i then v.to_i else v.to_f end
+ }
+ end
+ h+d.join(",")
+}.join(";")
diff --git a/externals/gridflow/bin/make-compose-makefile b/externals/gridflow/bin/make-compose-makefile
new file mode 100755
index 00000000..f7e5abca
--- /dev/null
+++ b/externals/gridflow/bin/make-compose-makefile
@@ -0,0 +1,30 @@
+#!/usr/bin/env ruby
+
+f = File.read("../compose-8859-1.pdd").split(/\s*;\s*/)
+g = File.open("Makefile","w")
+g.puts "default:: all"
+g.puts ""
+list = []
+
+[94,96,126,168,176,180,184].each {|a|
+ g.puts "#{a}u.hpgl: #{a}.hpgl Makefile"
+ dy = (if a==184 then 0 else 100 end)
+ g.puts "\t../../bin/hpgl_move 0 #{dy} < #{a}.hpgl > #{a}u.hpgl"
+ list << "#{a}u.hpgl"
+}
+
+f.each {|char|
+ a,b,c = char.split(/\s+/).map {|x| Integer x }
+ [0,32].each {|o|
+ d = c.to_s + (if o==0 and c>47 then "u" else "" end)
+ g.puts "#{a+o}.hpgl: #{b+o}.hpgl #{d}.hpgl Makefile"
+ g.puts "\tcat #{b+o}.hpgl #{d}.hpgl > #{a+o}.hpgl"
+ g.puts ""
+ list << "#{a+o}.hpgl"
+ }
+}
+
+g.puts "all:: "+list.join(" ")
+g.puts ""
+g.puts "clean::"
+g.puts "\trm "+list.join(" ")
diff --git a/externals/gridflow/bin/pd-tools.tcl b/externals/gridflow/bin/pd-tools.tcl
new file mode 100644
index 00000000..2951b260
--- /dev/null
+++ b/externals/gridflow/bin/pd-tools.tcl
@@ -0,0 +1,37 @@
+# (this proc is taken from desiredata)
+# split at message boundaries.
+# \n is wiped, then that character is reused temporarily to mean a quoted semicolon.
+proc pd_mess_split {e} {
+ set r {}
+ regsub -all "\n" $e " " y
+ regsub -all {\\;} $y "\n" z
+ foreach mess [split $z ";"] {
+ regsub -all "\n" $mess "\\;" mess
+ set mess [string trimleft $mess]
+ if {$mess != ""} {lappend r $mess}
+ }
+ return $r
+}
+
+proc pd_read_file {filename} {
+ set f [open $filename]
+ set r [pd_mess_split [read $f]]
+ close $f
+ return $r
+}
+
+proc pd_pickle {l} {
+ set i 0
+ set t ""
+ set n [llength $l]
+ foreach e $l {
+ incr n -1
+ #regsub -all "," $e "\\," e
+ append t $e
+ incr i [string length $e]
+ if {$i>65} {set i 0; append t "\n"} elseif {$n>0} {incr i; append t " "}
+ }
+ append t ";"
+ return $t
+}
+
diff --git a/externals/gridflow/bin/pdnonegative b/externals/gridflow/bin/pdnonegative
new file mode 100755
index 00000000..d707f568
--- /dev/null
+++ b/externals/gridflow/bin/pdnonegative
@@ -0,0 +1,66 @@
+#!/usr/bin/tclsh
+
+set argh0 [file normalize [file join [pwd] $argv0]]
+source [file dirname $argh0]/pd-tools.tcl
+
+set toplefts {}
+
+# for the recursion to work properly, restore should be checked before #N, and the check
+# for #N shouldn't do "continue", as well as other tricky index stuff.
+proc find_top_left {lines i} {
+ global filename toplefts
+ set toplefts_i [llength $toplefts]
+ lappend toplefts [list patate poil] ;# temporary dummy value so that subpatches are represented in the correct order
+ set j $i
+ set xmin +9999; set ymin +9999
+ set xmax -9999; set ymax -9999
+ while {$i < [llength $lines]} {
+ set list [split [lindex $lines $i] " "]
+ if {[string compare [lindex $list 1] "connect"]==0} {incr i; continue}
+ if {[string compare [lindex $list 1] "restore"]==0} {break}
+ if {[string compare [lindex $list 0] "#N"]==0} {set i [find_top_left $lines [expr $i+1]]}
+ set x [lindex $list 2]; if {$xmin > $x} {set xmin $x}; if {$xmax < $x} {set xmax $x}
+ set y [lindex $list 3]; if {$ymin > $y} {set ymin $y}; if {$ymax < $y} {set ymax $y}
+ incr i
+ }
+ puts [format "filename=%-32s patch at lines %4d thru %4d has xmin=%d ymin=%d xmax=%d ymax=%d" $filename $j $i $xmin $ymin $xmax $ymax]
+ lset toplefts $toplefts_i [list $xmin $ymin]
+ return $i
+}
+
+# somewhat copy-pasted from the above, sorry.
+proc move_objects {lines i} {
+ global toplefts fout
+ set xymin [lindex $toplefts 0]
+ set xmin [lindex $xymin 0]; if {$xmin > 0} {set xmin 0}
+ set ymin [lindex $xymin 1]; if {$ymin > 0} {set ymin 0}
+ set toplefts [lrange $toplefts 1 end]
+ while {$i < [llength $lines]} {
+ set list [split [lindex $lines $i] " "]
+ if {[string compare [lindex $list 1] "connect"]==0} {puts $fout [pd_pickle $list]; incr i; continue}
+ if {[string compare [lindex $list 1] "restore"]==0} {break}
+ if {[string compare [lindex $list 0] "#N"]==0} {
+ puts $fout [pd_pickle $list]
+ set i [move_objects $lines [expr $i+1]]
+ set list [split [lindex $lines $i] " "]
+ }
+ set x [expr [lindex $list 2]-$xmin]
+ set y [expr [lindex $list 3]-$ymin]
+ set list [lreplace $list 2 3 $x $y]
+ puts $fout [pd_pickle $list]
+ incr i
+ }
+ return $i
+}
+
+foreach filename $argv {
+ set lines [pd_read_file $filename]
+ find_top_left $lines 1
+ #continue
+ set fout [open $filename.new w]
+ puts $fout [pd_pickle [lindex $lines 0]]
+ move_objects $lines 1
+ close $fout
+ exec mv $filename $filename.old
+ exec mv $filename.new $filename
+}
diff --git a/externals/gridflow/bin/plusminus b/externals/gridflow/bin/plusminus
new file mode 100755
index 00000000..36f268f5
--- /dev/null
+++ b/externals/gridflow/bin/plusminus
@@ -0,0 +1,39 @@
+#!/usr/bin/env ruby
+# NOTE: this works with svn diff -u only!!!
+
+puts "-"*72
+
+$plustot=0
+$minustot=0
+
+def show
+ printf "%40s %+5d %+5d (net %+5d)\n", $file, $plus, -$minus, $plus-$minus
+end
+
+loop{
+ line = gets
+ break if not line
+ if /^\+\+\+/.match line then
+ x = line.split(/\s+/)
+ $plustot+=$plus if $plus
+ $minustot+=$minus if $minus
+ show if $file
+ $file = x[1]
+ $on=false
+ $plus=0
+ $minus=0
+ elsif /^\@\@/ =~ line then $on=true
+ elsif $on and /^\+/ =~ line and /^\-\-\-/ != line then $plus+=1
+ elsif $on and /^\-/ =~ line and /^\+\+\+/ != line then $minus+=1
+ end
+}
+
+$plustot+=$plus if $plus
+$minustot+=$minus if $minus
+show if $file
+
+$file="total"
+$plus=$plustot
+$minus=$minustot
+puts "-"*72
+show
diff --git a/externals/gridflow/bin/svn-mv b/externals/gridflow/bin/svn-mv
new file mode 100755
index 00000000..0ddadd5f
--- /dev/null
+++ b/externals/gridflow/bin/svn-mv
@@ -0,0 +1,5 @@
+#!/bin/bash
+mv "$1" "$2"
+svn remove "$1"
+svn add "$2"
+svn commit "$1" "$2"
diff --git a/externals/gridflow/bin/valg b/externals/gridflow/bin/valg
new file mode 100755
index 00000000..de0f040a
--- /dev/null
+++ b/externals/gridflow/bin/valg
@@ -0,0 +1,5 @@
+GFSOURCE=$HOME/src/gridflow
+SUPPFILE=$GFSOURCE/tests/suppressions.valg3
+
+valgrind --suppressions=$SUPPFILE --gen-suppressions=yes "$@"
+
diff --git a/externals/gridflow/bundled/g_canvas.h b/externals/gridflow/bundled/g_canvas.h
new file mode 100644
index 00000000..99658f2e
--- /dev/null
+++ b/externals/gridflow/bundled/g_canvas.h
@@ -0,0 +1,646 @@
+
+/* Copyright (c) 1997-1999 Miller Puckette.
+* For information on usage and redistribution, and for a DISCLAIMER OF ALL
+* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
+
+/* this file defines the structure for "glists" and related structures and
+functions. "Glists" and "canvases" and "graphs" used to be different
+structures until being unified in version 0.35.
+
+A glist occupies its own window if the "gl_havewindow" flag is set. Its
+appearance on its "parent" or "owner" (if it has one) is as a graph if
+"gl_isgraph" is set, and otherwise as a text box.
+
+A glist is "root" if it has no owner, i.e., a document window. In this
+case "gl_havewindow" is always set.
+
+We maintain a list of root windows, so that we can traverse the whole
+collection of everything in a Pd process.
+
+If a glist has a window it may still not be "mapped." Miniaturized
+windows aren't mapped, for example, but a window is also not mapped
+immediately upon creation. In either case gl_havewindow is true but
+gl_mapped is false.
+
+Closing a non-root window makes it invisible; closing a root destroys it.
+
+A glist that's just a text object on its parent is always "toplevel." An
+embedded glist can switch back and forth to appear as a toplevel by double-
+clicking on it. Single-clicking a text box makes the toplevel become visible
+and raises the window it's in.
+
+If a glist shows up as a graph on its parent, the graph is blanked while the
+glist has its own window, even if miniaturized.
+
+*/
+
+/* NOTE: this file describes Pd implementation details which may change
+in future releases. The public (stable) API is in m_pd.h. */
+
+#ifndef __G_CANVAS_H
+#define __G_CANVAS_H
+#ifndef DESIRE
+
+#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* --------------------- geometry ---------------------------- */
+#define IOWIDTH 7 /* width of an inlet/outlet in pixels */
+#define IOMIDDLE ((IOWIDTH-1)/2)
+#define GLIST_DEFGRAPHWIDTH 200
+#define GLIST_DEFGRAPHHEIGHT 140
+/* ----------------------- data ------------------------------- */
+
+typedef struct _updateheader
+{
+ struct _updateheader *upd_next;
+ unsigned int upd_array:1; /* true if array, false if glist */
+ unsigned int upd_queued:1; /* true if we're queued */
+} t_updateheader;
+
+ /* types to support glists grabbing mouse motion or keys from parent */
+typedef void (*t_glistmotionfn)(void *z, t_floatarg dx, t_floatarg dy);
+typedef void (*t_glistkeyfn)(void *z, t_floatarg key);
+#endif /*DESIRE*/
+
+
+EXTERN_STRUCT _rtext;
+#define t_rtext struct _rtext
+
+#ifndef DESIRE
+
+EXTERN_STRUCT _gtemplate;
+#define t_gtemplate struct _gtemplate
+
+EXTERN_STRUCT _guiconnect;
+#define t_guiconnect struct _guiconnect
+
+EXTERN_STRUCT _tscalar;
+#define t_tscalar struct _tscalar
+
+EXTERN_STRUCT _canvasenvironment;
+#define t_canvasenvironment struct _canvasenvironment
+
+EXTERN_STRUCT _fielddesc;
+#define t_fielddesc struct _fielddesc
+
+typedef struct _selection
+{
+ t_gobj *sel_what;
+ struct _selection *sel_next;
+} t_selection;
+
+ /* this structure is instantiated whenever a glist becomes visible. */
+typedef struct _editor
+{
+ t_updateheader e_upd; /* update header structure */
+ t_selection *e_updlist; /* list of objects to update */
+ t_rtext *e_rtext; /* text responder linked list */
+ t_selection *e_selection; /* head of the selection list */
+ t_rtext *e_textedfor; /* the rtext if any that we are editing */
+ t_gobj *e_grab; /* object being "dragged" */
+ t_glistmotionfn e_motionfn; /* ... motion callback */
+ t_glistkeyfn e_keyfn; /* ... keypress callback */
+ t_binbuf *e_connectbuf; /* connections to deleted objects */
+ t_binbuf *e_deleted; /* last stuff we deleted */
+ t_guiconnect *e_guiconnect; /* GUI connection for filtering messages */
+ struct _glist *e_glist; /* glist which owns this */
+ int e_xwas; /* xpos on last mousedown or motion event */
+ int e_ywas; /* ypos, similarly */
+ int e_selectline_index1; /* indices for the selected line if any */
+ int e_selectline_outno; /* (only valid if e_selectedline is set) */
+ int e_selectline_index2;
+ int e_selectline_inno;
+ t_outconnect *e_selectline_tag;
+ unsigned int e_onmotion: 3; /* action to take on motion */
+ unsigned int e_lastmoved: 1; /* one if mouse has moved since click */
+ unsigned int e_textdirty: 1; /* one if e_textedfor has changed */
+ unsigned int e_selectedline: 1; /* one if a line is selected */
+} t_editor;
+
+#define MA_NONE 0 /* e_onmotion: do nothing on mouse motion */
+#define MA_MOVE 1 /* drag the selection around */
+#define MA_CONNECT 2 /* make a connection */
+#define MA_REGION 3 /* selection region */
+#define MA_PASSOUT 4 /* send on to e_grab */
+#define MA_DRAGTEXT 5 /* drag in text editor to alter selection */
+
+/* editor structure for "garrays". We don't bother to delete and regenerate
+this structure when the "garray" becomes invisible or visible, although we
+could do so if the structure gets big (like the "editor" above.) */
+
+typedef struct _arrayvis
+{
+ t_updateheader av_upd; /* update header structure */
+ t_garray *av_garray; /* owning structure */
+} t_arrayvis;
+
+/* the t_tick structure describes where to draw x and y "ticks" for a glist */
+
+typedef struct _tick /* where to put ticks on x or y axes */
+{
+ float k_point; /* one point to draw a big tick at */
+ float k_inc; /* x or y increment per little tick */
+ int k_lperb; /* little ticks per big; 0 if no ticks to draw */
+} t_tick;
+
+/* the t_glist structure, which describes a list of elements that live on an
+area of a window.
+
+*/
+
+struct _glist
+{
+ t_object gl_obj; /* header in case we're a glist */
+ t_gobj *gl_list; /* the actual data */
+ struct _gstub *gl_stub; /* safe pointer handler */
+ int gl_valid; /* incremented when pointers might be stale */
+ struct _glist *gl_owner; /* parent glist, supercanvas, or 0 if none */
+ int gl_pixwidth; /* width in pixels (on parent, if a graph) */
+ int gl_pixheight;
+ float gl_x1; /* bounding rectangle in our own coordinates */
+ float gl_y1;
+ float gl_x2;
+ float gl_y2;
+ int gl_screenx1; /* screen coordinates when toplevel */
+ int gl_screeny1;
+ int gl_screenx2;
+ int gl_screeny2;
+ int gl_xmargin; /* origin for GOP rectangle */
+ int gl_ymargin;
+ t_tick gl_xtick; /* ticks marking X values */
+ int gl_nxlabels; /* number of X coordinate labels */
+ t_symbol **gl_xlabel; /* ... an array to hold them */
+ float gl_xlabely; /* ... and their Y coordinates */
+ t_tick gl_ytick; /* same as above for Y ticks and labels */
+ int gl_nylabels;
+ t_symbol **gl_ylabel;
+ float gl_ylabelx;
+ t_editor *gl_editor; /* editor structure when visible */
+ t_symbol *gl_name; /* symbol bound here */
+ int gl_font; /* nominal font size in points, e.g., 10 */
+ struct _glist *gl_next; /* link in list of toplevels */
+ t_canvasenvironment *gl_env; /* root canvases and abstractions only */
+ unsigned int gl_havewindow:1; /* true if we own a window */
+ unsigned int gl_mapped:1; /* true if, moreover, it's "mapped" */
+ unsigned int gl_dirty:1; /* (root canvas only:) patch has changed */
+ unsigned int gl_loading:1; /* am now loading from file */
+ unsigned int gl_willvis:1; /* make me visible after loading */
+ unsigned int gl_edit:1; /* edit mode */
+ unsigned int gl_isdeleting:1; /* we're inside glist_delete -- hack! */
+ unsigned int gl_goprect:1; /* draw rectangle for graph-on-parent */
+ unsigned int gl_isgraph:1; /* show as graph on parent */
+};
+
+#define gl_gobj gl_obj.te_g
+#define gl_pd gl_gobj.g_pd
+
+/* a data structure to describe a field in a pure datum */
+
+#define DT_FLOAT 0
+#define DT_SYMBOL 1
+#define DT_LIST 2
+#define DT_ARRAY 3
+
+typedef struct _dataslot
+{
+ int ds_type;
+ t_symbol *ds_name;
+ t_symbol *ds_arraytemplate; /* filled in for arrays only */
+} t_dataslot;
+
+typedef struct _template
+{
+ t_pd t_pdobj; /* header */
+ struct _gtemplate *t_list; /* list of "struct"/gtemplate objects */
+ t_symbol *t_sym; /* name */
+ int t_n; /* number of dataslots (fields) */
+ t_dataslot *t_vec; /* array of dataslots */
+} t_template;
+
+struct _array
+{
+ int a_n; /* number of elements */
+ int a_elemsize; /* size in bytes; LATER get this from template */
+ char *a_vec; /* array of elements */
+ t_symbol *a_templatesym; /* template for elements */
+ int a_valid; /* protection against stale pointers into array */
+ t_gpointer a_gp; /* pointer to scalar or array element we're in */
+ t_gstub *a_stub; /* stub for pointing into this array */
+};
+
+struct _garray
+{
+ t_gobj x_gobj;
+ t_scalar *x_scalar; /* scalar "containing" the array */
+ t_glist *x_glist; /* containing glist */
+ t_symbol *x_name; /* unexpanded name (possibly with leading '$') */
+ t_symbol *x_realname; /* expanded name (symbol we're bound to) */
+ char x_usedindsp; /* true if some DSP routine is using this */
+ char x_saveit; /* true if we should save this with parent */
+ char x_listviewing; /* true if list view window is open */
+ double x_lastupdate; /* T.Grill - clock_getlogicaltime() of last array update */
+};
+
+ /* structure for traversing all the connections in a glist */
+typedef struct _linetraverser
+{
+ t_canvas *tr_x;
+ t_object *tr_ob;
+ int tr_nout;
+ int tr_outno;
+ t_object *tr_ob2;
+ t_outlet *tr_outlet;
+ t_inlet *tr_inlet;
+ int tr_nin;
+ int tr_inno;
+ int tr_x11, tr_y11, tr_x12, tr_y12;
+ int tr_x21, tr_y21, tr_x22, tr_y22;
+ int tr_lx1, tr_ly1, tr_lx2, tr_ly2;
+ t_outconnect *tr_nextoc;
+ int tr_nextoutno;
+} t_linetraverser;
+
+/* function types used to define graphical behavior for gobjs, a bit like X
+widgets. We don't use Pd methods because Pd's typechecking can't specify the
+types of pointer arguments. Also it's more convenient this way, since
+every "patchable" object can just get the "text" behaviors. */
+
+ /* Call this to get a gobj's bounding rectangle in pixels */
+typedef void (*t_getrectfn)(t_gobj *x, struct _glist *glist,
+ int *x1, int *y1, int *x2, int *y2);
+ /* and this to displace a gobj: */
+typedef void (*t_displacefn)(t_gobj *x, struct _glist *glist, int dx, int dy);
+ /* change color to show selection: */
+typedef void (*t_selectfn)(t_gobj *x, struct _glist *glist, int state);
+ /* change appearance to show activation/deactivation: */
+typedef void (*t_activatefn)(t_gobj *x, struct _glist *glist, int state);
+ /* warn a gobj it's about to be deleted */
+typedef void (*t_deletefn)(t_gobj *x, struct _glist *glist);
+ /* making visible or invisible */
+typedef void (*t_visfn)(t_gobj *x, struct _glist *glist, int flag);
+ /* field a mouse click (when not in "edit" mode) */
+typedef int (*t_clickfn)(t_gobj *x, struct _glist *glist,
+ int xpix, int ypix, int shift, int alt, int dbl, int doit);
+ /* ... and later, resizing; getting/setting font or color... */
+
+struct _widgetbehavior
+{
+ t_getrectfn w_getrectfn;
+ t_displacefn w_displacefn;
+ t_selectfn w_selectfn;
+ t_activatefn w_activatefn;
+ t_deletefn w_deletefn;
+ t_visfn w_visfn;
+ t_clickfn w_clickfn;
+};
+
+/* -------- behaviors for scalars defined by objects in template --------- */
+/* these are set by "drawing commands" in g_template.c which add appearance to
+scalars, which live in some other window. If the scalar is just included
+in a canvas the "parent" is a misnomer. There is also a text scalar object
+which really does draw the scalar on the parent window; see g_scalar.c. */
+
+/* note how the click function wants the whole scalar, not the "data", so
+doesn't work on array elements... LATER reconsider this */
+
+ /* bounding rectangle: */
+typedef void (*t_parentgetrectfn)(t_gobj *x, struct _glist *glist,
+ t_word *data, t_template *tmpl, float basex, float basey,
+ int *x1, int *y1, int *x2, int *y2);
+ /* displace it */
+typedef void (*t_parentdisplacefn)(t_gobj *x, struct _glist *glist,
+ t_word *data, t_template *tmpl, float basex, float basey,
+ int dx, int dy);
+ /* change color to show selection */
+typedef void (*t_parentselectfn)(t_gobj *x, struct _glist *glist,
+ t_word *data, t_template *tmpl, float basex, float basey,
+ int state);
+ /* change appearance to show activation/deactivation: */
+typedef void (*t_parentactivatefn)(t_gobj *x, struct _glist *glist,
+ t_word *data, t_template *tmpl, float basex, float basey,
+ int state);
+ /* making visible or invisible */
+typedef void (*t_parentvisfn)(t_gobj *x, struct _glist *glist,
+ t_word *data, t_template *tmpl, float basex, float basey,
+ int flag);
+ /* field a mouse click */
+typedef int (*t_parentclickfn)(t_gobj *x, struct _glist *glist,
+ t_word *data, t_template *tmpl, t_scalar *sc, t_array *ap,
+ float basex, float basey,
+ int xpix, int ypix, int shift, int alt, int dbl, int doit);
+
+struct _parentwidgetbehavior
+{
+ t_parentgetrectfn w_parentgetrectfn;
+ t_parentdisplacefn w_parentdisplacefn;
+ t_parentselectfn w_parentselectfn;
+ t_parentactivatefn w_parentactivatefn;
+ t_parentvisfn w_parentvisfn;
+ t_parentclickfn w_parentclickfn;
+};
+
+ /* cursor definitions; used as return value for t_parentclickfn */
+#define CURSOR_RUNMODE_NOTHING 0
+#define CURSOR_RUNMODE_CLICKME 1
+#define CURSOR_RUNMODE_THICKEN 2
+#define CURSOR_RUNMODE_ADDPOINT 3
+#define CURSOR_EDITMODE_NOTHING 4
+#define CURSOR_EDITMODE_CONNECT 5
+#define CURSOR_EDITMODE_DISCONNECT 6
+EXTERN void canvas_setcursor(t_glist *x, unsigned int cursornum);
+
+extern t_canvas *canvas_editing; /* last canvas to start text edting */
+extern t_canvas *canvas_whichfind; /* last canvas we did a find in */
+extern t_canvas *canvas_list; /* list of all root canvases */
+extern t_class *vinlet_class, *voutlet_class;
+extern int glist_valid; /* incremented when pointers might be stale */
+
+#define PLOTSTYLE_POINTS 0 /* plotting styles for arrays */
+#define PLOTSTYLE_POLY 1
+#define PLOTSTYLE_BEZ 2
+
+/* ------------------- functions on any gobj ----------------------------- */
+EXTERN void gobj_getrect(t_gobj *x, t_glist *owner, int *x1, int *y1,
+ int *x2, int *y2);
+EXTERN void gobj_displace(t_gobj *x, t_glist *owner, int dx, int dy);
+EXTERN void gobj_select(t_gobj *x, t_glist *owner, int state);
+EXTERN void gobj_activate(t_gobj *x, t_glist *owner, int state);
+EXTERN void gobj_delete(t_gobj *x, t_glist *owner);
+EXTERN void gobj_vis(t_gobj *x, t_glist *glist, int flag);
+EXTERN int gobj_click(t_gobj *x, struct _glist *glist,
+ int xpix, int ypix, int shift, int alt, int dbl, int doit);
+EXTERN void gobj_save(t_gobj *x, t_binbuf *b);
+EXTERN void gobj_properties(t_gobj *x, struct _glist *glist);
+EXTERN void gobj_save(t_gobj *x, t_binbuf *b);
+EXTERN int gobj_shouldvis(t_gobj *x, struct _glist *glist);
+
+/* -------------------- functions on glists --------------------- */
+EXTERN t_glist *glist_new( void);
+EXTERN void glist_init(t_glist *x);
+EXTERN void glist_add(t_glist *x, t_gobj *g);
+EXTERN void glist_cleanup(t_glist *x);
+EXTERN void glist_free(t_glist *x);
+
+EXTERN void glist_clear(t_glist *x);
+EXTERN t_canvas *glist_getcanvas(t_glist *x);
+EXTERN int glist_isselected(t_glist *x, t_gobj *y);
+EXTERN void glist_select(t_glist *x, t_gobj *y);
+EXTERN void glist_deselect(t_glist *x, t_gobj *y);
+EXTERN void glist_noselect(t_glist *x);
+EXTERN void glist_selectall(t_glist *x);
+EXTERN void glist_delete(t_glist *x, t_gobj *y);
+EXTERN void glist_retext(t_glist *x, t_text *y);
+EXTERN void glist_grab(t_glist *x, t_gobj *y, t_glistmotionfn motionfn,
+ t_glistkeyfn keyfn, int xpos, int ypos);
+EXTERN int glist_isvisible(t_glist *x);
+EXTERN int glist_istoplevel(t_glist *x);
+EXTERN t_glist *glist_findgraph(t_glist *x);
+EXTERN int glist_getfont(t_glist *x);
+EXTERN void glist_sort(t_glist *canvas);
+EXTERN void glist_read(t_glist *x, t_symbol *filename, t_symbol *format);
+EXTERN void glist_mergefile(t_glist *x, t_symbol *filename, t_symbol *format);
+
+EXTERN float glist_pixelstox(t_glist *x, float xpix);
+EXTERN float glist_pixelstoy(t_glist *x, float ypix);
+EXTERN float glist_xtopixels(t_glist *x, float xval);
+EXTERN float glist_ytopixels(t_glist *x, float yval);
+EXTERN float glist_dpixtodx(t_glist *x, float dxpix);
+EXTERN float glist_dpixtody(t_glist *x, float dypix);
+
+EXTERN void glist_getnextxy(t_glist *gl, int *xval, int *yval);
+EXTERN void glist_glist(t_glist *g, t_symbol *s, int argc, t_atom *argv);
+EXTERN t_glist *glist_addglist(t_glist *g, t_symbol *sym,
+ float x1, float y1, float x2, float y2,
+ float px1, float py1, float px2, float py2);
+EXTERN void glist_arraydialog(t_glist *parent, t_symbol *name,
+ t_floatarg size, t_floatarg saveit, t_floatarg newgraph);
+EXTERN t_binbuf *glist_writetobinbuf(t_glist *x, int wholething);
+EXTERN int glist_isgraph(t_glist *x);
+EXTERN void glist_redraw(t_glist *x);
+EXTERN void glist_drawiofor(t_glist *glist, t_object *ob, int firsttime,
+ char *tag, int x1, int y1, int x2, int y2);
+EXTERN void glist_eraseiofor(t_glist *glist, t_object *ob, char *tag);
+EXTERN void canvas_create_editor(t_glist *x, int createit);
+void canvas_deletelinesforio(t_canvas *x, t_text *text,
+ t_inlet *inp, t_outlet *outp);
+
+
+/* -------------------- functions on texts ------------------------- */
+EXTERN void text_setto(t_text *x, t_glist *glist, char *buf, int bufsize);
+EXTERN void text_drawborder(t_text *x, t_glist *glist, char *tag,
+ int width, int height, int firsttime);
+EXTERN void text_eraseborder(t_text *x, t_glist *glist, char *tag);
+EXTERN int text_xcoord(t_text *x, t_glist *glist);
+EXTERN int text_ycoord(t_text *x, t_glist *glist);
+EXTERN int text_xpix(t_text *x, t_glist *glist);
+EXTERN int text_ypix(t_text *x, t_glist *glist);
+EXTERN int text_shouldvis(t_text *x, t_glist *glist);
+#endif /*DESIRE */
+
+/* -------------------- functions on rtexts ------------------------- */
+
+#define RTEXT_DOWN 1
+#define RTEXT_DRAG 2
+#define RTEXT_DBL 3
+#define RTEXT_SHIFT 4
+
+EXTERN t_rtext *rtext_new(t_glist *glist, t_text *who);
+EXTERN t_rtext *glist_findrtext(t_glist *gl, t_text *who);
+EXTERN void rtext_draw(t_rtext *x);
+EXTERN void rtext_erase(t_rtext *x);
+EXTERN t_rtext *rtext_remove(t_rtext *first, t_rtext *x);
+EXTERN int rtext_height(t_rtext *x);
+EXTERN void rtext_displace(t_rtext *x, int dx, int dy);
+EXTERN void rtext_select(t_rtext *x, int state);
+EXTERN void rtext_activate(t_rtext *x, int state);
+EXTERN void rtext_free(t_rtext *x);
+EXTERN void rtext_key(t_rtext *x, int n, t_symbol *s);
+EXTERN void rtext_mouse(t_rtext *x, int xval, int yval, int flag);
+EXTERN void rtext_retext(t_rtext *x);
+EXTERN int rtext_width(t_rtext *x);
+EXTERN int rtext_height(t_rtext *x);
+EXTERN char *rtext_gettag(t_rtext *x);
+EXTERN void rtext_gettext(t_rtext *x, char **buf, int *bufsize);
+EXTERN void rtext_getseltext(t_rtext *x, char **buf, int *bufsize);
+
+/* -------------------- functions on canvases ------------------------ */
+#ifndef DESIRE
+EXTERN t_class *canvas_class;
+
+EXTERN t_canvas *canvas_new(void *dummy, t_symbol *sel, int argc, t_atom *argv);
+EXTERN t_symbol *canvas_makebindsym(t_symbol *s);
+EXTERN void canvas_vistext(t_canvas *x, t_text *y);
+EXTERN void canvas_fixlinesfor(t_canvas *x, t_text *text);
+EXTERN void canvas_deletelinesfor(t_canvas *x, t_text *text);
+EXTERN void canvas_stowconnections(t_canvas *x);
+EXTERN void canvas_restoreconnections(t_canvas *x);
+EXTERN void canvas_redraw(t_canvas *x);
+
+EXTERN t_inlet *canvas_addinlet(t_canvas *x, t_pd *who, t_symbol *sym, t_symbol* h);
+EXTERN void canvas_rminlet(t_canvas *x, t_inlet *ip);
+EXTERN t_outlet *canvas_addoutlet(t_canvas *x, t_pd *who, t_symbol *sym);
+EXTERN void canvas_rmoutlet(t_canvas *x, t_outlet *op);
+EXTERN void canvas_redrawallfortemplate(t_template *tmpl, int action);
+EXTERN void canvas_redrawallfortemplatecanvas(t_canvas *x, int action);
+EXTERN void canvas_zapallfortemplate(t_canvas *tmpl);
+EXTERN void canvas_setusedastemplate(t_canvas *x);
+EXTERN t_canvas *canvas_getcurrent(void);
+EXTERN void canvas_setcurrent(t_canvas *x);
+EXTERN void canvas_unsetcurrent(t_canvas *x);
+EXTERN t_symbol *canvas_realizedollar(t_canvas *x, t_symbol *s);
+EXTERN t_canvas *canvas_getrootfor(t_canvas *x);
+EXTERN void canvas_dirty(t_canvas *x, t_int n);
+EXTERN int canvas_getfont(t_canvas *x);
+typedef int (*t_canvasapply)(t_canvas *x, t_int x1, t_int x2, t_int x3);
+
+EXTERN t_int *canvas_recurapply(t_canvas *x, t_canvasapply *fn,
+ t_int x1, t_int x2, t_int x3);
+
+EXTERN void canvas_resortinlets(t_canvas *x);
+EXTERN void canvas_resortoutlets(t_canvas *x);
+EXTERN void canvas_free(t_canvas *x);
+EXTERN void canvas_updatewindowlist( void);
+EXTERN void canvas_editmode(t_canvas *x, t_floatarg yesplease);
+EXTERN int canvas_isabstraction(t_canvas *x);
+EXTERN int canvas_istable(t_canvas *x);
+EXTERN int canvas_showtext(t_canvas *x);
+EXTERN void canvas_vis(t_canvas *x, t_floatarg f);
+EXTERN t_canvasenvironment *canvas_getenv(t_canvas *x);
+EXTERN void canvas_rename(t_canvas *x, t_symbol *s, t_symbol *dir);
+EXTERN void canvas_loadbang(t_canvas *x);
+EXTERN int canvas_hitbox(t_canvas *x, t_gobj *y, int xpos, int ypos,
+ int *x1p, int *y1p, int *x2p, int *y2p);
+EXTERN int canvas_setdeleting(t_canvas *x, int flag);
+
+typedef void (*t_undofn)(t_canvas *canvas, void *buf,
+ int action); /* a function that does UNDO/REDO */
+#define UNDO_FREE 0 /* free current undo/redo buffer */
+#define UNDO_UNDO 1 /* undo */
+#define UNDO_REDO 2 /* redo */
+EXTERN void canvas_setundo(t_canvas *x, t_undofn undofn, void *buf,
+ const char *name);
+EXTERN void canvas_noundo(t_canvas *x);
+EXTERN int canvas_getindex(t_canvas *x, t_gobj *y);
+
+EXTERN void canvas_connect(t_canvas *x,
+ t_floatarg fwhoout, t_floatarg foutno,t_floatarg fwhoin, t_floatarg finno);
+EXTERN void canvas_disconnect(t_canvas *x,
+ float index1, float outno, float index2, float inno);
+EXTERN int canvas_isconnected (t_canvas *x,
+ t_text *ob1, int n1, t_text *ob2, int n2);
+EXTERN void canvas_selectinrect(t_canvas *x, int lox, int loy, int hix, int hiy);
+
+
+/* ---- functions on canvasses as objects --------------------- */
+
+EXTERN void canvas_fattenforscalars(t_canvas *x,
+ int *x1, int *y1, int *x2, int *y2);
+EXTERN void canvas_visforscalars(t_canvas *x, t_glist *glist, int vis);
+EXTERN int canvas_clicksub(t_canvas *x, int xpix, int ypix, int shift,
+ int alt, int dbl, int doit);
+EXTERN t_glist *canvas_getglistonsuper(void);
+
+EXTERN void linetraverser_start(t_linetraverser *t, t_canvas *x);
+EXTERN t_outconnect *linetraverser_next(t_linetraverser *t);
+EXTERN void linetraverser_skipobject(t_linetraverser *t);
+
+/* --------- functions on garrays (graphical arrays) -------------------- */
+
+EXTERN t_template *garray_template(t_garray *x);
+
+/* -------------------- arrays --------------------- */
+EXTERN t_garray *graph_array(t_glist *gl, t_symbol *s, t_symbol *tmpl,
+ t_floatarg f, t_floatarg saveit);
+EXTERN t_array *array_new(t_symbol *templatesym, t_gpointer *parent);
+EXTERN void array_resize(t_array *x, int n);
+EXTERN void array_free(t_array *x);
+
+/* --------------------- gpointers and stubs ---------------- */
+EXTERN t_gstub *gstub_new(t_glist *gl, t_array *a);
+EXTERN void gstub_cutoff(t_gstub *gs);
+EXTERN void gpointer_setglist(t_gpointer *gp, t_glist *glist, t_scalar *x);
+
+/* --------------------- scalars ------------------------- */
+EXTERN void word_init(t_word *wp, t_template *tmpl, t_gpointer *gp);
+EXTERN void word_restore(t_word *wp, t_template *tmpl,
+ int argc, t_atom *argv);
+EXTERN t_scalar *scalar_new(t_glist *owner,
+ t_symbol *templatesym);
+EXTERN void word_free(t_word *wp, t_template *tmpl);
+EXTERN void scalar_getbasexy(t_scalar *x, float *basex, float *basey);
+EXTERN void scalar_redraw(t_scalar *x, t_glist *glist);
+
+/* ------helper routines for "garrays" and "plots" -------------- */
+EXTERN int array_doclick(t_array *array, t_glist *glist, t_scalar *sc, t_array *ap,
+ t_symbol *elemtemplatesym,
+ float linewidth, float xloc, float xinc, float yloc, float scalarvis,
+ t_fielddesc *xfield, t_fielddesc *yfield, t_fielddesc *wfield,
+ int xpix, int ypix, int shift, int alt, int dbl, int doit);
+
+EXTERN void array_getcoordinate(t_glist *glist,
+ char *elem, int xonset, int yonset, int wonset, int indx,
+ float basex, float basey, float xinc,
+ t_fielddesc *xfielddesc, t_fielddesc *yfielddesc, t_fielddesc *wfielddesc,
+ float *xp, float *yp, float *wp);
+
+EXTERN int array_getfields(t_symbol *elemtemplatesym,
+ t_canvas **elemtemplatecanvasp,
+ t_template **elemtemplatep, int *elemsizep,
+ t_fielddesc *xfielddesc, t_fielddesc *yfielddesc, t_fielddesc *wfielddesc,
+ int *xonsetp, int *yonsetp, int *wonsetp);
+
+/* --------------------- templates ------------------------- */
+EXTERN t_template *template_new(t_symbol *sym, int argc, t_atom *argv);
+EXTERN void template_free(t_template *x);
+EXTERN int template_match(t_template *x1, t_template *x2);
+EXTERN int template_find_field(t_template *x, t_symbol *name, int *p_onset,
+ int *p_type, t_symbol **p_arraytype);
+EXTERN t_float template_getfloat(t_template *x, t_symbol *fieldname, t_word *wp,
+ int loud);
+EXTERN void template_setfloat(t_template *x, t_symbol *fieldname, t_word *wp,
+ t_float f, int loud);
+EXTERN t_symbol *template_getsymbol(t_template *x, t_symbol *fieldname,
+ t_word *wp, int loud);
+EXTERN void template_setsymbol(t_template *x, t_symbol *fieldname,
+ t_word *wp, t_symbol *s, int loud);
+
+EXTERN t_template *gtemplate_get(t_gtemplate *x);
+EXTERN t_template *template_findbyname(t_symbol *s);
+EXTERN t_canvas *template_findcanvas(t_template *tmpl);
+EXTERN void template_notify(t_template *tmpl,
+ t_symbol *s, int argc, t_atom *argv);
+
+EXTERN t_float template_getfloat(t_template *x, t_symbol *fieldname,
+ t_word *wp, int loud);
+EXTERN void template_setfloat(t_template *x, t_symbol *fieldname,
+ t_word *wp, t_float f, int loud);
+EXTERN t_symbol *template_getsymbol(t_template *x, t_symbol *fieldname,
+ t_word *wp, int loud);
+EXTERN void template_setsymbol(t_template *x, t_symbol *fieldname,
+ t_word *wp, t_symbol *s, int loud);
+EXTERN t_float fielddesc_getcoord(t_fielddesc *f, t_template *tmpl,
+ t_word *wp, int loud);
+EXTERN void fielddesc_setcoord(t_fielddesc *f, t_template *tmpl,
+ t_word *wp, float pix, int loud);
+EXTERN t_float fielddesc_cvttocoord(t_fielddesc *f, float val);
+EXTERN float fielddesc_cvtfromcoord(t_fielddesc *f, float coord);
+
+
+/* ----------------------- guiconnects, g_guiconnect.c --------- */
+EXTERN t_guiconnect *guiconnect_new(t_pd *who, t_symbol *sym);
+EXTERN void guiconnect_notarget(t_guiconnect *x, double timedelay);
+
+/* ------------- IEMGUI routines used in other g_ files ---------------- */
+EXTERN t_symbol *iemgui_raute2dollar(t_symbol *s);
+EXTERN t_symbol *iemgui_dollar2raute(t_symbol *s);
+
+#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus)
+}
+#endif
+
+#endif /* DESIRE */
+#endif /* __G_CANVAS_H */
+
diff --git a/externals/gridflow/bundled/m_imp.h b/externals/gridflow/bundled/m_imp.h
new file mode 100644
index 00000000..d129bdbe
--- /dev/null
+++ b/externals/gridflow/bundled/m_imp.h
@@ -0,0 +1,82 @@
+/* Copyright (c) 1997-1999 Miller Puckette.
+* For information on usage and redistribution, and for a DISCLAIMER OF ALL
+* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
+
+/* This file contains function prototypes and data types used to implement
+Pd, but not shared with Pd objects. */
+
+/* NOTE: this file describes Pd implementation details which may change
+in future releases. The public (stable) API is in m_pd.h. */
+
+/* LATER consider whether to use 'char' for method arg types to save space */
+#ifndef __m_imp_h_
+
+/* the structure for a method handler ala Max */
+typedef struct _methodentry
+{
+ t_symbol *me_name;
+ t_gotfn me_fun;
+ t_atomtype me_arg[MAXPDARG+1];
+} t_methodentry;
+
+EXTERN_STRUCT _widgetbehavior;
+
+typedef void (*t_bangmethod)(t_pd *x);
+typedef void (*t_pointermethod)(t_pd *x, t_gpointer *gp);
+typedef void (*t_floatmethod)(t_pd *x, t_float f);
+typedef void (*t_symbolmethod)(t_pd *x, t_symbol *s);
+typedef void (*t_listmethod)(t_pd *x, t_symbol *s, int argc, t_atom *argv);
+typedef void (*t_anymethod)(t_pd *x, t_symbol *s, int argc, t_atom *argv);
+
+struct _class
+{
+ t_symbol *c_name; /* name (mostly for error reporting) */
+ t_symbol *c_helpname; /* name of help file */
+ t_symbol *c_externdir; /* directory extern was loaded from */
+ size_t c_size; /* size of an instance */
+ t_methodentry *c_methods; /* methods other than bang, etc below */
+ int c_nmethod; /* number of methods */
+ t_method c_freemethod; /* function to call before freeing */
+ t_bangmethod c_bangmethod; /* common methods */
+ t_pointermethod c_pointermethod;
+ t_floatmethod c_floatmethod;
+ t_symbolmethod c_symbolmethod;
+ t_listmethod c_listmethod;
+ t_anymethod c_anymethod;
+ struct _widgetbehavior *c_wb; /* "gobjs" only */
+ struct _parentwidgetbehavior *c_pwb;/* widget behavior in parent */
+ t_savefn c_savefn; /* function to call when saving */
+ t_propertiesfn c_propertiesfn; /* function to start prop dialog */
+ int c_floatsignalin; /* onset to float for signal input */
+ char c_gobj; /* true if is a gobj */
+ char c_patchable; /* true if we have a t_object header */
+ char c_firstin; /* if patchable, true if draw first inlet */
+ char c_drawcommand; /* a drawing command for a template */
+};
+
+
+/* m_obj.c */
+EXTERN int obj_noutlets(t_object *x);
+EXTERN int obj_ninlets(t_object *x);
+EXTERN t_outconnect *obj_starttraverseoutlet(t_object *x, t_outlet **op,
+ int nout);
+EXTERN t_outconnect *obj_nexttraverseoutlet(t_outconnect *lastconnect,
+ t_object **destp, t_inlet **inletp, int *whichp);
+EXTERN t_outconnect *obj_connect(t_object *source, int outno,
+ t_object *sink, int inno);
+EXTERN void obj_disconnect(t_object *source, int outno, t_object *sink,
+ int inno);
+EXTERN void outlet_setstacklim(void);
+EXTERN int obj_issignalinlet(t_object *x, int m);
+EXTERN int obj_issignaloutlet(t_object *x, int m);
+EXTERN int obj_nsiginlets(t_object *x);
+EXTERN int obj_nsigoutlets(t_object *x);
+EXTERN int obj_siginletindex(t_object *x, int m);
+EXTERN int obj_sigoutletindex(t_object *x, int m);
+
+/* misc */
+EXTERN void glob_evalfile(t_pd *ignore, t_symbol *name, t_symbol *dir);
+EXTERN void glob_initfromgui(void *dummy, t_symbol *s, int argc, t_atom *argv);
+EXTERN void glob_quit(void *dummy);
+#define __m_imp_h_
+#endif /* __m_imp_h_ */
diff --git a/externals/gridflow/configure b/externals/gridflow/configure
new file mode 100755
index 00000000..a188481c
--- /dev/null
+++ b/externals/gridflow/configure
@@ -0,0 +1,822 @@
+#!/usr/bin/env ruby
+# $Id: configure 4672 2009-11-02 03:19:02Z matju $
+=begin
+ GridFlow
+ Copyright (c) 2001-2009 by Mathieu Bouchard
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ See file ./COPYING for further informations on licensing terms.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+=end
+
+require "rbconfig"
+require "ftools"
+$CFLAGS = ""
+include Config
+OSX = !!( CONFIG["arch"] =~ /darwin/ )
+
+require "win32/process" if CONFIG["arch"] =~ /mingw/
+LOG = File.open "./config.log", "w"
+
+Red = "\e[0;1;31m"
+Green = "\e[0;1;32m"
+Light = "\e[0m"
+Dark = "\e[0;1;30m"
+Yellow = "\e[0;1;33;44m"
+
+$verbose=false
+LOG.puts "-"*64
+LOG.puts "Environment Variables: "
+ENV.each {|k,v| LOG.puts "#{k}=#{v}" }
+LOG.puts "-"*64
+
+puts
+if not File.exist?("./configure")
+ puts "Run me from the right directory please."
+ exit 1
+end
+
+begin Dir.mkdir "tmp"; rescue Errno::EEXIST; end
+
+#----------------------------------------------------------------#
+
+class Or
+ attr_reader :a
+ class<< self; alias [] new end
+ def initialize(*a) @a=a end
+ def to_s; @a.join " or "; end
+end
+
+def launch2(log,*command)
+ log << command.join(" ") << "\n"
+ r,w = IO.pipe
+ child = launch(nil,w,w,*command)
+ w.close
+ log << r.readlines.join << "\n"
+ ret = join_pid(child)
+ ret = ret.to_int if RUBY_VERSION > "1.7"
+ log << "error \##{ret}\n" if ret>0
+ return ret<=0
+end
+
+$conf={
+ :LDSOFLAGS => [],
+ :FEATURES => {},
+ :OPTIONS => [],
+ :DEFINES => {:CPU => nil},
+ :CC => "g++",
+ :OBJS => [],
+}
+
+def launch stdin,stdout,stderr,*command # -> returncode
+ child = fork
+ if not child then
+ STDIN .reopen stdin if stdin
+ STDOUT.reopen stdout if stdout
+ STDERR.reopen stderr if stderr
+ exec *command
+ #!@#$ what happens with exception upon exec ?
+ end
+ child
+end
+
+def join_pid pid
+ Process.waitpid2(pid)[1]
+end
+
+module Future; end
+
+class Feature
+ $features = []
+ def self.add(*a,&b) $features << Feature.new(*a,&b) end
+ def initialize(&b) instance_eval(&b) end
+ def self.attr2(sym,&b)
+ eval "def #{sym}(*args,&b)
+ raise args.inspect if args.length>1
+ if b then @#{sym}=b.extend Future
+ elsif args.length>0 then @#{sym}=args[0]
+ else if Future===@#{sym} then @#{sym}.call else @#{sym} end end end"
+ end
+ attr2 :tag
+ attr2 :name
+ attr2 :status
+ attr2 :uses_so
+ attr2 :uses_o
+ attr2 :uses_h
+ attr2 :uses_feature
+ attr2 :test
+ attr2 :options
+ attr2 :unless_feature
+ attr2 :action
+ attr2 :defines
+ def find_h name
+ if name[0..0]=="/" then
+ File.exist?(name)
+ else
+ $C_INCLUDE_PATH.find {|x| File.exist?(x+"/"+name)}
+ end
+ end
+ def c_test code, link=nil, options=[], feature=nil
+ link = (uses_so||[]).dup if not link
+ link=link.flatten
+ ldlpath = ENV["LD_LIBRARY_PATH"]
+ uses_h.each {|h|
+ find_h h or
+ /framework/ =~ (uses_so||[]).join(" ") or
+ raise "where is #{h} ?"
+ } if uses_h
+ ENV["LD_LIBRARY_PATH"] = ldlpath ? "./tmp:#{ldlpath}" : "./tmp"
+ link[0,0]=$conf[:LDSOFLAGS].find_all {|x| String===x and /^-L/ =~ x }.flatten
+ code=code.gsub(/#include#/) {
+ uses_h.map {|inc| "#include <#{inc}>\n" }.join""
+ }
+ log = ""
+ log << code << "\n"
+ binname = "tmp/#{$$}"
+ sourcename = binname+".cpp"
+ File.open(sourcename,"w") {|f| f.puts code }
+ command = ["/usr/bin/env", $conf[:CC]] +
+ $CFLAGS.split(/ /).reject{|x| x.length==0 }
+ if not launch2 log,*(command+options+[sourcename,
+ "-o", binname, *link])
+ pat = Regexp.new("^"+Regexp.quote(sourcename)+":\\d+: ")
+ errs = log.split("\n").find_all {|l| pat =~ l }
+ raise "gcc compilation error" if not errs or
+ errs.length==0
+ errs = errs[0].gsub(pat,"")
+ raise "gcc: #{errs}"
+ end
+ if not launch2 log,"tmp/#{$$}"
+ raise "runtime error"
+ end
+ return true
+ ensure
+ LOG.puts log
+ ENV["LD_LIBRARY_PATH"] = ldlpath if ldlpath
+ end
+ def asm_test code, *link
+ log = ""
+ log << code << "\n"
+ File.open("tmp/#{$$}.asm","w") {|f| f.puts code }
+ command = ["/usr/bin/env", "nasm",
+ "tmp/#{$$}.asm", "-f", "elf", "-o", "tmp/#{$$}.o"]
+ launch2 log,*command or return false
+ command = ["#{$conf[:CC]}","-o","tmp/#{$$}","tmp/#{$$}.o",*link]
+ launch2 log,*command or return false
+ command = ["tmp/#{$$}"]
+ launch2 log,*command or return false
+ true
+ ensure
+ LOG.puts log
+ end
+end
+
+#----------------------------------------------------------------#
+
+def read_ld_so_conf
+ return [] unless File.exist?("/etc/ld.so.conf")
+ x = File.open("/etc/ld.so.conf"){|f| f.read }.split("\s")
+ x.delete_if { x.length==0 }
+ x
+end
+
+def epath x; (ENV[x]||"").split(":") end
+
+$C_INCLUDE_PATH = (epath("CPLUS_INCLUDE_PATH") + epath("C_INCLUDE_PATH") + ["/usr/include"]).uniq
+$LIBRARY_PATH = (epath("LIBRARY_PATH") + ["/usr/lib","/lib"]).uniq
+$LD_LIBRARY_PATH = (epath("LD_LIBRARY_PATH") + read_ld_so_conf + ["/usr/lib","/lib"]).uniq
+$LIBX11DIR = [
+ "-L/usr/X11R6/lib", "-L/opt/gnome/lib",
+ "-L/usr/X11R6/lib64","-L/opt/gnome/lib64"]
+$LIBX11 = $LIBX11DIR + ["-lX11"]
+
+# making it easier for everybody I hope:
+def prepend_path base
+ bl = base+"/lib"
+ bi = base+"/include"
+ if not $LD_LIBRARY_PATH.include? bl and
+ not $LIBRARY_PATH.include? bl then
+ $conf[:LDSOFLAGS].unshift "-L"+bl
+ $LD_LIBRARY_PATH.unshift bl
+ $LIBRARY_PATH.unshift bl
+ end
+ #and not $CPLUS_INCLUDE_PATH.include? bi
+ if not $C_INCLUDE_PATH.include? bi then
+ $CFLAGS += " -I"+bi
+ $C_INCLUDE_PATH.unshift bi
+ end
+end
+prepend_path "/sw" if OSX
+prepend_path "/usr/local"
+prepend_path ENV["HOME"]
+$CFLAGS += " -I."
+$C_INCLUDE_PATH.unshift "."
+
+for var in [:$C_INCLUDE_PATH, :$LIBRARY_PATH, :$LD_LIBRARY_PATH] do
+ LOG.puts "#{var}: #{eval(var.to_s).inspect}"
+end
+
+LOG.puts "-"*64
+$CFLAGS += " -I/usr/X11R6/include"
+$C_INCLUDE_PATH.unshift "/usr/X11R6/include"
+
+#----------------------------------------------------------------#
+Feature.add {
+ tag :gcc3
+ name "GNU C++ Compiler 3 (or 4)"
+ options ["HAVE_GCC3"]
+ defines :GCC_VERSION => proc {
+ m = /GCC_VERSION\s+(.*)/.match(File.popen("tmp/#{$$}","r"){|f| f.read })
+ m[1]
+ }
+ # how does this handle two test procs again?
+ test proc {
+ pi=File.popen "#{$conf[:CC]} -v 2>&1", "r"
+ vline = pi.readlines.find {|l| /gcc version ([\d\.]+)/.match l }
+ version = $1
+ pi.close
+ if version < "3" then raise "version #{version} < 3" end
+ true
+ }
+ test proc {
+ c_test %{
+ #include <stdio.h>
+ int main () {
+ printf("GCC_VERSION %d.%d.%d\\n", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
+ return !(__GNUC__>=3);
+ }}}}
+Feature.add {
+ tag :stl
+ name "C++ Standard Template Library"
+ test proc {
+ c_test %{
+ #include <vector>
+ int main () {std::vector<int> foo;}}}}
+Feature.add {
+ tag :gcc64
+ name "GNU C++ in 64-bit mode"
+ options ["GCC64"]
+ test proc {
+ c_test %{
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <cstddef>
+ #include <sys/types.h>
+ #define T(a) printf("%s:%ld; ",#a,(long)sizeof(a));
+ int main () {
+ T(void *)T(ptrdiff_t)T(off_t)T(size_t)puts("");
+ T(char)T(short)T(int)T(long)T(long long)puts("");
+ T(float)T(double)puts("");
+ return !( sizeof(void*)==8 );
+ }}}}
+Feature.add {
+ tag :pentium
+ name "Pentium-compatible CPU"
+ action proc { $conf[:DEFINES][:CPU] ||= "pentium" }
+ options ["HAVE_PENTIUM"]
+ test proc {
+ (CONFIG["arch"] =~ /(i\d86|x86_64)/) or raise "#{CONFIG["arch"]} instead"
+ c_test '
+ #include <stdio.h>
+ char get_cpuid[]={
+ 96,49,192,15,162,139,124,36,36,137,31,
+ 137,87,4,137,79,8,137,71,12,97,195};
+ main() {
+ char result[16];
+ int code;
+ ((void(*)(char*))get_cpuid)(result);
+ code = ((int*)result)[3];
+ result[12]=0;
+ fprintf(stderr,"cpuid: name=\"%12s\", flags=0x%08x\n",
+ result,code);
+ return 0;}'}}
+Feature.add {
+ tag :mmx
+ uses_feature [:pentium]
+ uses_o ["src/mmx.o","src/mmx_loader.o"]
+ name "MMX-compatible CPU (using NASM)"
+ options ["HAVE_MMX"]
+ test proc { #!@#$ isn't 64-bit-compatible
+ asm_test '
+ global main
+ extern exit
+ align 16
+ SECTION .data
+ foo: dd 42,0
+ SECTION .text
+ main:
+ lea esi,[foo]
+ movq mm0,qword[esi]
+ paddd mm0,qword[esi]
+ movq qword [esi],mm0
+ emms
+ cmp dword [foo], 84
+ je yes
+ push long 1
+ call exit
+ yes:
+ push long 0
+ call exit
+ ', '-lc'}}
+Feature.add {
+ tag :x11
+ name "X11 Display Protocol"
+ uses_so $LIBX11
+ uses_h ["X11/Xlib.h"]
+ uses_o ["src/x11.o"]
+ test proc {
+ c_test "
+ #include#
+ int main () {return XSetErrorHandler==0;}"}}
+Feature.add {
+ tag :x11_shm
+ name "X11 acceleration by shared memory (XSHM plugin)"
+ uses_feature [:x11]
+ uses_so $LIBX11+["-lXext"]
+ uses_h ["X11/Xlib.h","sys/shm.h","X11/extensions/XShm.h"]
+ options ["HAVE_X11_SHARED_MEMORY"]
+ test proc {
+ c_test "
+ #include#
+ #include <X11/Xutil.h>
+ #include <X11/StringDefs.h>
+ #include <sys/ipc.h>
+ int main () {return XShmPutImage==0;}"}}
+Feature.add {
+ tag :sdl
+ name "Simple Directmedia Layer (experimental support)"
+ uses_so {
+ a=["-lSDL","-lpthread"]
+ a << "-lobjc" if OSX
+ a
+ }
+ uses_h ["SDL/SDL.h"]
+ uses_o ["src/sdl.o"]
+ test proc {
+ c_test "
+ #include#
+ #undef main
+ int main () {return SDL_MapRGB==0;}"}}
+Feature.add {
+ tag :objcpp
+ name "GNU/Apple ObjectiveC++ Compiler"
+ uses_h ["objc/Object.h"]
+ uses_so ["-lobjc"]
+ test proc {
+ c_test "
+ #include#
+ int main () { [[Object alloc] init]; }
+ ", nil, ["-xobjective-c++"]}}
+Feature.add {
+ tag :quartz
+ name "Apple Quartz/Cocoa Display"
+ uses_so ["-lobjc",["-framework","Cocoa"]]
+ uses_feature [:objcpp]
+ uses_h ["objc/Object.h","Cocoa/Cocoa.h"]
+ uses_o ["src/quartz.o"]
+ test proc {
+ c_test "
+ #include#
+ int main () {return CGImageRelease==0;}
+ ", nil, ["-xobjective-c++"]}}
+Feature.add {
+ tag :aalib
+ name "Ascii Art Library"
+ uses_so ["-laa"]
+ uses_h ["aalib.h"]
+ uses_o ["src/aalib.o"]
+ test proc {
+ c_test "
+ #define aa_hardwareparams aa_hardware_params
+ extern \"C\" {
+ #include#
+ };
+ int main () {return aa_init==0;}"}}
+Feature.add {
+ tag :netpbm
+ name "NetPBM 10 Library"
+ uses_so ["-lnetpbm"]
+ uses_h Or[["pam.h"],["netpbm/pam.h"]]
+ uses_o ["src/netpbm.o"]
+ test proc {|f|
+ f.c_test "
+ #include#
+ int main () {return pm_init==0;}"}}
+Feature.add {
+ tag :jpeg
+ name "JPEG Library"
+ uses_so ["-ljpeg"]
+ uses_h ["jpeglib.h"]
+ uses_o ["src/jpeg.o"]
+ test proc {
+ c_test "
+ extern \"C\" {
+ #include <stdio.h>
+ #include#
+ };
+ int main () {
+ return jpeg_write_scanlines==0;}"}}
+Feature.add {
+ tag :png
+ name "PNG Library"
+ uses_so ["-lpng","-lz"]
+ uses_h Or[["libpng12/png.h"],["png.h"]]
+ uses_o ["src/png.o"]
+ test proc {|f|
+ f.c_test %`
+ extern "C" {
+ #include <stdio.h>
+ #include#
+ };
+ int main () {
+ #define T(a) printf("%s:%d; ",#a,sizeof(a));
+ T(png_uint_32)T(long)puts("");
+ if (!png_check_sig) return 1;
+ return 0;}`}}
+Feature.add {
+ tag :videodev
+ name "Video4linux Digitizer Driver Interface"
+ uses_h ["linux/videodev.h"]
+ uses_o ["src/videodev.o"]
+ test proc {
+ c_test "
+ #include <stdlib.h>
+ #include#
+ int main () { struct video_window foo; return 0; }"}}
+Feature.add {
+ tag :dc1394
+ name "DC1394 for Linux"
+ uses_so ["-ldc1394_control"]
+ uses_h Or["libdc1394/dc1394_control.h","dc1394/control.h"]
+ uses_o ["src/dc1394.o"]
+ options ["HAVE_DC1394"]
+ test proc {|f|
+ f.c_test "
+ #include#
+ int main () {return dc1394_get_camera_port==0;}"}}
+Feature.add {
+ tag :mpeg3
+ name "HeroineWarrior LibMPEG3"
+ uses_so $LIBX11DIR+["-lmpeg3","-lpthread","-lm"]
+ uses_h Or["libmpeg3/libmpeg3.h","libmpeg3.h"]
+ uses_o ["src/mpeg3.o"]
+ test proc {|f|
+ f.c_test "
+ #include#
+ int main () { return mpeg3_open==0; }"}}
+Feature.add {
+ tag :quicktimeapple
+ name "Apple's QuickTime"
+ uses_so [["-framework","Quicktime"]]
+ uses_h ["QuickTime/QuickTime.h","QuickTime/Movies.h"]
+ uses_o ["src/quicktimeapple.o"]
+ test proc {
+ c_test "
+ #include#
+ int main () { return EnterMovies==0; }
+ "}}
+Feature.add {
+ tag :quicktimehw
+ unless_feature :quicktimeapple
+ name "Plaum's LibQuickTime"
+ uses_so Or[
+ $LIBX11DIR+["-lquicktime","-lpthread","-lpng","-ldl","-lglib" ,"-lz"],
+ $LIBX11DIR+["-lquicktime","-lpthread","-lpng","-ldl","-lglib-1.2","-lz"],
+ $LIBX11DIR+["-lquicktime","-lpthread","-lpng","-ldl","-lglib-2.0","-lz"]]
+ f = ["quicktime.h","colormodels.h","lqt.h","lqt_version.h","lqt_codecinfo.h"]
+ uses_h Or[
+ f.map{|x| "lqt/"+x },
+ f.map{|x| "quicktime/"+x }]
+ uses_o ["src/quicktimehw.o"]
+ test proc {|f|
+ f.c_test %`
+ #include <stdio.h>
+ #include#
+ int main () {
+ fprintf(stderr,"LQT_VERSION = %s\\n",
+ #ifdef LQT_VERSION
+ LQT_VERSION
+ #else
+ "(undefined)"
+ #endif
+ ); return quicktime_open==0; }
+ `}}
+Feature.add {
+ tag :puredata
+ name "PureData (or DesireData)"
+ options ["HAVE_PUREDATA"]
+ defines {
+ path = $C_INCLUDE_PATH.find {|x| File.exist?(x+"/m_pd.h")}
+ m = /PD_VERSION_INT\s+(.*)/.match(File.popen("tmp/#{$$}","r"){|f| f.read })
+ {:PD_VERSION_INT => m[1].to_i}
+ }
+ uses_h ["m_pd.h"]
+ test proc {
+ c_test %`
+ #include#
+ #include <stdio.h>
+ int main () {
+ printf("#define PD_VERSION_INT %d\\n",
+ #ifdef PD_MAJOR_VERSION
+ (int)(PD_MAJOR_VERSION*100+PD_MINOR_VERSION));
+ #else
+ (int)(PD_VERSION*100));
+ #endif
+ return 0;}`}}
+Feature.add {
+ tag :desiredata
+ name "DesireData"
+ uses_h ["m_pd.h"]
+ defines ["HAVE_DESIREDATA"]
+ test proc {
+ c_test %`
+ #include#
+ int main () {return !gobj_subscribe;}`}}
+Feature.add {
+ tag :opencv
+ name "Intel OpenCV"
+ uses_o ["src/opencv.o"]
+ uses_so ["-lcv"]
+ options ["HAVE_OPENCV"]
+ defines {{:OPENCV_SHARE_PATH => File.dirname($C_INCLUDE_PATH.find {|x| File.exist?(x+"/opencv/cv.h")}) + "/share/opencv"}}
+ test proc {
+ c_test %`
+ #include <opencv/cv.h>
+ int main () {return 0;}`}}
+Feature.add {
+ tag :fftw
+ name "FFTW (Fastest Fourier Transform in the West)"
+ uses_o ["src/fftw.o"]
+ uses_so ["-lfftw3f","-lfftw3"]
+ options ["HAVE_FFTW"]
+ test proc {
+ c_test %`
+ #include <fftw3.h>
+ int main () {return 0;}`}}
+Feature.add {
+ tag :opengl
+ name "OpenGL (for GEM support)"
+ uses_feature [:puredata]
+ uses_o ["src/gem.o"]
+ uses_so $LIBX11DIR+["-lGL"]
+ uses_h ["GL/gl.h"]
+ options ["HAVE_GEM"]
+ test proc {
+ c_test %`
+ #include#
+ int main () {return (GLint)0;}
+ `
+ }
+}
+#--------------------------------#
+
+$features_h = {}
+$features.each {|f| $features_h[f.tag]=f }
+
+def usage
+ log = ""
+ log << "usage: ./configure "
+ log << "[--use-compiler compiler] [--use-compiler-option option]* "
+ log << "[--use-cpu cpu] [--lite] [--debug]"
+ $features_h.keys.map {|k| k.to_s }.sort.each {|k| log << "[--no-#{k}] " }
+ $features_h.keys.map {|k| k.to_s }.sort.each {|k| log << "[--force-#{k}] " }
+ puts
+ while log.length>0 do puts log.slice!(/^.{1,70} /) end
+end
+
+$debug=false
+while ARGV.length>0 do
+ arg=ARGV.shift
+ case arg
+ when /=/
+ i=arg.index '='
+ ARGV.unshift arg[0..i-1], arg[i+1..-1]
+ when /^--no-/
+ name = arg[5..-1].untaint.intern
+ puts "there is no feature called #{name}" if not $features_h[name]
+ puts "--no: won't check for feature #{name}"
+ $features_h.delete name
+ when /^--force-/
+ name = arg[8..-1].untaint.intern
+ puts "there is no feature called #{name}" if not $features_h[name]
+ puts "--force: assuming #{name} is there"
+ $features_h[name].test nil
+ when "--debug"
+ puts "Debug Mode (more error checking; less speed)"
+ $debug=true
+ $conf[:OPTIONS].push :HAVE_DEBUG
+ when "--lite"
+ puts "Lite Mode (no float64, no int64)"
+ $conf[:OPTIONS].push :HAVE_LITE
+ when "--help"
+ usage; exit 0
+ when "--use-compiler"
+ $conf[:CC] = ARGV.shift
+ when "--use-compiler-option"
+ $CFLAGS += " "+ARGV.shift
+ when "--use-cpu"
+ $conf[:DEFINES][:CPU] = ARGV.shift
+ when "--verbose"
+ $verbose=true
+ else puts "unknown option \"#{arg}\""; usage; exit 1
+ end
+end
+
+if $debug
+ $CFLAGS += " -O0 -fno-inline"
+else
+ $CFLAGS += " -O3"
+end
+
+#--------------------------------#
+
+DUAL = Object.new
+DUAL.instance_eval {
+ def self.print x
+ LOG .puts x; LOG .flush
+ STDERR.print x; STDERR.flush
+ end
+ def self.puts(x) self.print x+"\n" end
+}
+
+def try feature
+ if Proc===feature.uses_so then feature.uses_so(feature.uses_so[]) end
+ if Or===feature.uses_so
+ k=1; feature.uses_so.a.each {|i|
+ e=feature.dup; e.uses_so i; e.name(e.name+" (try \##{k})")
+ r=try e; k+=1; return r if r }
+ return false
+ end
+ if Proc===feature.uses_h then feature.uses_h(feature.uses_h[]) end
+ if Or===feature.uses_h
+ k=1; feature.uses_h.a.each {|i|
+ i=[i] if String===i
+ e=feature.dup; e.uses_h i; e.name(e.name+" <#{i[0]}>")
+ r=try e; k+=1; return r if r }
+ return false
+ end
+ LOG.puts "", "-"*64
+ line = "[#{feature.tag}] #{feature.name}: "
+ DUAL.print Light + "[#{Yellow}#{feature.tag}#{Light}] #{feature.name}: "
+ arrow = "-"*([78-line.length,0].max)+ "> "
+ #DUAL.print Dark + arrow +Red
+ (feature.uses_feature||[]).find {|f|
+ if not (
+ if Or===f then f.a.find {|x| $conf[:FEATURES][x] } else $conf[:FEATURES][f] end
+ ) then
+ DUAL.puts Red+arrow+"disabled (would need #{f})"
+ return
+ end
+ }
+ if feature.status==:disabled then DUAL.puts Dark+arrow+"disabled (by author)"; return end
+ if not $features_h[feature.tag] then DUAL.puts Dark+arrow+"disabled (by user)"; return end
+ fu = feature.unless_feature || []
+ fu = [fu] if not Array===fu
+ for f in fu || [] do
+ if $conf[:FEATURES][f] then DUAL.puts Dark+arrow+"disabled (using #{f} instead)"; return end
+ end
+ if feature.test
+ begin tresult = feature.test.call(feature); rescue StandardError => e; end
+ if tresult
+ DUAL.puts Green+arrow+"found "+(if tresult!=true then " (#{tresult})" else "" end)
+ else
+ DUAL.puts Red+arrow+"missing "+(if e
+ then (if $verbose
+ then "(#{e} @ #{e.backtrace.join', '})"
+ else "(#{e})" end)
+ else "(return false)" end)
+ if e
+ LOG.puts e.inspect
+ LOG.puts e.backtrace
+ end
+ return false
+ end
+ else
+ puts Green+arrow+"enabled"
+ $conf[:FEATURES][feature.tag] = feature
+ feature.action.call if feature.action
+ end
+ feature.action.call if feature.action
+ $conf[:FEATURES][feature.tag] = feature
+ $conf[:LDSOFLAGS].concat(feature.uses_so||[])
+ $conf[:OBJS].concat(feature.uses_o||[])
+ $conf[:OPTIONS].concat(feature.options||[])
+ for k,v in feature.defines||{} do
+ $conf[:DEFINES][k]=(if Proc===v then v[] else v end)
+ end
+ true
+end
+
+DUAL.puts "This is the GridFlow 0.9.5 configurator"
+
+begin
+ $features.each {|feature| try feature }
+ensure
+ #!@#$ note: see END{} (duplication)
+ system "/bin/rm -f tmp/#{$$} tmp/#{$$}.c tmp/#{$$}.o tmp/#{$$}.asm"
+end
+
+puts Light
+
+$conf[:LDSOFLAGS].uniq!
+
+if not $conf[:FEATURES][:gcc3]
+ puts "You should install gcc 3.x; gcc 2.9.x is no longer supported"
+ puts "(you might use --force-gcc3 to pretend at your own risk)"
+ exit 1
+end
+
+if not $conf[:FEATURES][:puredata]
+ puts "PureData support is required (since GridFlow 0.9.0)"
+end
+
+#--------------------------------#
+
+LOG.puts "-"*64
+for z in [:LDSOFLAGS, :OPTIONS, :DEFINES, :OBJS] do
+ LOG.puts "#{z}: #{$conf[z].inspect}"
+end
+LOG.puts "-"*64
+RUBY = "$(RUBY_INSTALL_NAME)"
+
+puts "generating ./config.make"
+File.open("./config.make","w") {|f|
+ $CFLAGS += " -mcpu=$(CPU)" if $conf[:DEFINES][:CPU] and $conf[:DEFINES][:GCC_VERSION] < "4"
+ $CFLAGS += " -mtune=$(CPU)" if $conf[:DEFINES][:CPU] and $conf[:DEFINES][:GCC_VERSION] >= "4"
+ $CFLAGS += " -march=$(CPU)" if $conf[:DEFINES][:CPU]
+ $CFLAGS += " -DMACOSX" if OSX
+ f.puts "CFLAGS += " + $CFLAGS
+ f.puts "LDSOFLAGS += " + $conf[:LDSOFLAGS].flatten.join(" ")
+ for k in $conf[:OPTIONS] do f.puts "#{k}=yes" end
+ for k,v in $conf[:DEFINES] do f.puts "#{k}=#{v}" end
+ f.puts "CXX = #{$conf[:CC]}"
+ f.puts "OBJS = #{$conf[:OBJS].join(" ")}"
+ f.puts "DLEXT = #{CONFIG['DLEXT']}"
+ f.puts ""
+ if OSX then
+ f.puts "OS = darwin"
+ else
+ f.puts "OS = linux"
+ end
+} # end open config.make
+
+#--------------------------------#
+puts "generating config.h"
+File.open("config.h","w") {|f|
+f.puts "
+\#ifndef __CONFIG_H
+\#define __CONFIG_H
+/* this file was auto-generated by gridflow/configure */"
+f.puts "#define STARTUP_LIST(PRE) \\"
+f.puts $conf[:OBJS].map {|o|
+ oo = File.basename(o,'.o').split(/-/)[0]
+ "PRE startup_#{oo}();"
+}.join("\\\n")
+for k in $conf[:OPTIONS] do f.puts "\#define #{k}" end
+for k,v in $conf[:DEFINES] do f.puts "\#define #{k} "+v.inspect end
+
+def include_here(f,a,b,c=false)
+ return unless $conf[:FEATURES][b]
+ f.puts "\#ifdef #{a}_INCLUDE_HERE"
+ f.puts "extern \"C\" {"
+ for inc in $conf[:FEATURES][b].uses_h.to_a do
+ f.puts "\#include <#{inc}>"
+ end
+ f.puts "};"
+ f.puts "\#endif"
+end
+include_here f,"DC1394", :dc1394
+include_here f,"LIBMPEG", :mpeg3
+include_here f,"QUICKTIMEHW",:quicktimehw
+include_here f,"NETPBM",:netpbm,true
+
+f.puts "
+\#endif /* __CONFIG_H */"
+} # end open config.h
+
+#--------------------------------#
+for s in [
+"See ./config.log if you want the details of the configuration tests.",
+"If you are satisfied with that configuration, you may go on,",
+"and do \"make\". \"make install\" is not needed anymore,",
+"just move your gridflow directory to \"lib/pd/extra\".",
+"If you get stuck, you could contact the author about it,",
+"but first make sure you read \"doc/install.html\". ",
+""] do puts "\e[1m#{s}\e[0m" end
+
+#--------------------------------#
+END {
+ system "/bin/rm -f tmp/#{$$} tmp/#{$$}.c tmp/#{$$}.o tmp/#{$$}.asm"
+}
diff --git a/externals/gridflow/deprecated/0x40!.pd b/externals/gridflow/deprecated/0x40!.pd
new file mode 100644
index 00000000..fef510a8
--- /dev/null
+++ b/externals/gridflow/deprecated/0x40!.pd
@@ -0,0 +1,28 @@
+#N canvas 589 39 450 300 10;
+#X obj 37 38 inlet;
+#X obj 37 204 outlet;
+#X obj 37 57 t a a;
+#X obj 66 57 #type;
+#X obj 37 156 # +;
+#X msg 56 156 list \$1 #;
+#X obj 147 63 args op;
+#X obj 147 82 sel rand abs sq sqrt;
+#X msg 117 116 op rand;
+#X msg 160 116 op abs-;
+#X msg 246 116 op sqrt;
+#X msg 203 116 op sq-;
+#X connect 0 0 2 0;
+#X connect 2 0 4 0;
+#X connect 2 1 3 0;
+#X connect 3 0 5 0;
+#X connect 4 0 1 0;
+#X connect 5 0 4 1;
+#X connect 6 0 7 0;
+#X connect 7 0 8 0;
+#X connect 7 1 9 0;
+#X connect 7 2 11 0;
+#X connect 7 3 10 0;
+#X connect 8 0 4 0;
+#X connect 9 0 4 0;
+#X connect 10 0 4 0;
+#X connect 11 0 4 0;
diff --git a/externals/gridflow/deprecated/0x40complex_sq.pd b/externals/gridflow/deprecated/0x40complex_sq.pd
new file mode 100644
index 00000000..9933d443
--- /dev/null
+++ b/externals/gridflow/deprecated/0x40complex_sq.pd
@@ -0,0 +1,11 @@
+#N canvas 0 0 303 155 10;
+#X obj 17 15 inlet;
+#X obj 17 91 outlet;
+#X obj 17 53 # C.*;
+#X obj 17 34 t a a;
+#X obj 17 72 # C.* (0 -1);
+#X connect 0 0 3 0;
+#X connect 2 0 4 0;
+#X connect 3 0 2 0;
+#X connect 3 1 2 1;
+#X connect 4 0 1 0;
diff --git a/externals/gridflow/deprecated/0x40convolve.pd b/externals/gridflow/deprecated/0x40convolve.pd
new file mode 100644
index 00000000..cbf62936
--- /dev/null
+++ b/externals/gridflow/deprecated/0x40convolve.pd
@@ -0,0 +1,23 @@
+#N canvas 404 162 450 184 10;
+#X obj 14 15 inlet;
+#X obj 150 54 inlet;
+#X obj 14 159 outlet;
+#X msg 51 83 op \$1;
+#X obj 124 22 args op fold seed right;
+#X msg 84 83 fold \$1;
+#X msg 129 83 seed \$1;
+#X obj 177 83 t a;
+#X obj 205 53 inlet;
+#X obj 14 140 #convolve;
+#X connect 0 0 9 0;
+#X connect 1 0 6 0;
+#X connect 3 0 9 0;
+#X connect 4 0 3 0;
+#X connect 4 1 5 0;
+#X connect 4 2 6 0;
+#X connect 4 3 7 0;
+#X connect 5 0 9 0;
+#X connect 6 0 9 0;
+#X connect 7 0 9 1;
+#X connect 8 0 7 0;
+#X connect 9 0 2 0;
diff --git a/externals/gridflow/deprecated/0x40fold.pd b/externals/gridflow/deprecated/0x40fold.pd
new file mode 100644
index 00000000..04cfeda7
--- /dev/null
+++ b/externals/gridflow/deprecated/0x40fold.pd
@@ -0,0 +1,15 @@
+#N canvas 404 162 450 184 10;
+#X obj 14 15 inlet;
+#X obj 193 23 inlet;
+#X obj 14 129 outlet;
+#X obj 124 22 args op seed;
+#X msg 121 63 op \$1;
+#X msg 154 63 seed \$1;
+#X obj 14 110 #fold +;
+#X connect 0 0 6 0;
+#X connect 1 0 5 0;
+#X connect 3 0 4 0;
+#X connect 3 1 5 0;
+#X connect 4 0 6 0;
+#X connect 5 0 6 0;
+#X connect 6 0 2 0;
diff --git a/externals/gridflow/deprecated/0x40inner.pd b/externals/gridflow/deprecated/0x40inner.pd
new file mode 100644
index 00000000..ca4809b7
--- /dev/null
+++ b/externals/gridflow/deprecated/0x40inner.pd
@@ -0,0 +1,23 @@
+#N canvas 404 162 450 184 10;
+#X obj 14 15 inlet;
+#X obj 150 54 inlet;
+#X obj 14 159 outlet;
+#X msg 51 83 op \$1;
+#X obj 124 22 args op fold seed right;
+#X msg 84 83 fold \$1;
+#X msg 129 83 seed \$1;
+#X obj 14 140 #inner;
+#X obj 177 83 t a;
+#X obj 205 53 inlet;
+#X connect 0 0 7 0;
+#X connect 1 0 6 0;
+#X connect 3 0 7 0;
+#X connect 4 0 3 0;
+#X connect 4 1 5 0;
+#X connect 4 2 6 0;
+#X connect 4 3 8 0;
+#X connect 5 0 7 0;
+#X connect 6 0 7 0;
+#X connect 7 0 2 0;
+#X connect 8 0 7 1;
+#X connect 9 0 8 0;
diff --git a/externals/gridflow/deprecated/0x40scan.pd b/externals/gridflow/deprecated/0x40scan.pd
new file mode 100644
index 00000000..41036baf
--- /dev/null
+++ b/externals/gridflow/deprecated/0x40scan.pd
@@ -0,0 +1,15 @@
+#N canvas 404 162 450 184 10;
+#X obj 14 15 inlet;
+#X obj 193 23 inlet;
+#X obj 14 129 outlet;
+#X obj 124 22 args op seed;
+#X msg 121 63 op \$1;
+#X msg 154 63 seed \$1;
+#X obj 14 110 #scan +;
+#X connect 0 0 6 0;
+#X connect 1 0 5 0;
+#X connect 3 0 4 0;
+#X connect 3 1 5 0;
+#X connect 4 0 6 0;
+#X connect 5 0 6 0;
+#X connect 6 0 2 0;
diff --git a/externals/gridflow/deprecated/fork.pd b/externals/gridflow/deprecated/fork.pd
new file mode 100644
index 00000000..e4dbe1cb
--- /dev/null
+++ b/externals/gridflow/deprecated/fork.pd
@@ -0,0 +1,8 @@
+#N canvas 591 196 450 300 10;
+#X obj 19 14 inlet;
+#X obj 19 71 outlet;
+#X obj 49 52 outlet;
+#X obj 19 33 t a a;
+#X connect 0 0 3 0;
+#X connect 3 0 1 0;
+#X connect 3 1 2 0;
diff --git a/externals/gridflow/deprecated/listappend.pd b/externals/gridflow/deprecated/listappend.pd
new file mode 100644
index 00000000..72e9f144
--- /dev/null
+++ b/externals/gridflow/deprecated/listappend.pd
@@ -0,0 +1,10 @@
+#N canvas 0 0 450 300 10;
+#X obj 23 16 inlet;
+#X obj 23 54 outlet;
+#X obj 95 16 inlet;
+#X obj 23 35 list append;
+#X obj 134 35 args *;
+#X connect 0 0 3 0;
+#X connect 2 0 3 1;
+#X connect 3 0 1 0;
+#X connect 4 0 3 1;
diff --git a/externals/gridflow/deprecated/listelement.pd b/externals/gridflow/deprecated/listelement.pd
new file mode 100644
index 00000000..46bbd4e0
--- /dev/null
+++ b/externals/gridflow/deprecated/listelement.pd
@@ -0,0 +1,15 @@
+#N canvas 174 196 450 300 10;
+#X obj 26 19 inlet;
+#X obj 133 18 inlet;
+#X obj 129 120 outlet;
+#X obj 26 44 list split \$1;
+#X obj 69 63 list split 1;
+#X obj 69 82 route float symbol;
+#X text 199 82 (canonicalise selector);
+#X connect 0 0 3 0;
+#X connect 1 0 3 1;
+#X connect 3 1 4 0;
+#X connect 4 0 5 0;
+#X connect 5 0 2 0;
+#X connect 5 1 2 0;
+#X connect 5 2 2 0;
diff --git a/externals/gridflow/deprecated/listlength.pd b/externals/gridflow/deprecated/listlength.pd
new file mode 100644
index 00000000..68e56c33
--- /dev/null
+++ b/externals/gridflow/deprecated/listlength.pd
@@ -0,0 +1,6 @@
+#N canvas 720 260 450 300 10;
+#X obj 23 16 inlet;
+#X obj 23 35 list length;
+#X obj 23 54 outlet;
+#X connect 0 0 1 0;
+#X connect 1 0 2 0;
diff --git a/externals/gridflow/deprecated/listprepend.pd b/externals/gridflow/deprecated/listprepend.pd
new file mode 100644
index 00000000..e3cec2b9
--- /dev/null
+++ b/externals/gridflow/deprecated/listprepend.pd
@@ -0,0 +1,10 @@
+#N canvas 720 260 450 300 10;
+#X obj 23 16 inlet;
+#X obj 23 54 outlet;
+#X obj 23 35 list prepend;
+#X obj 102 16 inlet;
+#X obj 141 35 args *;
+#X connect 0 0 2 0;
+#X connect 2 0 1 0;
+#X connect 3 0 2 1;
+#X connect 4 0 2 1;
diff --git a/externals/gridflow/deprecated/listsublist.pd b/externals/gridflow/deprecated/listsublist.pd
new file mode 100644
index 00000000..0e35b631
--- /dev/null
+++ b/externals/gridflow/deprecated/listsublist.pd
@@ -0,0 +1,12 @@
+#N canvas 280 216 450 300 10;
+#X obj 26 19 inlet;
+#X obj 112 19 inlet;
+#X obj 69 82 outlet;
+#X obj 26 44 list split \$1;
+#X obj 69 63 list split \$2;
+#X obj 155 19 inlet;
+#X connect 0 0 3 0;
+#X connect 1 0 3 1;
+#X connect 3 1 4 0;
+#X connect 4 0 2 0;
+#X connect 5 0 4 1;
diff --git a/externals/gridflow/deprecated/messageappend.pd b/externals/gridflow/deprecated/messageappend.pd
new file mode 100644
index 00000000..cd439db3
--- /dev/null
+++ b/externals/gridflow/deprecated/messageappend.pd
@@ -0,0 +1,12 @@
+#N canvas 720 260 450 300 10;
+#X obj 23 16 inlet;
+#X obj 23 73 outlet;
+#X obj 95 16 inlet;
+#X obj 23 35 list append;
+#X obj 23 54 list trim;
+#X obj 134 35 args *;
+#X connect 0 0 3 0;
+#X connect 2 0 3 1;
+#X connect 3 0 4 0;
+#X connect 4 0 1 0;
+#X connect 5 0 3 1;
diff --git a/externals/gridflow/deprecated/messageprepend.pd b/externals/gridflow/deprecated/messageprepend.pd
new file mode 100644
index 00000000..addb7801
--- /dev/null
+++ b/externals/gridflow/deprecated/messageprepend.pd
@@ -0,0 +1,12 @@
+#N canvas 770 352 450 300 10;
+#X obj 23 16 inlet;
+#X obj 23 73 outlet;
+#X obj 23 35 list prepend;
+#X obj 102 16 inlet;
+#X obj 23 54 list trim;
+#X obj 141 35 args *;
+#X connect 0 0 2 0;
+#X connect 2 0 4 0;
+#X connect 3 0 2 1;
+#X connect 4 0 1 0;
+#X connect 5 0 2 1;
diff --git a/externals/gridflow/doc/Makefile b/externals/gridflow/doc/Makefile
new file mode 100644
index 00000000..865d34e7
--- /dev/null
+++ b/externals/gridflow/doc/Makefile
@@ -0,0 +1,7 @@
+all:: index.pd numop.pd numtype.pd
+
+index.pd: make_index.tcl locale/english.tcl
+ tclsh make_index.tcl > index.pd
+
+numop.pd numtype.pd: moulinette.tcl
+ tclsh moulinette.tcl
diff --git a/externals/gridflow/doc/about.pd b/externals/gridflow/doc/about.pd
new file mode 100644
index 00000000..6ebb5ad4
--- /dev/null
+++ b/externals/gridflow/doc/about.pd
@@ -0,0 +1,31 @@
+#N canvas 0 0 627 494 10;
+#X obj 0 453 doc_f;
+#N canvas 0 0 743 313 (subpatch) 0;
+#X obj 3 3 cnv 15 608 18 empty \$0-rect empty 2 9 1 13 -1 -262144 0
+;
+#X obj 511 3 cnv 15 100 18 empty \$0-rect2 GridFlow 1.0 2 9 1 12
+-1 -262144 0;
+#X coords 0 -1 1 1 614 24 1 0 0;
+#X restore 0 9 pd;
+#X text 96 280 Development of GridFlow 0.3.0 - 0.5.0 was made possible
+in part by a grant from the HRDC (DRHC) to Artengine.;
+#X text 96 311 Development of... much of GridFlow 0.8.x and 0.9.0 was
+made possible in part by a grant from the CSHRC.;
+#X text 96 371 Development of GridFlow 0.9.0 was made possible in part
+by Alexandre Castonguay's cooking.;
+#X text 96 260 GridFlow is sponsored by Artengine.;
+#X text 96 73 C++ Programming : Mathieu Bouchard;
+#X text 96 100 Pd Programming (abstractions) : Mathieu Bouchard;
+#X text 96 160 Pd Help Files (former ones) and Tutorials : Darsha Hewitt
+\, Stephanie Brodeur \, Alexandre Castonguay;
+#X text 96 130 Pd Help Files (current ones) : Mathieu Bouchard \, Patrick
+Boivin;
+#X text 19 47 Credits;
+#X text 16 231 Sponsors;
+#X text 96 195 OSX porting : Mathieu Bouchard \, James Tittle \, Adam
+Lindsay \, Patrick Boivin \, and others.;
+#X text 96 341 Development of [#from_pix] and [#to_pix] was sponsored
+by Videographe PARC;
+#X text 96 400 Development of GridFlow 0.9.3 and later has used Videographe
+as a meeting place. Since 0.9.6 \, the room is called Departement de
+Diagrammologie Algorithmique.;
diff --git a/externals/gridflow/doc/find_missing.rb b/externals/gridflow/doc/find_missing.rb
new file mode 100644
index 00000000..5ac44da0
--- /dev/null
+++ b/externals/gridflow/doc/find_missing.rb
@@ -0,0 +1,40 @@
+#!/usr/bin/env ruby
+
+a=[]
+`grep -nriw install ../src/*.[ch]xx ../src/*.m`.each {|line|
+ m=/install\(\"([^"]+)/.match(line)
+ a<<m[1] if m
+}
+
+b=Dir["../abstractions/*.pd"].map{|x|
+ x.gsub(/^\.\.\/abstractions\//,"").gsub(/\.pd$/,"")
+}
+
+c = Dir["flow_classes/*-help.pd" ].map{|x| x.gsub(/^flow_classes\//,"").gsub(/-help\.pd$/,"") }
+c.concat Dir["flow_classes/cv/*-help.pd"].map{|x| x.gsub(/^flow_classes\//,"").gsub(/-help\.pd$/,"") }
+ab=a+b
+
+d=[]
+File.open("index.pd") {|f|
+ f.each {|line|
+ m=/obj \d+ \d+ ([^ ;]+)/.match(line)
+ d<<m[1] if m
+ }
+}
+
+puts "missing from help files: "
+puts (ab-c).sort.join" "
+puts (ab-c).size
+puts ""
+
+puts "orphan help files:"
+puts (c-ab).sort.join" "
+puts ""
+
+puts "missing from index:"
+puts (ab-d).sort.join" "
+puts (ab-d).size
+puts ""
+
+puts "orphan index entries: "
+puts (d-ab).sort.join" "
diff --git a/externals/gridflow/doc/flow_classes/#-help.pd b/externals/gridflow/doc/flow_classes/#-help.pd
new file mode 100644
index 00000000..8a546e31
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#-help.pd
@@ -0,0 +1,55 @@
+#N canvas 648 0 632 642 10;
+#X obj 139 174 #color;
+#X obj 314 174 #color;
+#X text 245 135 select values below;
+#X text 138 155 A;
+#X text 313 155 B;
+#X obj 139 240 # +;
+#X obj 178 274 #color;
+#X obj 140 380 display;
+#X obj 139 274 t a a;
+#X text 152 342 warning: #color clips value to the 0..255 range;
+#X text 152 357 so use this [display] to view the true numbers;
+#X text 54 81 click on this object to select a numop to try out:;
+#X text 55 64 # applies a simple Numeric Operator (numop).;
+#X obj 94 120 doc/numop;
+#X obj 0 0 doc_h;
+#X obj 14 439 doc_cc 0;
+#X obj 3 409 doc_c 1..2;
+#X obj 3 534 doc_i 2;
+#X obj 14 564 doc_ii 0;
+#X obj 14 735 doc_oo 0;
+#X obj 14 461 doc_cc 1;
+#X obj 14 673 doc_ii 1;
+#X obj 3 705 doc_o 1;
+#X obj 97 439 doc_m c0 numop;
+#X obj 97 463 doc_m c1 grid;
+#X obj 97 564 doc_m i0 grid;
+#X obj 97 673 doc_m i1 grid;
+#X obj 97 651 doc_m i0 numop;
+#X text 232 564 on each element of this grid \, perform the operation
+together with the corresponding element of inlet 1 in the table of
+operators (at the top of this document)elements of inlet 0 are called
+"A" and elements of inlet 1are called "B". the resulting grid is the
+same size as theone in inlet 0;
+#X text 232 439 pick a way to combine the numbers. (see the numop table)
+;
+#X text 232 673 same as arg 1;
+#X text 232 651 same as arg 0;
+#X obj 97 735 doc_m o0 grid;
+#X text 232 463 any grid \, preferably shaped like the one that will
+be put in the left inlet \, or like a subpart of it (anyway the contents
+will be redim'ed on-the-fly to fit the grid of inlet-0 \, but the stored
+grid will not be modified itself);
+#X obj 0 765 doc_f;
+#X connect 0 0 5 0;
+#X connect 1 0 5 1;
+#X connect 5 0 8 0;
+#X connect 8 0 7 0;
+#X connect 8 1 6 0;
+#X connect 13 0 5 0;
+#X connect 23 1 29 0;
+#X connect 24 1 33 0;
+#X connect 25 1 28 0;
+#X connect 26 1 30 0;
+#X connect 27 1 31 0;
diff --git a/externals/gridflow/doc/flow_classes/#apply_colormap_channelwise-help.pd b/externals/gridflow/doc/flow_classes/#apply_colormap_channelwise-help.pd
new file mode 100644
index 00000000..61c29ebf
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#apply_colormap_channelwise-help.pd
@@ -0,0 +1,55 @@
+#N canvas 651 0 632 598 10;
+#X obj 25 293 #in;
+#X obj 25 342 #out window;
+#X text 232 537 Outputs the modified data as a grid.;
+#X text 12 27 This object is useful for color correction. for each
+pixel it takes it apart \, looks up each part separately in the colormap
+and constructs a new pixel from that.;
+#X obj 213 235 #for 0 256 1;
+#X obj 213 305 #outer gamma;
+#X msg 25 267 load bluemarble.jpg;
+#X obj 25 248 t b b;
+#X obj 289 261 #color 0 1024 1;
+#X msg 354 209 1024 512 256;
+#X obj 354 190 loadbang;
+#X obj 25 323 #apply_colormap_channelwise;
+#X obj 25 219 metro 100;
+#X obj 25 202 tgl 15 0 empty empty empty 0 -6 0 8 -24198 -1 -1 0 1
+;
+#X text 357 244 vary this:;
+#X obj 0 0 doc_h;
+#X obj 3 383 doc_c 0;
+#X obj 3 423 doc_i 2;
+#X obj 3 507 doc_o 1;
+#X obj 14 453 doc_ii 0;
+#X obj 14 475 doc_ii 1;
+#X obj 14 537 doc_oo 0;
+#X obj 97 453 doc_m i0 grid;
+#X text 12 70 currently works only with 3 channels at a time!;
+#X text 15 89 it also works on non-images \, for example on colormaps
+themselves \, but the last dimension must be channels \, and there
+must be three channels.;
+#X text 14 136 Note: if you just need to apply a palette on an indexed-color
+picture or greyscale picture \, you don't need this. Just use #store
+instead.;
+#X obj 0 569 doc_f;
+#X text 232 453 grid that will be modified by the colormap;
+#X text 232 475 Colormap (aka palette) is a grid[intensity \, channels]
+;
+#X obj 97 475 doc_m i1 grid;
+#X obj 97 537 doc_m o0 grid;
+#X connect 0 0 11 0;
+#X connect 4 0 5 0;
+#X connect 5 0 11 1;
+#X connect 6 0 0 0;
+#X connect 7 0 6 0;
+#X connect 7 1 4 0;
+#X connect 8 0 5 1;
+#X connect 9 0 8 0;
+#X connect 10 0 9 0;
+#X connect 11 0 1 0;
+#X connect 12 0 7 0;
+#X connect 13 0 12 0;
+#X connect 22 1 27 0;
+#X connect 29 1 28 0;
+#X connect 30 1 2 0;
diff --git a/externals/gridflow/doc/flow_classes/#background_model-help.pd b/externals/gridflow/doc/flow_classes/#background_model-help.pd
new file mode 100644
index 00000000..04cc2648
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#background_model-help.pd
@@ -0,0 +1,90 @@
+#N canvas 327 0 632 642 10;
+#X obj 58 86 #camera;
+#X obj 58 50 tgl 15 0 empty empty empty 0 -6 0 8 -24198 -1 -1 0 1;
+#X obj 194 115 tgl 15 0 empty empty binaryFlag 0 -6 0 8 -24198 -1 -1
+0 1;
+#X obj 126 96 tgl 15 0 empty empty addBackground 0 -6 0 8 -24198 -1
+-1 0 1;
+#X obj 266 105 hsl 128 15 0 700 0 0 empty empty outputThreshold -2
+-6 0 8 -260818 -1 -1 0 1;
+#X obj 41 86 bng 15 250 50 0 empty empty empty 0 -6 0 8 -24198 -1 -1
+;
+#X obj 58 286 #greyscale_to_rgb;
+#X text 72 224 Arguments : size of buffer \, columns \, rows \, channel
+;
+#X text 70 242 <-- output is a greyscale image;
+#X obj 58 305 #out window \, title backgroundModel;
+#X obj 58 324 fps detailed;
+#X obj 58 343 print;
+#X obj 146 198 #out window \, title variance;
+#X obj 235 160 #out window \, title Mean;
+#X obj 146 160 # << 2;
+#X obj 146 179 #clip;
+#X floatatom 280 128 5 0 0 0 - - -;
+#X obj 58 267 #clip;
+#X obj 58 67 metro 33.33;
+#X obj 58 141 #background_model 20 120 160 3;
+#X obj 14 658 doc_oo 0;
+#X obj 14 680 doc_oo 1;
+#X obj 14 702 doc_oo 2;
+#X obj 14 532 doc_ii 0;
+#X obj 14 552 doc_ii 1;
+#X obj 14 574 doc_ii 2;
+#X obj 14 596 doc_ii 3;
+#X obj 14 404 doc_cc 0;
+#X obj 14 426 doc_cc 1;
+#X obj 14 448 doc_cc 2;
+#X obj 14 470 doc_cc 3;
+#X text 232 552 addBackground;
+#X text 232 574 binary_flag;
+#X text 232 596 output_threshold;
+#X text 232 404 frames;
+#X text 232 426 height;
+#X text 232 448 width;
+#X text 232 470 channels;
+#X text 232 680 variance;
+#X text 232 702 mean;
+#X text 232 658 greyscale image;
+#X obj 0 0 doc_h;
+#X obj 0 734 doc_f;
+#X obj 3 374 doc_c 4;
+#X obj 3 502 doc_i 4;
+#X obj 3 628 doc_o 3;
+#X obj 97 596 doc_m i3;
+#X obj 97 404 doc_m c0 float;
+#X obj 97 426 doc_m c1 float;
+#X obj 97 448 doc_m c2 float;
+#X obj 97 470 doc_m c3 float;
+#X obj 97 552 doc_m i1 grid;
+#X obj 97 532 doc_m i0 grid;
+#X obj 97 574 doc_m i2 float bool;
+#X obj 97 658 doc_m o0 grid;
+#X obj 97 680 doc_m o1 grid;
+#X obj 97 702 doc_m o2 grid;
+#X connect 0 0 19 0;
+#X connect 1 0 18 0;
+#X connect 2 0 19 2;
+#X connect 3 0 19 1;
+#X connect 4 0 16 0;
+#X connect 4 0 19 3;
+#X connect 5 0 0 0;
+#X connect 6 0 9 0;
+#X connect 9 0 10 0;
+#X connect 10 0 11 0;
+#X connect 14 0 15 0;
+#X connect 15 0 12 0;
+#X connect 17 0 6 0;
+#X connect 18 0 0 0;
+#X connect 19 0 17 0;
+#X connect 19 1 14 0;
+#X connect 19 2 13 0;
+#X connect 46 1 33 0;
+#X connect 47 1 34 0;
+#X connect 48 1 35 0;
+#X connect 49 1 36 0;
+#X connect 50 1 37 0;
+#X connect 51 1 31 0;
+#X connect 53 1 32 0;
+#X connect 54 1 40 0;
+#X connect 55 1 38 0;
+#X connect 56 1 39 0;
diff --git a/externals/gridflow/doc/flow_classes/#border-help.pd b/externals/gridflow/doc/flow_classes/#border-help.pd
new file mode 100644
index 00000000..5486c419
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#border-help.pd
@@ -0,0 +1,44 @@
+#N canvas 597 51 632 499 10;
+#X obj 20 84 #in;
+#X obj 20 127 #out window;
+#X text 15 28 Creates a black border around an image.;
+#X msg 20 62 load working.jpg;
+#X text 232 206 top padding and left padding. defaults to (1 1 0).
+;
+#X text 232 228 bottom and right padding. defaults to (1 1 0).;
+#X obj 20 105 #border (5 10 0) (15 20 0);
+#X text 209 98 5 at the top;
+#X text 208 112 10 at the left;
+#X text 208 126 15 at the bottom;
+#X text 208 139 20 at the right;
+#X text 114 255 both arguments must have 3 elements. The third element
+is reserved for future use.;
+#X text 232 425 The original image surrounded by zero padding \, which
+usually means black pixels.;
+#X obj 14 425 doc_oo 0;
+#X obj 14 321 doc_ii 0;
+#X obj 14 341 doc_ii 1;
+#X obj 14 363 doc_ii 2;
+#X obj 14 206 doc_cc 0;
+#X obj 14 228 doc_cc 1;
+#X text 232 341 same as arg 0;
+#X text 232 363 same as arg 1;
+#X obj 0 0 doc_h;
+#X obj 0 470 doc_f;
+#X obj 3 176 doc_c 2;
+#X obj 3 291 doc_i 3;
+#X obj 3 395 doc_o 1;
+#X obj 97 206 doc_m c0 grid[3];
+#X obj 97 228 doc_m c1 grid[3];
+#X obj 97 321 doc_m i0 grid;
+#X obj 97 341 doc_m i1 list;
+#X obj 97 363 doc_m i2 list;
+#X obj 97 425 doc_m o0 grid;
+#X connect 0 0 6 0;
+#X connect 3 0 0 0;
+#X connect 6 0 1 0;
+#X connect 26 1 4 0;
+#X connect 27 1 5 0;
+#X connect 29 1 19 0;
+#X connect 30 1 20 0;
+#X connect 31 1 12 0;
diff --git a/externals/gridflow/doc/flow_classes/#camera-help.pd b/externals/gridflow/doc/flow_classes/#camera-help.pd
new file mode 100644
index 00000000..403f396f
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#camera-help.pd
@@ -0,0 +1,49 @@
+#N canvas 679 40 632 557 10;
+#X obj 86 164 #out window;
+#X obj 60 45 bng 15 250 50 0 empty empty empty 0 -6 0 8 -24198 -1 -1
+;
+#X obj 86 45 tgl 15 0 empty empty empty 0 -6 0 8 -24198 -1 -1 0 1;
+#X obj 86 183 fps detailed;
+#X obj 86 202 print;
+#X obj 86 71 metro 20;
+#X text 232 496 Returns a grid from the video capture device for every
+bang.;
+#X obj 86 145 #scale_by;
+#X text 151 111 <-- open the abstraction and configure for your camera
+before sending it a bang.;
+#X obj 86 112 #camera;
+#X obj 14 496 doc_oo 0;
+#X obj 14 399 doc_ii 0;
+#X obj 14 271 doc_cc 0;
+#X text 232 399 same as arg 0;
+#X text 232 421 same as the class of the camera object being used inside:
+see #io.videodev-help.pd for a LONG list of options;
+#X text 232 293 8: a linux device using the DC-1394 interface;
+#X text 232 315 9: an OSX device using the QuickTime camera interface
+;
+#X text 232 271 0..7: a linux device using the V4L1 interface (videodev.h)
+;
+#X text 232 337 -1: none;
+#X obj 0 0 doc_h;
+#X obj 0 528 doc_f;
+#X obj 3 241 doc_c 1;
+#X obj 3 369 doc_i 1;
+#X obj 3 466 doc_o 1;
+#X obj 97 271 doc_m c0 float/int;
+#X obj 97 496 doc_m o0 grid;
+#X obj 97 399 doc_m i0 device;
+#X obj 97 421 doc_m i0 <any>;
+#X connect 0 0 3 0;
+#X connect 1 0 9 0;
+#X connect 2 0 5 0;
+#X connect 3 0 4 0;
+#X connect 5 0 9 0;
+#X connect 7 0 0 0;
+#X connect 9 0 7 0;
+#X connect 24 1 15 0;
+#X connect 24 1 16 0;
+#X connect 24 1 17 0;
+#X connect 24 1 18 0;
+#X connect 25 1 6 0;
+#X connect 26 1 13 0;
+#X connect 27 1 14 0;
diff --git a/externals/gridflow/doc/flow_classes/#cast-help.pd b/externals/gridflow/doc/flow_classes/#cast-help.pd
new file mode 100644
index 00000000..970a7647
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#cast-help.pd
@@ -0,0 +1,67 @@
+#N canvas 646 0 632 564 10;
+#X obj 14 219 #print;
+#X obj 14 199 #cast float64;
+#X obj 269 218 #print;
+#X obj 126 218 #print;
+#X obj 269 198 #cast uint8;
+#X obj 126 198 #cast int32;
+#X floatatom 14 181 5 0 0 0 - - -;
+#X msg 126 177 9.8764 9 -32 0.3;
+#X obj 269 158 bng 15 250 50 0 empty empty empty 0 -6 0 8 -24198 -1
+-1;
+#X obj 306 79 nbx 8 14 -1e+37 1e+37 0 1 empty empty empty 0 -6 0 10
+-262144 -1 -1 2.1416 256;
+#X obj 356 96 nbx 8 14 -1e+37 1e+37 0 1 empty empty empty 0 -6 0 10
+-262144 -1 -1 45 256;
+#X obj 269 177 #store;
+#X obj 306 133 #pack 3 float32;
+#X obj 14 161 bng 15 250 50 0 empty empty empty 0 -6 0 8 -24198 -1
+-1;
+#X obj 126 157 bng 15 250 50 0 empty empty empty 0 -6 0 8 -24198 -1
+-1;
+#X text 12 26 Changes an entity of one data type into another. Returns
+a grid of the same dimensions containing all the same values after
+type conversion. While casting to a smaller type \, overflowing values
+will be truncated.;
+#X obj 406 113 nbx 8 14 -1e+37 1e+37 0 1 empty empty empty 0 -6 0 10
+-262144 -1 -1 45 256;
+#X text 232 358 Any grid;
+#X obj 14 420 doc_oo 0;
+#X obj 14 358 doc_ii 0;
+#X obj 14 283 doc_cc 0;
+#X text 232 420 Produces a grid of the same dimensions containing all
+the same values after type conversion.;
+#X text 232 455 conversion from float truncates fractional part (rounds
+towards zero);
+#X text 232 490 conversion to an int type may wrap (same as some #
+& or some # %);
+#X text 232 283 Number types are: uint8 \, int16 \, int32 \, int64
+\, float32 \, float64. see doc/numtype.pd for more info.;
+#X obj 306 154 #redim (2 2);
+#X obj 0 0 doc_h;
+#X obj 0 535 doc_f;
+#X obj 3 253 doc_c 1;
+#X obj 3 328 doc_i 1;
+#X obj 3 390 doc_o 1;
+#X obj 97 283 doc_m c0 symbol/numbertype;
+#X obj 97 358 doc_m i0 grid;
+#X obj 97 420 doc_m o0 grid;
+#X connect 1 0 0 0;
+#X connect 4 0 2 0;
+#X connect 5 0 3 0;
+#X connect 6 0 1 0;
+#X connect 7 0 5 0;
+#X connect 8 0 11 0;
+#X connect 9 0 12 0;
+#X connect 10 0 12 1;
+#X connect 11 0 4 0;
+#X connect 12 0 25 0;
+#X connect 13 0 6 0;
+#X connect 14 0 7 0;
+#X connect 16 0 12 2;
+#X connect 25 0 11 1;
+#X connect 31 1 24 0;
+#X connect 32 1 17 0;
+#X connect 33 1 21 0;
+#X connect 33 1 22 0;
+#X connect 33 1 23 0;
diff --git a/externals/gridflow/doc/flow_classes/#centroid-help.pd b/externals/gridflow/doc/flow_classes/#centroid-help.pd
new file mode 100644
index 00000000..81a8718f
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#centroid-help.pd
@@ -0,0 +1,29 @@
+#N canvas 669 0 632 376 10;
+#X obj 43 44 #centroid;
+#X obj 14 163 doc_ii 0;
+#X obj 14 251 doc_oo 0;
+#X obj 14 273 doc_oo 1;
+#X obj 14 295 doc_oo 2;
+#X text 232 163 will compute the centroid of the given grid \, which
+is a weighted average \, namely \, the average position weighted by
+the pixel values.;
+#X text 138 41 obsolete. please use [#moment] instead.;
+#X obj 3 327 doc_also;
+#X obj 103 327 #moment;
+#X text 232 251 (y x);
+#X text 232 273 y;
+#X text 232 295 x;
+#X obj 0 0 doc_h;
+#X obj 0 347 doc_f;
+#X obj 3 93 doc_c;
+#X obj 3 133 doc_i 1;
+#X obj 3 221 doc_o 3;
+#X obj 97 163 doc_m i0;
+#X obj 97 251 doc_m o0 grid;
+#X obj 97 295 doc_m o2 float;
+#X obj 97 273 doc_m o1 float;
+#X connect 7 1 8 0;
+#X connect 17 1 5 0;
+#X connect 18 1 9 0;
+#X connect 19 1 11 0;
+#X connect 20 1 10 0;
diff --git a/externals/gridflow/doc/flow_classes/#change-help.pd b/externals/gridflow/doc/flow_classes/#change-help.pd
new file mode 100644
index 00000000..cbef68ef
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#change-help.pd
@@ -0,0 +1,35 @@
+#N canvas 646 85 632 417 10;
+#X obj 38 95 #change;
+#X text 234 116 should be to [change] what GridFlow is to PureData.
+;
+#X obj 14 278 doc_ii 0;
+#X obj 14 338 doc_oo 0;
+#X obj 14 218 doc_cc 0;
+#X obj 3 368 doc_also;
+#X obj 103 368 change;
+#X obj 38 137 print;
+#X obj 44 118 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
+-1;
+#X obj 38 76 #pack;
+#X floatatom 72 58 5 0 0 0 - - -;
+#X floatatom 38 58 5 0 0 0 - - -;
+#X obj 72 41 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
+-1;
+#X obj 38 41 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
+-1;
+#X obj 0 0 doc_h;
+#X obj 0 388 doc_f;
+#X obj 3 188 doc_c 0..1;
+#X obj 3 248 doc_i 1;
+#X obj 3 308 doc_o 1;
+#X obj 97 218 doc_m c0 grid;
+#X obj 97 338 doc_m o0 grid;
+#X obj 97 278 doc_m i0 grid;
+#X connect 0 0 8 0;
+#X connect 0 0 7 0;
+#X connect 5 1 6 0;
+#X connect 9 0 0 0;
+#X connect 10 0 9 1;
+#X connect 11 0 9 0;
+#X connect 12 0 10 0;
+#X connect 13 0 11 0;
diff --git a/externals/gridflow/doc/flow_classes/#checkers-help.pd b/externals/gridflow/doc/flow_classes/#checkers-help.pd
new file mode 100644
index 00000000..1c737f08
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#checkers-help.pd
@@ -0,0 +1,26 @@
+#N canvas 692 0 632 404 10;
+#X obj 171 66 bng 15 250 50 0 empty empty empty 0 -6 0 8 -24198 -1
+-1;
+#X obj 171 135 #out window \, title checkers;
+#X obj 171 112 #checkers;
+#X text 232 330 Results in a checkered pattern of 50% / 75% greys in
+8 X 8 squares.;
+#X text 11 29 Displays a grid with a pattern of checkered squares.
+;
+#X obj 14 330 doc_oo 0;
+#X obj 14 256 doc_ii 0;
+#X obj 171 88 #for (0 0) (128 128) (1 1);
+#X text 232 256 typically the output of [#for (0 0) (height width)
+(1 1)];
+#X obj 0 0 doc_h;
+#X obj 0 375 doc_f;
+#X obj 3 186 doc_c 0;
+#X obj 3 226 doc_i 1;
+#X obj 3 300 doc_o 1;
+#X obj 97 256 doc_m i0 grid;
+#X obj 97 330 doc_m o0 grid;
+#X connect 0 0 7 0;
+#X connect 2 0 1 0;
+#X connect 7 0 2 0;
+#X connect 14 1 8 0;
+#X connect 15 1 3 0;
diff --git a/externals/gridflow/doc/flow_classes/#clip-help.pd b/externals/gridflow/doc/flow_classes/#clip-help.pd
new file mode 100644
index 00000000..9e494b44
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#clip-help.pd
@@ -0,0 +1,70 @@
+#N canvas 673 6 632 610 10;
+#X obj 51 163 #in;
+#X obj 51 189 # + 42;
+#X floatatom 88 166 5 0 0 0 - - -;
+#X obj 51 270 #out window;
+#X obj 51 114 t b b;
+#X obj 51 90 metro 100;
+#X obj 51 68 tgl 15 0 empty empty empty 0 -6 0 8 -24198 -1 -1 0 1;
+#X floatatom 127 211 5 0 0 0 - - -;
+#X floatatom 87 211 5 0 0 0 - - -;
+#X text 6 25 The [#clip] object is used with numops in order to set
+a lower and upper range to pixel values. This allows you to avoid over
+saturating the colours of your grid.;
+#X text 133 165 <-- vary this number;
+#X msg 81 138 open working.jpg;
+#X text 232 410 Grid values are clipped to the high and low values
+stored in the object;
+#X text 232 529 Outputs the modified grid;
+#X obj 103 561 # min;
+#X obj 145 561 # max;
+#X obj 187 561 clip;
+#X text 223 561 #numop-help.pd;
+#X text 319 561 gf_tutorial_image_6.pd;
+#X obj 51 240 #clip 0 255;
+#X text 139 231 <--if no creation argument is given the default range
+is 0-255.;
+#X obj 3 561 doc_also;
+#X obj 14 410 doc_ii 0;
+#X obj 14 445 doc_ii 1;
+#X obj 14 467 doc_ii 2;
+#X obj 14 529 doc_oo 0;
+#X obj 14 326 doc_cc 0;
+#X obj 14 348 doc_cc 1;
+#X text 232 445 same as arg 0;
+#X text 232 467 same as arg 1;
+#X text 232 326 minimum value (like [# max]);
+#X text 232 348 maximum value (like [# min]);
+#X obj 0 0 doc_h;
+#X obj 0 581 doc_f;
+#X obj 3 296 doc_c 2;
+#X obj 3 380 doc_i 3;
+#X obj 3 499 doc_o 1;
+#X obj 97 410 doc_m i0 grid;
+#X obj 97 445 doc_m i1 float int;
+#X obj 97 467 doc_m i2 float int;
+#X obj 97 529 doc_m o0 grid;
+#X obj 97 326 doc_m c0;
+#X obj 97 348 doc_m c1;
+#X connect 0 0 1 0;
+#X connect 1 0 19 0;
+#X connect 2 0 1 1;
+#X connect 4 0 0 0;
+#X connect 4 1 11 0;
+#X connect 5 0 4 0;
+#X connect 6 0 5 0;
+#X connect 7 0 19 2;
+#X connect 8 0 19 1;
+#X connect 11 0 0 0;
+#X connect 19 0 3 0;
+#X connect 21 1 14 0;
+#X connect 21 1 15 0;
+#X connect 21 1 16 0;
+#X connect 21 1 17 0;
+#X connect 21 1 18 0;
+#X connect 37 1 12 0;
+#X connect 38 1 28 0;
+#X connect 39 1 29 0;
+#X connect 40 1 13 0;
+#X connect 41 1 30 0;
+#X connect 42 1 31 0;
diff --git a/externals/gridflow/doc/flow_classes/#cluster_avg-help.pd b/externals/gridflow/doc/flow_classes/#cluster_avg-help.pd
new file mode 100644
index 00000000..50e844a0
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#cluster_avg-help.pd
@@ -0,0 +1,22 @@
+#N canvas 615 299 632 303 10;
+#X obj 14 60 doc_cc 0;
+#X obj 14 120 doc_ii 0;
+#X text 232 242 counts;
+#X text 232 220 sums;
+#X obj 14 140 doc_ii 1;
+#X obj 14 160 doc_ii 2;
+#X obj 14 220 doc_oo 0;
+#X obj 14 242 doc_oo 1;
+#X obj 0 0 doc_h;
+#X obj 0 274 doc_f;
+#X obj 3 30 doc_c 1;
+#X obj 3 90 doc_i 3;
+#X obj 3 190 doc_o 2;
+#X obj 97 160 doc_m i2 grid;
+#X obj 97 60 doc_m c0 int;
+#X obj 97 220 doc_m o0 grid;
+#X obj 97 242 doc_m o1 grid;
+#X obj 97 140 doc_m i1 float int;
+#X obj 97 120 doc_m i0 grid i;
+#X connect 15 1 3 0;
+#X connect 16 1 2 0;
diff --git a/externals/gridflow/doc/flow_classes/#color-help.pd b/externals/gridflow/doc/flow_classes/#color-help.pd
new file mode 100644
index 00000000..2fd0b3b7
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#color-help.pd
@@ -0,0 +1,44 @@
+#N canvas 653 126 632 519 10;
+#X obj 126 114 #color;
+#X text 308 126 <-- vary these;
+#X text 10 27 The [#color] object contains a triple slider for RGB
+value selection on each channel.;
+#X text 198 68 <-- click here;
+#X msg 126 68 255 0 204;
+#X msg 317 79 delegate steady 0;
+#X text 103 470 [hsl];
+#X obj 3 470 doc_also;
+#X text 232 253 whether to remove the color preview;
+#X text 232 209 lower bound;
+#X text 232 231 upper bound;
+#X obj 14 425 doc_oo 0;
+#X obj 14 315 doc_ii 0;
+#X obj 14 209 doc_cc 0;
+#X obj 14 231 doc_cc 1;
+#X obj 14 253 doc_cc 2;
+#X text 232 350 sends the rest of the message as a message to each
+of the sliders but not each of the numboxes.;
+#X text 232 315 replaces the current colour value inside [#color] \,
+including sliders and numboxes.;
+#X text 232 425 of size (3) representing a rgb colour or any other
+rgb-related settings you want to control with [#color].;
+#X obj 0 0 doc_h;
+#X obj 0 490 doc_f;
+#X obj 3 179 doc_c 3;
+#X obj 3 285 doc_i 1;
+#X obj 3 395 doc_o 1;
+#X obj 97 209 doc_m c0 float;
+#X obj 97 231 doc_m c1 float;
+#X obj 97 253 doc_m c2 bool;
+#X obj 97 315 doc_m i0 grid;
+#X obj 97 350 doc_m i0 delegate;
+#X obj 97 425 doc_m o0 grid;
+#X connect 4 0 0 0;
+#X connect 5 0 0 0;
+#X connect 7 1 6 0;
+#X connect 24 1 9 0;
+#X connect 25 1 10 0;
+#X connect 26 1 8 0;
+#X connect 27 1 17 0;
+#X connect 28 1 16 0;
+#X connect 29 1 18 0;
diff --git a/externals/gridflow/doc/flow_classes/#contrast-help.pd b/externals/gridflow/doc/flow_classes/#contrast-help.pd
new file mode 100644
index 00000000..7136bd29
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#contrast-help.pd
@@ -0,0 +1,72 @@
+#N canvas 678 0 632 613 10;
+#X obj 77 88 bng 15 250 50 0 empty empty empty 0 -6 0 8 -24198 -1 -1
+;
+#X obj 97 136 metro 100;
+#X obj 97 115 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1
+;
+#X obj 222 134 hsl 128 15 0 256 0 0 empty empty empty -2 -6 0 8 -262144
+-1 -1 0 1;
+#X obj 371 135 hsl 128 15 0 256 0 0 empty empty empty -2 -6 0 8 -262144
+-1 -1 0 1;
+#X floatatom 219 154 5 0 0 0 - - -;
+#X floatatom 368 157 5 0 0 0 - - -;
+#X msg 59 65 open bluemarble.jpg;
+#X obj 190 214 #out window;
+#X obj 59 162 #in;
+#X text 8 28 Adjusts the intensity of an image.;
+#X obj 190 189 #contrast;
+#X text 232 327 This value corresponds to the master contrast \, it
+varies the amount of incoming white. The default value is 256 and it
+has no effect.;
+#X text 232 279 This value corresponds to the secondary contrast (inverse
+whiteness) \, it varies the amount of incoming black into the image.
+The default value is 256 and it has no effect.;
+#X obj 103 564 #convolve;
+#X obj 169 564 #posterize;
+#X obj 241 564 #solarize;
+#X obj 307 564 #layer;
+#X text 366 118 contrast about black;
+#X text 216 118 contrast about white;
+#X obj 3 564 doc_also;
+#X obj 14 534 doc_oo 0;
+#X obj 14 415 doc_ii 0;
+#X obj 14 450 doc_ii 1;
+#X obj 14 472 doc_ii 2;
+#X text 232 415 produces a grid like the incoming grid but with different
+constrast.;
+#X text 7 42 resulting values outside 0-255 are automatically clipped.
+;
+#X obj 14 279 doc_cc 0;
+#X obj 14 327 doc_cc 1;
+#X text 232 450 same as arg 0;
+#X text 232 472 same as arg 1;
+#X obj 0 0 doc_h;
+#X obj 0 584 doc_f;
+#X obj 3 249 doc_c 0..2;
+#X obj 3 385 doc_i 3;
+#X obj 3 504 doc_o 1;
+#X obj 97 534 doc_m o0 grid;
+#X obj 97 415 doc_m i0 grid;
+#X obj 97 327 doc_m c1 grid;
+#X obj 97 279 doc_m c0 grid;
+#X obj 97 450 doc_m i1 grid;
+#X obj 97 472 doc_m i2 grid;
+#X connect 0 0 9 0;
+#X connect 1 0 9 0;
+#X connect 2 0 1 0;
+#X connect 3 0 5 0;
+#X connect 4 0 6 0;
+#X connect 5 0 11 1;
+#X connect 6 0 11 2;
+#X connect 7 0 9 0;
+#X connect 9 0 11 0;
+#X connect 11 0 8 0;
+#X connect 20 1 14 0;
+#X connect 20 1 15 0;
+#X connect 20 1 16 0;
+#X connect 20 1 17 0;
+#X connect 37 1 25 0;
+#X connect 38 1 12 0;
+#X connect 39 1 13 0;
+#X connect 40 1 29 0;
+#X connect 41 1 30 0;
diff --git a/externals/gridflow/doc/flow_classes/#convolve-help.pd b/externals/gridflow/doc/flow_classes/#convolve-help.pd
new file mode 100644
index 00000000..d644340d
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#convolve-help.pd
@@ -0,0 +1,67 @@
+#N canvas 678 0 632 642 10;
+#X obj 43 87 bng 15 250 50 0 empty empty empty 0 -6 0 8 -24198 -1 -1
+;
+#X msg 255 135 1 1 1 1 1 1 1 1 1;
+#X obj 255 113 loadbang;
+#X obj 255 157 #redim (3 3);
+#X obj 43 158 #in;
+#X obj 43 241 #out window;
+#X obj 103 723 #contrast;
+#X obj 169 723 #posterize;
+#X obj 241 723 #solarize;
+#X obj 307 723 #layer;
+#X obj 43 183 #convolve \, op ^ \, fold + \, seed 0;
+#X text 14 28 [#convolve] is used to perform various transformations
+on images such as blurring \, sharpening \, finding edges \, embossing
+\, cellular automata and many others.;
+#X text 232 316 This is the convolution grid and it gets stored in
+the other object. If rows2 and/or columns 2 are odd numbers \, then
+the centre of convolution is the middle of the convolution grid. If
+they are even numbers \, then the chosen centre will be slightly more
+to the left and/or to the top \, because the actual middle is between
+celle of the grid.;
+#X obj 3 723 doc_also;
+#X obj 14 691 doc_oo 0;
+#X obj 14 443 doc_ii 0;
+#X obj 14 629 doc_ii 1;
+#X text 155 216 here ^ is the parallel operator \, fold is indicated
+by + and 0 is its base (seed).;
+#X obj 14 316 doc_cc 0;
+#X text 232 691 Resulting image.;
+#X text 232 443 Splits the incoming grid into dim(rest...) parts \,
+for each of those parts at (y \, x). A rectangle of such parts \, centered
+around (y \, x) is combined with the convolution grid like a [#] of
+operation op_para. Then each such result is folded like [#fold] of
+operation op_fold and specified base. The results are assembled into
+a grid that is sent to the outlet. Near the borders of the grid \,
+coordinates wrap around. this means the whole grid has to be received
+before production of the next grid starts.;
+#X text 232 629 same as arg 0;
+#X msg 43 135 open scissors.jpg \, bang;
+#X obj 0 0 doc_h;
+#X obj 0 743 doc_f;
+#X obj 3 286 doc_c 0..1;
+#X obj 3 413 doc_i 2;
+#X obj 3 661 doc_o 1;
+#X obj 97 443 doc_m i0 grid;
+#X obj 97 629 doc_m i1 grid;
+#X obj 97 691 doc_m o0 grid;
+#X obj 97 589 doc_m i0 op numop;
+#X obj 97 569 doc_m i0 fold numop;
+#X obj 97 609 doc_m i0 seed grid;
+#X obj 97 316 doc_m c0 grid;
+#X connect 0 0 22 0;
+#X connect 1 0 3 0;
+#X connect 2 0 1 0;
+#X connect 3 0 10 1;
+#X connect 4 0 10 0;
+#X connect 10 0 5 0;
+#X connect 13 1 6 0;
+#X connect 13 1 7 0;
+#X connect 13 1 8 0;
+#X connect 13 1 9 0;
+#X connect 22 0 4 0;
+#X connect 28 1 20 0;
+#X connect 29 1 21 0;
+#X connect 30 1 19 0;
+#X connect 34 1 12 0;
diff --git a/externals/gridflow/doc/flow_classes/#dim-help.pd b/externals/gridflow/doc/flow_classes/#dim-help.pd
new file mode 100644
index 00000000..d86aaa70
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#dim-help.pd
@@ -0,0 +1,39 @@
+#N canvas 647 0 632 473 10;
+#X obj 22 178 print number_of_dimensions;
+#X obj 22 106 #in;
+#X obj 22 130 #dim;
+#X obj 22 154 #to_float;
+#X text 15 37 Outputs grid dimensions (columns \, row \, channels).
+;
+#X text 232 353 The received grid is output as a one dimensional grid
+representing grid dimensions. For example \, a grid sized like dim(240
+\, 320 \, 4) [#dim] will return a grid like dim(3) whose values are
+240 \, 320 \, 4;
+#X obj 3 323 doc_o 1;
+#X obj 103 424 #print;
+#X obj 151 424 #to_float;
+#X obj 217 424 #to_list;
+#X obj 3 424 doc_also;
+#X obj 14 278 doc_ii 0;
+#X obj 14 353 doc_oo 0;
+#X obj 97 278 doc_m i0 grid;
+#X obj 97 353 doc_m o0 grid;
+#X text 185 65 Returns list of dimensions as a grid. Given a grid sized
+like Dim(240 \, 320 \, 4) \, [#dim] will return a grid like Dim(3)
+\, whose values are 240 \, 320 \, 4 .;
+#X text 232 278 ignores any data contained within. sends a grid dim(length
+of dims) containing dims.;
+#X msg 22 66 load working.jpg;
+#X obj 0 0 doc_h;
+#X obj 0 444 doc_f;
+#X obj 3 208 doc_c;
+#X obj 3 248 doc_i 1;
+#X connect 1 0 2 0;
+#X connect 2 0 3 0;
+#X connect 3 0 0 0;
+#X connect 10 1 7 0;
+#X connect 10 1 8 0;
+#X connect 10 1 9 0;
+#X connect 13 1 16 0;
+#X connect 14 1 5 0;
+#X connect 17 0 1 0;
diff --git a/externals/gridflow/doc/flow_classes/#downscale_by-help.pd b/externals/gridflow/doc/flow_classes/#downscale_by-help.pd
new file mode 100644
index 00000000..14f427db
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#downscale_by-help.pd
@@ -0,0 +1,63 @@
+#N canvas 676 0 632 699 10;
+#X obj 181 115 metro 10;
+#X obj 181 96 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1
+;
+#X floatatom 251 130 5 0 0 0 - - -;
+#X obj 165 144 #in;
+#X msg 165 70 open bluemarble.jpg \, bang;
+#X floatatom 295 143 5 0 0 0 - - -;
+#X obj 251 162 #pack 2;
+#X obj 165 186 #downscale_by;
+#X obj 165 212 #out window;
+#X text 9 24 Scales down a picture by a specified amount.;
+#X obj 103 650 #scale_to;
+#X obj 169 650 #scale_by;
+#X obj 0 0 doc_h;
+#X obj 3 650 doc_also;
+#X obj 3 588 doc_o 1;
+#X obj 14 618 doc_oo 0;
+#X obj 3 491 doc_i 2;
+#X obj 14 521 doc_ii 0;
+#X obj 14 556 doc_ii 1;
+#X obj 14 280 doc_cc 0;
+#X obj 97 280 doc_m c0 grid;
+#X obj 3 250 doc_c 1..2;
+#X obj 97 521 doc_m i0 grid;
+#X text 232 280 The value defines the scale factor. A pack object allows
+you to vary the horizontal and vertical values idenpendently. In the
+example above \, inlet 0 of [#pack] varies the image on a vertical
+axis \, inlet 1 of [#pack] varies the image on a horizontal axis.;
+#X obj 97 556 doc_m i1 grid;
+#X text 232 556 same as arg 0;
+#X text 232 521 Scales down picture by specified amount. (See scale
+factor above);
+#X text 232 618 grid((factor/y) (factor/x) channels);
+#X text 232 354 factor is optional (default is 2).;
+#X obj 97 618 doc_m o0 grid;
+#X obj 14 411 doc_cc 1;
+#X obj 97 411 doc_m c1 symbol;
+#X text 232 411 "smoothly": does the downscale by averaging each block
+of pixels.;
+#X text 232 446 omitted: does the downscale by keeping only the top
+right pixel in the block.;
+#X obj 0 670 doc_f;
+#X text 232 376 if it's a single value \, then that factor is to be
+used for both rows and columns.;
+#X connect 0 0 3 0;
+#X connect 1 0 0 0;
+#X connect 2 0 6 0;
+#X connect 3 0 7 0;
+#X connect 4 0 3 0;
+#X connect 5 0 6 1;
+#X connect 6 0 7 1;
+#X connect 7 0 8 0;
+#X connect 13 1 10 0;
+#X connect 13 1 11 0;
+#X connect 20 1 23 0;
+#X connect 20 1 28 0;
+#X connect 20 1 35 0;
+#X connect 22 1 26 0;
+#X connect 24 1 25 0;
+#X connect 29 1 27 0;
+#X connect 31 1 32 0;
+#X connect 31 1 33 0;
diff --git a/externals/gridflow/doc/flow_classes/#draw_hpgl-help.pd b/externals/gridflow/doc/flow_classes/#draw_hpgl-help.pd
new file mode 100644
index 00000000..672e4689
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#draw_hpgl-help.pd
@@ -0,0 +1,35 @@
+#N canvas 576 129 632 396 10;
+#X obj 0 0 doc_h;
+#X obj 0 367 doc_f;
+#X obj 103 51 #draw_hpgl;
+#X obj 3 283 doc_o 2;
+#X obj 3 131 doc_i 5;
+#X obj 3 91 doc_c 0;
+#X obj 14 313 doc_oo 0;
+#X obj 14 335 doc_oo 1;
+#X obj 14 161 doc_ii 0;
+#X obj 14 183 doc_ii 1;
+#X obj 14 205 doc_ii 2;
+#X obj 14 227 doc_ii 3;
+#X obj 14 251 doc_ii 4;
+#X obj 97 227 doc_m i3 grid;
+#X obj 97 251 doc_m i4 grid;
+#X text 232 227 (x y) start;
+#X text 232 251 (x y) end;
+#X obj 97 161 doc_m i0 grid;
+#X obj 97 183 doc_m i1 grid;
+#X obj 97 205 doc_m i2 grid;
+#X text 232 161 image;
+#X text 232 183 color;
+#X text 232 205 command;
+#X obj 97 335 doc_m o1 bang;
+#X obj 97 313 doc_m o0 grid;
+#X text 232 335 time to draw;
+#X text 232 313 image drawn on;
+#X connect 13 1 15 0;
+#X connect 14 1 16 0;
+#X connect 17 1 20 0;
+#X connect 18 1 21 0;
+#X connect 19 1 22 0;
+#X connect 23 1 25 0;
+#X connect 24 1 26 0;
diff --git a/externals/gridflow/doc/flow_classes/#draw_image-help.pd b/externals/gridflow/doc/flow_classes/#draw_image-help.pd
new file mode 100644
index 00000000..a2fd7df4
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#draw_image-help.pd
@@ -0,0 +1,102 @@
+#N canvas 295 0 632 642 10;
+#X obj 172 147 #in;
+#X obj 135 181 #store;
+#X obj 135 46 tgl 15 0 empty empty empty 0 -6 0 8 -233017 -1 -1 0 1
+;
+#X obj 135 74 metro 40;
+#X obj 135 283 #out window \, title #draw_image-help;
+#X obj 172 99 bng 15 250 50 0 empty empty empty 0 -6 0 8 -233017 -1
+-1;
+#X obj 188 209 #in;
+#X obj 188 169 bng 15 250 50 0 empty empty empty 0 -6 0 8 -233017 -1
+-1;
+#X text 194 101 2 <-- open background image;
+#X text 211 171 1 <-- open foreground image;
+#X obj 387 238 #dim;
+#X obj 387 257 #to_list;
+#X obj 387 276 unpack f f;
+#X obj 393 295 pack f f;
+#X obj 393 314 # / 2;
+#X obj 368 314 # -;
+#X obj 135 307 #mouse;
+#X text 159 48 3 <-- activate rendering;
+#X msg 188 190 load g001.jpg;
+#X msg 172 120 load r001.jpg;
+#X msg 275 257 0 0;
+#X obj 275 238 loadbang;
+#X text 135 331 Move mouse cursor to change layer position;
+#X obj 0 0 doc_h;
+#X obj 3 455 doc_i 3;
+#X obj 3 775 doc_o 1;
+#X obj 14 805 doc_oo 0;
+#X obj 14 485 doc_ii 0;
+#X obj 14 708 doc_ii 1;
+#X obj 14 730 doc_ii 2;
+#X text 232 397 Normally \, you would use the "put" operator \; but
+others (like + and ^) can be interesting for color effects.;
+#X obj 135 258 #draw_image *>>8;
+#X obj 3 367 doc_c 1;
+#X obj 14 397 doc_cc 0;
+#X text 232 485 Background image.;
+#X msg 321 197 tile;
+#X text 232 708 Foreground image.;
+#X text 232 673 If 1 \, foreground image will be repeated to cover
+the background image.;
+#X text 232 529 If 1 \, foreground image (inlet 1) will be combined
+with background image (inlet 0) \, and then blended with background
+image according to transparency of foreground image \, and then inserted
+in the result. If 0 \, the blending doesn't occur \, as the transparency
+level is considered "opaque". Note that with alpha enabled \, the last
+channel of foreground image is cnsidered to represent transparency.
+;
+#X text 232 730 Initial foreground image position (y x) \, corresponding
+to top-left corner of foreground picture.;
+#X text 232 805 Resulting image.;
+#X obj 97 397 doc_m c0 numop;
+#X obj 97 485 doc_m i0 grid;
+#X obj 97 651 doc_m i0 tile;
+#X obj 97 507 doc_m i0 alpha;
+#X text 232 507 \$1=flag;
+#X text 232 651 \$1=flag;
+#X obj 97 708 doc_m i1 grid;
+#X obj 97 730 doc_m i2 (y x);
+#X obj 97 805 doc_m o0 grid;
+#X obj 0 837 doc_f;
+#X obj 97 629 doc_m i0 op;
+#X text 232 629 same as arg 0;
+#X connect 0 0 1 1;
+#X connect 1 0 31 0;
+#X connect 2 0 3 0;
+#X connect 3 0 1 0;
+#X connect 4 0 16 0;
+#X connect 5 0 19 0;
+#X connect 6 0 10 0;
+#X connect 6 0 31 1;
+#X connect 7 0 18 0;
+#X connect 10 0 11 0;
+#X connect 11 0 12 0;
+#X connect 12 0 13 0;
+#X connect 12 1 13 1;
+#X connect 13 0 14 0;
+#X connect 14 0 15 1;
+#X connect 15 0 31 2;
+#X connect 16 0 15 0;
+#X connect 16 1 15 0;
+#X connect 16 2 15 0;
+#X connect 16 3 15 0;
+#X connect 18 0 6 0;
+#X connect 19 0 0 0;
+#X connect 20 0 31 2;
+#X connect 21 0 20 0;
+#X connect 31 0 4 0;
+#X connect 35 0 31 0;
+#X connect 41 1 30 0;
+#X connect 42 1 34 0;
+#X connect 43 1 46 0;
+#X connect 43 1 37 0;
+#X connect 44 1 45 0;
+#X connect 44 1 38 0;
+#X connect 47 1 36 0;
+#X connect 48 1 39 0;
+#X connect 49 1 40 0;
+#X connect 51 1 52 0;
diff --git a/externals/gridflow/doc/flow_classes/#draw_points-help.pd b/externals/gridflow/doc/flow_classes/#draw_points-help.pd
new file mode 100644
index 00000000..21e2c3d2
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#draw_points-help.pd
@@ -0,0 +1,56 @@
+#N canvas 678 62 632 584 10;
+#X msg 21 163 240 320 3 #;
+#X obj 236 155 #outer + (0 9000);
+#X obj 236 174 # cos* 100;
+#X obj 236 193 # + 120;
+#X obj 236 117 #for 0 12 1;
+#X obj 236 100 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 236 136 # * 3000;
+#X obj 237 223 display;
+#X obj 21 183 #draw_points put (255 255 0);
+#X obj 21 203 #out window;
+#X text 26 77 [#draw_points] is not yet ready for use.;
+#X obj 0 0 doc_h;
+#X obj 3 365 doc_i 3;
+#X obj 3 493 doc_o 1;
+#X obj 14 523 doc_oo 0;
+#X obj 14 395 doc_ii 0;
+#X obj 14 439 doc_ii 1;
+#X obj 14 461 doc_ii 2;
+#X obj 3 261 doc_c 0..3;
+#X obj 14 291 doc_cc 0;
+#X obj 14 311 doc_cc 1;
+#X obj 14 333 doc_cc 2;
+#X obj 0 555 doc_f;
+#X obj 97 333 doc_m c2;
+#X obj 97 523 doc_m o0 grid;
+#X obj 97 291 doc_m c0 symbol/numop;
+#X obj 97 311 doc_m c1 grid;
+#X text 232 311 color;
+#X text 232 333 points;
+#X obj 97 395 doc_m i0 grid;
+#X obj 97 439 doc_m i1 grid;
+#X obj 97 461 doc_m i2 grid;
+#X obj 97 417 doc_m i0 op;
+#X text 232 417 same as arg 0;
+#X text 232 439 same as arg 1;
+#X text 232 461 same as arg 2;
+#X text 232 395 image to be drawn on;
+#X text 232 523 image that has been drawn on;
+#X connect 0 0 8 0;
+#X connect 1 0 2 0;
+#X connect 2 0 3 0;
+#X connect 3 0 7 0;
+#X connect 3 0 8 2;
+#X connect 4 0 6 0;
+#X connect 5 0 4 0;
+#X connect 6 0 1 0;
+#X connect 8 0 9 0;
+#X connect 23 1 28 0;
+#X connect 24 1 37 0;
+#X connect 26 1 27 0;
+#X connect 29 1 36 0;
+#X connect 30 1 34 0;
+#X connect 31 1 35 0;
+#X connect 32 1 33 0;
diff --git a/externals/gridflow/doc/flow_classes/#draw_polygon-help.pd b/externals/gridflow/doc/flow_classes/#draw_polygon-help.pd
new file mode 100644
index 00000000..a5afe5e9
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#draw_polygon-help.pd
@@ -0,0 +1,116 @@
+#N canvas 628 21 632 642 10;
+#X obj 20 349 #out window;
+#X obj 383 128 #color;
+#X obj 383 72 loadbang;
+#X obj 272 107 # rand;
+#X obj 20 256 #clip;
+#X obj 385 199 vradio 15 1 0 3 empty empty empty 0 -8 0 10 -241291
+-1 -1 0;
+#X text 402 200 fill;
+#X msg 385 265 draw \$1;
+#X obj 385 291 vradio 15 1 0 3 empty empty empty 0 -8 0 10 -241291
+-1 -1 0;
+#X text 403 291 none;
+#X msg 385 357 omit \$1;
+#X text 403 306 last;
+#X text 403 320 odd;
+#X obj 385 338 listread none last odd;
+#X obj 20 37 tgl 15 0 empty empty empty 17 7 0 10 -24198 -1 -1 0 1
+;
+#X obj 43 169 #checkers;
+#X obj 43 150 #for (0 0) (240 320) (1 1);
+#X obj 272 50 f;
+#X obj 297 50 + 1;
+#X obj 272 69 sel 0;
+#X obj 235 126 #store;
+#X obj 20 75 t b b b;
+#X msg 383 109 40 80 100;
+#X obj 50 104 loadbang;
+#X obj 322 50 % 30;
+#X obj 235 164 #fade_lin 4 4;
+#X obj 20 56 metro 33.3667;
+#X obj 385 246 listread fill line point;
+#X text 402 214 line;
+#X text 402 228 point;
+#X msg 272 88 8 2 # 240 320;
+#X msg 459 110 3 # 255;
+#X msg 115 169 240 320 3 #;
+#X obj 6 188 #store;
+#X obj 27 151 bng 15 250 50 0 empty empty empty 17 7 0 10 -241291 -1
+-1;
+#X obj 20 287 shunt;
+#X obj 57 288 tgl 15 0 empty empty empty 17 7 0 10 -241291 -1 -1 0
+1;
+#X obj 50 306 #fade (16 4 1);
+#X obj 0 0 doc_h;
+#X obj 3 389 doc_c 0..3;
+#X obj 3 508 doc_i 3;
+#X obj 3 614 doc_o 1;
+#X obj 14 644 doc_oo 0;
+#X obj 14 538 doc_ii 0;
+#X obj 14 560 doc_ii 1;
+#X obj 14 582 doc_ii 2;
+#X obj 14 419 doc_cc 0;
+#X obj 14 454 doc_cc 1;
+#X obj 14 476 doc_cc 2;
+#X obj 20 237 #draw_polygon ^ 1;
+#X text 232 419 Normally \, you would use the "put" operator \; but
+the + and ^ can be interesting for color effects.;
+#X text 232 538 Picture on which the polygon will be superimposed.
+;
+#X text 232 560 Color. (see argument 1);
+#X text 232 454 Color of the polygon.;
+#X text 232 644 Resulting picture.;
+#X text 232 476 Vertices of the polygon.;
+#X text 232 582 Vertices. (see argument 2);
+#X obj 97 419 doc_m c0 symbol/numop;
+#X obj 97 454 doc_m c1 grid;
+#X obj 97 476 doc_m c2 grid;
+#X obj 97 538 doc_m i0 grid;
+#X obj 97 560 doc_m i1 grid;
+#X obj 97 582 doc_m i2 grid;
+#X obj 97 644 doc_m o0 grid;
+#X obj 0 676 doc_f;
+#X connect 1 0 49 1;
+#X connect 2 0 31 0;
+#X connect 3 0 20 1;
+#X connect 4 0 35 0;
+#X connect 5 0 27 0;
+#X connect 7 0 49 0;
+#X connect 8 0 13 0;
+#X connect 10 0 49 0;
+#X connect 13 0 10 0;
+#X connect 14 0 26 0;
+#X connect 15 0 33 1;
+#X connect 16 0 15 0;
+#X connect 17 0 18 0;
+#X connect 17 0 19 0;
+#X connect 18 0 24 0;
+#X connect 19 0 30 0;
+#X connect 20 0 25 0;
+#X connect 21 0 33 0;
+#X connect 21 1 20 0;
+#X connect 21 2 17 0;
+#X connect 22 0 1 0;
+#X connect 23 0 32 0;
+#X connect 24 0 17 1;
+#X connect 25 0 49 2;
+#X connect 26 0 21 0;
+#X connect 27 0 7 0;
+#X connect 30 0 3 0;
+#X connect 31 0 1 0;
+#X connect 32 0 33 1;
+#X connect 33 0 49 0;
+#X connect 34 0 16 0;
+#X connect 35 0 0 0;
+#X connect 35 1 37 0;
+#X connect 36 0 35 1;
+#X connect 37 0 0 0;
+#X connect 49 0 4 0;
+#X connect 57 1 50 0;
+#X connect 58 1 53 0;
+#X connect 59 1 55 0;
+#X connect 60 1 51 0;
+#X connect 61 1 52 0;
+#X connect 62 1 56 0;
+#X connect 63 1 54 0;
diff --git a/externals/gridflow/doc/flow_classes/#draw_rect-help.pd b/externals/gridflow/doc/flow_classes/#draw_rect-help.pd
new file mode 100644
index 00000000..a66a4945
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#draw_rect-help.pd
@@ -0,0 +1,40 @@
+#N canvas 335 118 632 443 10;
+#X obj 0 0 doc_h;
+#X obj 0 414 doc_f;
+#X obj 122 57 #draw_rect;
+#X obj 14 126 doc_cc 0;
+#X obj 14 148 doc_cc 1;
+#X obj 14 170 doc_cc 2;
+#X obj 3 96 doc_c 2..3;
+#X text 232 126 op;
+#X text 232 148 color;
+#X text 232 170 polygon;
+#X obj 97 126 doc_m c0 symbol;
+#X obj 97 148 doc_m c1 grid;
+#X obj 97 170 doc_m c2 grid;
+#X obj 3 202 doc_i 3;
+#X obj 3 352 doc_o 1;
+#X obj 14 382 doc_oo 0;
+#X obj 14 232 doc_ii 0;
+#X obj 14 298 doc_ii 1;
+#X obj 14 320 doc_ii 2;
+#X obj 97 232 doc_m i0 grid;
+#X obj 97 254 doc_m i0 outline;
+#X obj 97 298 doc_m i1 grid;
+#X obj 97 320 doc_m i2 grid;
+#X text 232 298 same as arg 1;
+#X text 232 232 picture to draw on;
+#X text 232 254 0: fill rectangle;
+#X text 232 276 1: draw outline only (1 pixel thickness);
+#X text 232 382 picture drawn on;
+#X obj 97 382 doc_m o0 grid;
+#X text 232 320 same as arg 2;
+#X connect 10 1 7 0;
+#X connect 11 1 8 0;
+#X connect 12 1 9 0;
+#X connect 19 1 24 0;
+#X connect 20 1 26 0;
+#X connect 20 1 25 0;
+#X connect 21 1 23 0;
+#X connect 22 1 29 0;
+#X connect 28 1 27 0;
diff --git a/externals/gridflow/doc/flow_classes/#draw_slider-help.pd b/externals/gridflow/doc/flow_classes/#draw_slider-help.pd
new file mode 100644
index 00000000..fa406625
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#draw_slider-help.pd
@@ -0,0 +1,56 @@
+#N canvas 587 8 632 619 10;
+#X obj 28 87 metro 100;
+#X obj 28 70 tgl 15 0 empty empty empty 17 7 0 10 -24198 -1 -1 0 1
+;
+#X obj 28 183 #out window;
+#X text 232 413 Grid values are clipped to the high and low values
+stored in the object;
+#X text 232 558 Outputs the modified grid;
+#X text 232 448 An integer can be used to vary the minimum value of
+the range.;
+#X text 232 483 An integer can be used to vary the maximum value of
+the range.;
+#X obj 28 106 #in scissors.jpg;
+#X obj 238 89 hsl 128 15 0 127 0 0 empty empty empty -2 -8 0 10 -241291
+-1 -1 0 1;
+#X text 378 88 <-- value to be displayed;
+#X msg 126 135 255 200 150;
+#X text 209 135 <-- colour;
+#X obj 28 164 #draw_slider put (0 255 0) (255 0 255) (40 40 80 200)
+0 127;
+#X text 5 25 Draws a slider-like rectangle on an image.;
+#X obj 0 0 doc_h;
+#X obj 3 383 doc_i 3;
+#X obj 3 528 doc_o 1;
+#X obj 14 558 doc_oo 0;
+#X obj 14 413 doc_ii 0;
+#X obj 14 448 doc_ii 1;
+#X obj 14 483 doc_ii 2;
+#X obj 14 253 doc_cc 0;
+#X obj 14 273 doc_cc 1;
+#X obj 14 293 doc_cc 2;
+#X obj 14 313 doc_cc 3;
+#X obj 14 333 doc_cc 4;
+#X obj 97 333 doc_m c4;
+#X obj 97 253 doc_m c0 symbol/numop;
+#X obj 97 273 doc_m c1 grid[3];
+#X obj 97 293 doc_m c2 grid[3];
+#X obj 97 313 doc_m c3 grid;
+#X obj 3 223 doc_c 6;
+#X obj 14 353 doc_cc 5;
+#X obj 97 353 doc_m c5;
+#X obj 97 413 doc_m i0 grid;
+#X obj 97 448 doc_m i1 float int;
+#X obj 97 483 doc_m i2 float int;
+#X obj 97 558 doc_m o0 grid;
+#X obj 0 590 doc_f;
+#X connect 0 0 7 0;
+#X connect 1 0 0 0;
+#X connect 7 0 12 0;
+#X connect 8 0 12 2;
+#X connect 10 0 12 1;
+#X connect 12 0 2 0;
+#X connect 34 1 3 0;
+#X connect 35 1 5 0;
+#X connect 36 1 6 0;
+#X connect 37 1 4 0;
diff --git a/externals/gridflow/doc/flow_classes/#edit_polygon-help.pd b/externals/gridflow/doc/flow_classes/#edit_polygon-help.pd
new file mode 100644
index 00000000..8ebd5849
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#edit_polygon-help.pd
@@ -0,0 +1,42 @@
+#N canvas 335 118 632 440 10;
+#X obj 0 0 doc_h;
+#X obj 0 411 doc_f;
+#X obj 65 56 #edit_polygon;
+#X obj 3 95 doc_c 3;
+#X obj 14 125 doc_cc 0;
+#X obj 14 147 doc_cc 1;
+#X obj 14 169 doc_cc 2;
+#X obj 97 125 doc_m c0 symbol;
+#X text 232 125 op;
+#X text 232 147 color;
+#X text 232 169 position;
+#X obj 97 147 doc_m c1 grid;
+#X obj 97 169 doc_m c2 grid;
+#X obj 3 201 doc_i 3;
+#X obj 3 327 doc_o 2;
+#X obj 14 357 doc_oo 0;
+#X obj 14 379 doc_oo 1;
+#X obj 14 231 doc_ii 0;
+#X obj 14 273 doc_ii 1;
+#X obj 14 295 doc_ii 2;
+#X obj 97 251 doc_m i0 position;
+#X obj 97 231 doc_m i0 grid;
+#X obj 97 273 doc_m i1 grid;
+#X obj 97 295 doc_m i2 grid;
+#X text 232 295 same as arg 2;
+#X text 232 273 same as arg 1;
+#X text 232 251 from [#out window];
+#X text 201 231 picture to draw on;
+#X text 232 357 picture drawn on;
+#X obj 97 357 doc_m o0 grid;
+#X obj 97 379 doc_m o1 <none>;
+#X text 232 379 for future use;
+#X text 237 54 probably not finished coding this. (?);
+#X connect 7 1 8 0;
+#X connect 11 1 9 0;
+#X connect 12 1 10 0;
+#X connect 20 1 26 0;
+#X connect 22 1 25 0;
+#X connect 23 1 24 0;
+#X connect 29 1 28 0;
+#X connect 30 1 31 0;
diff --git a/externals/gridflow/doc/flow_classes/#extract_diagonal-help.pd b/externals/gridflow/doc/flow_classes/#extract_diagonal-help.pd
new file mode 100644
index 00000000..f21b9272
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#extract_diagonal-help.pd
@@ -0,0 +1,32 @@
+#N canvas 0 0 632 547 10;
+#X obj 53 82 cv/#SVD;
+#X obj 70 104 display;
+#X obj 54 174 display;
+#X msg 53 63 2 2 f # 30 40 50 60;
+#X text 53 43 numbers coming from the equation of an ellipse;
+#X text 101 85 eigenvectors show the direction of axes of the ellipse
+;
+#X text 64 155 eigenvalues show the square of the length of the axes
+;
+#X obj 23 233 #extract_diagonal;
+#X obj 36 257 display;
+#X text 130 232 just keep the diagonal of the matrix;
+#X obj 24 324 display;
+#X text 99 304 just the radiuses;
+#X obj 23 304 # sqrt (f #);
+#X obj 0 0 doc_h;
+#X obj 3 358 doc_c 0;
+#X obj 3 398 doc_i 1;
+#X obj 3 458 doc_o 1;
+#X obj 14 488 doc_oo 0;
+#X obj 14 428 doc_ii 0;
+#X obj 0 518 doc_f;
+#X obj 97 428 doc_m i0 grid;
+#X obj 97 488 doc_m o0 grid;
+#X connect 0 0 2 0;
+#X connect 0 0 7 0;
+#X connect 0 1 1 0;
+#X connect 3 0 0 0;
+#X connect 7 0 8 0;
+#X connect 7 0 12 0;
+#X connect 12 0 10 0;
diff --git a/externals/gridflow/doc/flow_classes/#fade-help.pd b/externals/gridflow/doc/flow_classes/#fade-help.pd
new file mode 100644
index 00000000..fe3adfe5
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#fade-help.pd
@@ -0,0 +1,57 @@
+#N canvas 676 0 632 596 10;
+#X obj 253 236 #out window;
+#X obj 131 111 bng 15 250 50 0 empty empty empty 0 -6 0 8 -24198 -1
+-1;
+#X obj 131 150 #in;
+#X floatatom 295 218 5 0 0 0 - - -;
+#X obj 131 89 metro 500;
+#X obj 131 70 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1
+;
+#X obj 253 113 bng 15 250 50 0 empty empty empty 0 -6 0 8 -24198 -1
+-1;
+#X obj 253 152 #in;
+#X obj 253 91 metro 500;
+#X obj 253 72 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1
+;
+#X obj 253 217 #fade;
+#X obj 0 0 doc_h;
+#X obj 3 390 doc_i 2;
+#X obj 3 487 doc_o 1;
+#X obj 14 517 doc_oo 0;
+#X obj 14 420 doc_ii 0;
+#X obj 14 455 doc_ii 1;
+#X obj 3 275 doc_c 1;
+#X obj 97 420 doc_m i0 grid;
+#X obj 97 455 doc_m i1 grid;
+#X text 232 332 indicates the amount of one image being blended with
+the other. (ex: Integer 5 will take 20% (one fifth) of the first image
+and blend it with 80% of the next image.;
+#X obj 3 547 doc_also;
+#X obj 103 547 lop~;
+#X obj 139 547 rzero~;
+#X obj 14 332 doc_cc 0;
+#X obj 97 332 doc_m c0 grid;
+#X text 232 455 same as arg 0;
+#X obj 97 517 doc_m o0 grid;
+#X obj 0 567 doc_f;
+#X text 232 420 grids that are blended into each other over time.;
+#X msg 131 131 load b001.jpg;
+#X msg 253 133 load r001.jpg;
+#X text 11 29 temporal low-pass filter;
+#X connect 1 0 30 0;
+#X connect 2 0 10 0;
+#X connect 3 0 10 1;
+#X connect 4 0 1 0;
+#X connect 5 0 4 0;
+#X connect 6 0 31 0;
+#X connect 7 0 10 0;
+#X connect 8 0 6 0;
+#X connect 9 0 8 0;
+#X connect 10 0 0 0;
+#X connect 18 1 29 0;
+#X connect 19 1 26 0;
+#X connect 21 1 22 0;
+#X connect 21 1 23 0;
+#X connect 25 1 20 0;
+#X connect 30 0 2 0;
+#X connect 31 0 7 0;
diff --git a/externals/gridflow/doc/flow_classes/#fade_lin-help.pd b/externals/gridflow/doc/flow_classes/#fade_lin-help.pd
new file mode 100644
index 00000000..189ec0b9
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#fade_lin-help.pd
@@ -0,0 +1,36 @@
+#N canvas 684 0 632 543 10;
+#X obj 0 0 doc_h;
+#X obj 3 212 doc_c 2;
+#X obj 77 134 #fade_lin;
+#X obj 3 296 doc_i 3;
+#X obj 3 454 doc_o 1;
+#X obj 14 326 doc_ii 0;
+#X obj 14 400 doc_ii 1;
+#X obj 14 422 doc_ii 2;
+#X obj 14 484 doc_oo 0;
+#X obj 14 242 doc_cc 0;
+#X obj 14 264 doc_cc 1;
+#X obj 97 242 doc_m c0 grid;
+#X obj 97 264 doc_m c1 grid;
+#X text 232 242 maxraise;
+#X text 232 264 maxdrop;
+#X obj 97 326 doc_m i0 grid;
+#X text 232 326 produces on outlet 0 a piecewise-linear nonrecurrent
+fading according to the flow of incoming messages. For example \, if
+maxraise=2 and maxdrop=4 \, then with each new message an output is
+produced that is at most 2 more or 4 less than the previous output.
+;
+#X obj 97 400 doc_m i1 grid;
+#X obj 97 422 doc_m i2 grid;
+#X text 232 400 same as arg 0;
+#X text 232 422 same as arg 1;
+#X obj 0 514 doc_f;
+#X text 16 33 non-linear temporal lowpass filter;
+#X text 16 47 (piecewise-constant);
+#X text 14 61 it is named "lin" because it has an output similar to
+[line] \, though the input is much different.;
+#X connect 11 1 13 0;
+#X connect 12 1 14 0;
+#X connect 15 1 16 0;
+#X connect 17 1 19 0;
+#X connect 18 1 20 0;
diff --git a/externals/gridflow/doc/flow_classes/#fastblur-help.pd b/externals/gridflow/doc/flow_classes/#fastblur-help.pd
new file mode 100644
index 00000000..12ce00a6
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#fastblur-help.pd
@@ -0,0 +1,90 @@
+#N canvas 310 131 632 598 10;
+#N canvas 0 0 450 300 test 0;
+#X obj 264 137 # +;
+#X obj 23 58 #for (0 0) (5 5) (1 1);
+#X obj 23 96 #fold & \, seed 1;
+#X obj 23 41 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 23 115 #convolve (3 3 # 1 2 3 4 5 6 7 8 9) \, wrap 0 \, anti
+0;
+#X obj 22 77 # == 2;
+#X obj 23 134 #print;
+#X obj 264 156 #print;
+#X connect 0 0 7 0;
+#X connect 1 0 5 0;
+#X connect 2 0 0 0;
+#X connect 2 0 4 0;
+#X connect 3 0 1 0;
+#X connect 4 0 6 0;
+#X connect 5 0 2 0;
+#X restore 403 28 pd test convolve attr;
+#X obj 20 54 tgl 15 0 empty empty empty 0 -6 0 8 -24198 -1 -1 0 1;
+#X obj 38 55 metro 33.3667;
+#X obj 100 93 loadbang;
+#X obj 84 94 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 38 110 #store;
+#X obj 38 290 #out window;
+#X obj 39 330 display;
+#X obj 38 309 fps detailed;
+#X obj 84 110 #in teapot.png;
+#X obj 248 56 f;
+#X obj 274 56 + 1;
+#X obj 149 301 #pack;
+#X obj 38 85 t b b;
+#X obj 38 131 #fastblur;
+#X obj 255 96 expr 1+100*pow(sin($f1/25) \, 4);
+#X obj 244 76 expr 1+100*pow(sin($f1/20) \, 4);
+#X obj 150 167 vsl 15 128 1 128 0 0 empty empty empty 0 -8 0 8 -262144
+-1 -1 0 1;
+#X obj 170 167 vsl 15 128 1 128 0 0 empty empty empty 0 -8 0 8 -262144
+-1 -1 0 1;
+#X obj 248 37 spigot;
+#X obj 294 38 tgl 15 0 empty empty empty 0 -6 0 8 -241291 -1 -1 0 1
+;
+#X obj 38 270 #gamma 700;
+#X text 313 38 AUTO;
+#X obj 0 0 doc_h;
+#X obj 3 423 doc_i 2;
+#X obj 3 361 doc_c 1;
+#X obj 3 507 doc_o 1;
+#X obj 14 537 doc_oo 0;
+#X obj 14 453 doc_ii 0;
+#X obj 14 475 doc_ii 1;
+#X obj 14 391 doc_cc 0;
+#X obj 0 569 doc_f;
+#X obj 97 537 doc_m o0;
+#X obj 97 391 doc_m c0 grid;
+#X text 232 391 (y x) kernel size;
+#X obj 97 453 doc_m i0 grid;
+#X obj 97 475 doc_m i1 grid;
+#X text 232 475 same as arg 0;
+#X text 232 453 image to be blurred;
+#X text 232 537 image blurred;
+#X connect 1 0 2 0;
+#X connect 2 0 13 0;
+#X connect 3 0 9 0;
+#X connect 4 0 9 0;
+#X connect 5 0 14 0;
+#X connect 6 0 8 0;
+#X connect 8 0 7 0;
+#X connect 9 0 5 1;
+#X connect 10 0 11 0;
+#X connect 10 0 15 0;
+#X connect 10 0 16 0;
+#X connect 11 0 10 1;
+#X connect 12 0 14 1;
+#X connect 13 0 5 0;
+#X connect 13 1 19 0;
+#X connect 14 0 21 0;
+#X connect 15 0 18 0;
+#X connect 16 0 17 0;
+#X connect 17 0 12 0;
+#X connect 18 0 12 1;
+#X connect 19 0 10 0;
+#X connect 20 0 19 1;
+#X connect 21 0 6 0;
+#X connect 32 1 39 0;
+#X connect 33 1 34 0;
+#X connect 35 1 38 0;
+#X connect 36 1 37 0;
diff --git a/externals/gridflow/doc/flow_classes/#fft-help.pd b/externals/gridflow/doc/flow_classes/#fft-help.pd
new file mode 100644
index 00000000..1b240df9
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#fft-help.pd
@@ -0,0 +1,73 @@
+#N canvas 653 206 632 642 10;
+#X obj 13 144 #cast f;
+#X obj 13 236 #cast i;
+#X obj 13 86 #in teapot.png;
+#X obj 32 64 loadbang;
+#X obj 13 65 bng 15 250 50 0 empty empty empty 0 -6 0 8 -24198 -1 -1
+;
+#X obj 13 106 t a a;
+#X obj 13 198 #fft;
+#X msg 23 169 help;
+#X msg 43 197 skip \$1;
+#X obj 64 163 tgl 15 0 empty empty empty 0 -6 0 8 -241291 -1 -1 0 1
+;
+#X obj 52 106 s orig;
+#X obj 66 312 r orig;
+#X obj 13 331 #out window;
+#X obj 13 274 # + 128;
+#X obj 13 293 #clip;
+#X obj 13 125 #outer * (1 0);
+#X obj 13 255 #inner (1 0);
+#X text 89 255 convert complex to real (kicking dummy imaginary);
+#X text 100 125 convert real to complex (introducing dummy imaginary=0)
+;
+#X obj 13 217 # / (f # 16);
+#X obj 0 0 doc_h;
+#X obj 3 355 doc_c 0;
+#X obj 3 395 doc_i 1;
+#X obj 3 589 doc_o 1;
+#X obj 14 619 doc_oo 0;
+#X obj 14 425 doc_ii 0;
+#X obj 0 651 doc_f;
+#X obj 13 312 #join 1;
+#X obj 97 619 doc_m o0 grid;
+#X obj 97 425 doc_m i0 grid;
+#X obj 97 491 doc_m i0 sign;
+#X obj 97 535 doc_m i0 skip;
+#X text 232 557 1: skip the y dimension (do fft only along x);
+#X text 20 35 spatial fft;
+#X obj 97 447 doc_m i0 real;
+#X text 232 535 0: don't skip the y dimension (do fft along both y
+and x);
+#X text 232 491 1: forward fft;
+#X text 232 513 -1: backward fft;
+#X text 232 447 0: complex fft;
+#X text 232 469 1: real fft;
+#X text 232 425 grid to apply fft on;
+#X text 232 619 grid that fft was applied on;
+#X connect 0 0 6 0;
+#X connect 1 0 16 0;
+#X connect 2 0 5 0;
+#X connect 3 0 2 0;
+#X connect 4 0 2 0;
+#X connect 5 0 15 0;
+#X connect 5 1 10 0;
+#X connect 6 0 19 0;
+#X connect 7 0 6 0;
+#X connect 8 0 6 0;
+#X connect 9 0 8 0;
+#X connect 11 0 27 1;
+#X connect 13 0 14 0;
+#X connect 14 0 27 0;
+#X connect 15 0 0 0;
+#X connect 16 0 13 0;
+#X connect 19 0 1 0;
+#X connect 27 0 12 0;
+#X connect 28 1 41 0;
+#X connect 29 1 40 0;
+#X connect 30 1 36 0;
+#X connect 30 1 37 0;
+#X connect 31 1 32 0;
+#X connect 31 1 35 0;
+#X connect 34 1 39 0;
+#X connect 34 1 38 0;
diff --git a/externals/gridflow/doc/flow_classes/#finished-help.pd b/externals/gridflow/doc/flow_classes/#finished-help.pd
new file mode 100644
index 00000000..46a31bdb
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#finished-help.pd
@@ -0,0 +1,54 @@
+#N canvas 648 0 632 642 10;
+#X text 21 37 a bang is emitted every time a grid transmission ends
+;
+#X obj 23 114 bng 15 250 50 0 empty empty empty 0 -6 0 8 -233017 -1
+-1;
+#X obj 23 85 #finished;
+#X obj 0 0 doc_h;
+#X obj 3 568 doc_i 1;
+#X obj 3 630 doc_o 1;
+#X obj 3 528 doc_c 0;
+#X obj 14 660 doc_oo 0;
+#X obj 14 598 doc_ii 0;
+#X obj 97 598 doc_m i0 grid;
+#X obj 97 660 doc_m o0 bang;
+#X text 232 598 a bang is emitted every time a grid transmission ends.
+;
+#X obj 0 710 doc_f;
+#X obj 23 66 t a a;
+#X obj 89 66 #convolve (1 3 # 1 2 1);
+#X text 90 85 this is a pattern where [t b a] doesn't cut it \, because
+the bang would be output too early \, as it gets output at GRID_BEGIN
+time (the time at which the grid message is sent). But [#convolve]
+only outputs its contents after GRID_FLOW time \, which is what [#finished]
+ensures. However you still need a [t a a] \, because [#finished]'s
+GRID_FINISH time must happen after [#convolve]'s GRID_FINISH \, so
+that you can be sure that [#convolve] is really finished with producing
+its output.;
+#X obj 3 690 doc_also;
+#X obj 103 690 #t;
+#X text 39 278 the 2nd exception is that it definitely doesn't support
+any control-recursion (an object can't start processing a new message
+before it has finished processing its message).;
+#X obj 410 221 pdp_qt;
+#X obj 410 252 print;
+#X msg 409 199;
+#X text 40 327 the third exception is that the GRID atom type is not
+officially recognised by PureData because PureData provides no means
+for externals to register new atom types. You can see the effect of
+this in how GEM uses the POINTER atom type in an unstable way (which
+is also how GridFlow used to do it);
+#X text 38 215 this is one of GridFlow's exceptions to how much grid-processing
+is like normal pd message passing. there is also the [#t] class that
+provides a shortcut for the most common use pattern of [#t].;
+#X text 41 416 the fourth exception is that GridInlets support multiple
+selectors with quite peculiar autocasts \, meaning that [# +] can't
+support the equivalent of the 'list' message in the [+] class.;
+#X text 40 479 much of the text of this page should really go somewhere
+else \, but there is no place for it yet.;
+#X connect 2 0 1 0;
+#X connect 9 1 11 0;
+#X connect 13 0 2 0;
+#X connect 13 1 14 0;
+#X connect 16 1 17 0;
+#X connect 19 0 20 0;
diff --git a/externals/gridflow/doc/flow_classes/#fold-help.pd b/externals/gridflow/doc/flow_classes/#fold-help.pd
new file mode 100644
index 00000000..0120aad9
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#fold-help.pd
@@ -0,0 +1,80 @@
+#N canvas 678 0 632 661 10;
+#X obj 98 184 display;
+#X obj 29 252 display;
+#X text 26 38 Treats the grid as a grid of one- dimensional grids such
+that the same operation (here addition) will be performed on all its
+elements together with the base value. the results are combined back.
+each #fold operation removes a dimension. syntax: #fold <two-input
+operation> <starting value>;
+#X obj 143 249 #to_float;
+#X obj 143 274 print values;
+#X text 6 721 some other forms:;
+#X obj 140 722 #fold *;
+#X obj 17 695 #fold + \, seed 0;
+#X obj 211 722 #fold ^;
+#X obj 284 722 #fold &;
+#X obj 355 722 #fold |;
+#N canvas 0 0 500 313 more 1;
+#X obj 98 82 display;
+#X obj 28 48 #import (2 2 2);
+#X obj 29 170 display;
+#X msg 28 27 1 3 1 3 1 3 1 5;
+#X text 154 24 <-- clicking here creates a grid through [#import];
+#X obj 122 170 #to_float;
+#X obj 122 195 print values;
+#X obj 28 137 #fold + \, seed (0 0);
+#X connect 1 0 0 0;
+#X connect 1 0 7 0;
+#X connect 3 0 1 0;
+#X connect 5 0 6 0;
+#X connect 7 0 2 0;
+#X connect 7 0 5 0;
+#X restore 160 694 pd more info;
+#X msg 28 129 1 3 1 3 1 3 1 3 1 3 1 5;
+#X obj 28 153 #import (2 3 2);
+#X obj 28 224 #fold +;
+#X text 203 129 <-- clicking here creates a grid through [#import]
+;
+#X obj 3 324 doc_c 1;
+#X obj 3 386 doc_i 1;
+#X obj 3 570 doc_o 1;
+#X obj 0 0 doc_h;
+#X obj 14 600 doc_oo 0;
+#X obj 14 416 doc_ii 0;
+#X obj 14 354 doc_cc 0;
+#X text 219 155 [#fold +] computes totals;
+#X text 221 176 [#fold inv+] is an alternated sum (+/-);
+#X text 225 203 [#fold *] can compute the size of a grid using its
+dimension list;
+#X text 229 240 [#fold &] can mean "for all";
+#X text 228 260 [#fold |] can mean "there exists (at least one)";
+#X text 224 282 [#fold ^] can mean "there exists an odd number of..."
+;
+#X obj 97 354 doc_m c0 symbol/numop;
+#X text 232 354 the operator to fold with.;
+#X obj 97 416 doc_m i0 grid;
+#X obj 97 477 doc_m i0 op;
+#X obj 97 499 doc_m i0 seed;
+#X text 232 477 same as arg 0;
+#X text 232 416 replaces every subgrid by the result of a cascade on
+that subgrid. Doing that with seed value 0 and operation + on grid
+"2 3 5 7" will compute ((((0+2)+3)+5)+7) find the total "17".;
+#X text 232 499 the initial value for the folding. (default: whatever
+does nothing for the chosen op \; e.g. 0 + \, 0 - \, 1 * \, ...). this
+can be a grid of any size \, and this decides the size of the subgrids
+we are working on.;
+#X obj 97 600 doc_m o0 grid;
+#X text 232 600 Outputs a grid that has one less dimension than the
+input.;
+#X obj 0 632 doc_f;
+#X connect 3 0 4 0;
+#X connect 12 0 13 0;
+#X connect 13 0 0 0;
+#X connect 13 0 14 0;
+#X connect 14 0 1 0;
+#X connect 14 0 3 0;
+#X connect 29 1 30 0;
+#X connect 31 1 35 0;
+#X connect 32 1 34 0;
+#X connect 33 1 36 0;
+#X connect 37 1 38 0;
diff --git a/externals/gridflow/doc/flow_classes/#for-help.pd b/externals/gridflow/doc/flow_classes/#for-help.pd
new file mode 100644
index 00000000..28903e51
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#for-help.pd
@@ -0,0 +1,83 @@
+#N canvas 661 0 632 642 10;
+#X floatatom 13 197 5 0 0 0 - - -;
+#X floatatom 45 219 5 0 0 0 - - -;
+#X floatatom 78 238 5 0 0 0 - - -;
+#X obj 13 329 #print;
+#X obj 33 296 display;
+#X text 119 238 <-- step value;
+#X text 90 217 <-- upper bound;
+#X text 60 194 <-- lower bound;
+#X obj 13 261 #for 0 8 1;
+#X obj 264 328 #print;
+#X obj 314 288 display;
+#X msg 264 198 0 0;
+#X msg 369 244 1 1;
+#X msg 326 223 4 4;
+#X text 232 484 Upper bound;
+#X text 232 506 Step value;
+#X text 232 449 Lower bound. As with the other arguments \, they are
+overwritten when another value is given.;
+#X text 414 244 <-- step value (1);
+#X text 373 222 <-- upper bound (2);
+#X text 309 197 <-- lower bound (3);
+#X text 26 38 When given scalar bounds \, works like a regular [for]
+object plugged to a [#import] tuned for a Dim(size) where size is the
+number of values produced by a bang to that [for].;
+#X text 232 656 Sets the upper bound;
+#X text 232 678 Sets the step value;
+#X text 232 740 The result of the operation is a single dimension grid
+in the case of scalar values and variable dimensions for vectors.;
+#X obj 0 0 doc_h;
+#X obj 3 538 doc_i 3;
+#X obj 3 419 doc_c 3;
+#X text 232 568 activate object (send output);
+#X text 232 590 Sets the lower bound and activate;
+#X text 232 634 Sets the lower bound without activating;
+#X text 26 84 When given vector bounds \, will work like any number
+of [for] objects producing all possible combinations of their values
+in the proper order. (try it below);
+#X text 27 132 the formula for knowing the size of the output will
+be is floor((to-from)/step).;
+#X obj 14 740 doc_oo 0;
+#X obj 14 506 doc_cc 2;
+#X text 232 612 the three arguments at once;
+#X obj 14 449 doc_cc 0;
+#X obj 14 484 doc_cc 1;
+#X obj 14 568 doc_ii 0;
+#X obj 3 710 doc_o 1;
+#X obj 14 656 doc_ii 1;
+#X obj 14 678 doc_ii 2;
+#X text 11 177 With scalar bounds:;
+#X text 262 178 With vector bounds:;
+#X obj 97 612 doc_m i0 list;
+#X obj 97 568 doc_m i0 bang;
+#X obj 97 634 doc_m i0 set;
+#X obj 97 449 doc_m c0 grid;
+#X obj 97 484 doc_m c1 grid;
+#X obj 97 506 doc_m c2 grid;
+#X obj 97 590 doc_m i0 grid;
+#X obj 97 656 doc_m i1 grid;
+#X obj 97 678 doc_m i2 grid;
+#X obj 0 798 doc_f;
+#X obj 264 267 #for (0 0) (8 3) (1 1);
+#X obj 97 740 doc_m o0 grid;
+#X connect 0 0 8 0;
+#X connect 1 0 8 1;
+#X connect 2 0 8 2;
+#X connect 8 0 4 0;
+#X connect 8 0 3 0;
+#X connect 11 0 53 0;
+#X connect 12 0 53 2;
+#X connect 13 0 53 1;
+#X connect 43 1 34 0;
+#X connect 44 1 27 0;
+#X connect 45 1 29 0;
+#X connect 46 1 16 0;
+#X connect 47 1 14 0;
+#X connect 48 1 15 0;
+#X connect 49 1 28 0;
+#X connect 50 1 21 0;
+#X connect 51 1 22 0;
+#X connect 53 0 10 0;
+#X connect 53 0 9 0;
+#X connect 54 1 23 0;
diff --git a/externals/gridflow/doc/flow_classes/#from_pix-help.pd b/externals/gridflow/doc/flow_classes/#from_pix-help.pd
new file mode 100644
index 00000000..d92aa497
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#from_pix-help.pd
@@ -0,0 +1,89 @@
+#N canvas 679 122 632 642 10;
+#X text 169 629 \, game_of_life_gem.pd in the examples folder;
+#X text 232 575 Grid with 4 channels;
+#X text 232 478 With one boolean argument that selects the order in
+which the y dimension of the Grid will be read \, defaults to '1';
+#X text 103 629 [#to_pix];
+#X obj 37 128 tgl 15 0 empty empty empty 0 -6 0 8 -241291 -1 -1 0 1
+;
+#X msg 54 127 yflip \$1;
+#X obj 22 39 gemhead;
+#X obj 22 107 pix_image;
+#X msg 391 55 create \, 1;
+#X obj 391 36 loadbang;
+#X msg 455 56 destroy;
+#X text 36 201 Note : The fps is dependent on the gemwin framerate
+;
+#X text 101 184 <-- imports gemlist into Grids;
+#X text 232 456 Has to be a 'pix' gemlist;
+#X text 232 597 Passthrough outlet for gem chain;
+#X obj 0 0 doc_h;
+#X obj 3 298 doc_c 0;
+#X obj 3 545 doc_o 2;
+#X obj 3 629 doc_also;
+#X obj 14 575 doc_oo 0;
+#X obj 14 597 doc_oo 1;
+#X obj 3 338 doc_i 2;
+#X obj 14 368 doc_ii 0;
+#X obj 14 513 doc_ii 1;
+#X text 232 513 dummy inlet existing only for weird reasons \, please
+ignore.;
+#X obj 97 478 doc_m i0 yflip;
+#X obj 97 575 doc_m o0 grid;
+#X obj 0 649 doc_f;
+#X msg 30 82 open images/babbage.jpg;
+#X obj 97 513 doc_m i1 <none>;
+#X msg 186 90 open \$1;
+#X obj 186 71 openpanel;
+#X obj 186 54 bng 15 250 50 0 empty empty empty 17 7 0 10 -4034 -1
+-1;
+#X obj 30 62 loadbang;
+#X obj 22 242 fps;
+#X floatatom 22 261 5 0 0 0 - - -;
+#X obj 22 223 #out window \, title imported_pix;
+#X msg 159 109 cast b;
+#X msg 159 147 cast i;
+#X obj 22 179 #import_pix;
+#X obj 97 368 doc_m i0 cast;
+#X text 232 368 numbertype of grid to be output;
+#X msg 159 128 cast s;
+#X obj 97 390 doc_m i0 colorspace;
+#X text 232 412 colorspace rgb: output 3 channels;
+#X text 232 390 colorspace rgba: output 4 channels;
+#X msg 259 148 colorspace rgb;
+#X msg 259 168 colorspace rgba;
+#X obj 390 85 gemwin 150;
+#X text 232 434 (default: rgba);
+#X obj 97 456 doc_m i0 gem_state;
+#X obj 97 597 doc_m o1 gem_state;
+#X connect 4 0 5 0;
+#X connect 5 0 39 0;
+#X connect 6 0 7 0;
+#X connect 7 0 39 0;
+#X connect 8 0 48 0;
+#X connect 9 0 8 0;
+#X connect 10 0 48 0;
+#X connect 18 1 3 0;
+#X connect 18 1 0 0;
+#X connect 25 1 2 0;
+#X connect 26 1 1 0;
+#X connect 28 0 7 0;
+#X connect 29 1 24 0;
+#X connect 30 0 7 0;
+#X connect 31 0 30 0;
+#X connect 32 0 31 0;
+#X connect 33 0 28 0;
+#X connect 34 0 35 0;
+#X connect 36 0 34 0;
+#X connect 37 0 39 0;
+#X connect 38 0 39 0;
+#X connect 39 0 36 0;
+#X connect 40 1 41 0;
+#X connect 42 0 39 0;
+#X connect 43 1 44 0;
+#X connect 43 1 45 0;
+#X connect 43 1 49 0;
+#X connect 46 0 39 0;
+#X connect 47 0 39 0;
+#X connect 50 1 13 0;
+#X connect 51 1 14 0;
diff --git a/externals/gridflow/doc/flow_classes/#gamma-help.pd b/externals/gridflow/doc/flow_classes/#gamma-help.pd
new file mode 100644
index 00000000..adbec0dd
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#gamma-help.pd
@@ -0,0 +1,29 @@
+#N canvas 535 121 632 375 10;
+#X obj 0 0 doc_h;
+#X obj 0 346 doc_f;
+#X obj 57 63 #gamma;
+#X obj 3 118 doc_c 1;
+#X obj 3 180 doc_i 2;
+#X obj 3 264 doc_o 1;
+#X obj 14 148 doc_cc 0;
+#X obj 14 210 doc_ii 0;
+#X obj 14 232 doc_ii 1;
+#X obj 14 294 doc_oo 0;
+#X obj 3 326 doc_also;
+#X obj 103 326 # gamma;
+#X text 175 63 accelerated (cached) version of [# gamma];
+#X obj 97 210 doc_m i0 grid;
+#X obj 97 148 doc_m c0 float/int;
+#X obj 97 232 doc_m i1 float int;
+#X obj 97 294 doc_m o0 grid;
+#X text 232 148 positive int;
+#X text 175 82 note: this only accepts a single float argument \, whereas
+[# gamma] allows a grid argument.;
+#X text 232 232 same as arg 0;
+#X text 232 210 pixels to apply on;
+#X text 232 294 output pixels;
+#X connect 10 1 11 0;
+#X connect 13 1 20 0;
+#X connect 14 1 17 0;
+#X connect 15 1 19 0;
+#X connect 16 1 21 0;
diff --git a/externals/gridflow/doc/flow_classes/#grade-help.pd b/externals/gridflow/doc/flow_classes/#grade-help.pd
new file mode 100644
index 00000000..d05aeaea
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#grade-help.pd
@@ -0,0 +1,45 @@
+#N canvas 690 0 632 680 10;
+#X text 143 55 splits a dim[a... \, b] grid into dim[b] vectors that
+each contain numbers from 0 to b-1 indicating the ordering of the values.
+the result is a dim[a... \, b] grid.;
+#X floatatom 19 114 5 0 0 0 - - -;
+#X floatatom 60 114 5 0 0 0 - - -;
+#X floatatom 101 114 5 0 0 0 - - -;
+#X floatatom 142 114 5 0 0 0 - - -;
+#X obj 19 146 #pack 4;
+#X obj 19 179 #grade;
+#X obj 19 208 #print;
+#X obj 0 0 doc_h;
+#X obj 3 250 doc_c 0;
+#X obj 3 290 doc_i 1;
+#X obj 3 350 doc_o 1;
+#X obj 14 380 doc_oo 0;
+#X obj 14 320 doc_ii 0;
+#X obj 97 320 doc_m i0 grid;
+#X obj 97 380 doc_m o0 grid;
+#X text 232 380 splits a Dim[A... \, B] grid into Dim[B] vectors \,
+producing new Dim[B] vectors that each contain numbers from 0 to B-1
+indicating the ordering of the values. The result is a Dim[A... \,
+B] grid.;
+#X text 232 441 for example \, connecting a [#grade] to a [#outer ignore
+0] to a [#store] object \, storing a single vector into [#store] \,
+and sending the same vector to [#grade] \, will sort the values of
+the vector. however for higher-dimensional grids \, what should go
+between [#store] and [#grade] to achieve the same result would be more
+complex.;
+#X text 232 541 you may achieve different kinds of sorting by applying
+various filters before [#grade]. the possibilities are unlimited. if
+you plug [#grade] directly into another [#grade] \, you will get the
+inverse arrangement \, which allows to take the sorted values and make
+them unsorted in the original way. note that this is really not the
+same as just listing the values backwards.;
+#X obj 0 651 doc_f;
+#X connect 1 0 5 0;
+#X connect 2 0 5 1;
+#X connect 3 0 5 2;
+#X connect 4 0 5 3;
+#X connect 5 0 6 0;
+#X connect 6 0 7 0;
+#X connect 15 1 16 0;
+#X connect 15 1 17 0;
+#X connect 15 1 18 0;
diff --git a/externals/gridflow/doc/flow_classes/#greyscale_to_rgb-help.pd b/externals/gridflow/doc/flow_classes/#greyscale_to_rgb-help.pd
new file mode 100644
index 00000000..c98ea289
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#greyscale_to_rgb-help.pd
@@ -0,0 +1,26 @@
+#N canvas 693 0 632 471 10;
+#X obj 19 161 s xx;
+#X obj 19 185 r xx;
+#X obj 19 105 #in;
+#X obj 19 141 #rgb_to_greyscale;
+#X obj 19 205 #greyscale_to_rgb;
+#X obj 19 243 #out window;
+#X msg 19 74 load bluemarble.jpg;
+#X obj 0 0 doc_h;
+#X obj 3 278 doc_c 0;
+#X obj 3 318 doc_i 1;
+#X obj 3 380 doc_o 1;
+#X obj 14 348 doc_ii 0;
+#X obj 14 410 doc_oo 0;
+#X obj 97 348 doc_m i0;
+#X obj 97 410 doc_m o0;
+#X text 232 410 rgb pixels;
+#X text 232 348 greyscale pixels;
+#X obj 0 442 doc_f;
+#X connect 1 0 4 0;
+#X connect 2 0 3 0;
+#X connect 3 0 0 0;
+#X connect 4 0 5 0;
+#X connect 6 0 2 0;
+#X connect 13 1 16 0;
+#X connect 14 1 15 0;
diff --git a/externals/gridflow/doc/flow_classes/#hello-help.pd b/externals/gridflow/doc/flow_classes/#hello-help.pd
new file mode 100644
index 00000000..d759b412
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#hello-help.pd
@@ -0,0 +1,23 @@
+#N canvas 610 97 632 367 10;
+#X obj 92 137 #out window;
+#X obj 92 117 #hello;
+#X obj 92 77 loadbang;
+#X obj 0 0 doc_h;
+#X obj 3 170 doc_c;
+#X obj 0 334 doc_f;
+#X obj 3 210 doc_i 1;
+#X obj 14 240 doc_ii 0;
+#X obj 97 240 doc_m i0 list;
+#X text 232 240 Size of the grid.;
+#X obj 3 272 doc_o 1;
+#X obj 14 302 doc_oo 0;
+#X obj 97 302 doc_m o0 grid;
+#X text 9 35 Generates a television test pattern of 7 colour bars à
+la SMPTE.;
+#X text 232 302 Returns a grid representing the 7 colour bars.;
+#X msg 92 97 200 200;
+#X connect 1 0 0 0;
+#X connect 2 0 15 0;
+#X connect 8 1 9 0;
+#X connect 12 1 14 0;
+#X connect 15 0 1 0;
diff --git a/externals/gridflow/doc/flow_classes/#hueshift-help.pd b/externals/gridflow/doc/flow_classes/#hueshift-help.pd
new file mode 100644
index 00000000..7b5853d7
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#hueshift-help.pd
@@ -0,0 +1,20 @@
+#N canvas 692 0 632 364 10;
+#X obj 0 0 doc_h;
+#X obj 65 74 #hueshift;
+#X obj 3 105 doc_c 0..1;
+#X obj 3 165 doc_i 2;
+#X obj 3 275 doc_o 1;
+#X obj 14 195 doc_ii 0;
+#X obj 14 243 doc_ii 1;
+#X obj 14 135 doc_cc 0;
+#X obj 14 305 doc_oo 0;
+#X obj 97 135 doc_m c0 float;
+#X obj 97 195 doc_m i0 grid;
+#X obj 97 243 doc_m i1 float;
+#X text 232 243 same as arg 0;
+#X obj 97 305 doc_m o0 grid;
+#X text 232 195 RGB picture that gets hueshifted by a rotation in the
+colorwheel by the specified angle \; it gets sent to outlet 0;
+#X obj 0 335 doc_f;
+#X connect 10 1 14 0;
+#X connect 11 1 12 0;
diff --git a/externals/gridflow/doc/flow_classes/#import-help.pd b/externals/gridflow/doc/flow_classes/#import-help.pd
new file mode 100644
index 00000000..2620c142
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#import-help.pd
@@ -0,0 +1,88 @@
+#N canvas 648 0 632 642 10;
+#X msg 55 123 reset;
+#X obj 13 59 bng 15 250 50 0 empty empty empty 0 -6 0 8 -24198 -1 -1
+;
+#X msg 13 123 200;
+#X obj 13 100 until;
+#X msg 13 79 230400;
+#X obj 13 177 #out window;
+#X text 232 250 The argument establishes grid dimensions in parentheses
+in the order of columns \, rows and grid dimensions.;
+#X text 232 456 Symbols are considered as a list of ascii characters.
+;
+#X text 232 478 Like a sequence of ints sent one after another \, except
+in a single message.;
+#X text 232 680 The grid resulting from the incoming integers and/or
+grids is output from the outlet.;
+#X text 99 24 This object allows you to produce grids from non-grid
+data \, such as integers and lists of integers. This object also reframes/resyncs
+grids so that multiple grids may be joined together \, or single grids
+may be split. That kind of operation is already done implicitly in
+many cases (e.g. sending an integer or list to a grid-receiving inlet)
+but using this object you have greater flexibility on the conversion.
+;
+#X text 232 421 This equivalent to filtering the grid through an [#to_float]
+object. It is over ten times faster.;
+#X msg 157 125 per_message;
+#X msg 158 147 240 320 3;
+#X text 232 347 Begins a new grid if there is no current grid. puts
+that integer in the current grid. ends the grid if it is full. the
+constructed grid is not stored: it is streamed. the stream is buffered
+\, so the output is in packets of about a thousand numbers.;
+#X text 232 579 "per message" : the grid will shape itself according
+to the incoming data. Almost obsolete as sending a list to any grid
+inlet will result in the same except the latter can not be cast to
+other than int32.;
+#X text 232 535 "to_ascii \$1" converts ints as decimal in ascii codes
+;
+#X obj 294 166 #import;
+#X msg 294 144 to_ascii \$1;
+#X floatatom 294 124 5 0 0 0 - - -;
+#X obj 294 188 #print;
+#X obj 0 0 doc_h;
+#X obj 3 317 doc_i 2;
+#X obj 13 149 #import (240 320 3);
+#X obj 3 650 doc_o 1;
+#X obj 3 220 doc_c 2;
+#X text 232 285 default: i;
+#X obj 14 347 doc_ii 0;
+#X obj 14 557 doc_ii 1;
+#X obj 14 250 doc_cc 0;
+#X obj 14 285 doc_cc 1;
+#X obj 97 250 doc_m c0 grid;
+#X obj 97 285 doc_m c1 numtype;
+#X obj 97 347 doc_m i0 float;
+#X obj 97 456 doc_m i0 symbol;
+#X obj 97 478 doc_m i0 list;
+#X obj 97 513 doc_m i0 reset;
+#X text 232 513 aborts the current grid if there is one.;
+#X obj 97 535 doc_m i0 to_ascii;
+#X obj 97 421 doc_m i0 grid;
+#X obj 97 579 doc_m i1 per_message;
+#X obj 97 557 doc_m i1 grid;
+#X obj 14 680 doc_oo 0;
+#X obj 97 680 doc_m o0 grid;
+#X obj 0 725 doc_f;
+#X text 232 557 same as arg 0;
+#X connect 0 0 23 0;
+#X connect 1 0 4 0;
+#X connect 2 0 23 0;
+#X connect 3 0 2 0;
+#X connect 4 0 3 0;
+#X connect 12 0 23 1;
+#X connect 13 0 23 1;
+#X connect 17 0 20 0;
+#X connect 18 0 17 0;
+#X connect 19 0 18 0;
+#X connect 23 0 5 0;
+#X connect 31 1 6 0;
+#X connect 32 1 26 0;
+#X connect 33 1 14 0;
+#X connect 34 1 7 0;
+#X connect 35 1 8 0;
+#X connect 36 1 37 0;
+#X connect 38 1 16 0;
+#X connect 39 1 11 0;
+#X connect 40 1 15 0;
+#X connect 41 1 45 0;
+#X connect 43 1 9 0;
diff --git a/externals/gridflow/doc/flow_classes/#in-help.pd b/externals/gridflow/doc/flow_classes/#in-help.pd
new file mode 100644
index 00000000..cbb4cd46
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#in-help.pd
@@ -0,0 +1,236 @@
+#N canvas 679 0 632 642 10;
+#X obj 354 172 #out window;
+#X text 13 34 This object imports a grid \, usually an image \, video
+or live stream.;
+#X msg 362 126 open working.jpg;
+#X obj 354 106 bng 15 250 50 0 empty empty empty 0 -6 0 8 -24198 -1
+-1;
+#X text 55 181 <--click here;
+#X text 232 759 "loop 0" - turns off the loop option. The video stops
+once it reaches the end.;
+#X text 232 1060 Signals the end of a file and when a file is unreadable.
+;
+#X text 232 1038 Displays the resulting grid when connected to [#out
+window];
+#N canvas 82 93 663 454 quicktime 0;
+#X text 9 9 The following messages can be used to set parameters for
+video (.mov) files.;
+#X text 128 283 different versions of LibQuickTime may include support
+for different codecs \, and some may also support entirely different
+wrapper formats such as AVI.;
+#X text 129 367 Codecs must be set before first frame is written.;
+#X text 128 330 QuickTime library for Macintosh: Apple QuickTime (some
+codecs/features may not be available).;
+#X obj 9 272 cnv 15 24 17 empty empty empty 20 12 0 14 -241291 -66577
+0;
+#X msg 38 230 codec jpg;
+#X msg 23 116 framerate 33;
+#X msg 33 203 colorspace rgb;
+#X msg 18 78 size 400 600;
+#X obj 10 272 #in;
+#X text 145 117 Number of frames per second.;
+#X msg 32 171 parameter jpeg_quality 85;
+#X text 187 147 Determines window size when reading a video file.;
+#X text 129 230 quicktime library for linux accepts LibQuickTime (libquicktime.so).
+codecs currently available are: Raw \, jpeg \, png \, mipa \, yuv2
+\, yuv4.;
+#X text 134 84 Sets height and width. Must be set before setting the
+codec parameters and after setting framerate and codec.;
+#X text 107 230 <--;
+#X text 108 80 <--;
+#X text 119 118 <--;
+#X text 108 80 <--;
+#X text 108 80 <--;
+#X text 162 147 <--;
+#X text 212 173 <--;
+#X text 139 206 <--;
+#X text 237 174 Sets compression quality (100 being the highest quality
+\, but a large file. 75-85 is the standard setting).;
+#X text 163 209 Other colorspaces include rgba \, bgr \, bgra \, yuv
+\, yuva.;
+#X msg 10 54 open example.mov;
+#X msg 28 145 force_size 480 640;
+#X obj 103 427 #record;
+#X text 15 427 see also :;
+#X connect 5 0 9 0;
+#X connect 6 0 9 0;
+#X connect 7 0 9 0;
+#X connect 8 0 9 0;
+#X connect 11 0 9 0;
+#X connect 25 0 9 0;
+#X connect 26 0 9 0;
+#X restore 251 964 pd quicktime file messages;
+#X obj 354 150 #in;
+#X floatatom 202 195 5 0 0 0 - - -;
+#X msg 202 151 set 2;
+#X msg 202 107 loop 0;
+#X msg 202 129 loop 1;
+#X floatatom 32 285 5 0 0 0 - - -;
+#X msg 202 173 rewind;
+#X obj 41 267 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 17 227 #in;
+#X text 39 98 <--click here;
+#X obj 17 96 tgl 15 0 empty empty empty 0 -6 0 8 -24198 -1 -1 0 1;
+#X obj 17 120 metro 33.3;
+#X obj 356 234 bng 15 250 50 0 empty empty empty 0 -6 0 8 -24198 -1
+-1;
+#X obj 356 280 #out window;
+#X obj 356 258 #in sewing.jpg;
+#X text 378 234 <--click here;
+#X text 183 947 For info about messages specifically for quickTime
+files \, click on:;
+#N canvas 150 0 874 560 more 0;
+#X msg 191 388 open videodev \$1 \, get;
+#X msg 52 147 brightness 1000;
+#X msg 41 124 hue 1000;
+#X msg 26 101 color 1000;
+#X msg 65 171 contrast 1000;
+#X msg 14 78 whiteness 1000;
+#X msg 80 264 channel 2;
+#X msg 80 294 tuner 2;
+#X msg 81 324 norm 2;
+#X msg 81 352 frequency 2;
+#X msg 190 456 transfer mmap 4;
+#X msg 191 356 transfer read;
+#X msg 190 434 colorspace RGB24;
+#X msg 191 411 size 400 600;
+#X obj 14 441 #in;
+#X obj 192 172 #contrast;
+#X text 166 172 or;
+#X text 306 411 Sets height and width of the input.;
+#X text 322 488 In the case of mmap \, the extra numeric argument sets
+the queue length in number of frames \, so you can select an appropriate
+tradeoff between efficiency and latency.;
+#X text 16 12 Grid Settings;
+#X text 322 457 This is the standard and fastest way to receive pictures
+from the camera.;
+#X text 121 99 Message "get brightness" or "get" followed by any of
+the other colour attributes will display its values in the console.
+;
+#X text 375 390 Opens video device.;
+#X text 331 435 Supported values are RGB24 or YUV420P.;
+#X text 14 48 Color Adjustments;
+#X text 144 75 Values from 0 to 65535;
+#X text 283 412 <--;
+#X text 309 435 <--;
+#X text 345 390 <--;
+#X text 300 456 <--;
+#X text 287 357 <--;
+#X text 310 357 Some cameras/drivers only support "transfer read" and
+not mmap.;
+#X text 6 520 see also :;
+#X obj 92 520 #camera;
+#X connect 0 0 14 0;
+#X connect 1 0 14 0;
+#X connect 2 0 14 0;
+#X connect 3 0 14 0;
+#X connect 4 0 14 0;
+#X connect 5 0 14 0;
+#X connect 6 0 14 0;
+#X connect 7 0 14 0;
+#X connect 8 0 14 0;
+#X connect 9 0 14 0;
+#X connect 10 0 14 0;
+#X connect 11 0 14 0;
+#X connect 12 0 14 0;
+#X connect 13 0 14 0;
+#X restore 251 925 pd more info about video devices;
+#X text 183 908 For info about messages specifically for video devices
+\, click on:;
+#X text 169 213 (and turn off the metro);
+#X text 244 195 <-- vary this;
+#X text 352 74 IMAGE FILES:;
+#X text 12 72 VIDEO FILES:;
+#X obj 28 183 bng 15 250 50 0 empty empty empty 0 -6 0 8 -24198 -1
+-1;
+#X text 380 106 <-- click here;
+#X text 68 265 <-- sends a bang upon reaching;
+#X text 97 278 the end of the file;
+#X obj 17 305 #out window \, title video;
+#X text 232 724 "loop 1" - Restarts a video each time it reaches the
+end (default setting).;
+#X obj 41 248 route bang;
+#X msg 24 147 open violoncelle.mov;
+#X obj 0 0 doc_h;
+#X obj 3 450 doc_i 1;
+#X obj 3 1008 doc_o 2;
+#X obj 14 480 doc_ii 0;
+#X obj 14 1038 doc_oo 0;
+#X obj 14 1060 doc_oo 1;
+#X obj 3 332 doc_c 1..2;
+#X text 164 389 auto-open with auto-detect of the format-handler;
+#X text 207 409 auto-open with manual choice of the format-handler
+;
+#X obj 97 794 doc_m i0 open;
+#X obj 97 851 doc_m i0 set;
+#X obj 97 667 doc_m i0 close;
+#X obj 97 829 doc_m i0 rewind;
+#X obj 97 724 doc_m i0 loop;
+#X obj 97 645 doc_m i0 float int;
+#X obj 97 1038 doc_m o0 grid;
+#X obj 97 1060 doc_m o1 bang;
+#X obj 3 1127 doc_also;
+#X obj 103 1127 #out;
+#X obj 32 370 #in;
+#X obj 33 391 #in filename.suffix;
+#X obj 34 411 #in handler filename.suffix;
+#X text 64 369 nothing opened \, you have to open by yourself;
+#X text 232 794 \$1=filename. sends it as a resource to [#in]. For
+example: "open sewing.jpg".;
+#X obj 97 480 doc_m i0 bang;
+#X obj 97 1082 doc_m o1 float int;
+#X text 232 1082 frame number of the frame currently being viewed.
+Applies to formats that have frame numbers \, i.e. video.;
+#X text 232 480 A bang reads a frame and sends it through the outlet.
+Since frames from videos and live streams are read as a series of individual
+grids \, successive bangs advance through the frames. A bang reads
+a frame and sends it through the outlet. Since frames from videos and
+live streams are read as a series of individual grids \, successive
+bangs advance through the frames. this is format-specific. most formats
+produce grids that have dimensions (rows columns rgb). In formats that
+read from a file \, reading another picture will continue if there
+are several pictures in the same file \, but if the end of file is
+reached instead \, it will rewind and send the first picture again.
+;
+#X obj 0 1147 doc_f;
+#X text 232 667 Closes the video input device. Only necessary when
+you are using a live capture device.;
+#X text 232 829 Will rewind video to the beginning.;
+#X text 232 851 select the video frame numbered \$1 \, where 0 is the
+first frame. A bang must be sent to [#in] in order to display the frame.
+this only works with video file formats.;
+#X text 232 645 same as set \$1 \, bang;
+#X obj 97 702 doc_m i0 load;
+#X text 232 702 shortcut for open \$1 \, bang \, close;
+#X connect 2 0 9 0;
+#X connect 3 0 9 0;
+#X connect 9 0 0 0;
+#X connect 10 0 17 0;
+#X connect 11 0 17 0;
+#X connect 12 0 17 0;
+#X connect 13 0 17 0;
+#X connect 15 0 17 0;
+#X connect 17 0 36 0;
+#X connect 17 1 14 0;
+#X connect 17 1 38 0;
+#X connect 19 0 20 0;
+#X connect 20 0 17 0;
+#X connect 21 0 23 0;
+#X connect 23 0 22 0;
+#X connect 32 0 17 0;
+#X connect 38 0 16 0;
+#X connect 39 0 17 0;
+#X connect 49 1 63 0;
+#X connect 50 1 71 0;
+#X connect 51 1 69 0;
+#X connect 52 1 70 0;
+#X connect 53 1 37 0;
+#X connect 53 1 5 0;
+#X connect 54 1 72 0;
+#X connect 55 1 7 0;
+#X connect 56 1 6 0;
+#X connect 57 1 58 0;
+#X connect 64 1 67 0;
+#X connect 65 1 66 0;
+#X connect 73 1 74 0;
diff --git a/externals/gridflow/doc/flow_classes/#inner-help.pd b/externals/gridflow/doc/flow_classes/#inner-help.pd
new file mode 100644
index 00000000..612a2c6a
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#inner-help.pd
@@ -0,0 +1,56 @@
+#N canvas 666 0 632 642 10;
+#X obj 0 0 doc_h;
+#X obj 3 158 doc_c 1;
+#X obj 3 218 doc_i 2;
+#X obj 3 560 doc_o 1;
+#X obj 14 188 doc_cc 0;
+#X obj 14 248 doc_ii 0;
+#X obj 14 528 doc_ii 1;
+#X obj 14 590 doc_oo 0;
+#X text 232 248 Splits the Dim(anyA... \, lastA) left-hand grid into
+Dim(anyA...) pieces of Dim(lastA) size.;
+#X text 232 283 Splits the Dim(firstB \, anyB...) right-hand grid into
+Dim(anyB...) pieces of Dim(firstB) size.;
+#X text 232 318 On every piece pair \, does [#] using the specified
+op_para operation \, followed by a [#fold] using the specified op_fold
+operator and base value.;
+#X text 232 366 creates a Dim(anyA... \, anyB...) grid by assembling
+all the results together.;
+#X text 232 401 (note: lastA must be equal to firstB.);
+#X text 232 528 same as arg 0;
+#X text 232 471 the operation that combines the values from the two
+grids together. this defaults to "*" (as in the matrix product);
+#X text 232 423 the operation that combines the result of the "op"
+operations together. this defaults to "+" (as in the matrix product)
+;
+#X text 232 506 the base value for the fold;
+#X obj 0 640 doc_f;
+#X obj 97 248 doc_m i0 grid;
+#X obj 97 188 doc_m c0 grid;
+#X obj 97 471 doc_m i0 op;
+#X obj 97 506 doc_m i0 seed;
+#X obj 97 528 doc_m i1 grid;
+#X obj 97 590 doc_m o0 grid;
+#X obj 97 423 doc_m i0 fold;
+#X obj 3 620 doc_also;
+#X obj 103 620 #outer *;
+#X obj 163 620 #fold +;
+#X obj 62 89 #inner;
+#X text 160 48 think of this one as a special combination of [#outer]
+\, [#] and [#fold]. this is one of the most complex operations. It
+is very useful for performing linear transforms like rotations \, scalings
+\, shearings \, and some kinds of color remappings. A linear transform
+is done by something called matrix multiplication \, which happens
+to be [#inner]. [#inner] also does dot product and other funny operations.
+;
+#X connect 18 1 8 0;
+#X connect 18 1 9 0;
+#X connect 18 1 10 0;
+#X connect 18 1 11 0;
+#X connect 18 1 12 0;
+#X connect 20 1 14 0;
+#X connect 21 1 16 0;
+#X connect 22 1 13 0;
+#X connect 24 1 15 0;
+#X connect 25 1 26 0;
+#X connect 25 1 27 0;
diff --git a/externals/gridflow/doc/flow_classes/#io.aalib-help.pd b/externals/gridflow/doc/flow_classes/#io.aalib-help.pd
new file mode 100644
index 00000000..e97765d1
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#io.aalib-help.pd
@@ -0,0 +1,45 @@
+#N canvas 684 0 632 568 10;
+#X obj 0 0 doc_h;
+#X obj 3 67 doc_c;
+#X msg 48 109 open aalib X11;
+#X text 161 105 Normally "X11" with uppercase X \; else consult the
+AALib manual.;
+#X text 161 141 you can pass "commandline options" of AALib here \,
+after "X11" or whichever other thing you chose instead of "X11".;
+#X obj 3 179 doc_i 1;
+#X obj 3 477 doc_o 1;
+#X obj 14 209 doc_ii 0;
+#X obj 14 507 doc_oo 0;
+#X obj 97 507 doc_m o0 grid;
+#X obj 97 209 doc_m i0 grid;
+#X text 232 209 grid(rows columns 1): converts a greyscale image to
+an ascii image and possibly displays it. note that the image is typically
+downscaled by a factor of 2 by aalib itself.;
+#X text 232 257 grid(rows columns 2): the inverse of "dump". Both together
+in a loop allow to post-process aalib's buffer before displaying. Goes
+well with "draw" \, "autodraw". the first channel is for the ascii
+codes and the second channel is for the attributes (colour \, blink).
+;
+#X obj 97 432 doc_m i0 print;
+#X text 232 432 \$1=y \$2=x \$3=attr \$4=text where text is a symbol
+and the rest are ints.;
+#X obj 97 331 doc_m i0 autodraw;
+#X text 232 331 "autodraw 1" does a "draw" after each incoming grid.
+;
+#X text 232 353 "autodraw 0" does not.;
+#X obj 97 375 doc_m i0 draw;
+#X text 232 375 eventually you need to use this if you use "autodraw
+0".;
+#X obj 97 397 doc_m i0 dump;
+#X text 232 397 produces a Dim[y \, x \, 2] grid whose two channels
+are ascii character codes and character attributes.;
+#X obj 0 539 doc_f;
+#X text 232 507 result of 'dump';
+#X connect 9 1 23 0;
+#X connect 10 1 11 0;
+#X connect 10 1 12 0;
+#X connect 13 1 14 0;
+#X connect 15 1 16 0;
+#X connect 15 1 17 0;
+#X connect 18 1 19 0;
+#X connect 20 1 21 0;
diff --git a/externals/gridflow/doc/flow_classes/#io.grid-help.pd b/externals/gridflow/doc/flow_classes/#io.grid-help.pd
new file mode 100644
index 00000000..fc30e0cc
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#io.grid-help.pd
@@ -0,0 +1,44 @@
+#N canvas 689 0 632 608 10;
+#X obj 0 0 doc_h;
+#X obj 3 160 doc_i 1;
+#X text 62 37 This is GridFlow's special file format. This is the only
+I/O format that can hold nearly anything that the [#store] object can.
+;
+#X obj 3 92 doc_c ...;
+#X msg 62 127 open foo.grid;
+#X obj 14 190 doc_ii 0;
+#X obj 97 465 doc_m i0 type;
+#X text 232 465 type that the output will be written as. (#out only)
+;
+#X text 232 487 supported: uint8 int32 and perhaps some others;
+#X obj 97 369 doc_m i0 headerful;
+#X obj 97 404 doc_m i0 headerless;
+#X text 232 369 cancels "headerless" (and back to reading the real
+.grid format);
+#X text 232 404 instead of reading .grid files with header \, will
+read raw data \, faking a .grid header to itself. It will use the hereby
+specified dimension list \, as well as two other settings: type and
+endian.;
+#X obj 97 190 doc_m i0 endian;
+#X text 232 190 When writing "raw" data \, a file may be considered
+a long string of base 256 digits (called bytes) \, but different computers
+have different conventions for dealing with them:;
+#X text 232 238 big: A number will be written starting with the biggest
+digit. This is the natural way on the Macintosh \, Sun \, Amiga \,
+and so on.;
+#X text 232 286 little: A number will be written starting with the
+smallest digit. This is the natural way on the Intel 386/Pentium.;
+#X text 232 321 same: A number will be written in whichever way is
+more natural on this computer. The natural way is slightly faster to
+handle. This is the default setting.;
+#X obj 0 579 doc_f;
+#X obj 3 519 doc_o 1;
+#X obj 14 549 doc_oo 0;
+#X connect 6 1 7 0;
+#X connect 6 1 8 0;
+#X connect 9 1 11 0;
+#X connect 10 1 12 0;
+#X connect 13 1 14 0;
+#X connect 13 1 15 0;
+#X connect 13 1 16 0;
+#X connect 13 1 17 0;
diff --git a/externals/gridflow/doc/flow_classes/#io.jpeg-help.pd b/externals/gridflow/doc/flow_classes/#io.jpeg-help.pd
new file mode 100644
index 00000000..363c48a7
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#io.jpeg-help.pd
@@ -0,0 +1,16 @@
+#N canvas 666 0 632 245 10;
+#X obj 0 0 doc_h;
+#X obj 3 70 doc_i 1;
+#X obj 3 30 doc_c;
+#X obj 3 176 doc_o;
+#X obj 0 216 doc_f;
+#X obj 14 100 doc_ii 0;
+#X obj 97 100 doc_m i0 bang;
+#X obj 97 122 doc_m i0 grid;
+#X obj 97 144 doc_m i0 quality;
+#X text 232 100 read image (when in [#in]);
+#X text 232 122 write image (when in [#out]);
+#X text 232 144 quality percentage (when in [#out]);
+#X connect 6 1 9 0;
+#X connect 7 1 10 0;
+#X connect 8 1 11 0;
diff --git a/externals/gridflow/doc/flow_classes/#io.png-help.pd b/externals/gridflow/doc/flow_classes/#io.png-help.pd
new file mode 100644
index 00000000..0a2f1d05
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#io.png-help.pd
@@ -0,0 +1,18 @@
+#N canvas 674 0 632 267 10;
+#X obj 0 0 doc_h;
+#X obj 3 70 doc_i 1;
+#X obj 14 100 doc_ii 0;
+#X obj 97 100 doc_m i0 grid;
+#X text 232 100 1-channel is taken as Y 8 (greyscale);
+#X text 232 122 2-channel is taken as YA 8:8 (greyscale and transparency)
+;
+#X text 232 144 3-channel is taken as RGB 8:8:8;
+#X text 232 166 4-channel is taken as RGBA 8:8:8 (colour with transparency)
+;
+#X obj 3 30 doc_c;
+#X obj 3 198 doc_o;
+#X obj 0 238 doc_f;
+#X connect 3 1 4 0;
+#X connect 3 1 5 0;
+#X connect 3 1 6 0;
+#X connect 3 1 7 0;
diff --git a/externals/gridflow/doc/flow_classes/#io.quicktime-help.pd b/externals/gridflow/doc/flow_classes/#io.quicktime-help.pd
new file mode 100644
index 00000000..c4cb6713
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#io.quicktime-help.pd
@@ -0,0 +1,69 @@
+#N canvas 668 0 632 642 10;
+#X obj 0 0 doc_h;
+#X obj 3 218 doc_i 1;
+#X obj 14 248 doc_ii 0;
+#X text 190 43 Support for .mov files. This format supports frame-seek
+and frame-tell. Uses the HW-QuickTime library aka QuickTime4Linux (libquicktime.so).
+There is also a variant on the same library and that project is just
+called LibQuickTime. Some versions of those libraries may include support
+for different codecs \, and some also may support entirely different
+wrapper formats such as AVI. On Macintosh \, Apple QuickTime is used
+instead \, but several of the following messages may not be available.
+;
+#X obj 97 248 doc_m i0 codec;
+#X text 232 248 Allowed values are at least: raw \, jpeg \, png \,
+mjpa \, yuv2 \, yuv4. Some other values may allowed \, depending on
+the version of the library and which codec plugins are installed. Must
+be set before the first frame is written. only applies to [#out]. Choosing
+a codec is important because codecs influence greatly the speed of
+encoding \, the speed of decoding \, the size of the written file \,
+and its fidelity to the original content. Note that there exist other
+Apple-QuickTime codecs that are not supported by HW-QuickTime.;
+#X obj 97 584 doc_m i0 parameter;
+#X text 232 584 \$1=symbol \$2=int;
+#X text 232 606 Sets special codec-specific settings. For example:
+"parameter jpeg_quality 75";
+#X obj 97 479 doc_m i0 framerate;
+#X text 232 479 \$1=int;
+#X text 232 501 Sets the framerate of the file. This is not used by
+GridFlow when reading a file \, but other programs usually care.;
+#X obj 97 387 doc_m i0 colorspace;
+#X text 232 387 Allowed values are rgb \, rgba \, bgr \, bgra \, yuv
+\, yuva. Normally you don't need this.;
+#X obj 97 641 doc_m i0 size;
+#X text 232 641 \$1=height \$2=width;
+#X obj 3 721 doc_o 1;
+#X obj 3 901 doc_also;
+#X text 232 663 Forces a window size when writing. Usually this has
+to be used _after_ setting the framerate and codec and _before_ setting
+the codec-parameters. (Strange. Sorry.);
+#X text 232 422 \$1=height \$2=width;
+#X text 232 444 forces a window size when reading. this is a workaround
+for a problem in HW-QuickTime.;
+#X obj 3 178 doc_c;
+#X obj 0 921 doc_f;
+#X obj 97 422 doc_m i0 force_size;
+#X obj 97 549 doc_m i0 get;
+#X text 232 549 output various properties of the video that is open
+(#in) (see outlet 0);
+#X obj 14 751 doc_oo 0;
+#X obj 103 901 #io.mpeg;
+#X obj 97 751 doc_m o0 grid;
+#X obj 97 771 doc_m o0 codec symbol;
+#X obj 97 791 doc_m o0 depth float;
+#X obj 97 811 doc_m o0 framerate float;
+#X obj 97 831 doc_m o0 frames float;
+#X obj 97 851 doc_m o0 height float;
+#X obj 97 871 doc_m o0 width float;
+#X connect 4 1 5 0;
+#X connect 6 1 7 0;
+#X connect 6 1 8 0;
+#X connect 9 1 10 0;
+#X connect 9 1 11 0;
+#X connect 12 1 13 0;
+#X connect 14 1 15 0;
+#X connect 14 1 18 0;
+#X connect 17 1 27 0;
+#X connect 23 1 19 0;
+#X connect 23 1 20 0;
+#X connect 24 1 25 0;
diff --git a/externals/gridflow/doc/flow_classes/#io.videodev-help.pd b/externals/gridflow/doc/flow_classes/#io.videodev-help.pd
new file mode 100644
index 00000000..af431363
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#io.videodev-help.pd
@@ -0,0 +1,77 @@
+#N canvas 676 0 632 642 10;
+#X obj 0 0 doc_h;
+#X obj 26 50 #in videodev;
+#X obj 3 99 doc_c ...;
+#X obj 3 160 doc_i 1;
+#X obj 3 898 doc_o 1;
+#X obj 3 995 doc_also;
+#X obj 103 995 #io:quicktimecamera;
+#X msg 28 129 open videodev /dev/video0;
+#X obj 14 190 doc_ii 0;
+#X obj 97 210 doc_m i0 brightness;
+#X obj 97 539 doc_m i0 hue;
+#X obj 97 338 doc_m i0 colour;
+#X obj 97 378 doc_m i0 contrast;
+#X obj 97 868 doc_m i0 whiteness;
+#X obj 97 418 doc_m i0 get;
+#X obj 97 519 doc_m i0 help;
+#X obj 97 230 doc_m i0 channel;
+#X obj 97 768 doc_m i0 tuner;
+#X obj 97 579 doc_m i0 norm;
+#X obj 97 398 doc_m i0 frequency;
+#X obj 97 619 doc_m i0 transfer symbol;
+#X text 232 619 "read";
+#X text 232 663 "mmap": \$1=nframes (default:2);
+#X text 232 685 This is the normal (and fast) way of transferring pictures
+from the camera.;
+#X text 232 641 Some cameras/drivers only support this instead of mmap.
+;
+#X obj 97 828 doc_m i0 white_red;
+#X obj 97 788 doc_m i0 white_blue;
+#X obj 97 848 doc_m i0 white_speed;
+#X obj 97 808 doc_m i0 white_delay;
+#X obj 97 190 doc_m i0 auto_gain;
+#X obj 97 559 doc_m i0 noise_reduction;
+#X obj 97 358 doc_m i0 compression;
+#X obj 97 250 doc_m i0 colorspace;
+#X text 232 250 "y":;
+#X text 232 272 "yuv":;
+#X text 232 294 "rgb":;
+#X text 232 316 "magic":;
+#X obj 97 599 doc_m i0 size;
+#X text 188 764 \$1=y \$2=x;
+#X text 232 453 "min": minimum values for "size";
+#X text 232 475 "max": maximum values for "size";
+#X text 232 497 default: gets all attributes.;
+#X text 232 418 gets a specific attribute. a message is sent through
+right outlet.;
+#X text 232 720 In case of mmap \, the extra numeric argument sets
+the queue length in number of frames \, so you can select an appropriate
+tradeoff between efficiency and latency.;
+#X obj 0 1015 doc_f;
+#X obj 229 995 #io.dc1394;
+#X obj 14 928 doc_oo 0;
+#X obj 97 928 doc_m o0 grid;
+#X obj 97 950 doc_m o0 <any>;
+#X text 232 928 image coming out;
+#X text 232 950 most any inlet 0 message is also an outlet 0 message
+whose output can be triggered using 'get'.;
+#X text 130 51 get images from a V4L1 camera interface.;
+#X text 130 66 this is for Linux only.;
+#X connect 5 1 6 0;
+#X connect 5 1 45 0;
+#X connect 14 1 42 0;
+#X connect 14 1 39 0;
+#X connect 14 1 40 0;
+#X connect 14 1 41 0;
+#X connect 20 1 21 0;
+#X connect 20 1 24 0;
+#X connect 20 1 22 0;
+#X connect 20 1 23 0;
+#X connect 20 1 43 0;
+#X connect 32 1 33 0;
+#X connect 32 1 34 0;
+#X connect 32 1 35 0;
+#X connect 32 1 36 0;
+#X connect 47 1 49 0;
+#X connect 48 1 50 0;
diff --git a/externals/gridflow/doc/flow_classes/#io.x11-help.pd b/externals/gridflow/doc/flow_classes/#io.x11-help.pd
new file mode 100644
index 00000000..2ccd9a29
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#io.x11-help.pd
@@ -0,0 +1,150 @@
+#N canvas 648 0 632 642 10;
+#X obj 0 0 doc_h;
+#X obj 3 517 doc_c 0..;
+#X msg 40 554 open x11;
+#X msg 40 574 open x11 here;
+#X msg 40 614 open x11 local 0;
+#X text 178 555 synonym of "open x11 here".;
+#X text 181 574 connects to the default X11 server \, according to
+your environment variable "DISPLAY".;
+#X text 182 614 connects to a display server on this machine.;
+#X msg 39 645 open x11 remote foo.org 0;
+#X text 201 644 connects to a remote X11 display server using TCP.
+Port number will be 6000 plus the display number \, because of the
+X11 standard.;
+#X text 141 38 supports 15 \, 16 \, 24 \, 32-bit truecolor displays
+;
+#X text 141 57 now also support 8-bit indexed displays \, using a private
+colormap configured as 3:3:2 RGB. When using 8-bit you can specify
+the "use_stripes" option to use a completely different color scheme
+involving R \, G \, B diagonal stripes \, a kind of 6:6:6 RGB spread
+over three pixels.;
+#X text 141 129 If you are using Windows or MacOS 10: you will have
+to install a X11 server. This will emulate Unix display on your OS.
+(note: Unix systems also need a X11 server \, but it's built-in and
+handles the video driver directly). In the case of MacOS 10 and QNX
+that both use non-X11 display technology on top of a basically Unix
+OS \, the OS comes with a X11 server \, but it may be on a "bundled
+software" CD.;
+#X msg 37 700 open x11 display foo.org:0;
+#X obj 3 736 doc_i 1;
+#X obj 14 766 doc_ii 0;
+#X obj 97 788 doc_m i0 grid;
+#X text 232 788 with [#out] \, displays a frame;
+#X obj 97 766 doc_m i0 bang;
+#X text 232 766 with [#in] \, captures a frame;
+#X obj 97 852 doc_m i0 out_size;
+#X text 232 852 \$1=height \$2=width. changes the window's size \,
+just like sending a grid dim(height \, width \, 3) would. this affects
+the size of screen captures too.;
+#X obj 97 920 doc_m i0 setcursor;
+#X text 232 920 \$1=cursor_id. \$1=cursor_id. Selects one of the 64
+predefined cursors of X11. (Note that if your cursor table has them
+numbered from 0 to 126 using only even numbers \, then those cursor
+numbers are all doubled compared to the ones GridFlow uses.);
+#X obj 97 810 doc_m i0 hidecursor;
+#X text 232 810 This makes the cursor invisible.;
+#X obj 3 1903 doc_also;
+#X obj 103 1903 #io.quartz;
+#X obj 175 1903 #io.sdl;
+#X text 141 227 Destroying the object (or sending "close") should close
+the window.;
+#X obj 35 65 #out x11;
+#X text 140 259 because of the design of Xlib \, or if any of the connections
+involved crashes \, then the whole program has to be terminated. (don't
+you love xlib). Something similar happens if you close any of the windows
+yourself \, but IIRC this could be fixed.;
+#X text 140 330 only one window may be used per x11 connection (to
+simplify matters \; this doesn't reduce flexibility).;
+#X text 140 375 there is an additional argument that may be added to
+every "open" message \; if you don't put it \, a new toplevel window
+is created. if you put "root" then the screen's wallpaper will be used
+instead (it may fail to work with some popular window managers). You
+can also put a window number \, e.g. 0x28003ff \, you may connect to
+an existing window \; you can find out the number of a window by using
+a tool like xwininfo \, part of X11 standard tools.;
+#X obj 3 1084 doc_o 1;
+#X obj 14 1114 doc_oo 0;
+#X obj 97 1114 doc_m o0 grid;
+#X text 232 1114 grid(rows columns rgb);
+#X text 232 1136 resizes the window to the size of the grid \; encodes
+that grid in the display's pixel format \; also displays it if autodraw
+&gt \; 0 the values must be in range 0-255 \, or else they will be
+"wrapped".;
+#X obj 97 1415 doc_m o0 position;
+#X text 232 1415 \$1=y \$2=x \$3=buttons;
+#X text 232 1437 This is emitted every time the cursor moves inside
+the window connected to this format handler. This is also emitted when
+the cursor is dragging from inside to outside the window. This is also
+emitted when a mouse button is pressed.;
+#X text 232 1511 The y and x coordinates are relative to the upper
+right corner of the window. Specific button states may be extracted
+from the button value by applying [>> buttonnumber] and then checking
+whether the result is odd.;
+#X text 232 1572 0: Shift;
+#X text 232 1594 1: Caps Lock;
+#X text 232 1616 2: Control;
+#X text 232 1638 3: Alternate;
+#X text 232 1660 4: NumLock;
+#X text 232 1682 5: (unknown);
+#X text 232 1704 6: Meta or Window Key;
+#X text 232 1726 7: Scroll Lock;
+#X text 232 1748 8: Left Mouse Button;
+#X text 232 1770 9: Middle Mouse Button or Mouse Wheel Click;
+#X text 232 1792 10: Right Mouse Button;
+#X text 232 1814 11: Wheel Up;
+#X text 232 1836 12: Wheel Down;
+#X text 232 1858 NOTE: This message form may become longer in the future
+\, but the already defined parts will stay the same.;
+#X obj 97 1210 doc_m o0 keypress;
+#X obj 97 1345 doc_m o0 keyrelease;
+#X text 232 1210 \$1=y \$2=x \$3=buttons \$4=keyname;
+#X text 232 1345 \$1=y \$2=x \$3=buttons \$4=keyname;
+#X text 232 1232 Similar to position above \, but this is emitted when
+a keyboard key is pressed while this format handler's window is active.
+Keynames follow the X11 standard \, similarly to PureData's [keyname]
+object. The only exception is that keynames that are digits get prefixed
+by a capital D so that they don't get mistaken for actual numbers.
+NOTE: This message form may become longer in the future \, but the
+already defined parts will stay the same.;
+#X text 232 1367 Same as keypress but when a key gets released instead.
+NOTE: This message form may become longer in the future \, but the
+already defined parts will stay the same.;
+#X obj 0 1923 doc_f;
+#X obj 97 832 doc_m i0 move;
+#X obj 97 994 doc_m i0 shared_memory;
+#X obj 97 1054 doc_m i0 xvideo;
+#X obj 97 1014 doc_m i0 title;
+#X obj 97 1034 doc_m i0 warp;
+#X obj 97 900 doc_m i0 set_geometry;
+#X text 208 701 other syntax for 'remote'.;
+#X connect 16 1 17 0;
+#X connect 18 1 19 0;
+#X connect 20 1 21 0;
+#X connect 22 1 23 0;
+#X connect 24 1 25 0;
+#X connect 26 1 27 0;
+#X connect 26 1 28 0;
+#X connect 36 1 37 0;
+#X connect 36 1 38 0;
+#X connect 39 1 40 0;
+#X connect 39 1 41 0;
+#X connect 39 1 42 0;
+#X connect 39 1 43 0;
+#X connect 39 1 44 0;
+#X connect 39 1 45 0;
+#X connect 39 1 46 0;
+#X connect 39 1 47 0;
+#X connect 39 1 48 0;
+#X connect 39 1 49 0;
+#X connect 39 1 50 0;
+#X connect 39 1 51 0;
+#X connect 39 1 52 0;
+#X connect 39 1 53 0;
+#X connect 39 1 54 0;
+#X connect 39 1 55 0;
+#X connect 39 1 56 0;
+#X connect 57 1 59 0;
+#X connect 57 1 61 0;
+#X connect 58 1 60 0;
+#X connect 58 1 62 0;
diff --git a/externals/gridflow/doc/flow_classes/#join-help.pd b/externals/gridflow/doc/flow_classes/#join-help.pd
new file mode 100644
index 00000000..10e71f1c
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#join-help.pd
@@ -0,0 +1,72 @@
+#N canvas 648 0 632 642 10;
+#X obj 18 42 bng 15 250 50 0 empty empty empty 0 -6 0 8 -233017 -1
+-1;
+#X obj 211 40 bng 15 250 50 0 empty empty empty 0 -6 0 8 -233017 -1
+-1;
+#X text 174 228 the left grid and right grid must have the same number
+of elements in all dimensions except the one specified \, which will
+be the sum of the two corresponding;
+#X text 244 39 1 <--;
+#X text 45 41 2 <--;
+#X obj 18 222 #clip;
+#X obj 18 241 #out window;
+#X obj 18 106 #in;
+#X obj 211 125 #rgb_to_greyscale;
+#X obj 211 106 #in;
+#X obj 18 188 #perspective 128;
+#X text 175 160 creation argument is the index of the dimension by
+which the join will occur. for n-dimensional grids \, the dimensions
+are numbered from 0 to n-1. in addition \, negative numbers from -n
+to -1 may be used \, to which n will be added.;
+#X obj 0 0 doc_h;
+#X obj 3 666 doc_also;
+#X obj 3 288 doc_c 0..2;
+#X obj 3 409 doc_i 2;
+#X obj 3 606 doc_o 1;
+#X obj 18 161 #join 2;
+#X obj 14 318 doc_cc 0;
+#X obj 14 379 doc_cc 1;
+#X obj 14 439 doc_ii 0;
+#X obj 14 574 doc_ii 1;
+#X obj 14 636 doc_oo 0;
+#X obj 97 318 doc_m c0 float;
+#X obj 97 379 doc_m c1 grid;
+#X obj 97 439 doc_m i0;
+#X text 232 318 Which_dim is the number of the dimension by which the
+join will occur. For N-dimensional grids \, the dimensions are numbered
+from 0 to N-1. In addition \, negative numbers from -N to -1 may be
+used \, to which N will be added.;
+#X text 232 439 The left grid and right grid must have the same number
+of elements in all dimensions except the one specified. The result
+will have the same number of elements in all dimensions except the
+one specified \, which will be the sum of the two corresponding one.
+;
+#X text 232 513 For example \, joining a RGB picture Dim[y \, x \,
+3] and a greyscale picture Dim[y \, x \, 1] on dimension 2 (or -1)
+could make a RGBA picture Dim[y \, x \, 4] in which the greyscale image
+becomes the opacity channel.;
+#X text 232 574 same as arg 1;
+#X obj 97 574 doc_m i1 grid;
+#X obj 97 636 doc_m o0 grid;
+#X obj 0 686 doc_f;
+#X msg 18 83 load r001.jpg;
+#X msg 211 78 load b001.jpg;
+#X obj 103 666 listappend;
+#X obj 175 666 list append;
+#X text 234 381 grid to be appended to the left-inlet grid;
+#X connect 0 0 33 0;
+#X connect 1 0 34 0;
+#X connect 5 0 6 0;
+#X connect 7 0 17 0;
+#X connect 8 0 17 1;
+#X connect 9 0 8 0;
+#X connect 10 0 5 0;
+#X connect 13 1 35 0;
+#X connect 13 1 36 0;
+#X connect 17 0 10 0;
+#X connect 23 1 26 0;
+#X connect 25 1 27 0;
+#X connect 25 1 28 0;
+#X connect 30 1 29 0;
+#X connect 33 0 7 0;
+#X connect 34 0 9 0;
diff --git a/externals/gridflow/doc/flow_classes/#labelling-help.pd b/externals/gridflow/doc/flow_classes/#labelling-help.pd
new file mode 100644
index 00000000..053b6ee0
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#labelling-help.pd
@@ -0,0 +1,55 @@
+#N canvas 573 85 632 627 10;
+#X obj 0 0 doc_h;
+#X obj 0 598 doc_f;
+#X obj 71 60 #labelling;
+#X obj 3 300 doc_o 4;
+#X obj 3 190 doc_i 1;
+#X obj 14 330 doc_oo 0;
+#X obj 14 391 doc_oo 1;
+#X obj 14 487 doc_oo 2;
+#X obj 14 544 doc_oo 3;
+#X obj 14 220 doc_ii 0;
+#X obj 97 544 doc_m o3 float;
+#X obj 97 487 doc_m o2 grid;
+#X obj 97 391 doc_m o1 grid;
+#X obj 97 330 doc_m o0 grid;
+#X obj 97 220 doc_m i0 grid;
+#X obj 3 106 doc_c 0..1;
+#X text 232 136 0 : bidimensional form;
+#X text 232 158 1 : form for horizontal lines;
+#X text 232 220 single-channel picture to analyse. the content must
+be made of zeroes and ones (other values are reserved for making the
+output);
+#X text 232 330 single-channel picture in which every contiguous region
+(of ones) is labelled (flood-filled) using a number greater than or
+equal to 2 those numbers are sorted according to the smallest pixel
+index found in each region.;
+#X obj 97 268 doc_m i0 form;
+#X text 232 268 same as arg 0;
+#X text 232 391 when form=0: a grid[2 \, 2] giving the standard-deviation
+([#moment 2]) of each region;
+#X text 232 487 when form=0: a grid[2] giving the centre ([#moment
+1]) of each region;
+#X text 232 544 when form=0: area of each region (in number of pixels)
+;
+#X obj 97 566 doc_m o3 <gone>;
+#X text 232 566 when form=1: not present;
+#X text 232 522 when form=1: not present;
+#X obj 97 522 doc_m o2 <gone>;
+#X text 232 426 when form=1: a grid[2 \, 2] that is a 2-polygon \,
+that is \, just a straight line. this line is horizontal \, and its
+right-side bound is for the first pixel that is NOT in the region.
+;
+#X obj 14 136 doc_cc 0;
+#X obj 97 136 doc_m c0 float/int;
+#X connect 10 1 24 0;
+#X connect 11 1 23 0;
+#X connect 12 1 22 0;
+#X connect 12 1 29 0;
+#X connect 13 1 19 0;
+#X connect 14 1 18 0;
+#X connect 20 1 21 0;
+#X connect 25 1 26 0;
+#X connect 28 1 27 0;
+#X connect 31 1 16 0;
+#X connect 31 1 17 0;
diff --git a/externals/gridflow/doc/flow_classes/#layer-help.pd b/externals/gridflow/doc/flow_classes/#layer-help.pd
new file mode 100644
index 00000000..0cbedf0f
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#layer-help.pd
@@ -0,0 +1,47 @@
+#N canvas 686 0 632 512 10;
+#X text 176 92 opacity channel file;
+#X text 52 62 foreground file;
+#X text 383 83 background file;
+#X text 157 176 a picture that has an opacity level will be used as
+foreground vs a picture that has no opacity channel. the output is
+a picture that has no opacity channel;
+#X msg 202 40 load b001.jpg;
+#X obj 179 67 #in;
+#X obj 205 67 #rgb_to_greyscale;
+#X obj 351 83 #in;
+#X msg 374 58 load g001.jpg;
+#X msg 42 38 load r001.jpg;
+#X obj 19 63 #in;
+#X obj 19 175 #layer;
+#X obj 19 206 #out window;
+#X obj 0 0 doc_h;
+#X obj 3 245 doc_c 0;
+#X obj 3 395 doc_o 1;
+#X obj 3 285 doc_i 2;
+#X obj 14 425 doc_oo 0;
+#X obj 14 315 doc_ii 0;
+#X obj 14 350 doc_ii 1;
+#X text 232 315 An image that has an opacity channel. Will be used
+as foreground.;
+#X text 232 350 An image that has NO opacity channel. Will be used
+as background.;
+#X text 232 425 An image that has NO opacity channel. The opacity channel
+of the foreground image is used as weighting of how much either picture
+is seen in the result.;
+#X obj 19 128 #join -1;
+#X obj 97 315 doc_m i0 grid;
+#X obj 97 350 doc_m i1 grid;
+#X obj 97 425 doc_m o0 grid;
+#X obj 0 483 doc_f;
+#X connect 4 0 5 0;
+#X connect 5 0 6 0;
+#X connect 6 0 23 1;
+#X connect 7 0 11 1;
+#X connect 8 0 7 0;
+#X connect 9 0 10 0;
+#X connect 10 0 23 0;
+#X connect 11 0 12 0;
+#X connect 23 0 11 0;
+#X connect 24 1 20 0;
+#X connect 25 1 21 0;
+#X connect 26 1 22 0;
diff --git a/externals/gridflow/doc/flow_classes/#line_to_polygon-help.pd b/externals/gridflow/doc/flow_classes/#line_to_polygon-help.pd
new file mode 100644
index 00000000..50133629
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#line_to_polygon-help.pd
@@ -0,0 +1,40 @@
+#N canvas 623 73 632 537 10;
+#X obj 43 180 #draw_polygon put (255 255 255);
+#X obj 43 239 #out window;
+#X msg 43 161 240 320 3 #;
+#X obj 256 167 display;
+#X msg 125 102 2 2 # 10 10 229 309;
+#X obj 125 121 #line_to_polygon 4;
+#X obj 0 0 doc_h;
+#X obj 3 286 doc_c 1;
+#X obj 3 352 doc_i 2;
+#X obj 3 446 doc_o 1;
+#X obj 14 476 doc_oo 0;
+#X obj 14 382 doc_ii 0;
+#X obj 14 414 doc_ii 1;
+#X obj 14 316 doc_cc 0;
+#X obj 0 508 doc_f;
+#X obj 43 73 t b b;
+#X obj 43 46 bng 15 250 50 0 empty empty empty 17 7 0 10 -4034 -1 -1
+;
+#X obj 97 316 doc_m c0 float;
+#X text 232 316 Line width.;
+#X obj 97 392 doc_m i0 grid;
+#X obj 97 414 doc_m i1 float;
+#X text 232 414 Line width (same as argument 0);
+#X obj 97 476 doc_m o0;
+#X text 232 392 Grid containing a pair of coordinates.;
+#X text 232 476 Grid representing the vertices of the resulting polygon.
+;
+#X connect 0 0 1 0;
+#X connect 2 0 0 0;
+#X connect 4 0 5 0;
+#X connect 5 0 0 2;
+#X connect 5 0 3 0;
+#X connect 15 0 2 0;
+#X connect 15 1 4 0;
+#X connect 16 0 15 0;
+#X connect 17 1 18 0;
+#X connect 19 1 23 0;
+#X connect 20 1 21 0;
+#X connect 22 1 24 0;
diff --git a/externals/gridflow/doc/flow_classes/#make_arrow-help.pd b/externals/gridflow/doc/flow_classes/#make_arrow-help.pd
new file mode 100644
index 00000000..4fa076e6
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#make_arrow-help.pd
@@ -0,0 +1,20 @@
+#N canvas 623 133 632 373 10;
+#X obj 0 0 doc_h;
+#X obj 0 344 doc_f;
+#X obj 55 53 #make_arrow;
+#X obj 3 180 doc_c 0;
+#X obj 3 220 doc_i 1;
+#X obj 3 282 doc_o 1;
+#X obj 14 250 doc_ii 0;
+#X obj 14 312 doc_oo 0;
+#X obj 97 250 doc_m i0 grid;
+#X obj 97 312 doc_m o0 grid;
+#X text 232 312 grid[;
+#X obj 58 77 display;
+#X msg 55 34 4 # 10 20 30 40;
+#X text 212 95 can anyone figure out what is this ?;
+#X text 232 250 grid[euh];
+#X connect 2 0 11 0;
+#X connect 8 1 14 0;
+#X connect 9 1 10 0;
+#X connect 12 0 2 0;
diff --git a/externals/gridflow/doc/flow_classes/#make_cross-help.pd b/externals/gridflow/doc/flow_classes/#make_cross-help.pd
new file mode 100644
index 00000000..0e0685be
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#make_cross-help.pd
@@ -0,0 +1,47 @@
+#N canvas 444 135 632 419 10;
+#X obj 43 57 tgl 15 0 empty empty empty 17 7 0 10 -204786 -1 -1 0 1
+;
+#X obj 43 78 metro 100;
+#X obj 43 149 #out window;
+#X obj 43 130 #draw_polygon put (255 0 0);
+#X obj 202 111 #make_cross 120;
+#X msg 202 92 240 320;
+#X obj 202 57 loadbang;
+#X msg 289 92 150;
+#X obj 261 66 t b b;
+#X obj 261 44 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
+-1;
+#X obj 43 101 #camera 0;
+#X text 319 90 change cross size;
+#X obj 0 0 doc_h;
+#X obj 3 182 doc_c 1;
+#X obj 3 244 doc_i 2;
+#X obj 14 274 doc_ii 0;
+#X obj 14 296 doc_ii 1;
+#X obj 3 328 doc_o 1;
+#X obj 14 358 doc_oo 0;
+#X obj 14 212 doc_cc 0;
+#X obj 0 390 doc_f;
+#X obj 97 296 doc_m i1;
+#X obj 97 274 doc_m i0;
+#X obj 97 212 doc_m c0;
+#X obj 97 358 doc_m o0 grid;
+#X text 232 358 polygon;
+#X text 232 274 position of centre;
+#X text 232 212 size (radius);
+#X text 232 296 same as arg 0;
+#X connect 0 0 1 0;
+#X connect 1 0 10 0;
+#X connect 3 0 2 0;
+#X connect 4 0 3 2;
+#X connect 5 0 4 0;
+#X connect 6 0 5 0;
+#X connect 7 0 4 1;
+#X connect 8 0 5 0;
+#X connect 8 1 7 0;
+#X connect 9 0 8 0;
+#X connect 10 0 3 0;
+#X connect 21 1 28 0;
+#X connect 22 1 26 0;
+#X connect 23 1 27 0;
+#X connect 24 1 25 0;
diff --git a/externals/gridflow/doc/flow_classes/#moment-help.pd b/externals/gridflow/doc/flow_classes/#moment-help.pd
new file mode 100644
index 00000000..0d47f338
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#moment-help.pd
@@ -0,0 +1,164 @@
+#N canvas 663 46 632 642 10;
+#X obj 19 44 tgl 15 0 empty empty empty 0 -6 0 8 -24198 -1 -1 0 1;
+#X msg 234 48 4 2 # 1 1 1 -1 -1 -1 -1 1;
+#X obj 111 228 display;
+#X obj 43 258 display;
+#X obj 234 86 #rotate;
+#X obj 288 76 nbx 5 14 -1e+37 1e+37 0 1 empty empty empty 0 -6 0 10
+-241291 -1 -1 -1831 256;
+#X obj 288 92 * 100;
+#X obj 18 497 #out window;
+#X obj 67 181 #t;
+#X obj 110 207 #moment;
+#X msg 41 105 240 320 1 #;
+#X obj 41 124 #draw_polygon put (1 # 255);
+#X obj 426 123 #pack;
+#X obj 234 105 # +;
+#X obj 456 107 nbx 5 14 -1e+37 1e+37 0 1 empty empty empty 0 -6 0 10
+-241291 -1 -1 -45 256;
+#X obj 426 91 nbx 5 14 -1e+37 1e+37 0 1 empty empty empty 0 -6 0 10
+-241291 -1 -1 12 256;
+#X obj 426 72 #pack;
+#X obj 456 56 nbx 5 14 -1e+37 1e+37 0 1 empty empty empty 0 -6 0 10
+-241291 -1 -1 32 256;
+#X obj 426 40 nbx 5 14 -1e+37 1e+37 0 1 empty empty empty 0 -6 0 10
+-241291 -1 -1 49 256;
+#X obj 234 67 # *;
+#X obj 245 143 # inv+;
+#X obj 245 124 # +;
+#X obj 426 174 #pack;
+#X obj 456 158 nbx 5 14 -1e+37 1e+37 0 1 empty empty empty 0 -6 0 10
+-241291 -1 -1 149 256;
+#X obj 426 142 nbx 5 14 -1e+37 1e+37 0 1 empty empty empty 0 -6 0 10
+-241291 -1 -1 128 256;
+#X obj 41 143 #draw_polygon put (1 # 255);
+#X text 162 460 red filter;
+#X text 121 105 draw rectangles;
+#X text 238 31 rectangle polygon;
+#X obj 42 206 #moment 2;
+#X obj 269 192 #moment_polar;
+#X obj 356 212 display;
+#X obj 270 232 display;
+#X obj 5 81 bng 15 250 50 0 empty empty empty 0 -6 0 8 -24198 -1 -1
+;
+#X text 141 329 this is a fudge factor.;
+#X obj 18 516 fps;
+#X floatatom 18 535 5 0 0 0 - - -;
+#X text 143 341 depending on what you want to do \,;
+#X text 140 353 you set it to 2 \, 3 \, 4 \, whatever.;
+#X obj 402 314 #outer + (9000 0);
+#X obj 448 378 #transpose;
+#X obj 20 80 t b b b;
+#X obj 402 490 # + (120 160);
+#X obj 63 322 #cast f;
+#X obj 63 419 #inner \, seed (f #);
+#X obj 402 352 #cast f;
+#X obj 402 409 #inner \, seed (f #);
+#X obj 402 457 #cast i;
+#X obj 63 398 #swap;
+#X obj 402 276 #for 0 160 1;
+#X obj 63 379 # sqrt (f #);
+#X obj 63 341 # * (f # 3);
+#X obj 402 429 # / (f # 1000);
+#X obj 402 333 # cos* 1000;
+#X obj 402 295 # * 225;
+#X obj 18 459 #inner (1 3 # 1 0 0);
+#X obj 18 478 #draw_polygon + (0 255 255) (2 2 #);
+#X obj 19 61 metro 20;
+#X obj 18 164 #t;
+#X obj 63 360 cv/#SVD;
+#X obj 0 0 doc_h;
+#X obj 3 559 doc_c 0..1;
+#X obj 3 708 doc_i 2;
+#X obj 3 818 doc_o 1;
+#X obj 14 848 doc_oo 0;
+#X obj 14 738 doc_ii 0;
+#X obj 14 760 doc_ii 1;
+#X obj 14 589 doc_cc 0;
+#X obj 0 902 doc_f;
+#X obj 0 902 doc_f;
+#X obj 97 848 doc_m o0 grid;
+#X obj 97 760 doc_m i1 grid;
+#X obj 97 738 doc_m i0 grid;
+#X obj 97 589 doc_m c0 float;
+#X text 232 589 1: average index of the values in the grid \, weighted
+by the values themselves.;
+#X text 232 624 2: average square of index of the values in the grid
+\, weighted by the values themselves. this can be used to compute a
+variance (covariance) matrix \, which in turn can be fed to [#moment_polar]
+to figure out the standard deviation and the direction of the standard
+deviation.;
+#X text 232 848 mode 1: a grid[2];
+#X text 232 870 mode 2: a grid[2 \, 2];
+#X text 232 738 greyscale image;
+#X text 232 760 mode 2: alleged centroid (doesn't have to be the real
+centroid \, but when it is \, the output will be the variance matrix
+\; else it won't be a centred moment);
+#X connect 0 0 57 0;
+#X connect 1 0 19 0;
+#X connect 4 0 13 0;
+#X connect 5 0 6 0;
+#X connect 6 0 4 1;
+#X connect 7 0 35 0;
+#X connect 8 0 29 0;
+#X connect 8 1 9 0;
+#X connect 9 0 2 0;
+#X connect 9 0 29 1;
+#X connect 9 0 42 1;
+#X connect 10 0 11 0;
+#X connect 11 0 25 0;
+#X connect 12 0 13 1;
+#X connect 13 0 21 0;
+#X connect 13 0 20 0;
+#X connect 14 0 12 1;
+#X connect 15 0 12 0;
+#X connect 16 0 19 1;
+#X connect 17 0 16 1;
+#X connect 18 0 16 0;
+#X connect 19 0 4 0;
+#X connect 20 0 25 2;
+#X connect 21 0 11 2;
+#X connect 22 0 21 1;
+#X connect 22 0 20 1;
+#X connect 23 0 22 1;
+#X connect 24 0 22 0;
+#X connect 25 0 58 0;
+#X connect 29 0 3 0;
+#X connect 29 0 30 0;
+#X connect 29 0 43 0;
+#X connect 30 0 32 0;
+#X connect 30 1 31 0;
+#X connect 33 0 41 0;
+#X connect 35 0 36 0;
+#X connect 39 0 53 0;
+#X connect 40 0 46 1;
+#X connect 41 0 49 0;
+#X connect 41 1 10 0;
+#X connect 41 2 1 0;
+#X connect 42 0 56 2;
+#X connect 43 0 51 0;
+#X connect 44 0 40 0;
+#X connect 45 0 46 0;
+#X connect 46 0 52 0;
+#X connect 47 0 42 0;
+#X connect 48 0 44 0;
+#X connect 48 1 44 1;
+#X connect 49 0 54 0;
+#X connect 50 0 48 0;
+#X connect 51 0 59 0;
+#X connect 52 0 47 0;
+#X connect 53 0 45 0;
+#X connect 54 0 39 0;
+#X connect 55 0 56 0;
+#X connect 56 0 7 0;
+#X connect 57 0 41 0;
+#X connect 58 0 55 0;
+#X connect 58 1 8 0;
+#X connect 59 0 50 0;
+#X connect 59 1 48 1;
+#X connect 70 1 76 0;
+#X connect 70 1 77 0;
+#X connect 71 1 79 0;
+#X connect 72 1 78 0;
+#X connect 73 1 74 0;
+#X connect 73 1 75 0;
diff --git a/externals/gridflow/doc/flow_classes/#moment_polar-help.pd b/externals/gridflow/doc/flow_classes/#moment_polar-help.pd
new file mode 100644
index 00000000..d68966a6
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#moment_polar-help.pd
@@ -0,0 +1,25 @@
+#N canvas 455 225 632 371 10;
+#X text 232 226 must be a 2x2 symmetric matrix.;
+#X text 232 288 outlet 0: angle (only makes sense with a 2x2 matrix)
+as int;
+#X text 232 310 outlet 1: radiuses (from biggest to smallest) as float
+grid;
+#X text 30 61 please open this other help patch for a demo:;
+#X obj 0 0 doc_h;
+#X obj 3 121 doc_c 0;
+#X obj 3 161 doc_i 1;
+#X obj 3 258 doc_o 2;
+#X obj 14 288 doc_oo 0;
+#X obj 14 310 doc_oo 1;
+#X obj 14 191 doc_ii 0;
+#X obj 0 342 doc_f;
+#X obj 97 191 doc_m i0 grid;
+#X obj 97 288 doc_m o0 grid;
+#X obj 97 310 doc_m o1 grid;
+#X obj 37 77 #moment-help;
+#X text 232 191 inlet 0: variance matrix (aka covariance matrix) \,
+from [#moment 2] or compatible.;
+#X connect 12 1 16 0;
+#X connect 12 1 0 0;
+#X connect 13 1 1 0;
+#X connect 14 1 2 0;
diff --git a/externals/gridflow/doc/flow_classes/#motion_detection-help.pd b/externals/gridflow/doc/flow_classes/#motion_detection-help.pd
new file mode 100644
index 00000000..4acf4a15
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#motion_detection-help.pd
@@ -0,0 +1,83 @@
+#N canvas 536 0 632 642 10;
+#X obj 47 40 tgl 15 0 empty empty empty 0 -6 0 8 -24198 -1 -1 0 1;
+#X obj 47 315 print;
+#X obj 47 292 fps detailed;
+#X obj 47 57 metro 33.3667;
+#X obj 47 76 #camera;
+#X obj 96 132 vradio 15 1 0 2 empty empty empty 0 -6 0 8 -241291 -1
+-1 0;
+#X text 115 132 motion;
+#X text 116 146 presence;
+#X floatatom 223 237 7 0 0 0 - - -;
+#X obj 47 268 #out window;
+#X obj 209 168 tgl 15 0 empty empty empty 0 -6 0 8 -241291 -1 -1 0
+1;
+#X obj 74 105 hsl 128 15 0 127 0 0 empty empty empty -2 -6 0 8 -260818
+-1 -1 0 1;
+#X text 208 104 reduce the noise in the image;
+#X obj 156 237 nbx 5 14 -1e+37 1e+37 0 0 empty empty y -10 4 0 10 -24198
+-1 -1 0 256;
+#X obj 85 237 nbx 5 14 -1e+37 1e+37 0 0 empty empty x -10 4 0 10 -24198
+-1 -1 0 256;
+#X obj 47 183 #motion_detection;
+#X text 279 236 total amount of change;
+#X obj 177 142 tgl 15 0 empty empty empty 0 -6 0 8 -241291 -1 -1 0
+1;
+#X text 195 142 fade;
+#X text 227 168 crosshair;
+#X obj 0 0 doc_h;
+#X obj 0 678 doc_f;
+#X obj 3 378 doc_i 5;
+#X obj 3 338 doc_c 0;
+#X obj 3 550 doc_o 4;
+#X obj 14 580 doc_oo 0;
+#X obj 14 602 doc_oo 1;
+#X obj 14 624 doc_oo 2;
+#X obj 14 646 doc_oo 3;
+#X obj 14 408 doc_ii 0;
+#X obj 14 430 doc_ii 1;
+#X obj 14 452 doc_ii 2;
+#X obj 14 496 doc_ii 3;
+#X obj 14 518 doc_ii 4;
+#X obj 97 518 doc_m i4;
+#X obj 97 496 doc_m i3;
+#X obj 97 452 doc_m i2;
+#X obj 97 430 doc_m i1;
+#X obj 97 408 doc_m i0;
+#X obj 97 646 doc_m o3 float;
+#X obj 97 624 doc_m o2 float;
+#X obj 97 602 doc_m o1 float;
+#X text 232 602 x;
+#X text 232 624 y;
+#X text 232 646 amount of change;
+#X obj 97 580 doc_m o0 grid;
+#X text 232 580 image;
+#X text 232 518 crosshair;
+#X text 232 496 fade;
+#X text 232 452 0: motion;
+#X text 232 474 1: presence;
+#X text 232 430 noise reduction;
+#X text 232 408 camera input;
+#X connect 0 0 3 0;
+#X connect 2 0 1 0;
+#X connect 3 0 4 0;
+#X connect 4 0 15 0;
+#X connect 5 0 15 2;
+#X connect 9 0 2 0;
+#X connect 10 0 15 4;
+#X connect 11 0 15 1;
+#X connect 15 0 9 0;
+#X connect 15 1 14 0;
+#X connect 15 2 13 0;
+#X connect 15 3 8 0;
+#X connect 17 0 15 3;
+#X connect 34 1 47 0;
+#X connect 35 1 48 0;
+#X connect 36 1 49 0;
+#X connect 36 1 50 0;
+#X connect 37 1 51 0;
+#X connect 38 1 52 0;
+#X connect 39 1 44 0;
+#X connect 40 1 43 0;
+#X connect 41 1 42 0;
+#X connect 45 1 46 0;
diff --git a/externals/gridflow/doc/flow_classes/#mouse-help.pd b/externals/gridflow/doc/flow_classes/#mouse-help.pd
new file mode 100644
index 00000000..648afc0f
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#mouse-help.pd
@@ -0,0 +1,99 @@
+#N canvas 675 0 632 699 10;
+#X msg 59 113 setcursor 32;
+#X msg 40 90 hidecursor;
+#X text 125 88 <-- removes the cursor;
+#X text 159 110 <-- accepts 0 - 63;
+#X obj 136 148 print xy_clicked;
+#X obj 137 194 print xy_unclicked;
+#X obj 68 281 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1
+;
+#X obj 85 281 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1
+;
+#X obj 102 281 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0
+1;
+#X floatatom 139 292 5 0 0 0 - - -;
+#X obj 139 273 +;
+#X obj 173 273 t a;
+#X obj 137 218 print xy_moved;
+#X obj 136 170 print xy_dragged;
+#X obj 340 175 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1
+1;
+#X obj 360 175 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1
+1;
+#X obj 380 175 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1
+1;
+#X obj 400 151 loadbang;
+#X text 232 422 select buttons to be considered in click/drag/unclick
+;
+#X obj 40 145 #out window;
+#X obj 340 201 #pack 3;
+#X obj 0 0 doc_h;
+#X obj 3 330 doc_c 0;
+#X obj 3 370 doc_i 2;
+#X obj 3 454 doc_o 8;
+#X obj 14 484 doc_oo 0;
+#X obj 14 506 doc_oo 1;
+#X obj 14 528 doc_oo 2;
+#X obj 14 550 doc_oo 3;
+#X obj 14 572 doc_oo 4;
+#X obj 14 594 doc_oo 5;
+#X obj 14 616 doc_oo 6;
+#X obj 14 638 doc_oo 7;
+#X obj 14 400 doc_ii 0;
+#X obj 14 422 doc_ii 1;
+#X text 19 32 How to get the mouse coordinates and hide / change the
+cursor;
+#X obj 40 247 #mouse \, \, \, \, \,;
+#X obj 97 400 doc_m i0 list;
+#X text 232 484 (y x) click;
+#X text 232 506 (y x) drag;
+#X text 232 528 (y x) unclick;
+#X text 232 550 (y x) move;
+#X text 232 572 0 \, 1 button 1 status;
+#X text 232 594 0 \, 1 button 2 status;
+#X text 232 616 0 \, 1 button 3 status;
+#X text 232 638 mouse wheel difference: -1=up +1=down;
+#X obj 340 230 #to_list;
+#X text 232 400 what comes out of [#out window];
+#X obj 97 422 doc_m i1 list;
+#X obj 97 484 doc_m o0 list;
+#X obj 97 506 doc_m o1 list;
+#X obj 97 528 doc_m o2 list;
+#X obj 97 550 doc_m o3 list;
+#X obj 97 572 doc_m o4 float;
+#X obj 97 594 doc_m o5 float;
+#X obj 97 616 doc_m o6 float;
+#X obj 97 638 doc_m o7 float;
+#X obj 0 670 doc_f;
+#X connect 0 0 19 0;
+#X connect 1 0 19 0;
+#X connect 10 0 11 0;
+#X connect 10 0 9 0;
+#X connect 11 0 10 1;
+#X connect 14 0 20 0;
+#X connect 15 0 20 1;
+#X connect 16 0 20 2;
+#X connect 17 0 14 0;
+#X connect 17 0 15 0;
+#X connect 17 0 16 0;
+#X connect 19 0 36 0;
+#X connect 20 0 46 0;
+#X connect 36 0 4 0;
+#X connect 36 1 13 0;
+#X connect 36 2 5 0;
+#X connect 36 3 12 0;
+#X connect 36 4 6 0;
+#X connect 36 5 7 0;
+#X connect 36 6 8 0;
+#X connect 36 7 10 0;
+#X connect 37 1 47 0;
+#X connect 46 0 36 1;
+#X connect 48 1 18 0;
+#X connect 49 1 38 0;
+#X connect 50 1 39 0;
+#X connect 51 1 40 0;
+#X connect 52 1 41 0;
+#X connect 53 1 42 0;
+#X connect 54 1 43 0;
+#X connect 55 1 44 0;
+#X connect 56 1 45 0;
diff --git a/externals/gridflow/doc/flow_classes/#noise_gate_yuvs-help.pd b/externals/gridflow/doc/flow_classes/#noise_gate_yuvs-help.pd
new file mode 100644
index 00000000..a2003659
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#noise_gate_yuvs-help.pd
@@ -0,0 +1,26 @@
+#N canvas 591 265 632 338 10;
+#X obj 0 0 doc_h;
+#X obj 0 309 doc_f;
+#X obj 76 49 #noise_gate_yuvs;
+#X obj 3 150 doc_i 2;
+#X obj 3 247 doc_o 1;
+#X obj 3 88 doc_c 1;
+#X obj 14 277 doc_oo 0;
+#X obj 14 180 doc_ii 0;
+#X obj 14 215 doc_ii 1;
+#X obj 14 118 doc_cc 0;
+#X obj 97 118 doc_m c0 float/int;
+#X obj 97 180 doc_m i0 grid;
+#X text 203 44 sets pixels to (0 \, 0 \, 0) if their first component
+is lower than a certain threshold.;
+#X text 232 180 picture in signed YUV format (or whatever else works
+for you);
+#X obj 97 215 doc_m i1 float;
+#X text 232 215 same as arg 0;
+#X obj 97 277 doc_m o0 grid;
+#X text 232 118 threshold;
+#X text 232 277 filtered picture in signed YUV format;
+#X connect 10 1 17 0;
+#X connect 11 1 13 0;
+#X connect 14 1 15 0;
+#X connect 16 1 18 0;
diff --git a/externals/gridflow/doc/flow_classes/#out-help.pd b/externals/gridflow/doc/flow_classes/#out-help.pd
new file mode 100644
index 00000000..17d9d2e8
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#out-help.pd
@@ -0,0 +1,139 @@
+#N canvas 674 0 632 642 10;
+#X obj 15 325 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X text 10 71 Displaying a grid:;
+#X text 342 73 Saving a grid:;
+#X text 232 689 "rewind" rewinds to the beginning of a video file.
+Will overwrite previous data.;
+#X obj 15 100 bng 15 250 50 0 empty empty empty 0 -6 0 8 -24198 -1
+-1;
+#X obj 15 221 #in;
+#X msg 65 227 open window;
+#X msg 65 252 close;
+#X text 232 597 "close" closes the file and hides the display \, must
+be accompanied by message "open window" to reopen the display.;
+#X text 232 764 A bang notifies when a complete grid has been received.
+;
+#X text 12 32 Displays or saves an incoming grid (usually an image
+or a video).;
+#X obj 15 302 #out window \, title example;
+#X obj 127 100 bng 15 250 50 0 empty empty empty 0 -6 0 8 -24198 -1
+-1;
+#X obj 133 796 #record;
+#X msg 366 228 open somefile.jpg;
+#X text 232 654 "open filename.format" (ex: "open somefile.jpg") sets
+the filename to write to.;
+#X obj 351 96 bng 15 250 50 0 empty empty empty 0 -6 0 8 -24198 -1
+-1;
+#X obj 351 190 #in;
+#X obj 351 266 #out;
+#X msg 127 262 hidecursor;
+#X text 196 261 <-- linux only;
+#X text 232 632 "hidecursor" (linux only) hides the mouse cursor.;
+#X obj 0 0 doc_h;
+#X obj 3 371 doc_c n;
+#X obj 3 796 doc_also;
+#X obj 3 734 doc_o 1;
+#N canvas 140 137 570 615 More 1;
+#X text 203 143 open default display for screenshot;
+#X msg 82 197 open videodev /dev/video0;
+#X text 277 196 open a video device;
+#X msg 187 388 open x11 here;
+#X msg 158 337 open x11 local 10;
+#X text 298 390 connect to default display;
+#X text 297 338 connect to display #10 on this machine;
+#X msg 65 313 open x11 remote.host.bla.net 0;
+#X text 297 315 connect to remote machine on display #0;
+#X text 202 114 open an image file;
+#X msg 242 437 close;
+#X msg 83 142 open x11 here;
+#X msg 200 413 open window;
+#X text 299 413 opens a window x11 \, quartz or sdl;
+#X obj 23 223 cnv 15 23 17 empty empty empty 20 12 0 14 -241291 -66577
+0;
+#X obj 23 223 #in;
+#X obj 5 13 cnv 15 500 18 empty empty empty 20 12 0 14 -228992 -66577
+0;
+#X obj 14 14 #out;
+#X obj 23 480 #out;
+#X msg 53 114 open sewing.jpg;
+#X obj 23 72 bng 15 250 50 0 empty empty empty 0 -6 0 8 -24198 -1 -1
+;
+#X obj 23 93 t b b;
+#X msg 83 170 open lsd.mov;
+#X text 203 169 open a quicktime video;
+#X obj 97 74 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X msg 165 363 open save_here.jpg;
+#X text 298 362 select file to write to in jpg format;
+#X text 14 36 #out communicating grids (images) to/from devices \,
+sockets \, files;
+#X text 37 502 An incoming file is sent through the opened device or
+file. In single file format \, a subsequent picture overwrites the
+preceeding one. There are many more options.;
+#X connect 1 0 15 0;
+#X connect 3 0 18 0;
+#X connect 4 0 18 0;
+#X connect 7 0 18 0;
+#X connect 10 0 18 0;
+#X connect 11 0 15 0;
+#X connect 12 0 18 0;
+#X connect 15 0 18 0;
+#X connect 19 0 15 0;
+#X connect 20 0 21 0;
+#X connect 21 0 15 0;
+#X connect 21 1 19 0;
+#X connect 22 0 15 0;
+#X connect 24 0 15 0;
+#X connect 25 0 18 0;
+#X restore 140 334 pd More info about this object class;
+#X obj 3 488 doc_i 1;
+#X obj 14 518 doc_ii 0;
+#X obj 14 764 doc_oo 0;
+#X obj 97 518 doc_m i0 grid;
+#X obj 97 654 doc_m i0 open;
+#X obj 97 597 doc_m i0 close;
+#X obj 97 632 doc_m i0 hidecursor;
+#X obj 97 689 doc_m i0 rewind;
+#X obj 103 796 #in;
+#X text 188 426 auto-open with auto-detect of the format-handler;
+#X text 226 451 auto-open with manual choice of the format-handler
+;
+#X text 88 406 nothing opened \, you have to open by yourself;
+#X obj 46 407 #out;
+#X obj 46 428 #out filename.suffix;
+#X obj 46 449 #out handler filename.suffix;
+#X obj 97 553 doc_m i0 autoclose;
+#X obj 0 816 doc_f;
+#X obj 97 764 doc_m o0 bang;
+#X msg 15 117 load working.jpg;
+#X msg 127 117 load sewing.jpg;
+#X msg 351 113 load sewing.jpg;
+#X text 232 553 "autoclose 1": close after incoming image is finished.
+;
+#X text 232 575 "autoclose 0": doesn't.;
+#X text 232 518 write one frame (or in the case of [#out grid] \, one
+grid of any kind).;
+#X connect 4 0 45 0;
+#X connect 5 0 11 0;
+#X connect 6 0 11 0;
+#X connect 7 0 11 0;
+#X connect 11 0 0 0;
+#X connect 12 0 46 0;
+#X connect 14 0 18 0;
+#X connect 16 0 47 0;
+#X connect 17 0 18 0;
+#X connect 19 0 11 0;
+#X connect 24 1 35 0;
+#X connect 24 1 13 0;
+#X connect 30 1 50 0;
+#X connect 31 1 15 0;
+#X connect 32 1 8 0;
+#X connect 33 1 21 0;
+#X connect 34 1 3 0;
+#X connect 42 1 48 0;
+#X connect 42 1 49 0;
+#X connect 44 1 9 0;
+#X connect 45 0 5 0;
+#X connect 46 0 5 0;
+#X connect 47 0 17 0;
diff --git a/externals/gridflow/doc/flow_classes/#outer-help.pd b/externals/gridflow/doc/flow_classes/#outer-help.pd
new file mode 100644
index 00000000..b56f18f8
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#outer-help.pd
@@ -0,0 +1,105 @@
+#N canvas 668 0 632 642 10;
+#X obj 19 39 bng 15 250 50 0 empty empty empty 0 -6 0 8 -233017 -1
+-1;
+#X obj 19 130 spigot;
+#X obj 100 130 spigot;
+#X obj 67 130 == 0;
+#X obj 67 39 tgl 15 0 empty empty empty 0 -6 0 8 -233017 -1 -1 0 1
+;
+#X text 88 40 select pattern;
+#X text 17 296 combine channelless picture with gamma factors (r \,
+g \, b);
+#X obj 19 89 until;
+#X msg 19 68 128;
+#X obj 60 89 float 1;
+#X obj 115 89 + 1;
+#X obj 171 90 until;
+#X obj 212 90 float 1;
+#X obj 267 90 + 1;
+#X msg 171 69 4;
+#X obj 199 622 #finished;
+#X obj 103 622 #scan +;
+#X obj 265 622 #cast;
+#X obj 307 622 #ravel;
+#X obj 355 622 #grade;
+#X obj 403 622 #perspective;
+#X obj 171 111 #import (3);
+#X obj 171 132 # * 128;
+#X obj 19 109 #import (128);
+#X obj 19 162 #outer +;
+#X obj 100 161 #outer ^;
+#X obj 100 181 # * 2;
+#X obj 19 255 #outer gamma;
+#X obj 3 622 doc_also;
+#X obj 0 0 doc_h;
+#X obj 3 320 doc_c 1;
+#X obj 3 404 doc_i 2;
+#X obj 14 434 doc_ii 0;
+#X obj 14 530 doc_ii 1;
+#X obj 3 562 doc_o 1;
+#X obj 14 592 doc_oo 0;
+#X obj 19 277 #out window;
+#X obj 14 350 doc_cc 0;
+#X obj 97 434 doc_m i0 grid;
+#X obj 97 508 doc_m i0 op;
+#X obj 97 372 doc_m c0 op;
+#X obj 97 530 doc_m i1 grid;
+#X obj 97 592 doc_m o0 grid;
+#X obj 97 350 doc_m c0 grid;
+#X obj 157 622 #join;
+#X text 171 250 #outer does the same two-input operation between every
+possible pair of the left-side grid and the right side grid.;
+#X obj 392 102 display;
+#X text 387 32 Multiplication table:;
+#X obj 391 79 #outer * (1 2 3 4 5 6 7);
+#X msg 391 56 1 2 3 4 5;
+#X text 232 434 produces a grid of size Dim(anyA... \, anyB...) \,
+where numbers are the results of the operation on every element of
+A and every element of B. the resulting array can be very big. Don't
+try this on two pictures (the result will have 6 dimensions);
+#X text 232 508 same as arg 0;
+#X text 232 530 same as arg 1;
+#X text 232 350 grid B (see below);
+#X obj 0 642 doc_f;
+#X text 232 372 numop;
+#X connect 0 0 8 0;
+#X connect 0 0 14 0;
+#X connect 1 0 24 0;
+#X connect 1 0 24 1;
+#X connect 2 0 25 0;
+#X connect 2 0 25 1;
+#X connect 3 0 2 1;
+#X connect 4 0 1 1;
+#X connect 4 0 3 0;
+#X connect 7 0 9 0;
+#X connect 8 0 7 0;
+#X connect 9 0 10 0;
+#X connect 9 0 23 0;
+#X connect 10 0 9 1;
+#X connect 11 0 12 0;
+#X connect 12 0 13 0;
+#X connect 12 0 21 0;
+#X connect 13 0 12 1;
+#X connect 14 0 11 0;
+#X connect 21 0 22 0;
+#X connect 22 0 27 1;
+#X connect 23 0 1 0;
+#X connect 23 0 2 0;
+#X connect 24 0 27 0;
+#X connect 25 0 26 0;
+#X connect 26 0 27 0;
+#X connect 27 0 36 0;
+#X connect 28 1 16 0;
+#X connect 28 1 44 0;
+#X connect 28 1 15 0;
+#X connect 28 1 17 0;
+#X connect 28 1 18 0;
+#X connect 28 1 19 0;
+#X connect 28 1 20 0;
+#X connect 38 1 50 0;
+#X connect 39 1 51 0;
+#X connect 40 1 55 0;
+#X connect 41 1 52 0;
+#X connect 43 1 53 0;
+#X connect 48 0 46 0;
+#X connect 49 0 48 0;
diff --git a/externals/gridflow/doc/flow_classes/#pack-help.pd b/externals/gridflow/doc/flow_classes/#pack-help.pd
new file mode 100644
index 00000000..1f3614f4
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#pack-help.pd
@@ -0,0 +1,46 @@
+#N canvas 379 12 632 544 10;
+#X obj 23 178 #color;
+#X floatatom 85 77 5 0 0 0 - - -;
+#X floatatom 107 96 5 0 0 0 - - -;
+#X floatatom 129 115 5 0 0 0 - - -;
+#X text 162 90 <--click and drag to place numbers in the grid.;
+#X text 232 463 Outputs values from each individual inlet into a grid.
+;
+#X obj 0 0 doc_h;
+#X obj 3 349 doc_i n;
+#X obj 3 252 doc_c 0..2;
+#X text 14 28 Creates a one-dimensional grid (a Dim(N) vector) from
+individual integers.;
+#X text 232 379 every inlet is hot.;
+#X text 232 401 inlet order corresponds to value order in the grid.
+;
+#X obj 3 433 doc_o 1;
+#X obj 14 463 doc_oo 0;
+#X obj 14 379 doc_ii any;
+#X obj 14 282 doc_cc 0;
+#X obj 14 317 doc_cc 1;
+#X obj 97 282 doc_m c0 float/int;
+#X obj 97 317 doc_m c1 numtype;
+#X obj 97 379 doc_m iany float;
+#X obj 97 463 doc_m o0 grid[n];
+#X obj 0 515 doc_f;
+#X text 232 317 number type (default: int32);
+#X obj 85 135 #pack 3 f;
+#X obj 3 495 doc_also;
+#X obj 103 495 pack;
+#X obj 139 495 #unpack;
+#X obj 263 180 display;
+#X text 232 282 number of elements in the vector to be built (aka number
+of dimensions in the vector space) (default: 2);
+#X connect 1 0 23 0;
+#X connect 2 0 23 1;
+#X connect 3 0 23 2;
+#X connect 17 1 28 0;
+#X connect 18 1 22 0;
+#X connect 19 1 10 0;
+#X connect 19 1 11 0;
+#X connect 20 1 5 0;
+#X connect 23 0 0 0;
+#X connect 23 0 27 0;
+#X connect 24 1 25 0;
+#X connect 24 1 26 0;
diff --git a/externals/gridflow/doc/flow_classes/#perspective-help.pd b/externals/gridflow/doc/flow_classes/#perspective-help.pd
new file mode 100644
index 00000000..d67b92ac
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#perspective-help.pd
@@ -0,0 +1,49 @@
+#N canvas 675 0 632 550 10;
+#X text 153 55 transforms a dim[a... \, b] grid into a dim[a... \,
+b-1] grid. there is a projection plane perpendicular to the last axis
+and whose position is given by the creation argument. each vector's
+length is adjusted so that it lies onto that plane. then the last dimension
+of each vector is dropped;
+#X obj 30 127 #pack 3;
+#X floatatom 75 82 5 0 0 0 - - -;
+#X obj 77 100 max 1;
+#X floatatom 12 95 5 0 0 0 - - -;
+#X floatatom 52 57 5 0 0 0 - - -;
+#X obj 30 190 #print;
+#X obj 79 182 #print;
+#X obj 79 163 #perspective;
+#X obj 103 501 #redim;
+#X obj 151 501 #ravel;
+#X obj 0 0 doc_h;
+#X obj 3 501 doc_also;
+#X obj 3 217 doc_c 1;
+#X obj 3 279 doc_i 1;
+#X obj 3 441 doc_o 1;
+#X obj 14 471 doc_oo 0;
+#X obj 14 309 doc_ii 0;
+#X obj 14 247 doc_cc 0;
+#X obj 97 309 doc_m i0 grid;
+#X obj 97 471 doc_m o0 grid;
+#X text 232 309 transforms a Dim[A... \, B] grid into a Dim[A... \,
+B-1] grid. There is a projection plane perpendicular to the last axis
+and whose position is given by the "depth" parameter. Each vector's
+length is adjusted so that it lies onto that plane. Then the last dimension
+of each vector is dropped.;
+#X text 232 383 useful for converting from 3-D geometry to 2-D geometry.
+Also useful for converting homogeneous 3-D into regular 3-D \, as homogeneous
+3-D is really just regular 4-D...(!);
+#X obj 97 247 doc_m c0 float;
+#X text 232 247 depth;
+#X obj 0 521 doc_f;
+#X connect 1 0 6 0;
+#X connect 1 0 8 0;
+#X connect 2 0 3 0;
+#X connect 3 0 1 2;
+#X connect 4 0 1 0;
+#X connect 5 0 1 1;
+#X connect 8 0 7 0;
+#X connect 12 1 9 0;
+#X connect 12 1 10 0;
+#X connect 19 1 21 0;
+#X connect 19 1 22 0;
+#X connect 23 1 24 0;
diff --git a/externals/gridflow/doc/flow_classes/#polygon_area-help.pd b/externals/gridflow/doc/flow_classes/#polygon_area-help.pd
new file mode 100644
index 00000000..6d7a661c
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#polygon_area-help.pd
@@ -0,0 +1,28 @@
+#N canvas 628 15 632 522 10;
+#X obj 0 0 doc_h;
+#X obj 0 493 doc_f;
+#X obj 58 239 #polygon_area;
+#X obj 59 259 display;
+#X msg 58 96 4 2 # 10 10 10 310 230 310 230 10;
+#X text 93 116 220 x 300 rectangle;
+#X obj 79 146 display;
+#X text 11 36 Find area of a polygon in square pixels.;
+#X obj 3 309 doc_c 0;
+#X obj 3 349 doc_i 1;
+#X obj 3 418 doc_o 1;
+#X obj 58 77 loadbang;
+#X obj 14 379 doc_ii 0;
+#X obj 97 379 doc_m i0 grid;
+#X text 232 379 Vertices of the polygon.;
+#X obj 14 448 doc_oo 0;
+#X obj 97 448 doc_m o0 grid;
+#X text 232 448 Grid of only one element representing the area of the
+polygon received from inlet 0;
+#X obj 58 115 # +;
+#X connect 2 0 3 0;
+#X connect 4 0 18 0;
+#X connect 11 0 4 0;
+#X connect 13 1 14 0;
+#X connect 16 1 17 0;
+#X connect 18 0 2 0;
+#X connect 18 0 6 0;
diff --git a/externals/gridflow/doc/flow_classes/#polygon_comparator-help.pd b/externals/gridflow/doc/flow_classes/#polygon_comparator-help.pd
new file mode 100644
index 00000000..5dd99ec8
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#polygon_comparator-help.pd
@@ -0,0 +1,85 @@
+#N canvas 566 0 632 642 10;
+#X obj 255 129 #outer + (0 9000);
+#X text 333 91 make regular triangle;
+#X obj 255 227 #rotate;
+#X obj 209 53 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1
+;
+#X obj 308 227 * 100;
+#X floatatom 308 211 5 0 0 0 - - -;
+#X obj 268 72 t b b;
+#X obj 255 246 #polygon_comparator;
+#X obj 209 72 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 255 186 #t;
+#X obj 228 53 metro 1000;
+#X text 30 254 BUG: first try doesn't work;
+#X text 67 265 please bang twice;
+#X msg 381 149 4 2 # 1 1 1 -1 -1 -1 -1 1;
+#X obj 391 195 display;
+#X obj 255 110 # * 12000;
+#X obj 255 91 #for 0 3 1;
+#X obj 381 169 # * (100 100);
+#X obj 255 167 # + (0 0);
+#X obj 255 148 # cos* (100 100);
+#X obj 215 278 #fold min;
+#X obj 295 278 #fold max;
+#X obj 215 297 #to_float;
+#X obj 295 297 #to_float;
+#X obj 381 129 loadbang;
+#X obj 215 316 nbx 8 14 -1e+37 1e+37 0 0 empty empty empty 0 -6 0 9
+-262144 -1 -1 0 256;
+#X obj 295 316 nbx 8 14 -1e+37 1e+37 0 0 empty empty empty 0 -6 0 9
+-262144 -1 -1 0 256;
+#X text 232 453 or method "precision" for setting the size of the output
+grid.;
+#X text 232 510 in which the peak represents the amount of similarity
+between the two polygons \, and the position of the peak represents
+the optimal rotation for maximum overlapping of the polygons. The rotation
+origin is assumed to be the centroid (#moment 1);
+#X text 24 239 NOTE: requires [#fft];
+#X text 33 150 translations \, e.g. [# +];
+#X text 33 168 rotations \, e.g. [#rotate];
+#X obj 0 0 doc_h;
+#X obj 3 361 doc_c;
+#X obj 3 401 doc_i 2;
+#X obj 3 594 doc_o 1;
+#X text 232 488 a 2-D polygon as N by 2 grid;
+#X text 232 431 a 2-D polygon as N by 2 grid;
+#X obj 14 431 doc_ii 0;
+#X obj 14 488 doc_ii 1;
+#X obj 14 624 doc_oo 0;
+#X obj 0 654 doc_f;
+#X obj 97 431 doc_m i0 grid;
+#X obj 97 488 doc_m i1;
+#X text 8 114 Comparisons are meant to be invariant;
+#X text 8 126 to the following transformations:;
+#X text 33 186 scalar scalings \, e.g. [# *] with;
+#X text 33 198 only one value.;
+#X obj 97 624 doc_m o0 grid;
+#X connect 0 0 19 0;
+#X connect 2 0 7 0;
+#X connect 3 0 10 0;
+#X connect 4 0 2 1;
+#X connect 5 0 4 0;
+#X connect 6 1 16 0;
+#X connect 7 0 20 0;
+#X connect 7 0 21 0;
+#X connect 8 0 6 0;
+#X connect 9 0 2 0;
+#X connect 10 0 6 0;
+#X connect 13 0 17 0;
+#X connect 15 0 0 0;
+#X connect 16 0 15 0;
+#X connect 17 0 14 0;
+#X connect 17 0 7 1;
+#X connect 18 0 9 0;
+#X connect 19 0 18 0;
+#X connect 20 0 22 0;
+#X connect 21 0 23 0;
+#X connect 22 0 25 0;
+#X connect 23 0 26 0;
+#X connect 24 0 13 0;
+#X connect 42 1 37 0;
+#X connect 42 1 27 0;
+#X connect 43 1 36 0;
+#X connect 43 1 28 0;
diff --git a/externals/gridflow/doc/flow_classes/#polygon_each_edge-help.pd b/externals/gridflow/doc/flow_classes/#polygon_each_edge-help.pd
new file mode 100644
index 00000000..06afba8a
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#polygon_each_edge-help.pd
@@ -0,0 +1,22 @@
+#N canvas 338 225 632 377 10;
+#X obj 51 139 #print;
+#X obj 51 83 # +;
+#X obj 51 102 #polygon_each_edge;
+#X obj 0 0 doc_h;
+#X obj 3 170 doc_c;
+#X obj 3 210 doc_i 1;
+#X obj 3 273 doc_o 1;
+#X obj 14 303 doc_oo 0;
+#X obj 14 240 doc_ii 0;
+#X obj 0 348 doc_f;
+#X msg 51 48 4 2 # 0 0 0 20 20 20 20 0;
+#X obj 97 240 doc_m i0 grid;
+#X obj 97 303 doc_m o0 grid;
+#X text 232 240 Vertices of the polygon;
+#X text 232 303 Returns a grid contaning a vertex pair for each edge
+of the polygon.;
+#X connect 1 0 2 0;
+#X connect 2 0 0 0;
+#X connect 10 0 1 0;
+#X connect 11 1 13 0;
+#X connect 12 1 14 0;
diff --git a/externals/gridflow/doc/flow_classes/#polygon_moment-help.pd b/externals/gridflow/doc/flow_classes/#polygon_moment-help.pd
new file mode 100644
index 00000000..41ee2986
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#polygon_moment-help.pd
@@ -0,0 +1,64 @@
+#N canvas 678 0 632 610 10;
+#X msg 263 58 4 2 # 1 1 1 5 5 5 5 1;
+#X text 413 58 should give 3 3;
+#X obj 282 188 display;
+#X obj 203 219 #outer + (-4 4);
+#X obj 203 238 #transpose;
+#X obj 37 64 metro 42;
+#X obj 37 47 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1
+;
+#X msg 37 83 240 320 3 #;
+#X obj 37 256 #out window;
+#X obj 37 122 #draw_polygon + (255 0 0);
+#X obj 37 219 #draw_rect + (255 255 0);
+#X obj 378 188 display;
+#X obj 377 168 #polygon_moment 2;
+#X obj 281 168 #polygon_moment;
+#X obj 263 77 # * (10 20);
+#X obj 263 96 #rotate;
+#X floatatom 316 98 5 0 0 0 - - -;
+#X obj 0 0 doc_h;
+#X obj 3 375 doc_i 2;
+#X obj 3 291 doc_c 1;
+#X obj 3 516 doc_o 1;
+#X obj 14 546 doc_oo 0;
+#X obj 14 405 doc_ii 0;
+#X obj 14 427 doc_ii 1;
+#X obj 14 321 doc_cc 0;
+#X obj 97 321 doc_m c0 float;
+#X text 232 321 1: first-order moment (average);
+#X text 232 343 2: second-order moment (standard-deviation);
+#X obj 97 546 doc_m o0 grid;
+#X obj 97 405 doc_m i0 grid;
+#X obj 97 427 doc_m i1 grid;
+#X text 232 427 centre to subtract from the input;
+#X text 232 449 in the case of an average \, you'd leave this unused
+;
+#X text 232 471 but in the case of a standard-deviation \, you'd put
+the average in here \, unless you want a nonstandard deviation.;
+#X text 232 546 polygon. size (N 2);
+#X text 232 405 polygon. size (N 2);
+#X obj 0 578 doc_f;
+#X connect 0 0 14 0;
+#X connect 3 0 4 0;
+#X connect 4 0 10 2;
+#X connect 5 0 7 0;
+#X connect 6 0 5 0;
+#X connect 7 0 9 0;
+#X connect 9 0 10 0;
+#X connect 10 0 8 0;
+#X connect 12 0 11 0;
+#X connect 13 0 2 0;
+#X connect 13 0 3 0;
+#X connect 14 0 15 0;
+#X connect 15 0 9 2;
+#X connect 15 0 13 0;
+#X connect 15 0 12 0;
+#X connect 16 0 15 1;
+#X connect 25 1 26 0;
+#X connect 25 1 27 0;
+#X connect 28 1 34 0;
+#X connect 29 1 35 0;
+#X connect 30 1 31 0;
+#X connect 30 1 32 0;
+#X connect 30 1 33 0;
diff --git a/externals/gridflow/doc/flow_classes/#polygon_perimetre-help.pd b/externals/gridflow/doc/flow_classes/#polygon_perimetre-help.pd
new file mode 100644
index 00000000..6409a635
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#polygon_perimetre-help.pd
@@ -0,0 +1,23 @@
+#N canvas 335 118 632 342 10;
+#X obj 0 0 doc_h;
+#X obj 0 313 doc_f;
+#X obj 47 64 #polygon_perimetre;
+#X obj 3 129 doc_c 0;
+#X obj 3 169 doc_i 1;
+#X obj 3 231 doc_o 1;
+#X obj 14 261 doc_oo 0;
+#X obj 14 199 doc_ii 0;
+#X obj 97 261 doc_m o0 grid;
+#X obj 97 199 doc_m i0 grid;
+#X text 232 261 perimetre as grid[];
+#X text 232 199 polygon as grid[N \, 2] or any cyclic path as grid[N
+\, M];
+#X text 187 44 finds the perimetre of a sequence of points in which
+the last point is assumed to connect back to the first point. this
+not need be an actual polygon (because points don't need to be coplanar
+for this calculation to work).;
+#X obj 3 293 doc_also;
+#X obj 103 293 #polygon_area;
+#X connect 8 1 10 0;
+#X connect 9 1 11 0;
+#X connect 13 1 14 0;
diff --git a/externals/gridflow/doc/flow_classes/#polygon_radial_map-help.pd b/externals/gridflow/doc/flow_classes/#polygon_radial_map-help.pd
new file mode 100644
index 00000000..e08e8017
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#polygon_radial_map-help.pd
@@ -0,0 +1,55 @@
+#N canvas 486 64 632 526 10;
+#X obj 244 185 #polygon_radial_map;
+#X text 70 40 makes a 1-D panoramic (polar) rendering of a polygon.
+;
+#X text 69 57 if you want to make standardized (translation-independent)
+renderings of polygons \, first substract [#polygon_moment] (or a variant
+thereof) from the polygon.;
+#X obj 244 280 #outer * (255 255 255);
+#X obj 244 299 #out window;
+#X obj 24 193 t b a;
+#X obj 24 240 #draw_polygon put (255 224 200);
+#X msg 24 221 240 320 3 # 0 60 90;
+#X obj 244 242 #for 128 0 -1;
+#X obj 24 259 #out window;
+#X obj 244 140 #t;
+#X obj 274 141 #polygon_moment;
+#X obj 293 162 display;
+#X obj 244 166 # -;
+#X obj 392 184 display;
+#X msg 24 116 4 2 # 30 30 30 250 120 200 170 90;
+#X obj 244 204 t a a;
+#X obj 244 223 #finished;
+#X obj 244 261 #outer <;
+#X obj 0 0 doc_h;
+#X obj 3 333 doc_c 0;
+#X obj 3 373 doc_i 1;
+#X obj 3 435 doc_o 1;
+#X obj 14 465 doc_oo 0;
+#X obj 14 403 doc_ii 0;
+#X obj 0 497 doc_f;
+#X obj 97 465 doc_m o0 grid;
+#X obj 97 403 doc_m i0 grid;
+#X text 232 403 polygon;
+#X text 232 465 radial map;
+#X connect 0 0 16 0;
+#X connect 3 0 4 0;
+#X connect 5 0 7 0;
+#X connect 5 1 6 2;
+#X connect 6 0 9 0;
+#X connect 7 0 6 0;
+#X connect 8 0 18 0;
+#X connect 10 0 13 0;
+#X connect 10 1 11 0;
+#X connect 11 0 12 0;
+#X connect 11 0 13 1;
+#X connect 13 0 0 0;
+#X connect 13 0 14 0;
+#X connect 15 0 5 0;
+#X connect 15 0 10 0;
+#X connect 16 0 17 0;
+#X connect 16 1 18 1;
+#X connect 17 0 8 0;
+#X connect 18 0 3 0;
+#X connect 26 1 29 0;
+#X connect 27 1 28 0;
diff --git a/externals/gridflow/doc/flow_classes/#posterize-help.pd b/externals/gridflow/doc/flow_classes/#posterize-help.pd
new file mode 100644
index 00000000..3ca6cba7
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#posterize-help.pd
@@ -0,0 +1,63 @@
+#N canvas 674 0 632 625 10;
+#X obj 178 114 bng 15 250 50 0 empty empty empty 0 -6 0 8 -4034 -1
+-1;
+#X text 274 230 2 - 255;
+#X msg 217 157 open bluemarble.jpg;
+#X obj 197 179 #in;
+#X obj 178 203 #store;
+#X obj 178 251 #posterize;
+#X obj 103 570 #convolve;
+#X obj 169 570 #contrast;
+#X obj 235 570 #solarize;
+#X obj 301 570 #layer;
+#X obj 0 0 doc_h;
+#X obj 3 570 doc_also;
+#X obj 3 424 doc_i 2;
+#X obj 3 508 doc_o 1;
+#X obj 14 538 doc_oo 0;
+#X obj 14 454 doc_ii 0;
+#X obj 14 476 doc_ii 1;
+#X text 10 35 Reduces the number of possible intensities in an image:
+it rounds the color values. The effect is mostly apparent with a low
+number of levels.;
+#X obj 202 271 #out window \, title original;
+#X obj 178 291 #out window \, title modified;
+#X obj 178 136 t b b b;
+#X floatatom 235 230 5 0 0 0 - - -;
+#X msg 235 210 2;
+#X obj 235 190 loadbang;
+#X obj 97 454 doc_m i0 grid;
+#X obj 97 476 doc_m i1 float int;
+#X obj 97 538 doc_m o0 grid;
+#X text 232 538 posterised image;
+#X obj 3 323 doc_c 1;
+#X obj 14 353 doc_cc 0;
+#X obj 97 353 doc_m c0 float/int;
+#X text 11 75 example: simulate the 216-color "web" palette using 6
+levels. simulate a 15-bit display using 32 levels .;
+#X text 232 353 Number of possible levels per channel. The levels are
+equally spaced \, with the lowest at 0 and the highest at 255 the minimum
+number of levels is 2 and the default value is also 2;
+#X obj 0 590 doc_f;
+#X text 232 454 original image;
+#X text 232 476 same as arg 0;
+#X connect 0 0 20 0;
+#X connect 2 0 3 0;
+#X connect 3 0 4 1;
+#X connect 4 0 5 0;
+#X connect 4 0 18 0;
+#X connect 5 0 19 0;
+#X connect 11 1 6 0;
+#X connect 11 1 7 0;
+#X connect 11 1 8 0;
+#X connect 11 1 9 0;
+#X connect 20 0 4 0;
+#X connect 20 1 3 0;
+#X connect 20 2 2 0;
+#X connect 21 0 5 1;
+#X connect 22 0 21 0;
+#X connect 23 0 22 0;
+#X connect 24 1 34 0;
+#X connect 25 1 35 0;
+#X connect 26 1 27 0;
+#X connect 30 1 32 0;
diff --git a/externals/gridflow/doc/flow_classes/#print-help.pd b/externals/gridflow/doc/flow_classes/#print-help.pd
new file mode 100644
index 00000000..b15e8ff4
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#print-help.pd
@@ -0,0 +1,73 @@
+#N canvas 408 30 632 632 10;
+#X text 15 32 Displays the dimensions of a grid in the console. If
+the grid has less than two dimensions it will display all grid data.
+;
+#X floatatom 213 105 5 0 0 0 - - -;
+#X floatatom 235 126 5 0 0 0 - - -;
+#X floatatom 257 146 5 0 0 0 - - -;
+#X obj 71 116 #in;
+#X obj 100 158 #import (3 3 3);
+#X msg 100 110 3 3 3 # 27;
+#X obj 100 134 # rand;
+#X msg 71 88 load sewing.jpg;
+#X obj 71 251 #print paprika;
+#X text 232 409 Incoming grid.;
+#X obj 103 582 #dim;
+#X obj 139 582 #to_float;
+#X obj 205 582 #to_list;
+#X obj 265 582 print;
+#X text 232 431 select between base 2 \, 8 \, 10 \, 16;
+#X text 232 453 stop printing after that number of rows;
+#X text 232 475 stop printing after that number of characters on the
+same line;
+#X obj 213 165 #pack 3;
+#X msg 368 188 base 2;
+#X msg 368 208 base 8;
+#X msg 368 228 base 10;
+#X msg 368 248 base 16;
+#X msg 370 159 maxrows 10;
+#X msg 370 136 trunc 20;
+#X obj 0 0 doc_h;
+#X obj 3 379 doc_i 1;
+#X obj 3 295 doc_c 0..1;
+#X obj 3 582 doc_also;
+#X obj 14 550 doc_oo 0;
+#X obj 14 409 doc_ii 0;
+#X obj 3 520 doc_o 2;
+#X obj 14 325 doc_cc 0;
+#X obj 97 325 doc_m c0 float|symbol;
+#X text 232 325 prefix before the printed element in the console.;
+#X text 232 347 default: no prefix;
+#X obj 97 409 doc_m i0 grid;
+#X obj 97 431 doc_m i0 base int;
+#X obj 97 453 doc_m i0 maxrows int;
+#X obj 97 475 doc_m i0 trunc int;
+#X obj 97 550 doc_m o0 grid;
+#X text 232 550 probably unused;
+#X obj 0 603 doc_f;
+#X connect 1 0 18 0;
+#X connect 2 0 18 1;
+#X connect 3 0 18 2;
+#X connect 4 0 9 0;
+#X connect 5 0 9 0;
+#X connect 6 0 7 0;
+#X connect 7 0 5 0;
+#X connect 8 0 4 0;
+#X connect 18 0 9 0;
+#X connect 19 0 9 0;
+#X connect 20 0 9 0;
+#X connect 21 0 9 0;
+#X connect 22 0 9 0;
+#X connect 23 0 9 0;
+#X connect 24 0 9 0;
+#X connect 28 1 11 0;
+#X connect 28 1 12 0;
+#X connect 28 1 13 0;
+#X connect 28 1 14 0;
+#X connect 33 1 34 0;
+#X connect 33 1 35 0;
+#X connect 36 1 10 0;
+#X connect 37 1 15 0;
+#X connect 38 1 16 0;
+#X connect 39 1 17 0;
+#X connect 40 1 41 0;
diff --git a/externals/gridflow/doc/flow_classes/#ravel-help.pd b/externals/gridflow/doc/flow_classes/#ravel-help.pd
new file mode 100644
index 00000000..2f167e57
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#ravel-help.pd
@@ -0,0 +1,42 @@
+#N canvas 691 0 632 493 10;
+#X obj 20 80 bng 15 250 50 0 empty empty empty 0 -6 0 8 -233017 -1
+-1;
+#X obj 20 231 print before;
+#X obj 140 233 print after;
+#X obj 20 142 #in;
+#X obj 20 188 #dim;
+#X obj 103 444 #redim (1);
+#X obj 175 444 #perspective;
+#X obj 140 190 #dim;
+#X obj 140 169 #ravel;
+#X obj 0 0 doc_h;
+#X obj 3 267 doc_c 0;
+#X obj 3 307 doc_i 1;
+#X obj 3 444 doc_also;
+#X obj 3 382 doc_o 1;
+#X obj 14 412 doc_oo 0;
+#X obj 14 337 doc_ii 0;
+#X obj 97 337 doc_m i0 grid;
+#X obj 97 412 doc_m o0 grid;
+#X text 232 337 like [#redim] but always produce a 1-D grid with the
+same total number of elements.;
+#X obj 0 464 doc_f;
+#X msg 20 120 load bluemarble.jpg;
+#X obj 20 210 #to_list;
+#X obj 140 212 #to_list;
+#X text 143 55 like #redim but always produces a 1-D grid with the
+same total number of elements.;
+#X text 232 412 1-D grid;
+#X connect 0 0 20 0;
+#X connect 3 0 4 0;
+#X connect 3 0 8 0;
+#X connect 4 0 21 0;
+#X connect 7 0 22 0;
+#X connect 8 0 7 0;
+#X connect 12 1 5 0;
+#X connect 12 1 6 0;
+#X connect 16 1 18 0;
+#X connect 17 1 24 0;
+#X connect 20 0 3 0;
+#X connect 21 0 1 0;
+#X connect 22 0 2 0;
diff --git a/externals/gridflow/doc/flow_classes/#record-help.pd b/externals/gridflow/doc/flow_classes/#record-help.pd
new file mode 100644
index 00000000..2cbb9721
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#record-help.pd
@@ -0,0 +1,53 @@
+#N canvas 525 0 632 584 10;
+#X obj 79 121 #camera;
+#X obj 79 70 tgl 15 0 empty empty empty 0 -6 0 8 -24198 -1 -1 0 1;
+#X obj 105 153 #out window;
+#X obj 154 70 hsl 128 15 20 300 0 0 empty empty empty -2 -6 0 8 -260818
+-1 -1 0 1;
+#X obj 105 172 fps detailed;
+#X obj 105 191 print;
+#X obj 79 98 metro 100;
+#X obj 93 220 bng 15 250 50 0 empty empty empty 0 -6 0 8 -24198 -1
+-1;
+#X obj 123 269 bng 15 250 50 0 empty empty empty 0 -6 0 8 -24198 -1
+-1;
+#X obj 108 244 bng 15 250 50 0 empty empty empty 0 -6 0 8 -24198 -1
+-1;
+#X obj 79 299 #record;
+#X text 232 461 Starts recording to the file.;
+#X text 232 483 Stops recording.;
+#X text 232 426 Opens a dialog window in which to type the filename
+to be recorded \, the defualt encoding is quicktime (raw).;
+#X text 22 33 Record a quicktime file with [#out];
+#X text 113 218 <-- 1 select filename;
+#X text 128 243 <-- 2 start recording;
+#X text 143 269 <-- 3 stop recording;
+#X text 142 298 <-- open for more options;
+#X obj 0 0 doc_h;
+#X obj 3 374 doc_i 4;
+#X obj 3 334 doc_c 0;
+#X obj 3 515 doc_o 0;
+#X obj 14 404 doc_ii 0;
+#X obj 14 426 doc_ii 1;
+#X obj 14 461 doc_ii 2;
+#X obj 14 483 doc_ii 3;
+#X obj 97 404 doc_m i0 grid;
+#X obj 97 426 doc_m i1 bang;
+#X obj 97 461 doc_m i2 bang;
+#X obj 97 483 doc_m i3 bang;
+#X obj 0 555 doc_f;
+#X text 232 404 images to be recorded go here.;
+#X connect 0 0 2 0;
+#X connect 0 0 10 0;
+#X connect 1 0 6 0;
+#X connect 2 0 4 0;
+#X connect 3 0 6 1;
+#X connect 4 0 5 0;
+#X connect 6 0 0 0;
+#X connect 7 0 10 1;
+#X connect 8 0 10 3;
+#X connect 9 0 10 2;
+#X connect 27 1 32 0;
+#X connect 28 1 13 0;
+#X connect 29 1 11 0;
+#X connect 30 1 12 0;
diff --git a/externals/gridflow/doc/flow_classes/#redim-help.pd b/externals/gridflow/doc/flow_classes/#redim-help.pd
new file mode 100644
index 00000000..6ccd005c
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#redim-help.pd
@@ -0,0 +1,59 @@
+#N canvas 680 0 632 624 10;
+#X text 86 37 rearrange a grid's values according to new dimensions
+;
+#X obj 21 36 bng 15 250 50 0 empty empty empty 0 -6 0 8 -24198 -1 -1
+;
+#X obj 21 103 #in;
+#X obj 111 154 #out window;
+#X obj 103 575 #ravel;
+#X obj 151 575 #perspective;
+#X obj 21 154 #out window;
+#X obj 21 127 t a a;
+#X obj 111 124 #redim (120 160 3);
+#X text 232 443 Outputs the redimensioned data as a grid.;
+#X msg 232 131 240 320 3;
+#X msg 226 95 400 400 3;
+#X obj 0 0 doc_h;
+#X obj 3 277 doc_i 2;
+#X obj 3 193 doc_c 1;
+#X obj 3 575 doc_also;
+#X obj 3 413 doc_o 1;
+#X obj 14 307 doc_ii 0;
+#X obj 14 381 doc_ii 1;
+#X obj 14 443 doc_oo 0;
+#X obj 14 223 doc_cc 0;
+#X obj 97 223 doc_m c0 grid;
+#X text 232 223 dimension list \, (120 160 3) in this example.;
+#X obj 97 307 doc_m i0 grid;
+#X text 232 245 same as the dimension list of #import;
+#X text 232 307 the elements of this grid are serialized. if the resulting
+grid must be larger \, the sequence is repeated as much as necessary.
+if the resulting grid must be smaller \, the sequence is truncated.
+then the elements are deserialized to form the resulting grid.;
+#X obj 97 381 doc_m i1 grid;
+#X text 232 381 same as arg 0;
+#X obj 97 443 doc_m o0 grid;
+#X text 232 465 example: with a 240 320 RGB image \, [#redim 120 640
+3] will visually separate the even lines (left) from the odd lines
+(right). contrary to this \, [#redim 640 120 3] will split every line
+and put its left half on a even line and the right half on the following
+odd line. [#redim] 480 320 3 will repeat the input image twice in the
+output image. [#redim] 240 50 3 will only keep the 50 top lines.;
+#X obj 0 595 doc_f;
+#X msg 21 81 load working.jpg;
+#X connect 1 0 31 0;
+#X connect 2 0 7 0;
+#X connect 7 0 6 0;
+#X connect 7 1 8 0;
+#X connect 8 0 3 0;
+#X connect 10 0 8 1;
+#X connect 11 0 8 1;
+#X connect 15 1 4 0;
+#X connect 15 1 5 0;
+#X connect 21 1 22 0;
+#X connect 21 1 24 0;
+#X connect 23 1 25 0;
+#X connect 26 1 27 0;
+#X connect 28 1 9 0;
+#X connect 28 1 29 0;
+#X connect 31 0 2 0;
diff --git a/externals/gridflow/doc/flow_classes/#reinterval-help.pd b/externals/gridflow/doc/flow_classes/#reinterval-help.pd
new file mode 100644
index 00000000..7ec9082f
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#reinterval-help.pd
@@ -0,0 +1,33 @@
+#N canvas 335 118 632 382 10;
+#X obj 0 0 doc_h;
+#X obj 0 353 doc_f;
+#X obj 98 61 #reinterval;
+#X obj 3 101 doc_c 0;
+#X obj 3 141 doc_i 5;
+#X obj 3 291 doc_o 1;
+#X obj 14 171 doc_ii 0;
+#X obj 14 193 doc_ii 1;
+#X obj 14 215 doc_ii 2;
+#X obj 14 237 doc_ii 3;
+#X obj 14 259 doc_ii 4;
+#X obj 14 321 doc_oo 0;
+#X obj 97 171 doc_m i0 grid;
+#X obj 97 193 doc_m i1 grid;
+#X obj 97 215 doc_m i2 grid;
+#X obj 97 237 doc_m i3 grid;
+#X obj 97 259 doc_m i4 grid;
+#X obj 97 321 doc_m o0 grid;
+#X text 232 171 values to be rescaled;
+#X text 232 321 rescaled values;
+#X text 232 193 old start;
+#X text 232 215 old end;
+#X text 232 237 new start;
+#X text 232 259 new end;
+#X text 187 46 multiply and add to values such that the old start becomes
+the new start \, and the old end becomes the new end.;
+#X connect 12 1 18 0;
+#X connect 13 1 20 0;
+#X connect 14 1 21 0;
+#X connect 15 1 22 0;
+#X connect 16 1 23 0;
+#X connect 17 1 19 0;
diff --git a/externals/gridflow/doc/flow_classes/#remap_image-help.pd b/externals/gridflow/doc/flow_classes/#remap_image-help.pd
new file mode 100644
index 00000000..0c704ab6
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#remap_image-help.pd
@@ -0,0 +1,53 @@
+#N canvas 690 0 632 578 10;
+#X text 19 26 Transforms a grid by displacing pixels.;
+#X obj 27 154 bng 15 250 50 0 empty empty empty 0 -6 0 8 -24198 -1
+-1;
+#X obj 46 179 #in;
+#X floatatom 156 201 5 0 0 0 - - -;
+#X obj 140 229 # +;
+#X msg 61 153 open sewing.jpg;
+#X text 201 199 <-- Modify value to see transformation.;
+#X text 178 152 <-- open image;
+#X obj 46 261 #out window \, title remapped;
+#X obj 46 97 tgl 15 0 empty empty empty 0 -6 0 8 -24198 -1 -1 0 1;
+#X obj 46 120 metro 33.3667;
+#X text 19 45 If you chain indexmap (coordinate) transformations from
+outlet 1 to inlet 1 \, then sending an image in inlet 0 will emit its
+deformation out of outlet 0;
+#X obj 46 229 #remap_image;
+#X text 187 229 <-- change the numop to change the transformation;
+#X obj 103 529 #rotate;
+#X obj 0 0 doc_h;
+#X obj 3 295 doc_c 0;
+#X obj 3 335 doc_i 2;
+#X obj 3 529 doc_also;
+#X obj 3 432 doc_o 2;
+#X obj 14 365 doc_ii 0;
+#X obj 14 387 doc_ii 1;
+#X obj 14 462 doc_oo 0;
+#X obj 14 497 doc_oo 1;
+#X obj 97 365 doc_m i0 grid;
+#X text 232 365 grid to be remapped;
+#X obj 97 497 doc_m o1 grid;
+#X text 232 497 indexmap of dummy coordinates \, to be deformed;
+#X obj 97 387 doc_m i1 grid;
+#X text 232 387 modified version of what came out of outlet 1 \, which
+will determine the remapping;
+#X obj 97 462 doc_m o0 grid;
+#X text 232 462 the grid from inlet 0 after being remapped using the
+grid from inlet 1;
+#X obj 0 549 doc_f;
+#X connect 1 0 2 0;
+#X connect 2 0 12 0;
+#X connect 3 0 4 1;
+#X connect 4 0 12 1;
+#X connect 5 0 2 0;
+#X connect 9 0 10 0;
+#X connect 10 0 2 0;
+#X connect 12 0 8 0;
+#X connect 12 1 4 0;
+#X connect 18 1 14 0;
+#X connect 24 1 25 0;
+#X connect 26 1 27 0;
+#X connect 28 1 29 0;
+#X connect 30 1 31 0;
diff --git a/externals/gridflow/doc/flow_classes/#reverse-help.pd b/externals/gridflow/doc/flow_classes/#reverse-help.pd
new file mode 100644
index 00000000..71c6fe6c
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#reverse-help.pd
@@ -0,0 +1,65 @@
+#N canvas 668 0 632 642 10;
+#X obj 258 177 #color;
+#X obj 301 320 #color;
+#X obj 259 378 display;
+#X obj 258 319 t a a;
+#X text 15 57 Swaps the values of incoming grids while preserving the
+number of Dimensions between incoming and outgoing grids.;
+#X obj 22 257 #in;
+#X obj 22 176 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 22 371 #out window;
+#X obj 87 259 hradio 15 1 0 6 empty empty empty 0 -6 0 8 -260818 -1
+-1 0;
+#X obj 87 277 - 3;
+#X floatatom 87 297 5 0 0 0 - - -;
+#X obj 22 314 #reverse 0;
+#X obj 258 300 #reverse 0;
+#X obj 323 245 hradio 15 1 0 6 empty empty empty 0 -6 0 8 -260818 -1
+-1 0;
+#X obj 323 263 - 3;
+#X floatatom 323 283 5 0 0 0 - - -;
+#X obj 0 0 doc_h;
+#X obj 3 416 doc_c 1;
+#X obj 3 517 doc_i 2;
+#X obj 3 601 doc_o 1;
+#X obj 14 631 doc_oo 0;
+#X obj 14 547 doc_ii 0;
+#X obj 14 569 doc_ii 1;
+#X obj 14 446 doc_cc 0;
+#X obj 97 631 doc_m o0 grid;
+#X obj 97 547 doc_m i0 grid;
+#X obj 97 446 doc_m c0 float;
+#X obj 97 569 doc_m i1 float;
+#X text 232 569 same as arg 0;
+#X text 232 446 dimension number of the dimension by which the reverse
+will occur. For N-dimensional grids \, the dimensions are numbered
+from 0 to N-1. In addition \, negative numbers from -N to -1 may be
+used \, to which N will be added.;
+#X obj 0 663 doc_f;
+#X text 232 547 grid to be reversed;
+#X text 232 631 reversed grid;
+#X msg 22 226 load b001.jpg;
+#X text 16 92 for an image \, 0 or -3 does vertical flip \, 1 or -2
+does horizontal flip \, and 2 or -1 does channel flip. if you do this
+on something else than an image \, you may see why the negative numbers
+are supported: if you make a grid of multiple images \, then -1 will
+always refer to the channels dimension no matter what.;
+#X connect 0 0 12 0;
+#X connect 3 0 2 0;
+#X connect 3 1 1 0;
+#X connect 5 0 11 0;
+#X connect 6 0 33 0;
+#X connect 8 0 9 0;
+#X connect 9 0 10 0;
+#X connect 10 0 11 1;
+#X connect 11 0 7 0;
+#X connect 12 0 3 0;
+#X connect 13 0 14 0;
+#X connect 14 0 15 0;
+#X connect 15 0 12 1;
+#X connect 24 1 32 0;
+#X connect 25 1 31 0;
+#X connect 26 1 29 0;
+#X connect 27 1 28 0;
+#X connect 33 0 5 0;
diff --git a/externals/gridflow/doc/flow_classes/#rgb_to_greyscale-help.pd b/externals/gridflow/doc/flow_classes/#rgb_to_greyscale-help.pd
new file mode 100644
index 00000000..c370a754
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#rgb_to_greyscale-help.pd
@@ -0,0 +1,27 @@
+#N canvas 689 0 632 401 10;
+#X obj 166 183 #out window;
+#X obj 166 112 #in;
+#X obj 166 137 #rgb_to_greyscale;
+#X obj 174 91 bng 15 250 50 0 empty empty empty 0 -6 0 8 -24198 -1
+-1;
+#X msg 166 68 open working.jpg;
+#X obj 166 160 #greyscale_to_rgb;
+#X obj 0 0 doc_h;
+#X obj 3 208 doc_c 0;
+#X obj 3 248 doc_i 1;
+#X obj 3 310 doc_o 1;
+#X obj 14 340 doc_oo 0;
+#X obj 14 278 doc_ii 0;
+#X text 15 27 Creates a greyscale image from a rgb color image.;
+#X obj 97 278 doc_m i0 grid;
+#X text 232 278 presumed to be an RGB image;
+#X obj 97 340 doc_m o0 grid;
+#X text 232 340 the image converted to greyscale.;
+#X obj 0 372 doc_f;
+#X connect 1 0 2 0;
+#X connect 2 0 5 0;
+#X connect 3 0 1 0;
+#X connect 4 0 1 0;
+#X connect 5 0 0 0;
+#X connect 13 1 14 0;
+#X connect 15 1 16 0;
diff --git a/externals/gridflow/doc/flow_classes/#rgb_to_yuv-help.pd b/externals/gridflow/doc/flow_classes/#rgb_to_yuv-help.pd
new file mode 100644
index 00000000..cbb7ab1f
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#rgb_to_yuv-help.pd
@@ -0,0 +1,30 @@
+#N canvas 205 69 632 421 10;
+#X obj 324 188 #out window;
+#X obj 273 87 bng 15 250 50 0 empty empty empty 0 -6 0 8 -24198 -1
+-1;
+#X obj 255 107 #in;
+#X msg 255 61 open sewing.jpg;
+#X obj 324 150 #rgb_to_yuv;
+#X text 5 152 This displays the image as RGB:;
+#X text 99 190 This displays the image as YUV:;
+#X text 23 26 Converts an RGB color model image to a YUV color model
+image.;
+#X obj 226 152 #out window;
+#X obj 0 0 doc_h;
+#X obj 3 268 doc_i 1;
+#X obj 3 228 doc_c 0;
+#X obj 3 330 doc_o 1;
+#X obj 14 360 doc_oo 0;
+#X obj 14 298 doc_ii 0;
+#X obj 0 392 doc_f;
+#X obj 97 298 doc_m i0 grid;
+#X obj 97 360 doc_m o0 grid;
+#X text 232 298 image in RGB format.;
+#X text 232 360 image in YUV format.;
+#X connect 1 0 2 0;
+#X connect 2 0 4 0;
+#X connect 2 0 8 0;
+#X connect 3 0 2 0;
+#X connect 4 0 0 0;
+#X connect 16 1 18 0;
+#X connect 17 1 19 0;
diff --git a/externals/gridflow/doc/flow_classes/#rotate-help.pd b/externals/gridflow/doc/flow_classes/#rotate-help.pd
new file mode 100644
index 00000000..f8167a45
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#rotate-help.pd
@@ -0,0 +1,49 @@
+#N canvas 689 0 632 445 10;
+#X obj 180 121 #rotate;
+#X text 4 26 The [#rotate] performs rotations on indexmaps and polygons
+and such objects.;
+#X obj 163 83 bng 15 250 50 0 empty empty empty 0 -6 0 8 -24198 -1
+-1;
+#X obj 80 98 #in;
+#X obj 227 99 hsl 40 15 0 35999 0 0 empty empty empty -2 -6 0 8 -262144
+-1 -1 0 1;
+#X obj 80 121 #remap_image;
+#X obj 80 142 #out window \, title #rotate;
+#X obj 9 57 tgl 15 0 empty empty empty 0 -6 0 8 -233017 -1 -1 0 1;
+#X obj 9 76 metro 100;
+#X text 232 274 The Grid passed in inlet 0 will be the grid on which
+the rotation will be performed.;
+#X floatatom 243 123 7 0 0 0 - - -;
+#X msg 80 57 open b001.jpg;
+#X obj 0 0 doc_h;
+#X obj 3 244 doc_i 2;
+#X obj 3 169 doc_c 1;
+#X text 232 371 Outputs the result of the rotation and needs to be
+sent to a [#remap_image] to be visualised.;
+#X obj 3 341 doc_o 1;
+#X obj 14 371 doc_oo 0;
+#X obj 14 274 doc_ii 0;
+#X obj 14 309 doc_ii 1;
+#X obj 14 199 doc_cc 0;
+#X obj 97 199 doc_m c0 float;
+#X obj 97 274 doc_m i0 grid;
+#X obj 97 309 doc_m i1 float;
+#X text 232 309 same as arg 0;
+#X obj 97 371 doc_m o0 grid;
+#X obj 0 416 doc_f;
+#X text 232 199 integer number (0 to 35999) as a creation argument
+which initializes the first angle of rotation.;
+#X connect 0 0 5 1;
+#X connect 2 0 3 0;
+#X connect 3 0 5 0;
+#X connect 4 0 0 1;
+#X connect 4 0 10 0;
+#X connect 5 0 6 0;
+#X connect 5 1 0 0;
+#X connect 7 0 8 0;
+#X connect 8 0 3 0;
+#X connect 11 0 3 0;
+#X connect 21 1 27 0;
+#X connect 22 1 9 0;
+#X connect 23 1 24 0;
+#X connect 25 1 15 0;
diff --git a/externals/gridflow/doc/flow_classes/#rotatificator-help.pd b/externals/gridflow/doc/flow_classes/#rotatificator-help.pd
new file mode 100644
index 00000000..e31066a3
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#rotatificator-help.pd
@@ -0,0 +1,50 @@
+#N canvas 604 245 632 581 10;
+#X obj 0 0 doc_h;
+#X obj 0 552 doc_f;
+#X obj 20 64 #rotatificator;
+#X text 191 138 named in honour of Laszlo Zlotz (a character from Achille
+Talon);
+#X obj 3 532 doc_also;
+#X obj 103 532 #rotate;
+#X obj 3 286 doc_i 2;
+#X obj 3 418 doc_o 1;
+#X obj 14 448 doc_oo 0;
+#X obj 14 316 doc_ii 0;
+#X obj 14 386 doc_ii 1;
+#X obj 97 316 doc_m i0 float;
+#X obj 97 338 doc_m i0 axis;
+#X obj 3 180 doc_c 3;
+#X obj 14 210 doc_cc 0;
+#X obj 14 232 doc_cc 1;
+#X obj 14 254 doc_cc 2;
+#X obj 97 448 doc_m o0 grid;
+#X obj 97 386 doc_m i1;
+#X obj 97 210 doc_m c0 float/int;
+#X obj 97 232 doc_m c1 float/int;
+#X obj 97 254 doc_m c2 float/int;
+#X text 232 210 from;
+#X text 232 232 to;
+#X text 232 254 n;
+#X text 232 338 \$1=from (default:0) \; \$2=to (default: 1) \; \$3=n
+(default: 2);
+#X text 232 386 angle;
+#X text 232 316 scale;
+#X text 192 44 generates a N by N rotation matrix that rotates through
+two dimensions of your choice (from \, to) by a certain angle (in centidegrees).
+values produced are integers. the rotation matrix is multiplied by
+the given scale factor such that after an eventual [#inner] \, a division
+by the same amount would be performed. greater scale factors are more
+precise.;
+#X text 232 448 rotation matrix such that if rows 'from' and 'to' were
+deleted and columns 'from' and 'to' were deleted \, you'd have an identity
+matrix. in other words \, the rotation happens in a plane space made
+of the two dimensions represented by those two rows and two columns.
+;
+#X connect 4 1 5 0;
+#X connect 11 1 27 0;
+#X connect 12 1 25 0;
+#X connect 17 1 29 0;
+#X connect 18 1 26 0;
+#X connect 19 1 22 0;
+#X connect 20 1 23 0;
+#X connect 21 1 24 0;
diff --git a/externals/gridflow/doc/flow_classes/#saturation-help.pd b/externals/gridflow/doc/flow_classes/#saturation-help.pd
new file mode 100644
index 00000000..f493dde7
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#saturation-help.pd
@@ -0,0 +1,52 @@
+#N canvas 115 0 632 551 10;
+#X obj 47 267 print;
+#X obj 47 227 #out window;
+#X text 313 178 OR;
+#X text 295 140 global saturation;
+#X obj 47 248 fps detailed;
+#X text 260 197 per-channel saturation;
+#X msg 251 135 0;
+#X obj 251 114 loadbang;
+#X obj 254 156 hsl 137 15 -256 512 0 0 empty empty empty -2 -6 0 8
+-260818 -128992 -1 4533 1;
+#X floatatom 212 157 5 0 0 0 - - -;
+#X obj 47 65 tgl 15 0 empty empty empty 0 -6 0 8 -24198 -1 -1 0 1;
+#X obj 47 99 metro 33.3667;
+#X msg 204 198 3 # \$1;
+#X obj 47 134 #in babbage.jpg;
+#X obj 204 224 #color -256 512 1;
+#X obj 47 203 #saturation -128;
+#X obj 0 0 doc_h;
+#X obj 3 376 doc_i 2;
+#X obj 3 301 doc_c 1;
+#X obj 3 460 doc_o 1;
+#X obj 14 406 doc_ii 0;
+#X obj 14 428 doc_ii 1;
+#X obj 14 490 doc_oo 0;
+#X obj 14 331 doc_cc 0;
+#X text 232 428 same as arg 0;
+#X obj 97 331 doc_m c0 float/int;
+#X obj 97 406 doc_m i0 grid;
+#X obj 97 428 doc_m i1 grid;
+#X obj 97 490 doc_m o0 grid;
+#X obj 0 522 doc_f;
+#X text 232 406 image to be modified;
+#X text 232 331 Saturation multiplier. 256 does nothing. 0 turns to
+greyscale. -256 does like [#hueshift 18000].;
+#X text 232 490 modified image;
+#X connect 1 0 4 0;
+#X connect 4 0 0 0;
+#X connect 6 0 8 0;
+#X connect 7 0 6 0;
+#X connect 8 0 9 0;
+#X connect 8 0 12 0;
+#X connect 10 0 11 0;
+#X connect 11 0 13 0;
+#X connect 12 0 14 0;
+#X connect 13 0 15 0;
+#X connect 14 0 15 1;
+#X connect 15 0 1 0;
+#X connect 25 1 31 0;
+#X connect 26 1 30 0;
+#X connect 27 1 24 0;
+#X connect 28 1 32 0;
diff --git a/externals/gridflow/doc/flow_classes/#scale_by-help.pd b/externals/gridflow/doc/flow_classes/#scale_by-help.pd
new file mode 100644
index 00000000..5b61d091
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#scale_by-help.pd
@@ -0,0 +1,57 @@
+#N canvas 690 0 632 610 10;
+#X obj 11 82 tgl 15 0 empty empty empty 0 -6 0 8 -24198 -1 -1 0 1;
+#X obj 11 102 metro 100;
+#X obj 89 149 #in;
+#X obj 103 561 #scale_to;
+#X obj 169 561 #downscale_by;
+#X text 232 507 Outputs the resulting scaled image.;
+#X obj 89 207 #out window \, title #scale_by;
+#X msg 89 85 open bluemarble.jpg \, bang;
+#X obj 89 183 #scale_by 2;
+#X text 7 28 The [#scale_by] scales the image received by the row and
+column factors passed. A single value applies the scaling uniformly
+on the row and columns.;
+#X msg 227 129 2 # 2 1;
+#X msg 230 152 2 # 2 3;
+#X floatatom 181 131 5 0 0 0 - - -;
+#X text 232 362 The Grid on which the scale_to will be performed.;
+#X obj 0 0 doc_h;
+#X obj 3 332 doc_i 2;
+#X obj 3 477 doc_o 1;
+#X text 232 265 The scaling factor (defaults to 2).;
+#X obj 3 561 doc_also;
+#X obj 14 507 doc_oo 0;
+#X obj 14 362 doc_ii 0;
+#X obj 14 445 doc_ii 1;
+#X obj 14 265 doc_cc 0;
+#X obj 97 362 doc_m i0 grid;
+#X obj 97 265 doc_m c0 grid;
+#X obj 97 445 doc_m i1 grid;
+#X obj 3 235 doc_c 0..1;
+#X text 232 445 same as arg 0;
+#X text 232 287 if it's a single value \, then that factor is to be
+used for both rows and columns.;
+#X text 232 384 duplicates each pixel several times in width and several
+times in height \, where the number of times is determined by the factor
+described above. twice those of the incoming grid. It is several times
+faster.;
+#X text 232 529 grid((factor*y) (factor*x) channels);
+#X obj 97 507 doc_m o0 grid;
+#X obj 0 581 doc_f;
+#X connect 0 0 1 0;
+#X connect 1 0 2 0;
+#X connect 2 0 8 0;
+#X connect 7 0 2 0;
+#X connect 8 0 6 0;
+#X connect 10 0 8 1;
+#X connect 11 0 8 1;
+#X connect 12 0 8 1;
+#X connect 18 1 3 0;
+#X connect 18 1 4 0;
+#X connect 23 1 13 0;
+#X connect 23 1 29 0;
+#X connect 24 1 17 0;
+#X connect 24 1 28 0;
+#X connect 25 1 27 0;
+#X connect 31 1 5 0;
+#X connect 31 1 30 0;
diff --git a/externals/gridflow/doc/flow_classes/#scale_to-help.pd b/externals/gridflow/doc/flow_classes/#scale_to-help.pd
new file mode 100644
index 00000000..54adb77a
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#scale_to-help.pd
@@ -0,0 +1,66 @@
+#N canvas 674 0 632 523 10;
+#X obj 11 75 tgl 15 0 empty empty empty 0 -6 0 8 -24198 -1 -1 0 1;
+#X obj 11 94 metro 100;
+#X obj 89 171 #scale_to (133 133);
+#X obj 89 133 #in;
+#X obj 284 159 #pack;
+#X obj 325 138 hsl 128 15 0 640 0 0 empty empty empty 0 -8 0 8 -260818
+-1 -1 0 1;
+#X obj 325 158 hsl 128 15 0 640 0 0 empty empty empty 0 -8 0 8 -260818
+-1 -1 0 1;
+#X obj 89 208 #out window \, title #scale_to;
+#X obj 169 474 #downscale_by;
+#X msg 89 73 open scissors.jpg \, bang;
+#X obj 300 183 #print;
+#X msg 284 75 2 # 500 500;
+#X obj 412 97 #print;
+#X msg 284 94 2 # 100 500;
+#X msg 285 115 2 # 500 100;
+#X text 460 133 height;
+#X text 460 155 width;
+#X text 232 442 Outputs the resulting scaled image.;
+#X text 232 270 A (height width) pair of integers indicating the size
+to scale to image to. This initial argument is required.;
+#X text 232 345 The Grid passed at inlet 0 will be the image on which
+the scale_to will be performed.;
+#X text 284 58 2 grid size values y=500 x=500;
+#X obj 103 474 #scale_by;
+#X text 9 22 The [#scale_to] scales the image received to the x and
+y values passed. Initial creation arguments are mandatory (0 0) otherwise.
+;
+#X obj 0 0 doc_h;
+#X obj 3 315 doc_i 2;
+#X obj 3 240 doc_c 1;
+#X obj 3 474 doc_also;
+#X obj 3 412 doc_o 1;
+#X obj 14 442 doc_oo 0;
+#X obj 14 345 doc_ii 0;
+#X obj 14 380 doc_ii 1;
+#X obj 14 270 doc_cc 0;
+#X obj 97 270 doc_m c0 (int int);
+#X obj 97 345 doc_m i0 grid;
+#X text 232 380 same as arg 0;
+#X obj 97 380 doc_m i1 (int int);
+#X obj 97 442 doc_m o0 grid;
+#X obj 0 494 doc_f;
+#X connect 0 0 1 0;
+#X connect 1 0 3 0;
+#X connect 2 0 7 0;
+#X connect 3 0 2 0;
+#X connect 4 0 2 1;
+#X connect 4 0 10 0;
+#X connect 5 0 4 0;
+#X connect 6 0 4 1;
+#X connect 9 0 3 0;
+#X connect 11 0 2 1;
+#X connect 11 0 12 0;
+#X connect 13 0 2 1;
+#X connect 13 0 12 0;
+#X connect 14 0 2 1;
+#X connect 14 0 12 0;
+#X connect 26 1 21 0;
+#X connect 26 1 8 0;
+#X connect 32 1 18 0;
+#X connect 33 1 19 0;
+#X connect 35 1 34 0;
+#X connect 36 1 17 0;
diff --git a/externals/gridflow/doc/flow_classes/#scan-help.pd b/externals/gridflow/doc/flow_classes/#scan-help.pd
new file mode 100644
index 00000000..06bad143
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#scan-help.pd
@@ -0,0 +1,48 @@
+#N canvas 664 0 632 547 10;
+#X floatatom 17 76 5 0 0 0 - - -;
+#X floatatom 62 76 5 0 0 0 - - -;
+#X floatatom 109 76 5 0 0 0 - - -;
+#X floatatom 17 245 5 0 0 0 - - -;
+#X floatatom 56 245 5 0 0 0 - - -;
+#X floatatom 96 245 5 0 0 0 - - -;
+#X obj 17 116 #pack 3;
+#X obj 17 147 #scan +;
+#X obj 17 206 #unpack 3;
+#X obj 103 498 #fold +;
+#X obj 0 0 doc_h;
+#X obj 3 498 doc_also;
+#X obj 3 274 doc_c 1;
+#X obj 3 336 doc_i 1;
+#X obj 3 438 doc_o 1;
+#X obj 14 468 doc_oo 0;
+#X obj 14 304 doc_cc 0;
+#X text 69 35 computes subtotals and stuff;
+#X text 165 74 replaces every Dim(last) subgrid by all the results
+of cascading the operator on that subgrid \, producing a Dim(dims \,
+last) grid.;
+#X text 165 127 For example \, with base value 0 and operation + on
+grid "2 3 5 7" will compute 0+2=2 \, 2+3=5 \, 5+5=10 \, 10+7=17 \,
+and give the subtotals "2 5 10 17".;
+#X obj 14 366 doc_ii 0;
+#X obj 97 366 doc_m i0 grid;
+#X obj 97 386 doc_m i0 op;
+#X obj 97 408 doc_m i0 seed;
+#X text 165 191 [#scan +] computes subtotals \; this can be used \,
+for example \, to convert a regular probability distribution into a
+cumulative one. (or in general \, discrete integration);
+#X obj 0 518 doc_f;
+#X obj 97 468 doc_m o0 grid;
+#X obj 97 304 doc_m c0 symbol;
+#X text 232 304 numop;
+#X text 232 386 same as arg 0;
+#X connect 0 0 6 0;
+#X connect 1 0 6 1;
+#X connect 2 0 6 2;
+#X connect 6 0 7 0;
+#X connect 7 0 8 0;
+#X connect 8 0 3 0;
+#X connect 8 1 4 0;
+#X connect 8 2 5 0;
+#X connect 11 1 9 0;
+#X connect 22 1 29 0;
+#X connect 27 1 28 0;
diff --git a/externals/gridflow/doc/flow_classes/#seq_fold-help.pd b/externals/gridflow/doc/flow_classes/#seq_fold-help.pd
new file mode 100644
index 00000000..df26fff8
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#seq_fold-help.pd
@@ -0,0 +1,55 @@
+#N canvas 677 0 632 548 10;
+#X obj 125 63 route end;
+#X obj 126 162 display;
+#X obj 125 106 #seq_fold;
+#X obj 154 130 # +;
+#X msg 125 43 2 1 \, 3 2 \, 5 3 \, 7 4 \, end;
+#X msg 206 82 0 0;
+#X obj 206 63 loadbang;
+#X obj 92 193 #print AAA;
+#X obj 0 0 doc_h;
+#X obj 3 225 doc_c;
+#X obj 3 265 doc_i 4;
+#X obj 14 423 doc_oo 0;
+#X obj 14 445 doc_oo 1;
+#X obj 14 467 doc_oo 2;
+#X obj 3 393 doc_o 3;
+#X obj 14 295 doc_ii 0;
+#X obj 14 317 doc_ii 1;
+#X obj 14 339 doc_ii 2;
+#X obj 14 361 doc_ii 3;
+#X obj 0 519 doc_f;
+#X obj 97 295 doc_m i0 bang;
+#X obj 97 317 doc_m i1 grid;
+#X obj 97 339 doc_m i2 grid;
+#X obj 97 361 doc_m i3 grid;
+#X obj 97 423 doc_m o0 grid;
+#X obj 97 445 doc_m o1 grid;
+#X obj 97 467 doc_m o2 grid;
+#X obj 3 499 doc_also;
+#X obj 103 499 seq_fold;
+#X text 232 445 to outside left inlet;
+#X text 232 467 to outside right inlet;
+#X text 232 423 final result;
+#X text 232 361 from outside outlet;
+#X text 232 339 seed;
+#X text 232 295 output the final result;
+#X text 232 317 sequence of values to be folded;
+#X connect 0 0 2 0;
+#X connect 0 1 2 1;
+#X connect 2 0 1 0;
+#X connect 2 0 7 0;
+#X connect 2 1 3 0;
+#X connect 2 2 3 1;
+#X connect 3 0 2 3;
+#X connect 4 0 0 0;
+#X connect 5 0 2 2;
+#X connect 6 0 5 0;
+#X connect 20 1 34 0;
+#X connect 21 1 35 0;
+#X connect 22 1 33 0;
+#X connect 23 1 32 0;
+#X connect 24 1 31 0;
+#X connect 25 1 29 0;
+#X connect 26 1 30 0;
+#X connect 27 1 28 1;
diff --git a/externals/gridflow/doc/flow_classes/#slice-help.pd b/externals/gridflow/doc/flow_classes/#slice-help.pd
new file mode 100644
index 00000000..df793231
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#slice-help.pd
@@ -0,0 +1,47 @@
+#N canvas 206 135 632 525 10;
+#X obj 38 190 display;
+#X text 36 213 should print subgrid: 3 5 8 13 21;
+#X msg 37 145 0 1 1 2 3 5 8 13 21 34 55 89;
+#X obj 37 170 #slice 4 9;
+#X obj 256 109 #slice (1 1) (3 3);
+#X obj 257 130 display;
+#X obj 256 90 #redim (4 4);
+#X obj 256 71 #for 0 16 1;
+#X obj 256 54 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X text 259 177 should print subgrid: 2 2 # 5 6 9 10;
+#X obj 0 0 doc_h;
+#X obj 3 244 doc_c 2;
+#X obj 3 328 doc_i 3;
+#X obj 3 434 doc_o 1;
+#X obj 14 464 doc_oo 0;
+#X obj 14 380 doc_ii 1;
+#X obj 14 358 doc_ii 0;
+#X obj 14 402 doc_ii 2;
+#X obj 14 274 doc_cc 0;
+#X obj 14 296 doc_cc 1;
+#X obj 0 496 doc_f;
+#X obj 97 274 doc_m c0 grid;
+#X obj 97 296 doc_m c1 grid;
+#X obj 97 358 doc_m i0 grid;
+#X obj 97 380 doc_m i1 grid;
+#X obj 97 402 doc_m i2 grid;
+#X obj 97 464 doc_m o0 grid;
+#X text 232 380 same as arg 0;
+#X text 232 402 same as arg 1;
+#X text 232 464 slice;
+#X text 232 358 grid to be sliced;
+#X text 232 296 end positions (as in #for);
+#X text 232 274 start positions as in #for);
+#X connect 2 0 3 0;
+#X connect 3 0 0 0;
+#X connect 4 0 5 0;
+#X connect 6 0 4 0;
+#X connect 7 0 6 0;
+#X connect 8 0 7 0;
+#X connect 21 1 32 0;
+#X connect 22 1 31 0;
+#X connect 23 1 30 0;
+#X connect 24 1 27 0;
+#X connect 25 1 28 0;
+#X connect 26 1 29 0;
diff --git a/externals/gridflow/doc/flow_classes/#solarize-help.pd b/externals/gridflow/doc/flow_classes/#solarize-help.pd
new file mode 100644
index 00000000..02240cc0
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#solarize-help.pd
@@ -0,0 +1,39 @@
+#N canvas 690 0 632 491 10;
+#X obj 170 140 bng 15 250 50 0 empty empty empty 0 -6 0 8 -4034 -1
+-1;
+#X obj 170 219 #solarize;
+#X obj 170 183 #in;
+#X obj 103 442 #convolve;
+#X obj 169 442 #contrast;
+#X obj 235 442 #posterize;
+#X obj 307 442 #layer;
+#X obj 0 0 doc_h;
+#X obj 3 442 doc_also;
+#X obj 3 278 doc_c;
+#X obj 3 380 doc_o 1;
+#X obj 3 318 doc_i 1;
+#X obj 14 410 doc_oo 0;
+#X obj 14 348 doc_ii 0;
+#X obj 247 215 #out window \, title original;
+#X obj 170 240 #out window \, title modified;
+#X obj 97 410 doc_m o0 grid;
+#X obj 97 348 doc_m i0 grid;
+#X obj 0 462 doc_f;
+#X msg 170 157 load bluemarble.jpg;
+#X text 12 36 Makes medium intensities brightest. Formerly brightest
+colors become darkest \, formerly darkest stays darkest. This filter
+is non-linear (but piecewise-linear). It's like a 200% contrast \,
+except that overflows are mirrored instead of clipped or wrapped.;
+#X text 232 348 pixels;
+#X text 232 410 pixels;
+#X connect 0 0 19 0;
+#X connect 1 0 15 0;
+#X connect 2 0 1 0;
+#X connect 2 0 14 0;
+#X connect 8 1 3 0;
+#X connect 8 1 4 0;
+#X connect 8 1 5 0;
+#X connect 8 1 6 0;
+#X connect 16 1 22 0;
+#X connect 17 1 21 0;
+#X connect 19 0 2 0;
diff --git a/externals/gridflow/doc/flow_classes/#sort-help.pd b/externals/gridflow/doc/flow_classes/#sort-help.pd
new file mode 100644
index 00000000..f2cdc61c
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#sort-help.pd
@@ -0,0 +1,45 @@
+#N canvas 484 136 632 572 10;
+#X obj 28 250 #sort;
+#X msg 28 45 0 1 1 2 3 5 8 13 21 34 55 89;
+#X msg 28 102 12 # 666;
+#X obj 28 121 # rand;
+#X obj 28 178 #store;
+#X obj 28 140 #grade;
+#X obj 28 64 t a a;
+#X obj 28 83 #finished;
+#X obj 58 204 display;
+#X obj 28 159 #outer + (0);
+#X text 151 140 shuffle;
+#X obj 58 274 display;
+#X text 140 252 unshuffle;
+#X obj 0 0 doc_h;
+#X obj 3 311 doc_c 0;
+#X obj 3 351 doc_i 1;
+#X obj 3 461 doc_o 1;
+#X obj 3 523 doc_also;
+#X obj 103 523 #grade;
+#X obj 14 491 doc_oo 0;
+#X obj 14 381 doc_ii 0;
+#X obj 0 543 doc_f;
+#X obj 97 381 doc_m i0 grid;
+#X obj 97 491 doc_m o0 grid;
+#X text 232 491 sorted data;
+#X text 232 381 1-D grid to be sorted;
+#X text 232 403 this takes an average time proportional to N log N
+(a pass on the data takes N time \, and sorting something twice bigger
+takes an extra pass);
+#X connect 0 0 11 0;
+#X connect 1 0 6 0;
+#X connect 2 0 3 0;
+#X connect 3 0 5 0;
+#X connect 4 0 0 0;
+#X connect 4 0 8 0;
+#X connect 5 0 9 0;
+#X connect 6 0 7 0;
+#X connect 6 1 4 1;
+#X connect 7 0 2 0;
+#X connect 9 0 4 0;
+#X connect 17 1 18 0;
+#X connect 22 1 25 0;
+#X connect 22 1 26 0;
+#X connect 23 1 24 0;
diff --git a/externals/gridflow/doc/flow_classes/#spread-help.pd b/externals/gridflow/doc/flow_classes/#spread-help.pd
new file mode 100644
index 00000000..9c6fc31a
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#spread-help.pd
@@ -0,0 +1,79 @@
+#N canvas 673 0 632 642 10;
+#X text 1 25 makes noise;
+#X obj 207 42 bng 15 250 50 0 empty empty empty 0 -6 0 8 -233017 -1
+-1;
+#X obj 221 134 tgl 15 0 empty empty empty 0 -6 0 8 -233017 -1 -1 0
+1;
+#X floatatom 368 241 5 0 0 0 - - -;
+#X floatatom 78 163 5 0 0 0 - - -;
+#X obj 20 88 until;
+#X obj 20 51 bng 15 250 50 0 empty empty empty 0 -6 0 8 -233017 -1
+-1;
+#X msg 20 69 65536;
+#X obj 61 88 float;
+#X obj 101 88 + 1;
+#X text 219 308 we limit here \, because the values might go out of
+range;
+#X obj 149 73 metro 50;
+#X obj 149 51 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1
+;
+#X obj 20 129 #import (256 256 2);
+#X obj 195 269 #store;
+#X obj 195 341 #out window;
+#X obj 310 341 #out window;
+#X obj 310 291 #clip;
+#X obj 148 124 #in;
+#X obj 249 247 shunt;
+#X obj 0 0 doc_h;
+#X obj 3 491 doc_c 1;
+#X obj 3 633 doc_o 1;
+#X obj 3 551 doc_i 2;
+#X text 210 147 switch displays \, use this to get an image into the
+#store;
+#X obj 14 663 doc_oo 0;
+#X obj 14 581 doc_ii 0;
+#X obj 14 601 doc_ii 1;
+#X obj 14 521 doc_cc 0;
+#X obj 97 581 doc_m i0 grid;
+#X obj 97 663 doc_m o0 grid;
+#X text 326 33 typically you plug a [#for] into this object \, and
+you plug this object into the left side of a [#store]. it will scatter
+pixels around \, giving an "unpolished glass" effec.t;
+#X text 326 89 if you put a picture in it \, however \, it will add
+noise. The resulting values may be out of range \, so you may need
+to clip them using min/max.;
+#X text 54 364 [#spread] scatters the pixels in an image. Not all original
+pixels will appear \, and some may get duplicated (triplicated \, etc)
+randomly. Some wrap-around effect will occur close to the edges.;
+#X text 52 425 Sending an integer to inlet 1 sets the amount of spreading
+in maximum number of pixels + 1 even values translate the whole image
+by half a pixel due to rounding .;
+#X obj 0 693 doc_f;
+#X obj 97 601 doc_m i1 grid;
+#X obj 97 521 doc_m c0 grid;
+#X text 232 601 same as arg 0;
+#X obj 20 197 #spread 1;
+#X obj 310 270 #spread 1;
+#X msg 207 89 load r001.jpg;
+#X connect 1 0 41 0;
+#X connect 2 0 19 1;
+#X connect 3 0 40 1;
+#X connect 4 0 39 1;
+#X connect 5 0 8 0;
+#X connect 6 0 7 0;
+#X connect 7 0 5 0;
+#X connect 8 0 9 0;
+#X connect 8 0 13 0;
+#X connect 9 0 8 1;
+#X connect 11 0 18 0;
+#X connect 12 0 11 0;
+#X connect 13 0 39 0;
+#X connect 14 0 15 0;
+#X connect 17 0 16 0;
+#X connect 18 0 19 0;
+#X connect 19 0 14 1;
+#X connect 19 1 40 0;
+#X connect 36 1 38 0;
+#X connect 39 0 14 0;
+#X connect 40 0 17 0;
+#X connect 41 0 18 0;
diff --git a/externals/gridflow/doc/flow_classes/#store-help.pd b/externals/gridflow/doc/flow_classes/#store-help.pd
new file mode 100644
index 00000000..bc4a52c0
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#store-help.pd
@@ -0,0 +1,111 @@
+#N canvas 602 0 632 642 10;
+#X floatatom 132 89 5 0 0 0 - - -;
+#X floatatom 177 89 5 0 0 0 - - -;
+#X floatatom 20 160 5 0 0 0 - - -;
+#X floatatom 132 200 5 0 0 0 - - -;
+#X text 115 201 R:;
+#X floatatom 193 200 5 0 0 0 - - -;
+#X floatatom 253 200 5 0 0 0 - - -;
+#X text 176 201 G:;
+#X text 237 201 B:;
+#X floatatom 73 161 5 0 0 0 - - -;
+#X text 1 161 X:;
+#X text 58 162 Y:;
+#X obj 132 107 #pack;
+#X obj 296 134 #in;
+#X msg 296 115 load r001.jpg;
+#X obj 20 131 #unpack;
+#X obj 132 175 #unpack 3;
+#X obj 134 150 #store;
+#X text 129 54 this example allows you to select a single pixel from
+the loaded picture and view its rgb value.;
+#X text 8 24 The [#store] stores exactly one grid \, using the right
+inlet. You fetch it back \, or selected subparts using the left inlet.
+;
+#X obj 296 181 display;
+#X obj 86 94 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 296 161 display;
+#X obj 296 96 loadbang;
+#X obj 3 341 doc_i 2;
+#X obj 0 0 doc_h;
+#X obj 3 279 doc_c 1;
+#X obj 14 371 doc_ii 0;
+#X obj 14 571 doc_ii 1;
+#X obj 3 882 doc_o 1;
+#X obj 14 912 doc_oo 0;
+#X obj 14 309 doc_cc 0;
+#X obj 97 309 doc_m c0 grid;
+#X obj 97 406 doc_m i0 grid;
+#X obj 97 371 doc_m i0 bang;
+#X text 232 371 A bang at the left inlet will cause [#store] to send
+its value to the outlet.;
+#X obj 97 571 doc_m i1 grid;
+#X text 232 571 when in reassign mode \, this is same as arg 0;
+#X text 232 593 when it put_at mode \, it basically keeps the previous
+arg 0 or reassignment \, but replaces a selected part inside of it.
+;
+#X obj 97 824 doc_m i1 reassign;
+#X obj 97 663 doc_m i1 put_at;
+#X obj 97 912 doc_m o0 grid;
+#X text 232 406 in this grid \, the last dimension refers to subparts
+of the stored grid. sending a Dim(200 \, 200 \, 2) on a [#store] that
+holds a Dim(240 \, 320 \, 3) will cause the [#store] to handle the
+incoming grid as a Dim(200 \, 200) of Dim(2)'s \, where each Dim(2)
+represents a position in a Dim(240 \, 320) of Dim(3)'s. therefore the
+resulting grid will be a Dim(200 \, 200) of Dim(3) which is a Dim(200
+\, 200 \, 3). in practice this example would be used for generating
+a 200*200 RGB picture from a 200*200 XY map and a 240*320 RGB picture.
+this object can be logically used in the same way for many purposes
+including color palettes \, tables of probabilities \, tables of statistics
+\, whole animations \, etc.;
+#X text 232 824 makes it so that sending a grid to inlet 1 detaches
+the old buffer from [#store] and attaches a new one instead. This is
+the default.;
+#X text 232 663 makes it so that sending a grid to inlet 1 writes into
+the existing buffer of [#store].;
+#X text 232 698 example: suppose you have [#store 10 240 320 3]. then
+"put_at 3" will allow to write a Dim[240 \, 320 \, 3] grid in indices
+(3 \, y \, x \, c) where y \, x \, c are indices of the incoming grid.
+in other words \, if that's a buffer of 10 RGB frames \, you'd be replacing
+frame #3. Furthermore \, it also allows you to write a Dim[n \, 240
+\, 320 \, 3] grid at (3+f \, y \, x \, c) where f \, y \, x \, c are
+indices of the incoming grid \, replacing frame #3 \, #4 \, ... up
+to #3+n-1. Here n is at most 7 because the last frame in the buffer
+is #9.;
+#X text 194 227 that way of working extends to other kinds of data
+you'd put in Grids \, in any numbers of dimensions. because \, as usual
+\, [#store] wouldn't know the difference.;
+#X text 232 912 grids as stored \, as indexed \, or as assembled from
+multiple indexings.;
+#X obj 0 957 doc_f;
+#X text 232 309 initial value to be stored;
+#X obj 97 628 doc_m i1 op;
+#X text 232 628 recombination operator used by put_at \, just like
+arg 0 of [#draw_image];
+#X connect 0 0 12 0;
+#X connect 1 0 12 1;
+#X connect 12 0 15 0;
+#X connect 12 0 17 0;
+#X connect 12 0 22 0;
+#X connect 13 0 17 1;
+#X connect 14 0 13 0;
+#X connect 15 0 2 0;
+#X connect 15 1 9 0;
+#X connect 16 0 3 0;
+#X connect 16 1 5 0;
+#X connect 16 2 6 0;
+#X connect 17 0 16 0;
+#X connect 17 0 20 0;
+#X connect 21 0 17 0;
+#X connect 23 0 14 0;
+#X connect 32 1 49 0;
+#X connect 33 1 42 0;
+#X connect 34 1 35 0;
+#X connect 36 1 37 0;
+#X connect 36 1 38 0;
+#X connect 39 1 43 0;
+#X connect 40 1 44 0;
+#X connect 40 1 45 0;
+#X connect 41 1 47 0;
+#X connect 50 1 51 0;
diff --git a/externals/gridflow/doc/flow_classes/#swap-help.pd b/externals/gridflow/doc/flow_classes/#swap-help.pd
new file mode 100644
index 00000000..70263b36
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#swap-help.pd
@@ -0,0 +1,25 @@
+#N canvas 335 118 632 379 10;
+#X obj 0 0 doc_h;
+#X obj 0 350 doc_f;
+#X obj 60 55 #swap;
+#X text 223 55 grid equivalent of [swap];
+#X obj 3 168 doc_i 2;
+#X obj 3 250 doc_o 2;
+#X obj 14 198 doc_ii 0;
+#X obj 14 218 doc_ii 1;
+#X obj 14 280 doc_oo 0;
+#X obj 14 300 doc_oo 1;
+#X obj 97 198 doc_m i0 grid;
+#X obj 97 218 doc_m i1 grid;
+#X obj 97 280 doc_m o0 grid;
+#X obj 97 300 doc_m o1 grid;
+#X obj 3 330 doc_also;
+#X obj 103 330 swap;
+#X obj 14 136 doc_cc 0;
+#X obj 3 106 doc_c 0..1;
+#X text 232 136 same as [#store];
+#X text 232 218 same as arg 0;
+#X obj 97 136 doc_m c0 grid;
+#X connect 11 1 19 0;
+#X connect 14 1 15 0;
+#X connect 20 1 18 0;
diff --git a/externals/gridflow/doc/flow_classes/#t-help.pd b/externals/gridflow/doc/flow_classes/#t-help.pd
new file mode 100644
index 00000000..a8c4f064
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#t-help.pd
@@ -0,0 +1,58 @@
+#N canvas 78 0 632 554 10;
+#X obj 10 134 #in teapot.png;
+#X obj 10 161 t a a;
+#X obj 40 181 #convolve (1 3 # -1 2 -1);
+#X obj 267 181 #convolve (1 3 # -1 2 -1);
+#X obj 10 112 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 237 161 #t;
+#X obj 237 205 # *>>8;
+#X obj 10 205 # *>>8;
+#X text 257 112 Works;
+#X text 8 64 In some situations \, a grid hasn't finished entering
+the right-hand side \, when an object begins receiving on the left-hand
+side. in those cases you should use #t.;
+#X obj 237 113 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 10 234 #out window \, title doesnt_work;
+#X obj 237 233 #out window \, title works;
+#X text 8 25 The [#t] trigger object sequences grid operations in a
+right-to-left order. It outputs its input from right to left.;
+#X text 28 112 Doesn't work (all black);
+#X obj 237 134 #in teapot.png;
+#X text 232 425 The same grid received in inlet 0 is first sent to
+the outlet 0;
+#X text 232 460 The same grid received in inlet 0 is sent to the outlet
+1 after it was sent to outlet 0;
+#X text 232 337 The Grid passed in inlet 0 will be first sent to the
+right most outlet and then to the second from the right (the left outlet
+in this case).;
+#X obj 0 0 doc_h;
+#X obj 3 307 doc_i 1;
+#X obj 3 395 doc_o 2;
+#X obj 3 267 doc_c 0;
+#X obj 3 505 doc_also;
+#X obj 14 337 doc_ii 0;
+#X obj 14 425 doc_oo 0;
+#X obj 14 460 doc_oo 1;
+#X obj 97 337 doc_m i0 grid;
+#X obj 97 425 doc_m o0 grid;
+#X obj 97 460 doc_m o1 grid;
+#X obj 0 525 doc_f;
+#X obj 103 505 t;
+#X connect 0 0 1 0;
+#X connect 1 0 7 0;
+#X connect 1 1 2 0;
+#X connect 2 0 7 1;
+#X connect 3 0 6 1;
+#X connect 4 0 0 0;
+#X connect 5 0 6 0;
+#X connect 5 1 3 0;
+#X connect 6 0 12 0;
+#X connect 7 0 11 0;
+#X connect 10 0 15 0;
+#X connect 15 0 5 0;
+#X connect 23 1 31 0;
+#X connect 27 1 18 0;
+#X connect 28 1 16 0;
+#X connect 29 1 17 0;
diff --git a/externals/gridflow/doc/flow_classes/#text_to_image-help.pd b/externals/gridflow/doc/flow_classes/#text_to_image-help.pd
new file mode 100644
index 00000000..238dab37
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#text_to_image-help.pd
@@ -0,0 +1,24 @@
+#N canvas 685 0 632 345 10;
+#X obj 0 0 doc_h;
+#X obj 33 40 #text_to_image;
+#X obj 3 71 doc_c 0;
+#X obj 3 111 doc_i 3;
+#X obj 3 256 doc_o 1;
+#X obj 14 141 doc_ii 0;
+#X obj 14 176 doc_ii 1;
+#X obj 14 211 doc_ii 2;
+#X obj 97 141 doc_m i0 bang;
+#X text 232 141 transforming the data into an image suitable for #draw_image.
+;
+#X obj 14 286 doc_oo 0;
+#X obj 97 286 doc_m o0 grid;
+#X obj 97 211 doc_m i2 grid;
+#X obj 97 176 doc_m i1 grid;
+#X text 232 176 2 by 3 matrix representing the colours to use (e.g.
+(2 3 # 0 170 0 255 255 0) means yellow on green);
+#X obj 0 316 doc_f;
+#X text 232 211 font grid \, for example \, from [#in grid lucida-typewriter-12.grid]
+;
+#X connect 8 1 9 0;
+#X connect 12 1 16 0;
+#X connect 13 1 14 0;
diff --git a/externals/gridflow/doc/flow_classes/#to_float-help.pd b/externals/gridflow/doc/flow_classes/#to_float-help.pd
new file mode 100644
index 00000000..16886baf
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#to_float-help.pd
@@ -0,0 +1,29 @@
+#N canvas 678 0 632 446 10;
+#X obj 15 188 cnv 15 55 17 empty empty empty 20 12 0 14 -241291 -66577
+0;
+#X obj 39 135 display;
+#X msg 15 73 1 2 3 4 5 6 7 8;
+#X text 138 73 <-- create the grid here;
+#X obj 15 188 #to_float;
+#X text 12 27 Produces sequences of floats from grid data. Useful for
+the integration into the rest of PureData.;
+#X obj 15 216 print converted_grid;
+#X obj 15 100 #import (2 2 2);
+#X obj 0 0 doc_h;
+#X obj 3 280 doc_i 1;
+#X obj 3 240 doc_c;
+#X obj 14 372 doc_oo 0;
+#X obj 14 310 doc_ii 0;
+#X obj 3 342 doc_o 1;
+#X obj 97 310 doc_m i0 grid;
+#X obj 97 372 doc_m o0 float;
+#X obj 0 417 doc_f;
+#X text 232 310 content to be finely chopped;
+#X text 232 372 a sequence of floats that the incoming grid is transformed
+into. they are output in normal grid order.;
+#X connect 2 0 7 0;
+#X connect 4 0 6 0;
+#X connect 7 0 1 0;
+#X connect 7 0 4 0;
+#X connect 14 1 17 0;
+#X connect 15 1 18 0;
diff --git a/externals/gridflow/doc/flow_classes/#to_list-help.pd b/externals/gridflow/doc/flow_classes/#to_list-help.pd
new file mode 100644
index 00000000..51a376ea
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#to_list-help.pd
@@ -0,0 +1,31 @@
+#N canvas 544 108 632 450 10;
+#X obj 15 164 cnv 15 52 17 empty empty empty 20 12 0 14 -241291 -66577
+0;
+#X obj 50 115 display;
+#X msg 14 64 1 2 3 4 5 6 7 8;
+#X obj 161 217 display;
+#X text 12 27 Produces a list from grid data. Useful for the integration
+into the rest of PureData.;
+#X text 130 63 <-- create the grid here;
+#X obj 14 165 #to_list;
+#X obj 14 216 print converted_grid;
+#X obj 14 91 #import (2 2 2);
+#X obj 0 0 doc_h;
+#X obj 3 346 doc_o 1;
+#X obj 3 284 doc_i 1;
+#X obj 3 244 doc_c 0;
+#X text 232 376 The grid is transformed into a single message containing
+a sequence of floats.;
+#X obj 14 314 doc_ii 0;
+#X obj 14 376 doc_oo 0;
+#X obj 97 314 doc_m i0 grid;
+#X obj 97 376 doc_m o0 list;
+#X obj 0 421 doc_f;
+#X text 232 314 will be transformed into a list.;
+#X connect 2 0 8 0;
+#X connect 6 0 3 0;
+#X connect 6 0 7 0;
+#X connect 8 0 1 0;
+#X connect 8 0 6 0;
+#X connect 16 1 19 0;
+#X connect 17 1 13 0;
diff --git a/externals/gridflow/doc/flow_classes/#to_literal-help.pd b/externals/gridflow/doc/flow_classes/#to_literal-help.pd
new file mode 100644
index 00000000..15f076e8
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#to_literal-help.pd
@@ -0,0 +1,34 @@
+#N canvas 556 102 632 540 10;
+#X obj 0 0 doc_h;
+#X obj 0 511 doc_f;
+#X obj 96 289 #to_literal;
+#X obj 102 312 display;
+#X obj 3 347 doc_c 0;
+#X obj 3 387 doc_i 1;
+#X obj 3 449 doc_o 1;
+#X obj 14 417 doc_ii 0;
+#X obj 14 479 doc_oo 0;
+#X obj 97 417 doc_m i0 grid;
+#X obj 102 146 display;
+#X obj 96 165 # +;
+#X text 123 166 "do nothing": just convert literal to grid;
+#X obj 102 224 display;
+#X msg 96 123 3 3 # 2 3 5 7 11 13 17 19 23;
+#X obj 97 479 doc_m o0 list;
+#X text 232 479 grid literal;
+#X msg 118 62 3 2 f # 0.1 0.333333 2.71828 3.14159 1.4142 1.61803;
+#X obj 118 103 # + (f #);
+#X obj 96 201 t a;
+#X obj 124 83 display;
+#X text 232 417 any grid;
+#X connect 2 0 3 0;
+#X connect 9 1 21 0;
+#X connect 11 0 19 0;
+#X connect 14 0 10 0;
+#X connect 14 0 11 0;
+#X connect 15 1 16 0;
+#X connect 17 0 18 0;
+#X connect 17 0 20 0;
+#X connect 18 0 19 0;
+#X connect 19 0 13 0;
+#X connect 19 0 2 0;
diff --git a/externals/gridflow/doc/flow_classes/#to_pix-help.pd b/externals/gridflow/doc/flow_classes/#to_pix-help.pd
new file mode 100644
index 00000000..199ab591
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#to_pix-help.pd
@@ -0,0 +1,107 @@
+#N canvas 661 0 632 665 10;
+#X msg 365 61 create \, 1;
+#X obj 365 42 loadbang;
+#X msg 157 139 open violoncelle.mov;
+#X obj 130 72 tgl 15 0 empty empty empty 17 7 0 10 -4034 -1 -1 0 1
+;
+#X obj 45 52 gemhead;
+#X obj 45 272 pix_texture;
+#X obj 13 720 cnv 15 500 17 empty empty empty 20 12 0 14 -228992 -66577
+0;
+#X obj 13 720 cnv 15 500 17 empty empty empty 20 12 0 14 -228992 -66577
+0;
+#X obj 13 720 cnv 15 500 17 empty empty empty 20 12 0 14 -228992 -66577
+0;
+#X obj 13 720 cnv 15 500 17 empty empty empty 20 12 0 14 -228992 -66577
+0;
+#X text 19 721 see also :;
+#X text 102 720 [#import_pix];
+#X msg 429 62 destroy;
+#X obj 365 93 gemwin 30;
+#X obj 157 117 loadbang;
+#X text 150 69 <-- start playing the video;
+#X text 94 250 <-- imports gridflow grids into GEM;
+#X text 181 720 \, game_of_life_gem.pd in the examples folder;
+#X obj 45 253 #to_pix;
+#X text 232 591 Modified gemstate so that the pix is equal to the Grid
+of inlet 1;
+#X text 232 472 Something coming from [gemhead];
+#X msg 57 217 yflip \$1;
+#X obj 57 197 tgl 15 0 empty empty empty 17 7 0 10 -257985 -1 -1 0
+1;
+#X text 232 494 With one boolean argument that selects the order in
+which the y dimension of the Grid will be read \, defaults to '1';
+#X obj 45 291 rectangle 4 3;
+#X obj 0 0 doc_h;
+#X obj 3 442 doc_i 2;
+#X obj 3 561 doc_o 1;
+#X obj 3 402 doc_c 0;
+#X obj 14 472 doc_ii 0;
+#X obj 14 529 doc_ii 1;
+#X obj 14 591 doc_oo 0;
+#X obj 97 472 doc_m i0 gem_state;
+#X obj 97 494 doc_m i0 yflip;
+#X obj 97 529 doc_m i1 grid;
+#X obj 97 591 doc_m o0 gem_state;
+#X obj 0 636 doc_f;
+#X obj 397 243 b;
+#X obj 397 263 fps;
+#X floatatom 397 282 5 0 0 0 - - -;
+#X obj 130 162 #in;
+#X msg 310 134 cast b;
+#X msg 310 154 cast s;
+#X msg 310 174 cast i;
+#X obj 140 195 shunt;
+#X obj 176 196 tgl 15 0 empty empty empty 17 7 0 10 -257985 -1 -1 0
+1;
+#N canvas 0 22 458 308 to_rgba_if_not_already 0;
+#X obj 130 221 #rgb_to_rgba;
+#X obj 131 103 #dim;
+#X obj 103 173 shunt;
+#X obj 131 126 #unpack 3;
+#X obj 104 29 inlet;
+#X obj 104 56 t a a;
+#X obj 103 265 outlet;
+#X obj 131 150 == 3;
+#X connect 0 0 6 0;
+#X connect 1 0 3 0;
+#X connect 2 0 6 0;
+#X connect 2 1 0 0;
+#X connect 3 2 7 0;
+#X connect 4 0 5 0;
+#X connect 5 0 2 0;
+#X connect 5 1 1 0;
+#X connect 7 0 2 1;
+#X restore 167 214 pd to_rgba_if_not_already;
+#X text 40 353 Note : you can get some timebased 'moire' effects if
+the arguments to the [gemwin] and the [metro] are not synched;
+#X text 232 529 Grid with 3 or 4 channels (4th channel gets destroyed)
+;
+#X obj 130 93 metro 33.3667;
+#X connect 0 0 13 0;
+#X connect 1 0 0 0;
+#X connect 2 0 40 0;
+#X connect 3 0 49 0;
+#X connect 4 0 18 0;
+#X connect 5 0 24 0;
+#X connect 12 0 13 0;
+#X connect 14 0 2 0;
+#X connect 18 0 5 0;
+#X connect 21 0 18 0;
+#X connect 22 0 21 0;
+#X connect 32 1 20 0;
+#X connect 33 1 23 0;
+#X connect 34 1 48 0;
+#X connect 35 1 19 0;
+#X connect 37 0 38 0;
+#X connect 38 0 39 0;
+#X connect 40 0 37 0;
+#X connect 40 0 44 0;
+#X connect 41 0 40 0;
+#X connect 42 0 40 0;
+#X connect 43 0 40 0;
+#X connect 44 0 18 1;
+#X connect 44 1 46 0;
+#X connect 45 0 44 1;
+#X connect 46 0 18 1;
+#X connect 49 0 40 0;
diff --git a/externals/gridflow/doc/flow_classes/#to_symbol-help.pd b/externals/gridflow/doc/flow_classes/#to_symbol-help.pd
new file mode 100644
index 00000000..f991d814
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#to_symbol-help.pd
@@ -0,0 +1,52 @@
+#N canvas 648 0 632 642 10;
+#X obj 11 498 cnv 15 63 17 empty empty empty 20 12 0 14 -241291 -66577
+0;
+#X obj 176 469 display;
+#X obj 174 557 display;
+#X symbolatom 353 559 12 0 0 0 - - -;
+#X msg 11 409 72 101 108 108 111 32 87 111 114 108 100 33;
+#X obj 11 428 #import (3 2 2);
+#X text 324 409 <-- create the grid here;
+#X obj 11 498 #to_symbol;
+#X obj 11 557 print converted_grid;
+#X obj 0 0 doc_h;
+#X obj 3 691 doc_o 1;
+#X obj 3 629 doc_i 1;
+#X obj 3 589 doc_c 0;
+#X text 11 102 note that a zero value will cause pd to truncate the
+symbol there. thus a symbol may have less bytes than the grid it was
+made from.;
+#X text 10 147 remember that a byte is not necessarily a codepoint
+\, a codepoint is not necessarily a character \, and all characters
+don't always have the same width. these distinctions don't matter for
+all encodings.;
+#X text 11 32 Produces a symbol from grid data in its input. The values
+are expected to be valid in the character encoding that you are using
+\, but no check will be performed for that \, and additionally \, no
+check will be made that the generated symbol only contains characters
+that can be put in a symbol.;
+#X obj 14 659 doc_ii 0;
+#X obj 14 721 doc_oo 0;
+#X obj 97 659 doc_m i0 grid;
+#X obj 97 721 doc_m o0 symbol;
+#X obj 0 753 doc_f;
+#X text 232 659 will be transformed into a symbol.;
+#X text 232 721 symbol made of grid elements as bytes.;
+#X text 12 211 in the future \, this might work at the level of codepoints
+instead. thus with today's default UTF-8 (compact unicode) encoding
+\, &eacute \; has to be written as 195 169 \, you would be able to
+write it as just 233 (as with iso-latin-1) and it would get converted
+to 195 169 automatically. however there is still another form of this
+character that is made as two codepoints \, 101 (e) and the "dead acute"
+character \, separately \, on systems that support it.;
+#X text 14 342 at this point \, though \, most branches of pd still
+can't handle utf-8 properly \, so there isn't much of a hurry in adding
+utf-8 support to [#to_symbol]...;
+#X connect 4 0 5 0;
+#X connect 5 0 1 0;
+#X connect 5 0 7 0;
+#X connect 7 0 2 0;
+#X connect 7 0 3 0;
+#X connect 7 0 8 0;
+#X connect 18 1 21 0;
+#X connect 19 1 22 0;
diff --git a/externals/gridflow/doc/flow_classes/#transpose-help.pd b/externals/gridflow/doc/flow_classes/#transpose-help.pd
new file mode 100644
index 00000000..9537434a
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#transpose-help.pd
@@ -0,0 +1,37 @@
+#N canvas 674 0 632 444 10;
+#X obj 3 150 doc_c 2;
+#X obj 36 65 #transpose;
+#X obj 3 234 doc_i 3;
+#X obj 3 353 doc_o 1;
+#X obj 0 0 doc_h;
+#X obj 14 180 doc_cc 0;
+#X obj 14 202 doc_cc 1;
+#X obj 14 264 doc_ii 0;
+#X obj 14 299 doc_ii 1;
+#X obj 14 321 doc_ii 2;
+#X obj 14 383 doc_oo 0;
+#X obj 97 180 doc_m c0 float;
+#X obj 97 202 doc_m c1 float;
+#X obj 97 264 doc_m i0 grid;
+#X obj 97 299 doc_m i1 float;
+#X obj 97 321 doc_m i2 float;
+#X obj 97 383 doc_m o0 grid;
+#X text 232 264 swaps the two specified dimensions \; dimension numbers
+are as in [#join].;
+#X text 232 180 dimension number;
+#X text 232 202 dimension number;
+#X text 232 299 same as arg 0;
+#X text 232 321 same as arg 1;
+#X obj 0 415 doc_f;
+#X text 226 58 remaps contents of a grid by swapping dimensions of
+indices. for example \, [#transpose 0 1] does the same as [#remap_image]x[#reverse].
+;
+#X text 232 383 remapped image;
+#X text 228 108 this is like matrix-transposition that you frequently
+read about in linear algebra books.;
+#X connect 11 1 18 0;
+#X connect 12 1 19 0;
+#X connect 13 1 17 0;
+#X connect 14 1 20 0;
+#X connect 15 1 21 0;
+#X connect 16 1 24 0;
diff --git a/externals/gridflow/doc/flow_classes/#type-help.pd b/externals/gridflow/doc/flow_classes/#type-help.pd
new file mode 100644
index 00000000..4f765f5f
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#type-help.pd
@@ -0,0 +1,26 @@
+#N canvas 0 0 632 350 10;
+#X obj 3 117 doc_c 0;
+#X obj 3 157 doc_i 1;
+#X obj 3 217 doc_o 1;
+#X obj 14 247 doc_oo 0;
+#X obj 14 187 doc_ii 0;
+#X text 138 34 gives a symbol representing the numeric type of the
+grid received.;
+#X obj 97 247 doc_m o0 symbol;
+#X obj 97 187 doc_m i0 grid;
+#X obj 3 301 doc_also;
+#X obj 103 301 #dim;
+#X obj 139 301 #finished;
+#X obj 0 0 doc_h;
+#X obj 0 321 doc_f;
+#X obj 17 65 #type;
+#X symbolatom 17 84 10 0 0 0 - - -;
+#X msg 27 38 3 3 f # 10.4;
+#X text 232 247 numbertype in long form.;
+#X text 232 269 one of: uint8 int16 int32 int64 float32 float64;
+#X connect 6 1 16 0;
+#X connect 6 1 17 0;
+#X connect 8 1 9 0;
+#X connect 8 1 10 0;
+#X connect 13 0 14 0;
+#X connect 15 0 13 0;
diff --git a/externals/gridflow/doc/flow_classes/#unpack-help.pd b/externals/gridflow/doc/flow_classes/#unpack-help.pd
new file mode 100644
index 00000000..7068382a
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#unpack-help.pd
@@ -0,0 +1,28 @@
+#N canvas 286 66 632 455 10;
+#X obj 17 61 #color;
+#X floatatom 17 195 5 0 0 0 - - -;
+#X floatatom 46 174 5 0 0 0 - - -;
+#X floatatom 75 152 5 0 0 0 - - -;
+#X text 196 84 <--click and drag to view grid values.;
+#X obj 17 128 #unpack 3;
+#X obj 0 0 doc_h;
+#X obj 3 304 doc_i 1;
+#X obj 3 364 doc_o n;
+#X text 12 28 Outputs individual values from a grid.;
+#X obj 3 228 doc_c 1;
+#X text 232 394 Outputs grid dimensions as individual numbers.;
+#X obj 14 334 doc_ii 0;
+#X obj 14 394 doc_oo any;
+#X obj 14 258 doc_cc 0;
+#X obj 97 259 doc_m c0 float/int;
+#X obj 97 334 doc_m i0 grid;
+#X obj 97 394 doc_m oany float;
+#X obj 0 426 doc_f;
+#X text 232 259 number of outlets. usually corresponds to the number
+of grid dimensions. (default: 2);
+#X connect 0 0 5 0;
+#X connect 5 0 1 0;
+#X connect 5 1 2 0;
+#X connect 5 2 3 0;
+#X connect 15 1 19 0;
+#X connect 17 1 11 0;
diff --git a/externals/gridflow/doc/flow_classes/#window-help.pd b/externals/gridflow/doc/flow_classes/#window-help.pd
new file mode 100644
index 00000000..aec81f45
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/#window-help.pd
@@ -0,0 +1,33 @@
+#N canvas 514 151 632 415 10;
+#X obj 0 0 doc_h;
+#X obj 0 386 doc_f;
+#X obj 149 56 tgl 15 0 empty empty click_me 17 7 0 10 -4034 -1 -1 0
+1;
+#X obj 47 55 #window alakazou;
+#X obj 14 140 doc_cc 0;
+#X obj 3 110 doc_c 0..1;
+#X obj 97 140 doc_m c0 symbol;
+#X text 232 140 window title;
+#X obj 3 172 doc_i 2;
+#X obj 14 202 doc_ii 0;
+#X obj 14 272 doc_ii 1;
+#X obj 97 237 doc_m i0 state;
+#X text 232 272 same as 'state';
+#X obj 97 202 doc_m i0 grid;
+#X obj 97 272 doc_m i1 bool;
+#X obj 3 366 doc_also;
+#X obj 103 366 #out;
+#X text 232 202 as with #out window when state=1 \; else ignored when
+state=0;
+#X text 232 237 1 to open the window \; 0 to close it.;
+#X obj 3 304 doc_o 1;
+#X obj 14 334 doc_oo 0;
+#X obj 97 334 doc_m o0 ...;
+#X text 232 334 whatever [#out window] outputs.;
+#X connect 2 0 3 1;
+#X connect 6 1 7 0;
+#X connect 11 1 18 0;
+#X connect 13 1 17 0;
+#X connect 14 1 12 0;
+#X connect 15 1 16 0;
+#X connect 21 1 22 0;
diff --git a/externals/gridflow/doc/flow_classes/0x40complex_sq-help.pd b/externals/gridflow/doc/flow_classes/0x40complex_sq-help.pd
new file mode 100644
index 00000000..42ca0f5a
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/0x40complex_sq-help.pd
@@ -0,0 +1,52 @@
+#N canvas 648 0 632 537 10;
+#X obj 21 109 @complex_sq;
+#X text 176 59 this object computes the square of complex numbers.
+if seeing imaginary as Y and real as X \, then this operation squares
+the distance of a point from origin and doubles the angle between it
+and the +X half-axis clockwise. :);
+#X floatatom 21 58 5 0 0 0 - - -;
+#X floatatom 21 188 5 0 0 0 - - -;
+#X floatatom 64 58 5 0 0 0 - - -;
+#X floatatom 58 188 5 0 0 0 - - -;
+#X obj 21 78 #pack;
+#X obj 114 185 #print;
+#X obj 21 159 #unpack;
+#X obj 103 488 # +;
+#X obj 133 488 # abs-;
+#X obj 3 488 doc_also;
+#X obj 181 488 # C.sq-;
+#X obj 3 324 doc_c 0;
+#X obj 3 364 doc_i 1;
+#X obj 3 426 doc_o 1;
+#X obj 0 0 doc_h;
+#X obj 14 456 doc_oo 0;
+#X obj 14 394 doc_ii 0;
+#X obj 97 394 doc_m i0 grid;
+#X obj 97 456 doc_m o0 grid;
+#X text 232 394 grid of size (... \, 2);
+#X text 232 456 grid of same size;
+#X obj 0 508 doc_f;
+#X text 178 128 However \, this (old) object is backwards from the
+rest of GridFlow because it puts Imaginary before Real. [#fft] puts
+the Real part first. Open this abstraction to discover the new way
+to square a complex number. (The extra multiplication is the net result
+of swapping components before and after the squaring);
+#X text 178 212 used on an indexmap (#remap_image) \, this makes each
+thing appear twice \, each appearance spanning half of the original
+angle. straight lines become hyperbolic \, etc.;
+#X text 179 259 In the original version of GridFlow (aka Video4jmax
+0.2) \, the first example patch was feedback_fractal \, which used
+this operation with a [#remap_image] \, though it was expressed in
+much different terms back then.;
+#X connect 0 0 7 0;
+#X connect 0 0 8 0;
+#X connect 2 0 6 0;
+#X connect 4 0 6 1;
+#X connect 6 0 0 0;
+#X connect 8 0 3 0;
+#X connect 8 1 5 0;
+#X connect 11 1 9 1;
+#X connect 11 1 10 0;
+#X connect 11 1 12 0;
+#X connect 19 1 21 0;
+#X connect 20 1 22 0;
diff --git a/externals/gridflow/doc/flow_classes/args-demo.pd b/externals/gridflow/doc/flow_classes/args-demo.pd
new file mode 100644
index 00000000..54e3cfe7
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/args-demo.pd
@@ -0,0 +1,27 @@
+#N canvas 0 0 613 300 10;
+#X obj 152 20 args hello (world a 42) *;
+#X obj 43 96 print args;
+#X obj 152 3 bng 15 250 50 0 empty empty empty 17 7 0 10 -24198 -1
+-1;
+#X obj 18 35 inlet;
+#X obj 18 233 outlet;
+#X obj 18 54 t a;
+#X obj 18 155 route temperature pression etc;
+#X obj 266 85 display;
+#X obj 209 105 display;
+#X text 270 69 rest of arguments (*);
+#X text 17 174 do whatever you want with those args;
+#X obj 223 230 t a;
+#X text 230 211 anything else coming from first inlet or named args
+;
+#X obj 153 125 display;
+#X text 157 106 hello;
+#X text 213 86 world;
+#X connect 0 0 13 0;
+#X connect 0 1 8 0;
+#X connect 0 2 7 0;
+#X connect 2 0 0 0;
+#X connect 3 0 5 0;
+#X connect 5 0 6 0;
+#X connect 5 0 1 0;
+#X connect 6 3 11 0;
diff --git a/externals/gridflow/doc/flow_classes/args-help.pd b/externals/gridflow/doc/flow_classes/args-help.pd
new file mode 100644
index 00000000..d7f6a345
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/args-help.pd
@@ -0,0 +1,50 @@
+#N canvas 648 0 632 631 10;
+#X text 354 70 demo default args;
+#X text 354 90 demo rest of args;
+#X text 354 130 demo missing args;
+#X text 354 110 demo comma args;
+#X obj 0 0 doc_h;
+#X obj 3 352 doc_i 1;
+#X obj 3 153 doc_c n;
+#X obj 14 382 doc_ii 0;
+#X obj 3 518 doc_o 1..;
+#X obj 97 382 doc_m i0 bang;
+#X obj 14 183 doc_cc any;
+#X obj 97 183 doc_m cany symbol;
+#X text 232 183 "*" represents the rest of arguments;
+#X text 232 205 other symbols represent mandatory arguments;
+#X obj 0 602 doc_f;
+#X obj 14 548 doc_oo any;
+#X obj 97 548 doc_m oany <atom>;
+#X text 232 548 output of single argument;
+#X text 232 570 output of rest of arguments \, if last arg of [args]
+is a "*".;
+#X obj 97 570 doc_m oany <list>;
+#X text 232 382 sends one message per outlet right-to-left. if there
+is a wildcard (*) as the last argument \, any extra arguments go there
+as a list message. Then for any missing arguments that have default
+values \, the default values are sent \, right to left. Then for each
+present argument that is not extra \, that argument will be sent on
+its own outlet. Finally \, each init-message (comma-separated) is parsed
+from the arguments and sent (magically) to the first inlet of the abstraction
+itself.;
+#X obj 97 227 doc_m cany nested-list;
+#X text 232 227 represent optional arguments as nested-lists;
+#X text 232 249 inside the nested-list \, \$1 must be the name of the
+argument \, \$2 must be "a" (the single letter) \, and \$3 must be
+the default value. the "a" is actually for future use (type-checking).
+;
+#X text 97 314 the star can only occur once and at the end \, and all
+optionals must follow all mandatories.;
+#X obj 12 89 args-demo pommes poires ananas biscuits-soda;
+#X obj 12 129 args-demo;
+#X obj 12 69 args-demo blah;
+#X obj 12 109 args-demo dorval \, temperature -18 \, pression 99.5
+;
+#X connect 9 1 20 0;
+#X connect 11 1 12 0;
+#X connect 11 1 13 0;
+#X connect 16 1 17 0;
+#X connect 19 1 18 0;
+#X connect 21 1 22 0;
+#X connect 21 1 23 0;
diff --git a/externals/gridflow/doc/flow_classes/ascii-help.pd b/externals/gridflow/doc/flow_classes/ascii-help.pd
new file mode 100644
index 00000000..b7ae57d5
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/ascii-help.pd
@@ -0,0 +1,25 @@
+#N canvas 442 305 632 357 10;
+#X obj 39 73 ascii;
+#X floatatom 39 41 5 0 0 0 - - -;
+#X obj 39 92 print;
+#X text 135 74 write integer as decimal in ascii codes;
+#X text 232 195 number to be converted into ascii codes;
+#X obj 0 0 doc_h;
+#X obj 3 227 doc_o 1;
+#X obj 3 165 doc_i 1;
+#X obj 14 195 doc_ii 0;
+#X obj 14 257 doc_oo 0;
+#X obj 3 125 doc_c 0;
+#X obj 97 195 doc_m i0 float int;
+#X obj 97 257 doc_m o0 float;
+#X obj 0 328 doc_f;
+#X msg 86 40 1e+06;
+#X text 232 257 a sequence of floats corresponding to the ascii codes
+of the input integer as written in decimal. the sign is written in
+the case of negative values. exponential notation is used for large
+numbers.;
+#X connect 0 0 2 0;
+#X connect 1 0 0 0;
+#X connect 11 1 4 0;
+#X connect 12 1 15 0;
+#X connect 14 0 0 0;
diff --git a/externals/gridflow/doc/flow_classes/ascii_to_f-help.pd b/externals/gridflow/doc/flow_classes/ascii_to_f-help.pd
new file mode 100644
index 00000000..a506c274
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/ascii_to_f-help.pd
@@ -0,0 +1,31 @@
+#N canvas 335 118 632 388 10;
+#X obj 0 0 doc_h;
+#X obj 0 359 doc_f;
+#X obj 31 75 ascii_to_f;
+#X text 200 74 parser for floats written in ascii as sequences of floats
+;
+#X obj 3 134 doc_c 0;
+#X obj 3 174 doc_i 1;
+#X obj 3 236 doc_o 2;
+#X obj 14 266 doc_oo 0;
+#X obj 14 327 doc_oo 1;
+#X obj 14 204 doc_ii 0;
+#X obj 97 204 doc_m i0;
+#X obj 97 327 doc_m o1 float;
+#X obj 97 266 doc_m o0 float;
+#X text 232 327 integer coming from inlet 0 but unrecognised;
+#X text 232 204 ascii bytes (integer);
+#X floatatom 31 100 8 0 0 0 - - -;
+#X obj 90 100 display;
+#X msg 30 50 51 \, 46 \, 49 \, 52 \, 49 \, 53 \, 57 \, 51 \, 0;
+#X text 232 266 float value successfully parsed. note that this is
+output only when an unrecognised character is received \, because otherwise
+\, it can't be known for sure that the number is finished.;
+#X text 201 93 recognises plus \, minus \, period \, but no exponents
+\, infinities nor NaN.;
+#X connect 2 0 15 0;
+#X connect 2 1 16 0;
+#X connect 10 1 14 0;
+#X connect 11 1 13 0;
+#X connect 12 1 18 0;
+#X connect 17 0 2 0;
diff --git a/externals/gridflow/doc/flow_classes/cv/#CornerHarris-help.pd b/externals/gridflow/doc/flow_classes/cv/#CornerHarris-help.pd
new file mode 100644
index 00000000..6d4aaf9d
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/cv/#CornerHarris-help.pd
@@ -0,0 +1,14 @@
+#N canvas 599 185 568 336 10;
+#X obj 0 0 doc_h cv/;
+#X obj 0 307 doc_f;
+#X obj 73 53 cv/#CornerHarris;
+#X obj 3 87 doc_c 0;
+#X obj 3 127 doc_i 1;
+#X obj 14 157 doc_ii 0;
+#X obj 3 247 doc_o 1;
+#X obj 14 277 doc_oo 0;
+#X obj 97 277 doc_m o0 grid;
+#X obj 97 157 doc_m i0 grid;
+#X obj 97 197 doc_m i0 block_size;
+#X obj 97 177 doc_m i0 aperture_size;
+#X obj 97 217 doc_m i0 k;
diff --git a/externals/gridflow/doc/flow_classes/cv/#Ellipse-help.pd b/externals/gridflow/doc/flow_classes/cv/#Ellipse-help.pd
new file mode 100644
index 00000000..be29f945
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/cv/#Ellipse-help.pd
@@ -0,0 +1,24 @@
+#N canvas 580 166 568 551 10;
+#X obj 0 0 doc_h cv/;
+#X obj 0 443 doc_f;
+#X obj 94 47 cv/#Ellipse;
+#X obj 3 81 doc_c 0;
+#X obj 3 121 doc_i 1;
+#X obj 3 361 doc_o 2;
+#X obj 14 151 doc_ii 0;
+#X obj 14 391 doc_oo 0;
+#X obj 14 411 doc_oo 1;
+#X obj 97 411 doc_m o1;
+#X obj 97 391 doc_m o0 grid;
+#X obj 97 151 doc_m i0 grid;
+#X obj 97 211 doc_m i0 center;
+#X obj 97 191 doc_m i0 axes;
+#X obj 97 171 doc_m i0 angle;
+#X obj 97 311 doc_m i0 start_angle;
+#X obj 97 251 doc_m i0 end_angle;
+#X obj 97 231 doc_m i0 color;
+#X obj 97 331 doc_m i0 thickness;
+#X obj 97 271 doc_m i0 line_type;
+#X obj 97 291 doc_m i0 shift;
+#X text 200 411 attributes;
+#X connect 9 1 21 0;
diff --git a/externals/gridflow/doc/flow_classes/cv/#Invert-help.pd b/externals/gridflow/doc/flow_classes/cv/#Invert-help.pd
new file mode 100644
index 00000000..095a6b4e
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/cv/#Invert-help.pd
@@ -0,0 +1,32 @@
+#N canvas 335 118 568 535 10;
+#X obj 0 0 doc_h cv/;
+#X obj 0 506 doc_f;
+#X text 88 75 just convert to grid;
+#X obj 55 157 cv/#Invert;
+#X obj 61 178 display;
+#X obj 22 75 # + (f #);
+#X msg 22 56 3 3 f # 1 2 0 3 0 4 5 6 0;
+#X obj 29 96 display;
+#X obj 3 366 doc_i 1;
+#X obj 3 426 doc_o 1;
+#X obj 3 486 doc_also;
+#X obj 100 486 cv/#SVD;
+#X obj 22 157 #t;
+#X obj 23 259 display;
+#X obj 14 396 doc_ii 0;
+#X obj 14 456 doc_oo 0;
+#X obj 3 326 doc_c;
+#X obj 97 396 doc_m i0 grid;
+#X obj 97 456 doc_m o0 grid;
+#X obj 22 239 #inner \, seed (f #);
+#X text 224 105 finds the float matrix that would cancel a given float
+matrix \, if both were to be put in [#inner] together.;
+#X connect 3 0 4 0;
+#X connect 3 0 19 1;
+#X connect 5 0 7 0;
+#X connect 5 0 12 0;
+#X connect 6 0 5 0;
+#X connect 10 1 11 0;
+#X connect 12 0 19 0;
+#X connect 12 1 3 0;
+#X connect 19 0 13 0;
diff --git a/externals/gridflow/doc/flow_classes/cv/#KMeans-help.pd b/externals/gridflow/doc/flow_classes/cv/#KMeans-help.pd
new file mode 100644
index 00000000..166e0aeb
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/cv/#KMeans-help.pd
@@ -0,0 +1,29 @@
+#N canvas 642 52 560 437 10;
+#X obj 20 190 #out window;
+#X obj 20 63 #in babbage.jpg;
+#X obj 20 46 bng 15 250 50 0 empty empty empty 17 7 0 10 -24198 -1
+-1;
+#X obj 20 102 #cast f;
+#X obj 37 44 loadbang;
+#X obj 20 171 #inner (1 3 # 85 51 15);
+#X obj 42 150 #print;
+#X obj 102 93 #out window;
+#X msg 225 86 mode channels;
+#X obj 20 121 cv/#KMeans 8 \, termcrit (8 nil);
+#X obj 0 0 doc_h cv/;
+#X obj 3 221 doc_c 1;
+#X obj 3 280 doc_i 2;
+#X obj 3 369 doc_o 1;
+#X obj 14 304 doc_ii 0;
+#X obj 14 328 doc_ii 1;
+#X obj 14 393 doc_oo 0;
+#X obj 14 245 doc_cc 0;
+#X connect 1 0 3 0;
+#X connect 1 0 7 0;
+#X connect 2 0 1 0;
+#X connect 3 0 9 0;
+#X connect 4 0 1 0;
+#X connect 5 0 0 0;
+#X connect 8 0 9 0;
+#X connect 9 0 5 0;
+#X connect 9 0 6 0;
diff --git a/externals/gridflow/doc/flow_classes/cv/#SVD-help.pd b/externals/gridflow/doc/flow_classes/cv/#SVD-help.pd
new file mode 100644
index 00000000..ba012df1
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/cv/#SVD-help.pd
@@ -0,0 +1,44 @@
+#N canvas 335 0 568 576 10;
+#X obj 0 0 doc_h cv/;
+#X obj 0 547 doc_f;
+#X obj 19 160 cv/#SVD;
+#X text 200 46 Singular Value Decomposition;
+#X obj 3 306 doc_c 0;
+#X obj 3 346 doc_i 1;
+#X obj 3 408 doc_o 3;
+#X obj 14 376 doc_ii 0;
+#X obj 14 438 doc_oo 0;
+#X obj 14 460 doc_oo 1;
+#X obj 14 482 doc_oo 2;
+#X obj 97 438 doc_m o0 grid;
+#X obj 97 460 doc_m o1 grid;
+#X obj 97 482 doc_m o2 grid;
+#X obj 28 88 display;
+#X text 82 65 just turn into a real grid;
+#X obj 210 161 display;
+#X obj 210 225 display;
+#X obj 20 225 display;
+#X msg 19 46 3 3 f # 1 0 0 0 2 3 0 3 -2;
+#X obj 19 65 # + (f #);
+#X text 287 89 for finding eigenvalues and eigenvectors.;
+#X obj 97 376 doc_m i0 grid;
+#X text 200 376 N by N matrix to decompose;
+#X text 200 438 N by N diagonal matrix containing eigenvalues;
+#X text 200 460 N by N matrix containing eigenvectors;
+#X text 200 482 N by N matrix containing fudge factors: typically contains
+only zeroes \, ones \, and minus ones.;
+#X obj 3 527 doc_also;
+#X obj 97 527 #extract_diagonal;
+#X obj 211 527 cv/#Invert;
+#X connect 2 0 18 0;
+#X connect 2 1 17 0;
+#X connect 2 2 16 0;
+#X connect 11 1 24 0;
+#X connect 12 1 25 0;
+#X connect 13 1 26 0;
+#X connect 19 0 20 0;
+#X connect 20 0 14 0;
+#X connect 20 0 2 0;
+#X connect 22 1 23 0;
+#X connect 27 1 28 0;
+#X connect 27 1 29 0;
diff --git a/externals/gridflow/doc/flow_classes/cv/#numop-help.pd b/externals/gridflow/doc/flow_classes/cv/#numop-help.pd
new file mode 100644
index 00000000..d8a26a75
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/cv/#numop-help.pd
@@ -0,0 +1,60 @@
+#N canvas 683 36 568 668 10;
+#X obj 22 114 #print;
+#X msg 22 69 2 2 # 0 1 2 3;
+#X obj 22 92 cv/#Add (2 2 # 0 1 2 3);
+#X obj 22 189 #print;
+#X msg 22 144 2 2 # 0 1 2 3;
+#X obj 267 114 #print;
+#X msg 267 69 2 2 # 0 1 2 3;
+#X obj 267 191 #print;
+#X obj 22 167 cv/#Sub (2 2 # 0 1 2 3);
+#X obj 267 92 cv/#Mul (2 2 # 0 1 2 3);
+#X obj 267 169 cv/#Div (2 2 # 0 1 2 3);
+#X msg 396 146 2 2 # 0 1 42 666;
+#X msg 396 69 2 2 # 0 1 42 666;
+#X msg 151 144 2 2 # 0 1 42 666;
+#X msg 151 69 2 2 # 0 1 42 666;
+#X obj 0 0 doc_h cv/;
+#X msg 267 146 2 2 # 0 1 2 -3000;
+#X text 424 167 rounds towards zero;
+#X obj 3 412 doc_c 1;
+#X obj 14 442 doc_cc 0;
+#X obj 3 472 doc_i 2;
+#X obj 14 502 doc_ii 0;
+#X obj 14 522 doc_ii 1;
+#X obj 3 552 doc_o 1;
+#X obj 14 582 doc_oo 0;
+#X obj 0 612 doc_f;
+#X obj 22 261 #print;
+#X msg 22 213 2 2 # 0 1 2 3;
+#X msg 151 213 2 2 # 0 1 42 666;
+#X obj 22 237 cv/#And (2 2 # 0 1 2 3);
+#X obj 267 261 #print;
+#X msg 267 213 2 2 # 0 1 2 3;
+#X msg 396 213 2 2 # 0 1 42 666;
+#X obj 267 333 #print;
+#X msg 267 285 2 2 # 0 1 2 3;
+#X msg 396 285 2 2 # 0 1 42 666;
+#X obj 267 237 cv/#Or (2 2 # 0 1 2 3);
+#X obj 267 309 cv/#Xor (2 2 # 0 1 2 3);
+#X connect 1 0 2 0;
+#X connect 2 0 0 0;
+#X connect 4 0 8 0;
+#X connect 6 0 9 0;
+#X connect 8 0 3 0;
+#X connect 9 0 5 0;
+#X connect 10 0 7 0;
+#X connect 11 0 10 1;
+#X connect 12 0 9 1;
+#X connect 13 0 8 1;
+#X connect 14 0 2 1;
+#X connect 16 0 10 0;
+#X connect 27 0 29 0;
+#X connect 28 0 29 1;
+#X connect 29 0 26 0;
+#X connect 31 0 36 0;
+#X connect 32 0 36 1;
+#X connect 34 0 37 0;
+#X connect 35 0 37 1;
+#X connect 36 0 30 0;
+#X connect 37 0 33 0;
diff --git a/externals/gridflow/doc/flow_classes/display-help.pd b/externals/gridflow/doc/flow_classes/display-help.pd
new file mode 100644
index 00000000..9ed72fec
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/display-help.pd
@@ -0,0 +1,24 @@
+#N canvas 674 0 632 415 10;
+#X obj 90 185 display;
+#X msg 319 61 0 1 2 3 5 8 13;
+#X floatatom 319 89 5 0 0 0 - - -;
+#X obj 89 58 #color;
+#X obj 0 0 doc_h;
+#X obj 3 211 doc_c 0;
+#X obj 3 251 doc_i 1;
+#X obj 3 326 doc_o 0;
+#X obj 14 281 doc_ii 0;
+#X obj 3 366 doc_also;
+#X obj 103 366 print;
+#X obj 145 366 #print;
+#X obj 0 386 doc_f;
+#X obj 97 281 doc_m i0 <any>;
+#X text 294 142 GUI object equivalent to [print] and [#print].;
+#X text 232 281 Displays the received message in the box \, resizing
+the box so that the message fits exactly.;
+#X connect 1 0 0 0;
+#X connect 2 0 0 0;
+#X connect 3 0 0 0;
+#X connect 9 1 10 0;
+#X connect 9 1 11 0;
+#X connect 13 1 15 0;
diff --git a/externals/gridflow/doc/flow_classes/doc_add-help.pd b/externals/gridflow/doc/flow_classes/doc_add-help.pd
new file mode 100644
index 00000000..d80f048a
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/doc_add-help.pd
@@ -0,0 +1,23 @@
+#N canvas 283 161 632 333 10;
+#X obj 0 0 doc_h;
+#X obj 0 304 doc_f;
+#X obj 108 45 doc_add;
+#X obj 3 154 doc_i 2;
+#X obj 3 264 doc_o 0;
+#X obj 14 184 doc_ii 0;
+#X obj 14 219 doc_ii 1;
+#X obj 97 219 doc_m i1 float;
+#X obj 97 184 doc_m i0 bang;
+#X obj 3 92 doc_c 1;
+#X obj 14 122 doc_cc 0;
+#X obj 97 122 doc_m c0 symbol;
+#X text 195 37 add one [doc_m] to a given subsection.;
+#X text 194 57 for use by [doc_c] [doc_i] [doc_o] only.;
+#X text 232 184 add one [doc_m] with a blank \$2 (will show up as "~unspecified~")
+;
+#X text 232 219 y position of top of the parent (as given by outlet
+1 of [doc_layout]);
+#X text 232 122 subsection id \, such as "c0" \, "i3" or "oany".;
+#X connect 7 1 15 0;
+#X connect 8 1 14 0;
+#X connect 11 1 16 0;
diff --git a/externals/gridflow/doc/flow_classes/doc_also-help.pd b/externals/gridflow/doc/flow_classes/doc_also-help.pd
new file mode 100644
index 00000000..c88d7e85
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/doc_also-help.pd
@@ -0,0 +1,18 @@
+#N canvas 383 90 632 297 10;
+#X obj 0 0 doc_h;
+#X obj 0 268 doc_f;
+#X obj 3 84 doc_c 0;
+#X obj 3 124 doc_i 0;
+#X text 173 46 an auto-positioning documentation footer.;
+#X obj 3 164 doc_o 2;
+#X obj 14 194 doc_oo 0;
+#X obj 14 216 doc_oo 1;
+#X obj 97 194 doc_m o0 <none>;
+#X obj 97 216 doc_m o1 <evil>;
+#X text 232 194 this outlet is unused;
+#X text 232 216 this outlet is reserved for evil purposes;
+#X obj 3 248 doc_also;
+#X text 103 248 [doc_f];
+#X connect 8 1 10 0;
+#X connect 9 1 11 0;
+#X connect 12 1 13 0;
diff --git a/externals/gridflow/doc/flow_classes/doc_below-help.pd b/externals/gridflow/doc/flow_classes/doc_below-help.pd
new file mode 100644
index 00000000..b4ac21cb
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/doc_below-help.pd
@@ -0,0 +1,40 @@
+#N canvas 335 118 632 420 10;
+#X obj 0 0 doc_h;
+#X obj 0 391 doc_f;
+#X obj 102 50 doc_below;
+#X obj 3 95 doc_c 3;
+#X obj 3 223 doc_i 3;
+#X obj 3 329 doc_o 1;
+#X obj 14 359 doc_oo 0;
+#X obj 14 253 doc_ii 0;
+#X obj 14 275 doc_ii 1;
+#X obj 14 297 doc_ii 2;
+#X obj 14 125 doc_cc 0;
+#X obj 14 147 doc_cc 1;
+#X obj 14 191 doc_cc 2;
+#X obj 97 297 doc_m i2;
+#X obj 97 253 doc_m i0 list;
+#X obj 97 359 doc_m o0 list;
+#X obj 97 125 doc_m c0 symbol;
+#X obj 97 275 doc_m i1 symbol;
+#X text 232 275 same as arg 0;
+#X text 232 297 same as arg 1;
+#X obj 97 191 doc_m c2 float;
+#X obj 97 147 doc_m c1 float;
+#X text 232 147 0: just this node;
+#X text 232 169 1: recursively;
+#X text 218 41 this is to appear directly in the body of an element
+that appears in a help patch (there should be no subpatches involved
+in this case \, because of the uplevels);
+#X text 232 125 relative name such as c/0 or o/any/float;
+#X text 232 191 extra padding in pixels;
+#X text 232 253 (x y) to transform;
+#X text 232 359 (x y) \, usually the same as what came in.;
+#X connect 13 1 19 0;
+#X connect 14 1 27 0;
+#X connect 15 1 28 0;
+#X connect 16 1 25 0;
+#X connect 17 1 18 0;
+#X connect 20 1 26 0;
+#X connect 21 1 22 0;
+#X connect 21 1 23 0;
diff --git a/externals/gridflow/doc/flow_classes/doc_bottom-help.pd b/externals/gridflow/doc/flow_classes/doc_bottom-help.pd
new file mode 100644
index 00000000..b17f8b4a
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/doc_bottom-help.pd
@@ -0,0 +1,27 @@
+#N canvas 335 118 632 372 10;
+#X obj 0 0 doc_h;
+#X obj 0 343 doc_f;
+#X obj 114 54 doc_bottom;
+#X obj 3 162 doc_i 2;
+#X obj 3 281 doc_o 1;
+#X obj 14 311 doc_oo 0;
+#X obj 14 192 doc_ii 0;
+#X obj 14 236 doc_ii 1;
+#X obj 97 311 doc_m o0 float;
+#X text 232 311 y position;
+#X obj 97 236 doc_m i1 symbol;
+#X obj 97 192 doc_m i0 float;
+#X obj 97 214 doc_m i0 before;
+#X text 232 192 y position;
+#X obj 3 100 doc_c 1;
+#X obj 14 130 doc_cc 0;
+#X obj 97 130 doc_m c0 float;
+#X text 232 130 0 or 1 whether to use the "before" directive.;
+#X text 232 214 used for sorting by name (id);
+#X text 232 236 node whose direct children should be queried (specified
+without the \$0);
+#X connect 8 1 9 0;
+#X connect 10 1 19 0;
+#X connect 11 1 13 0;
+#X connect 12 1 18 0;
+#X connect 16 1 17 0;
diff --git a/externals/gridflow/doc/flow_classes/doc_c-help.pd b/externals/gridflow/doc/flow_classes/doc_c-help.pd
new file mode 100644
index 00000000..2362e2e8
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/doc_c-help.pd
@@ -0,0 +1,17 @@
+#N canvas 335 118 632 258 10;
+#X obj 0 0 doc_h;
+#X obj 0 229 doc_f;
+#X text 146 38 an auto-positioning documentation header;
+#X obj 3 67 doc_c 1;
+#X obj 3 129 doc_i 0;
+#X obj 3 169 doc_o 0;
+#X obj 14 97 doc_cc 0;
+#X obj 97 97 doc_m c0 float;
+#X text 232 97 number of creation arguments in the class being documented.
+;
+#X obj 3 209 doc_also;
+#X text 103 209 [doc_i];
+#X text 157 209 [doc_o];
+#X connect 7 1 8 0;
+#X connect 9 1 10 0;
+#X connect 9 1 11 0;
diff --git a/externals/gridflow/doc/flow_classes/doc_cc-help.pd b/externals/gridflow/doc/flow_classes/doc_cc-help.pd
new file mode 100644
index 00000000..041cf718
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/doc_cc-help.pd
@@ -0,0 +1,15 @@
+#N canvas 335 118 632 242 10;
+#X obj 0 0 doc_h;
+#X obj 3 73 doc_c;
+#X obj 3 113 doc_i;
+#X obj 3 153 doc_o;
+#X obj 0 213 doc_f;
+#X text 144 35 auto-positioning documentation subheader for a specific
+creation argument.;
+#X obj 3 193 doc_also;
+#X text 103 193 [doc_c];
+#X text 157 193 [doc_ii];
+#X text 217 193 [doc_oo];
+#X connect 6 1 7 0;
+#X connect 6 1 8 0;
+#X connect 6 1 9 0;
diff --git a/externals/gridflow/doc/flow_classes/doc_editmode-help.pd b/externals/gridflow/doc/flow_classes/doc_editmode-help.pd
new file mode 100644
index 00000000..3c69aa5d
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/doc_editmode-help.pd
@@ -0,0 +1,16 @@
+#N canvas 451 192 632 304 10;
+#X obj 0 0 doc_h;
+#X obj 0 275 doc_f;
+#X obj 103 51 doc_editmode;
+#X obj 3 113 doc_c 0;
+#X obj 3 153 doc_i 2;
+#X obj 3 235 doc_o 0;
+#X obj 14 183 doc_ii 0;
+#X obj 14 203 doc_ii 1;
+#X obj 97 183 doc_m i0 float;
+#X obj 97 203 doc_m i1 float;
+#X text 200 182 x position of the button to manage;
+#X text 232 203 1: also manage the rectangle;
+#X text 226 50 used for handling the changes that happen when switching
+from and to edit mode in GridFlow's documentation.;
+#X connect 9 1 11 0;
diff --git a/externals/gridflow/doc/flow_classes/doc_exist-help.pd b/externals/gridflow/doc/flow_classes/doc_exist-help.pd
new file mode 100644
index 00000000..aaf53a39
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/doc_exist-help.pd
@@ -0,0 +1,26 @@
+#N canvas 215 276 632 354 10;
+#X obj 0 0 doc_h;
+#X obj 0 325 doc_f;
+#X obj 116 44 doc_exist;
+#X obj 3 82 doc_c 1;
+#X obj 3 157 doc_i 2;
+#X obj 3 241 doc_o 1;
+#X obj 14 271 doc_oo 0;
+#X obj 14 187 doc_ii 0;
+#X obj 14 209 doc_ii 1;
+#X obj 14 112 doc_cc 0;
+#X obj 97 112 doc_m c0 symbol;
+#X text 232 112 relative name of object to be checked for. the \$0
+of the parent will be automatically added (with a slash).;
+#X obj 97 187 doc_m i0 bang;
+#X obj 97 209 doc_m i1 symbol;
+#X text 232 209 same as arg 0;
+#X obj 97 271 doc_m o0 float;
+#X text 232 187 perform a check and output the result;
+#X text 232 271 0: not found;
+#X text 232 293 1: found;
+#X connect 10 1 11 0;
+#X connect 12 1 16 0;
+#X connect 13 1 14 0;
+#X connect 15 1 17 0;
+#X connect 15 1 18 0;
diff --git a/externals/gridflow/doc/flow_classes/doc_f-help.pd b/externals/gridflow/doc/flow_classes/doc_f-help.pd
new file mode 100644
index 00000000..3c210670
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/doc_f-help.pd
@@ -0,0 +1,7 @@
+#N canvas 335 118 632 227 10;
+#X obj 0 0 doc_h;
+#X obj 0 198 doc_f;
+#X obj 3 78 doc_c 0;
+#X obj 3 118 doc_i 0;
+#X obj 3 158 doc_o 0;
+#X text 173 46 an auto-positioning documentation footer.;
diff --git a/externals/gridflow/doc/flow_classes/doc_h-help.pd b/externals/gridflow/doc/flow_classes/doc_h-help.pd
new file mode 100644
index 00000000..00b71c86
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/doc_h-help.pd
@@ -0,0 +1,13 @@
+#N canvas 409 226 632 269 10;
+#X obj 0 0 doc_h;
+#X obj 0 240 doc_f;
+#X text 126 40 an auto-positioning documentation header;
+#X obj 3 160 doc_i 0;
+#X obj 3 200 doc_o 0;
+#X obj 3 72 doc_c 1;
+#X obj 14 102 doc_cc 0;
+#X obj 97 102 doc_m c0 symbol;
+#X text 232 102 namespace prefix (can't be figured out automatically
+for now). must include trailing slash. hopefully this is a temporary
+measure.;
+#X connect 7 1 8 0;
diff --git a/externals/gridflow/doc/flow_classes/doc_i-help.pd b/externals/gridflow/doc/flow_classes/doc_i-help.pd
new file mode 100644
index 00000000..ba2cbbcb
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/doc_i-help.pd
@@ -0,0 +1,10 @@
+#N canvas 454 262 632 251 10;
+#X obj 0 0 doc_h;
+#X obj 0 222 doc_f;
+#X obj 3 80 doc_c 1;
+#X obj 3 142 doc_i 0;
+#X obj 3 182 doc_o 0;
+#X obj 14 110 doc_cc 0;
+#X obj 97 110 doc_m c0 float;
+#X text 232 110 number of inlets in the class being documented;
+#X connect 6 1 7 0;
diff --git a/externals/gridflow/doc/flow_classes/doc_ii-help.pd b/externals/gridflow/doc/flow_classes/doc_ii-help.pd
new file mode 100644
index 00000000..9858cce7
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/doc_ii-help.pd
@@ -0,0 +1,15 @@
+#N canvas 335 118 632 260 10;
+#X obj 0 0 doc_h;
+#X obj 3 91 doc_c;
+#X obj 3 131 doc_i;
+#X obj 3 171 doc_o;
+#X obj 0 231 doc_f;
+#X text 132 41 auto-positioning documentation subheader for a specific
+inlet.;
+#X text 103 211 doc_i;
+#X text 145 211 doc_cc;
+#X text 193 211 doc_oo;
+#X obj 3 211 doc_also;
+#X connect 9 1 6 0;
+#X connect 9 1 7 0;
+#X connect 9 1 8 0;
diff --git a/externals/gridflow/doc/flow_classes/doc_layout-help.pd b/externals/gridflow/doc/flow_classes/doc_layout-help.pd
new file mode 100644
index 00000000..6ddf5154
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/doc_layout-help.pd
@@ -0,0 +1,46 @@
+#N canvas 335 118 632 473 10;
+#X obj 0 0 doc_h;
+#X obj 0 444 doc_f;
+#X obj 3 91 doc_c 4;
+#X obj 14 121 doc_cc 0;
+#X obj 14 156 doc_cc 1;
+#X obj 14 178 doc_cc 2;
+#X obj 14 200 doc_cc 3;
+#X obj 97 200 doc_m c3 symbol;
+#X text 232 200 parent;
+#X text 232 178 height;
+#X text 232 156 width;
+#X text 232 121 relative id \, such as c0/hello \, to which the parent's
+\$0 will be automatically prefixed (with an extra slash);
+#X obj 3 232 doc_i 2;
+#X obj 3 360 doc_o 2;
+#X obj 14 390 doc_oo 0;
+#X obj 14 412 doc_oo 1;
+#X obj 97 390 doc_m o0 <none>;
+#X text 232 412 current (x y) position of the object;
+#X obj 97 412 doc_m o1 list;
+#X obj 97 328 doc_m i1 list;
+#X text 232 328 new (x y) position after processing the output of outlet
+1;
+#X obj 97 284 doc_m i0 name;
+#X obj 97 306 doc_m i0 parent;
+#X obj 97 262 doc_m i0 height;
+#X text 232 262 same as arg 2;
+#X text 232 284 same as arg 0;
+#X text 232 306 same as arg 3;
+#X obj 14 262 doc_ii 0;
+#X obj 14 328 doc_ii 1;
+#X obj 97 156 doc_m c1 float;
+#X obj 97 178 doc_m c2 float;
+#X obj 97 121 doc_m c0 symbol;
+#X text 109 49 used by all [doc_...] abstractions for their own positioning
+;
+#X connect 7 1 8 0;
+#X connect 18 1 17 0;
+#X connect 19 1 20 0;
+#X connect 21 1 25 0;
+#X connect 22 1 26 0;
+#X connect 23 1 24 0;
+#X connect 29 1 10 0;
+#X connect 30 1 9 0;
+#X connect 31 1 11 0;
diff --git a/externals/gridflow/doc/flow_classes/doc_m-help.pd b/externals/gridflow/doc/flow_classes/doc_m-help.pd
new file mode 100644
index 00000000..3a955e48
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/doc_m-help.pd
@@ -0,0 +1,78 @@
+#N canvas 335 0 632 700 10;
+#X obj 0 0 doc_h;
+#X obj 0 1031 doc_f;
+#X obj 3 347 doc_c 2;
+#X obj 3 911 doc_i 0;
+#X obj 3 951 doc_o 2;
+#X obj 14 981 doc_oo 0;
+#X obj 14 1001 doc_oo 1;
+#X obj 14 377 doc_cc 0;
+#X obj 14 425 doc_cc 1;
+#X obj 97 377 doc_m c0 symbol;
+#X obj 97 425 doc_m c1 symbol;
+#X text 232 377 code for associating to a specific [doc_c] \, [doc_i]
+or [doc_o]. for example \, to associate with [doc_c 3] \, the code
+is c3;
+#X text 232 425 in the case of [doc_i] or [doc_o] \, this is either
+a selector or a meta-selector.;
+#X text 232 556 the sorting order of [doc_m] elements in a given subsection
+is alphabetical except for those five at the beginning: bang \, float
+\, grid \, symbol \, pointer \, list. and this one at the very end:
+<any>.;
+#X text 232 617 a list of meta-selectors:;
+#X text 232 639 <any>: represents the anything-method;
+#X text 232 661 <none>: is for writing anything of interest (?) about
+nothing at all. when present \, this is usually the only entry in the
+given subsection \, and it usually just says that the inlet or outlet
+is meant to be useless. typically \, no messages are accepted in the
+inlet \, or else \, all messages are accepted without doing anything
+with them \, or in the case of outlet \, nothing ever comes out of
+it.;
+#X text 232 796 <evil>: is like <none> \, except that the outlet that
+bears it will do weird things to the object it gets connected to. things
+that are very different from sending mere messages.;
+#X text 232 866 <hpgl>: this stands for a pd message version of the
+HPGL protocol.;
+#X text 232 460 in the case of [doc_c] \, we're just faking that this
+is a selector \, but you better only use atom types here: float \,
+grid \, symbol \, pointer \, <atom>.;
+#X text 232 844 <atom>: this stands for float \, grid \, symbol \,
+or pointer.;
+#X obj 97 981 doc_m o0 <none>;
+#X obj 97 1001 doc_m o1 <evil>;
+#X text 232 761 <gone>: is like none \, except the inlet or outlet
+is completely missing.;
+#X text 190 37 style guide for comments:;
+#X text 190 59 do not say "accepts a grid that will do blah blah" \,
+because all methods are accepting messages anyway. but do not say "a
+grid that will do blah blah" \, because "grid" is already specified
+by the [doc_m]. in some sentence structures it will be clearer to say
+"the grid" in some places rather than not.;
+#X text 232 508 a meta-selector is a name written within <> marks.
+those represent special things that aren't really selectors \, as well
+as sets of several selectors (or of many of them).;
+#X text 190 142 say "image that will do blah blah" if an image is expected
+\, but note that not so many objects really require images as inputs.
+;
+#X text 192 186 there is also a difference between hard limitations
+\, and expected interpretations. for example \, if we say "an rgb image"
+and mean it and are right about it \, then only 3-dimensional grids
+will be accepted \, and only those with 3 elements in the last dimension
+will be accepted \, but it is up to us to think of that last dimension
+to represent rgb \, it is up to us to think that this last dimension
+is channels \, and that the other dimensions are rows and columns.
+however \, to ease the reading \, thinks like "(rows columns 3)" and
+"rgb image" will be said even though much of GridFlow itself doesn't
+care about it.;
+#X connect 9 1 11 0;
+#X connect 10 1 12 0;
+#X connect 10 1 26 0;
+#X connect 10 1 13 0;
+#X connect 10 1 14 0;
+#X connect 10 1 15 0;
+#X connect 10 1 16 0;
+#X connect 10 1 17 0;
+#X connect 10 1 18 0;
+#X connect 10 1 19 0;
+#X connect 10 1 20 0;
+#X connect 10 1 23 0;
diff --git a/externals/gridflow/doc/flow_classes/doc_make-help.pd b/externals/gridflow/doc/flow_classes/doc_make-help.pd
new file mode 100644
index 00000000..422e889c
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/doc_make-help.pd
@@ -0,0 +1,25 @@
+#N canvas 543 148 632 330 10;
+#X obj 0 0 doc_h;
+#X obj 0 301 doc_f;
+#X obj 93 51 doc_make;
+#X obj 3 177 doc_i 2;
+#X obj 3 261 doc_o 0;
+#X obj 14 207 doc_ii 0;
+#X obj 14 229 doc_ii 1;
+#X obj 14 123 doc_cc 0;
+#X obj 97 123 doc_m c0 symbol id;
+#X text 232 123 something like c0 \, i0 \, o0 \, just like the \$1
+of [doc_m];
+#X obj 97 207 doc_m i0 bang;
+#X obj 97 229 doc_m i1 float;
+#X text 232 207 generate subsections;
+#X obj 3 93 doc_c 2;
+#X obj 14 145 doc_cc 1;
+#X obj 97 145 doc_m c1 float;
+#X text 232 145 how many subsections;
+#X text 232 229 starting position of new subsections;
+#X text 169 51 reserved for use by [doc_c] \, [doc_i] and [doc_o];
+#X connect 8 1 9 0;
+#X connect 10 1 12 0;
+#X connect 11 1 17 0;
+#X connect 15 1 16 0;
diff --git a/externals/gridflow/doc/flow_classes/doc_o-help.pd b/externals/gridflow/doc/flow_classes/doc_o-help.pd
new file mode 100644
index 00000000..4481e7a5
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/doc_o-help.pd
@@ -0,0 +1,11 @@
+#N canvas 565 290 632 249 10;
+#X obj 0 0 doc_h;
+#X obj 0 220 doc_f;
+#X text 173 43 an auto-positioning documentation header;
+#X obj 3 78 doc_c 1;
+#X obj 3 140 doc_i 0;
+#X obj 14 108 doc_cc 0;
+#X obj 3 180 doc_o 0;
+#X obj 97 108 doc_m c0 float;
+#X text 232 108 number of outlets in the class being documented;
+#X connect 7 1 8 0;
diff --git a/externals/gridflow/doc/flow_classes/doc_oo-help.pd b/externals/gridflow/doc/flow_classes/doc_oo-help.pd
new file mode 100644
index 00000000..9ad3e905
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/doc_oo-help.pd
@@ -0,0 +1,15 @@
+#N canvas 546 210 632 258 10;
+#X obj 0 0 doc_h;
+#X obj 0 229 doc_f;
+#X text 103 209 doc_ii;
+#X text 151 209 doc_cc;
+#X text 199 209 doc_o;
+#X obj 3 89 doc_c 1;
+#X obj 3 129 doc_i 0;
+#X obj 3 169 doc_o 0;
+#X text 129 45 auto-positioning documentation subheader for a specific
+outlet.;
+#X obj 3 209 doc_also;
+#X connect 9 1 2 0;
+#X connect 9 1 3 0;
+#X connect 9 1 4 0;
diff --git a/externals/gridflow/doc/flow_classes/for-help.pd b/externals/gridflow/doc/flow_classes/for-help.pd
new file mode 100644
index 00000000..8868e367
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/for-help.pd
@@ -0,0 +1,56 @@
+#N canvas 480 175 632 542 10;
+#X obj 41 115 print;
+#X obj 41 73 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X text 40 135 should print 10 23 36 49 62 75 88 101;
+#X obj 41 91 for 10 114 13;
+#X obj 0 0 doc_h;
+#X obj 3 179 doc_c 3;
+#X obj 3 285 doc_i 3;
+#X obj 3 433 doc_o 1;
+#X obj 14 315 doc_ii 0;
+#X obj 14 379 doc_ii 1;
+#X obj 14 401 doc_ii 2;
+#X obj 14 463 doc_oo 0;
+#X obj 14 209 doc_cc 0;
+#X obj 14 231 doc_cc 1;
+#X obj 14 253 doc_cc 2;
+#X obj 0 513 doc_f;
+#X obj 97 463 doc_m o0 float;
+#X obj 97 401 doc_m i2 float;
+#X obj 97 379 doc_m i1 float;
+#X obj 97 335 doc_m i0 float;
+#X obj 97 357 doc_m i0 set;
+#X obj 97 315 doc_m i0 bang;
+#X obj 3 493 doc_also;
+#X obj 103 493 #for 0 0 1;
+#X obj 175 493 until;
+#X obj 97 209 doc_m c0 float;
+#X obj 97 231 doc_m c1 float;
+#X obj 97 253 doc_m c2 float;
+#X text 232 209 from;
+#X text 232 231 to;
+#X text 232 253 step;
+#X text 232 379 same as arg 1;
+#X text 232 401 same as arg 2;
+#X text 232 357 same as arg 0;
+#X text 232 335 same as set \$1 \, bang;
+#X text 41 151 note that 114 should not be included!;
+#X text 192 42 count from a value to another value. the latter value
+is excluded \, such that [for 0 10 1] and for [10 20 1] have no common
+outputs.;
+#X msg 72 68 set 0;
+#X msg 71 42 5;
+#X connect 1 0 3 0;
+#X connect 3 0 0 0;
+#X connect 17 1 32 0;
+#X connect 18 1 31 0;
+#X connect 19 1 34 0;
+#X connect 20 1 33 0;
+#X connect 22 1 23 0;
+#X connect 22 1 24 0;
+#X connect 25 1 28 0;
+#X connect 26 1 29 0;
+#X connect 27 1 30 0;
+#X connect 37 0 3 0;
+#X connect 38 0 3 0;
diff --git a/externals/gridflow/doc/flow_classes/foreach-help.pd b/externals/gridflow/doc/flow_classes/foreach-help.pd
new file mode 100644
index 00000000..a7f5ff02
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/foreach-help.pd
@@ -0,0 +1,19 @@
+#N canvas 635 118 632 307 10;
+#X obj 0 0 doc_h;
+#X obj 31 51 foreach;
+#X obj 3 96 doc_c 0;
+#X obj 3 136 doc_i 1;
+#X obj 14 166 doc_ii 0;
+#X obj 97 166 doc_m i0 list;
+#X obj 3 198 doc_o 1;
+#X obj 14 228 doc_oo 0;
+#X text 232 166 Outputs N messages \, one per list element \, in order.
+;
+#X obj 0 278 doc_f;
+#X obj 97 228 doc_m o0 <atom>;
+#X obj 3 258 doc_also;
+#X obj 103 258 drip 0;
+#X text 183 49 split a message into separate atoms and output them
+all.;
+#X connect 5 1 8 0;
+#X connect 11 1 12 0;
diff --git a/externals/gridflow/doc/flow_classes/fps-help.pd b/externals/gridflow/doc/flow_classes/fps-help.pd
new file mode 100644
index 00000000..55ab816e
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/fps-help.pd
@@ -0,0 +1,71 @@
+#N canvas 648 0 632 642 10;
+#X obj 0 0 doc_h;
+#X obj 27 52 fps;
+#X obj 3 94 doc_c 1;
+#X obj 14 124 doc_cc 0;
+#X obj 97 124 doc_m c0 symbol;
+#X obj 3 178 doc_i 1;
+#X obj 14 208 doc_ii 0;
+#X obj 97 208 doc_m i0 bang;
+#X obj 97 291 doc_m i0 detailed;
+#X obj 97 335 doc_m i0 mode;
+#X obj 97 467 doc_m i0 period;
+#X obj 3 521 doc_o 1;
+#X obj 14 551 doc_oo 0;
+#X obj 97 551 doc_m o0 float;
+#X obj 97 573 doc_m o0 list;
+#X text 232 423 "logical" uses [timer];
+#X text 232 445 "process" uses [cputime];
+#X text 232 401 "cpu" uses [tsctime];
+#X text 232 335 "real" uses [realtime];
+#X text 232 357 "user" uses [usertime];
+#X text 232 379 "system" uses [systemtime];
+#X obj 3 666 doc_also;
+#X obj 103 666 realtime;
+#X obj 163 666 usertime;
+#X obj 223 666 systemtime;
+#X obj 295 666 tsctime;
+#X obj 349 666 timer;
+#X obj 391 666 cputime;
+#X text 232 208 Times at which bangs are received are stored until
+a large enough sample of those is accumulated. Large enough is defined
+to be whenever the timespan exceeds one second. Then a report is made
+through the outlet.;
+#X text 232 489 exceptionally \, anything else gets ignored.;
+#X text 232 551 (terse) this is the messages-per-second rating.;
+#X text 232 573 (detailed) this is: messages-per-second \, followed
+by five values of milliseconds-per-message: minimum \, median \, maximum
+\, average \, standard deviation.;
+#X text 232 621 (the average happens to be simply 1000 divided by the
+messages-per-second \, but it is convenient to have it anyway);
+#X obj 0 686 doc_f;
+#X obj 97 489 doc_m i0 <any>;
+#X text 232 146 "detailed": see outlet 0 list;
+#X text 232 124 "terse": see outlet 0 float;
+#X text 232 313 1: same as arg 0 detailed;
+#X text 232 291 0: same as arg 0 terse;
+#X text 232 467 minimum time between updates;
+#X text 185 52 measures frames per second... or bangs per second in
+general;
+#X connect 4 1 36 0;
+#X connect 4 1 35 0;
+#X connect 7 1 28 0;
+#X connect 8 1 37 0;
+#X connect 8 1 38 0;
+#X connect 9 1 18 0;
+#X connect 9 1 19 0;
+#X connect 9 1 20 0;
+#X connect 9 1 17 0;
+#X connect 9 1 15 0;
+#X connect 9 1 16 0;
+#X connect 10 1 39 0;
+#X connect 13 1 30 0;
+#X connect 14 1 32 0;
+#X connect 14 1 31 0;
+#X connect 21 1 22 0;
+#X connect 21 1 23 0;
+#X connect 21 1 24 0;
+#X connect 21 1 25 0;
+#X connect 21 1 26 0;
+#X connect 21 1 27 0;
+#X connect 34 1 29 0;
diff --git a/externals/gridflow/doc/flow_classes/gf.oneshot-help.pd b/externals/gridflow/doc/flow_classes/gf.oneshot-help.pd
new file mode 100644
index 00000000..f207434d
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/gf.oneshot-help.pd
@@ -0,0 +1,42 @@
+#N canvas 680 22 632 504 10;
+#X text 29 34 Like [spigot] \, but turns itself off after each message
+\, so you have to turn it on again to making it pass another message.
+;
+#X msg 195 125 1;
+#X obj 171 125 bng 15 250 50 0 empty empty empty 0 -6 0 8 -24198 -1
+-1;
+#X msg 127 88 test;
+#X obj 127 199 print;
+#X floatatom 168 90 5 0 0 0 - - -;
+#X floatatom 171 200 5 0 0 0 - - -;
+#X text 232 125 <-- both will reset the object;
+#X text 232 441 Outputs incoming message.;
+#X text 232 366 Resets the object so that the next mesage will be passed
+through.;
+#X obj 127 159 gf.oneshot;
+#X obj 3 301 doc_i 2;
+#X obj 0 0 doc_h;
+#X obj 14 366 doc_ii 1;
+#X obj 14 441 doc_oo 0;
+#X obj 3 411 doc_o 1;
+#X obj 14 331 doc_ii 0;
+#X obj 3 239 doc_c 1;
+#X obj 14 269 doc_cc 0;
+#X text 232 269 Whether to start open (default: 1);
+#X text 232 331 Incoming messages can be Grids \, Symbols \, Integers
+\, Lists \, etc.;
+#X obj 0 473 doc_f;
+#X obj 97 269 doc_m c0 bool;
+#X obj 97 366 doc_m i1 bang;
+#X obj 97 441 doc_m o0 <any>;
+#X obj 97 331 doc_m i0 <any>;
+#X connect 1 0 10 1;
+#X connect 2 0 10 1;
+#X connect 3 0 10 0;
+#X connect 5 0 10 0;
+#X connect 10 0 4 0;
+#X connect 10 0 6 0;
+#X connect 22 1 19 0;
+#X connect 23 1 9 0;
+#X connect 24 1 8 0;
+#X connect 25 1 20 0;
diff --git a/externals/gridflow/doc/flow_classes/hpgl_find_bbox-help.pd b/externals/gridflow/doc/flow_classes/hpgl_find_bbox-help.pd
new file mode 100644
index 00000000..758f6560
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/hpgl_find_bbox-help.pd
@@ -0,0 +1,21 @@
+#N canvas 335 118 632 322 10;
+#X obj 0 293 doc_f;
+#X obj 0 0 doc_h;
+#X obj 94 48 hpgl_find_bbox;
+#X obj 3 81 doc_c 0;
+#X obj 3 121 doc_i 2;
+#X obj 3 231 doc_o 1;
+#X obj 14 151 doc_ii 0;
+#X obj 14 173 doc_ii 1;
+#X obj 14 261 doc_oo 0;
+#X obj 97 151 doc_m i0 <hpgl>;
+#X obj 97 173 doc_m i1 bang;
+#X obj 97 261 doc_m o0 grid;
+#X text 232 261 (2 2)-grid representing bounding box.;
+#X text 232 151 HPGL stream to find the bounding box of.;
+#X text 232 173 outputs the bounding box of all coordinates used so
+far in PA \, PD \, PU commands. if no such coordinates have been used
+so far \, it will output funny nonsense values instead.;
+#X connect 9 1 13 0;
+#X connect 10 1 14 0;
+#X connect 11 1 12 0;
diff --git a/externals/gridflow/doc/flow_classes/hpgl_font_render-help.pd b/externals/gridflow/doc/flow_classes/hpgl_font_render-help.pd
new file mode 100644
index 00000000..2764f4a5
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/hpgl_font_render-help.pd
@@ -0,0 +1,178 @@
+#N canvas 604 0 632 642 10;
+#X obj 215 53 until;
+#X obj 215 36 bng 15 250 50 0 empty empty empty 17 7 0 10 -24198 -1
+-1;
+#X obj 148 36 tgl 15 0 empty empty empty 17 7 0 10 -24198 -1 -1 0 1
+;
+#X msg 222 77 rewind;
+#X obj 312 171 print bogus;
+#X obj 112 317 loadbang;
+#X obj 220 171 print command;
+#X obj 132 256 #store;
+#X obj 303 195 loadbang;
+#X obj 220 152 spigot;
+#X obj 266 153 tgl 15 0 empty empty empty 17 7 0 10 -241291 -1 -1 0
+1;
+#X obj 33 503 fps;
+#X obj 306 38 bng 15 250 50 0 empty empty empty 17 7 0 10 -258699 -1
+-1;
+#X obj 148 53 metro 1;
+#X obj 224 382 #pack;
+#X obj 254 366 nbx 5 14 -1e+37 1e+37 0 1 empty empty empty 0 -8 0 10
+-241291 -1 -1 0 256;
+#X obj 224 350 nbx 5 14 -1e+37 1e+37 0 1 empty empty empty 0 -8 0 10
+-241291 -1 -1 0 256;
+#X obj 280 382 #pack;
+#X obj 310 366 nbx 5 14 -1e+37 1e+37 0 1 empty empty empty 0 -8 0 10
+-241291 -1 -1 750 256;
+#X obj 280 350 nbx 5 14 -1e+37 1e+37 0 1 empty empty empty 0 -8 0 10
+-241291 -1 -1 1000 256;
+#X obj 109 283 gf.oneshot;
+#X obj 132 200 t b b;
+#X obj 33 522 nbx 5 14 -1e+37 1e+37 0 0 empty empty empty 0 -8 0 10
+-225271 -1 -1 0 256;
+#X obj 33 192 gf.oneshot;
+#X obj 63 156 bng 15 250 50 0 empty empty empty 17 7 0 10 -24198 -1
+-1;
+#X obj 63 173 t b b;
+#X obj 98 364 #draw_hpgl;
+#X obj 33 484 #out window;
+#X obj 130 157 f;
+#X obj 155 157 + 1;
+#X obj 130 176 sel;
+#X text 362 35 TODO: look for bug in [#in grid] code...;
+#X obj 215 131 plotter_parser;
+#X obj 312 152 spigot;
+#X obj 358 153 tgl 15 0 empty empty empty 17 7 0 10 -241291 -1 -1 0
+1;
+#X obj 128 440 # >> 4;
+#X msg 112 336 3 # 255 255 255;
+#X msg 303 214 480 640 3 #;
+#X obj 63 463 #gamma;
+#X obj 109 465 nbx 5 14 -1e+37 1e+37 0 1 empty empty empty 0 -8 0 10
+-241291 -1 -1 350 256;
+#X obj 128 402 #convolve (3 3 # 0 1 0 1 12 1);
+#X obj 128 421 # + 7;
+#X obj 98 440 t a;
+#X obj 137 384 tgl 15 0 empty empty empty 17 7 0 10 -241291 -1 -1 0
+1;
+#X obj 143 229 t a a;
+#X obj 33 444 shunt;
+#X obj 72 445 tgl 15 0 empty empty empty 17 7 0 10 -241291 -1 -1 0
+1;
+#X obj 98 383 shunt;
+#X obj 221 287 hpgl_find_bbox;
+#X obj 311 288 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 221 306 #to_list;
+#X msg 221 325 PU \$1 \$2 \, PD \$3 \$2 \$3 \$4 \$1 \$4 \$1 \$2;
+#X obj 215 99 #in grid lots_of_text.hpgl \, headerless \, type b;
+#X obj 148 72 t b b b b;
+#X obj 215 252 hpgl_font_render images/hershey \, spacing 10 \, scaling
+0.12 \, rowheight 54 \, wrap 666;
+#X obj 155 176 % 16;
+#X obj 0 0 doc_h;
+#X obj 3 555 doc_c 1;
+#X obj 3 617 doc_i 2;
+#X obj 3 701 doc_o 1;
+#X obj 14 731 doc_oo 0;
+#X obj 14 647 doc_ii 0;
+#X obj 14 669 doc_ii 1;
+#X obj 14 585 doc_cc 0;
+#X obj 0 763 doc_f;
+#N canvas 0 0 450 300 tests 0;
+#X obj 15 242 outlet;
+#X msg 53 31 PU 0 10 \, PD 1000 10;
+#X msg 64 68 PU 0 0 \, print_from_ascii 116 114 97 98 111 117 108 105
+100 111 110;
+#X msg 77 123 PU 50 550 \, print_from_ascii 97 13 10 108 13 10 108
+13 10 244;
+#X msg 87 179 PU 0 0 \, LB world;
+#X connect 1 0 0 0;
+#X connect 2 0 0 0;
+#X connect 3 0 0 0;
+#X connect 4 0 0 0;
+#X restore 241 209 pd tests;
+#X obj 97 585 doc_m c0 symbol;
+#X text 232 585 font folder;
+#X obj 97 647 doc_m i0 <hpgl>;
+#X obj 97 731 doc_m o0 <hpgl>;
+#X text 232 647 containing LB or print_from_ascii commands;
+#X text 232 731 NOT containing LB or print_from_ascii commands anymore
+;
+#X obj 97 669 doc_m i1 symbol;
+#X text 232 669 same as arg 0;
+#X connect 0 0 52 0;
+#X connect 1 0 0 0;
+#X connect 2 0 13 0;
+#X connect 3 0 52 0;
+#X connect 5 0 36 0;
+#X connect 7 0 20 0;
+#X connect 8 0 37 0;
+#X connect 9 0 6 0;
+#X connect 10 0 9 1;
+#X connect 11 0 22 0;
+#X connect 12 0 3 0;
+#X connect 12 0 37 0;
+#X connect 13 0 53 0;
+#X connect 14 0 26 3;
+#X connect 15 0 14 1;
+#X connect 16 0 14 0;
+#X connect 17 0 26 4;
+#X connect 18 0 17 1;
+#X connect 19 0 17 0;
+#X connect 20 0 26 0;
+#X connect 21 0 7 0;
+#X connect 21 1 20 1;
+#X connect 21 1 28 0;
+#X connect 23 0 45 0;
+#X connect 24 0 25 0;
+#X connect 25 0 7 0;
+#X connect 25 1 23 1;
+#X connect 26 0 47 0;
+#X connect 26 1 21 0;
+#X connect 27 0 11 0;
+#X connect 28 0 29 0;
+#X connect 28 0 30 0;
+#X connect 29 0 55 0;
+#X connect 30 0 24 0;
+#X connect 32 0 9 0;
+#X connect 32 0 54 0;
+#X connect 32 1 33 0;
+#X connect 33 0 4 0;
+#X connect 34 0 33 1;
+#X connect 35 0 42 0;
+#X connect 36 0 26 1;
+#X connect 37 0 7 1;
+#X connect 38 0 27 0;
+#X connect 39 0 38 1;
+#X connect 40 0 41 0;
+#X connect 41 0 35 0;
+#X connect 42 0 44 0;
+#X connect 43 0 47 1;
+#X connect 44 0 23 0;
+#X connect 44 1 7 1;
+#X connect 45 0 27 0;
+#X connect 45 1 38 0;
+#X connect 46 0 45 1;
+#X connect 47 0 42 0;
+#X connect 47 1 40 0;
+#X connect 48 0 50 0;
+#X connect 49 0 48 1;
+#X connect 50 0 51 0;
+#X connect 52 0 32 0;
+#X connect 52 1 0 1;
+#X connect 52 1 2 0;
+#X connect 52 1 24 0;
+#X connect 53 0 52 0;
+#X connect 53 1 52 0;
+#X connect 53 2 52 0;
+#X connect 53 3 52 0;
+#X connect 54 0 26 2;
+#X connect 54 0 48 0;
+#X connect 55 0 28 1;
+#X connect 65 0 54 0;
+#X connect 66 1 67 0;
+#X connect 68 1 70 0;
+#X connect 69 1 71 0;
+#X connect 72 1 73 0;
diff --git a/externals/gridflow/doc/flow_classes/hpgl_op-help.pd b/externals/gridflow/doc/flow_classes/hpgl_op-help.pd
new file mode 100644
index 00000000..0ed87a04
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/hpgl_op-help.pd
@@ -0,0 +1,30 @@
+#N canvas 679 174 632 352 10;
+#X obj 0 0 doc_h;
+#X obj 0 323 doc_f;
+#X obj 93 42 hpgl_op;
+#X text 208 40 applies the same numop on all PA \, PD \, PU commands
+of the incoming HPGL stream;
+#X obj 3 80 doc_c 2;
+#X obj 3 164 doc_i 2;
+#X obj 3 248 doc_o 1;
+#X obj 14 110 doc_cc 0;
+#X obj 14 132 doc_cc 1;
+#X obj 14 194 doc_ii 0;
+#X obj 14 216 doc_ii 1;
+#X obj 14 278 doc_oo 0;
+#X obj 97 110 doc_m c0 symbol/numop;
+#X obj 97 132 doc_m c1 grid;
+#X obj 97 194 doc_m i0 <hpgl>;
+#X obj 97 278 doc_m o0 <hpgl>;
+#X obj 97 216 doc_m i1 grid;
+#X text 232 194 incoming HPGL commands;
+#X text 232 278 outgoing HPGL commands: same as incoming except coordinates
+of PA \, PU \, PD will have been changed.;
+#X text 232 216 same as argument 1;
+#X text 232 132 same as argument 1 of [#];
+#X text 232 110 same as argument 0 of [#];
+#X connect 12 1 21 0;
+#X connect 13 1 20 0;
+#X connect 14 1 17 0;
+#X connect 15 1 18 0;
+#X connect 16 1 19 0;
diff --git a/externals/gridflow/doc/flow_classes/hpgl_track_position-help.pd b/externals/gridflow/doc/flow_classes/hpgl_track_position-help.pd
new file mode 100644
index 00000000..17e987c6
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/hpgl_track_position-help.pd
@@ -0,0 +1,21 @@
+#N canvas 335 118 632 310 10;
+#X obj 0 281 doc_f;
+#X obj 0 0 doc_h;
+#X obj 43 52 hpgl_track_position;
+#X obj 3 133 doc_i 2;
+#X obj 3 217 doc_o 1;
+#X text 188 47 looks at PA \, PD \, PU in a HPGL stream to figure out
+what's the current position.;
+#X obj 3 93 doc_c 0;
+#X obj 14 163 doc_ii 0;
+#X obj 14 185 doc_ii 1;
+#X obj 14 247 doc_oo 0;
+#X obj 97 163 doc_m i0 <hpgl>;
+#X obj 97 185 doc_m i1 bang;
+#X obj 97 249 doc_m o0 grid;
+#X text 232 249 last position in the last PA \, PD or PU.;
+#X text 232 185 causes the last position to be output.;
+#X text 232 163 a HPGL stream.;
+#X connect 10 1 15 0;
+#X connect 11 1 14 0;
+#X connect 12 1 13 0;
diff --git a/externals/gridflow/doc/flow_classes/interval_overlap-help.pd b/externals/gridflow/doc/flow_classes/interval_overlap-help.pd
new file mode 100644
index 00000000..8956e701
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/interval_overlap-help.pd
@@ -0,0 +1,46 @@
+#N canvas 335 118 632 455 10;
+#X obj 0 0 doc_h;
+#X obj 0 426 doc_f;
+#X obj 77 49 interval_overlap;
+#X text 236 45 check whether two 1-D intervals overlap;
+#X obj 3 86 doc_c 4;
+#X obj 3 214 doc_i 4;
+#X obj 3 342 doc_o 1;
+#X obj 14 116 doc_cc 0;
+#X obj 14 138 doc_cc 1;
+#X obj 14 160 doc_cc 2;
+#X obj 14 182 doc_cc 3;
+#X obj 14 244 doc_ii 0;
+#X obj 14 266 doc_ii 1;
+#X obj 14 288 doc_ii 2;
+#X obj 14 310 doc_ii 3;
+#X obj 14 372 doc_oo 0;
+#X obj 97 116 doc_m c0 float;
+#X obj 97 138 doc_m c1 float;
+#X obj 97 160 doc_m c2 float;
+#X obj 97 182 doc_m c3 float;
+#X obj 97 244 doc_m i0 float;
+#X obj 97 266 doc_m i1 float;
+#X obj 97 288 doc_m i2 float;
+#X obj 97 310 doc_m i3 float;
+#X obj 97 372 doc_m o0 float;
+#X text 232 372 1: they overlap;
+#X text 232 394 0: they don't;
+#X text 232 116 start1;
+#X text 232 138 end1;
+#X text 232 160 start2;
+#X text 232 182 end2;
+#X text 232 244 same as arg 0;
+#X text 232 266 same as arg 1;
+#X text 232 310 same as arg 3;
+#X text 232 288 same as arg 2;
+#X connect 16 1 27 0;
+#X connect 17 1 28 0;
+#X connect 18 1 29 0;
+#X connect 19 1 30 0;
+#X connect 20 1 31 0;
+#X connect 21 1 32 0;
+#X connect 22 1 34 0;
+#X connect 23 1 33 0;
+#X connect 24 1 25 0;
+#X connect 24 1 26 0;
diff --git a/externals/gridflow/doc/flow_classes/inv0x2a-help.pd b/externals/gridflow/doc/flow_classes/inv0x2a-help.pd
new file mode 100644
index 00000000..c0787d4b
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/inv0x2a-help.pd
@@ -0,0 +1,78 @@
+#N canvas 584 51 632 545 10;
+#X obj 219 121 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 219 163 #in;
+#X obj 263 164 tgl 15 0 empty empty empty 0 -6 0 8 -260818 -1 -1 0
+1;
+#X obj 219 82 tgl 15 0 empty empty empty 0 -6 0 8 -24198 -1 -1 0 1
+;
+#X obj 219 185 shunt 2;
+#X text 369 140 image loader;
+#X obj 219 101 metro 33.3667;
+#X obj 219 238 #out window \, title inv+;
+#X text 349 221 Outputs negated image;
+#X text 68 221 Outputs initial image;
+#X obj 338 188 hsl 128 15 1000 65000 0 0 empty empty empty -2 -6 0
+8 -262144 -1 -1 0 1;
+#X obj 187 496 swap;
+#X floatatom 34 102 5 0 0 0 - - -;
+#X floatatom 57 120 5 0 0 0 - - -;
+#X floatatom 34 176 5 0 0 0 - - -;
+#X floatatom 105 104 5 0 0 0 - - -;
+#X floatatom 149 121 5 0 0 0 - - -;
+#X floatatom 105 178 5 0 0 0 - - -;
+#X obj 105 147 inv* 10;
+#X obj 103 496 inv+;
+#X obj 139 496 # inv*;
+#X text 8 24 The [inv*] performs an inversion on the data passed to
+it. If you consider inlet 0 as the variable "a" and inlet 1 as variable
+"b" \, [inv*] performs the operation "b/a" on the values passed to
+it.;
+#X text 232 464 Outputs the result of the operation "b/a".;
+#X obj 263 209 # inv* 4000;
+#X text 288 163 inversion;
+#X obj 0 0 doc_h;
+#X obj 34 145 inv*;
+#X obj 3 350 doc_i 2;
+#X obj 3 434 doc_o 1;
+#X obj 3 288 doc_c 1;
+#X obj 3 496 doc_also;
+#X obj 14 380 doc_ii 0;
+#X obj 14 402 doc_ii 1;
+#X obj 14 464 doc_oo 0;
+#X obj 14 318 doc_cc 0;
+#X text 323 91 numerical operator of the Grid object;
+#X obj 97 318 doc_m c0 float;
+#X obj 97 380 doc_m i0 float;
+#X obj 97 402 doc_m i1 float;
+#X obj 97 464 doc_m o0 float;
+#X obj 0 516 doc_f;
+#X text 232 318 number that the left inlet values will be divided by.
+;
+#X msg 219 139 load r001.jpg;
+#X text 232 380 a: divisor;
+#X text 232 402 b: dividend;
+#X text 323 78 Another application: inv* as a;
+#X connect 0 0 42 0;
+#X connect 1 0 4 0;
+#X connect 2 0 4 1;
+#X connect 3 0 6 0;
+#X connect 4 0 7 0;
+#X connect 4 1 23 0;
+#X connect 6 0 0 0;
+#X connect 10 0 23 1;
+#X connect 12 0 26 0;
+#X connect 13 0 26 1;
+#X connect 15 0 18 0;
+#X connect 16 0 18 1;
+#X connect 18 0 17 0;
+#X connect 23 0 7 0;
+#X connect 26 0 14 0;
+#X connect 30 1 19 1;
+#X connect 30 1 20 0;
+#X connect 30 1 11 0;
+#X connect 36 1 41 0;
+#X connect 37 1 43 0;
+#X connect 38 1 44 0;
+#X connect 39 1 22 0;
+#X connect 42 0 1 0;
diff --git a/externals/gridflow/doc/flow_classes/inv0x2b-help.pd b/externals/gridflow/doc/flow_classes/inv0x2b-help.pd
new file mode 100644
index 00000000..99a05e09
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/inv0x2b-help.pd
@@ -0,0 +1,75 @@
+#N canvas 652 22 632 574 10;
+#X obj 219 121 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X text 288 163 negative;
+#X obj 219 163 #in;
+#X obj 263 164 tgl 15 0 empty empty empty 0 -6 0 8 -260818 -1 -1 0
+1;
+#X obj 219 82 tgl 15 0 empty empty empty 0 -6 0 8 -24198 -1 -1 0 1
+;
+#X obj 219 185 shunt 2;
+#X text 369 140 image loader;
+#X msg 219 139 open r001.jpg \, bang;
+#X obj 219 101 metro 33.3667;
+#X obj 219 238 #out window \, title inv+;
+#X text 349 221 Outputs negated image;
+#X text 68 221 Outputs initial image;
+#X obj 331 192 hsl 128 15 0 255 0 0 empty empty empty -2 -6 0 8 -262144
+-1 -1 0 1;
+#X obj 151 525 swap;
+#X obj 154 525 swap;
+#X text 9 24 The [inv+] performs an inversion on the data passed to
+it. If you consider inlet 0 as the variable "a" and inlet 1 as variable
+"b" \, [inv+] performs the operation "b-a" on the values passed to
+it.;
+#X floatatom 34 102 5 0 0 0 - - -;
+#X floatatom 57 119 5 0 0 0 - - -;
+#X floatatom 34 176 5 0 0 0 - - -;
+#X obj 103 525 # inv+;
+#X obj 34 146 inv+;
+#X obj 263 211 # inv+ 255;
+#X text 232 493 Outputs the result of the operation "b-a".;
+#X floatatom 105 104 5 0 0 0 - - -;
+#X floatatom 149 121 5 0 0 0 - - -;
+#X floatatom 105 178 5 0 0 0 - - -;
+#X obj 105 145 inv+ 10;
+#X obj 3 353 doc_i 2;
+#X obj 0 0 doc_h;
+#X obj 3 525 doc_also;
+#X obj 14 383 doc_ii 0;
+#X obj 14 418 doc_ii 1;
+#X obj 3 463 doc_o 1;
+#X obj 14 493 doc_oo 0;
+#X obj 3 278 doc_c 1;
+#X obj 14 308 doc_cc 0;
+#X obj 97 308 doc_m c0 float;
+#X obj 97 383 doc_m i0 float;
+#X obj 97 418 doc_m i1 float;
+#X obj 97 493 doc_m o0 float;
+#X obj 0 545 doc_f;
+#X text 232 308 number that the left inlet values will be subtracted
+from.;
+#X text 232 383 a: the value to subtract;
+#X text 232 418 b: the value to subtract from;
+#X connect 0 0 7 0;
+#X connect 2 0 5 0;
+#X connect 3 0 5 1;
+#X connect 4 0 8 0;
+#X connect 5 0 9 0;
+#X connect 5 1 21 0;
+#X connect 7 0 2 0;
+#X connect 8 0 0 0;
+#X connect 12 0 21 1;
+#X connect 16 0 20 0;
+#X connect 17 0 20 1;
+#X connect 20 0 18 0;
+#X connect 21 0 9 0;
+#X connect 23 0 26 0;
+#X connect 24 0 26 1;
+#X connect 26 0 25 0;
+#X connect 29 1 19 0;
+#X connect 29 1 13 0;
+#X connect 36 1 41 0;
+#X connect 37 1 42 0;
+#X connect 38 1 43 0;
+#X connect 39 1 22 0;
diff --git a/externals/gridflow/doc/flow_classes/list.==-help.pd b/externals/gridflow/doc/flow_classes/list.==-help.pd
new file mode 100644
index 00000000..6e38a0a9
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/list.==-help.pd
@@ -0,0 +1,23 @@
+#N canvas 653 141 632 343 10;
+#X obj 0 0 doc_h;
+#X obj 0 314 doc_f;
+#X obj 84 56 list.==;
+#X text 174 49 compare two lists and tell whether they are exactly
+equal to each other.;
+#X obj 3 110 doc_c any;
+#X obj 14 140 doc_cc any;
+#X obj 97 140 doc_m cany <any>;
+#X obj 3 172 doc_i 2;
+#X obj 3 252 doc_o 1;
+#X obj 14 202 doc_ii 0;
+#X obj 14 222 doc_ii 1;
+#X obj 14 282 doc_oo 0;
+#X obj 97 202 doc_m i0 list;
+#X obj 97 222 doc_m i1 list;
+#X obj 97 282 doc_m o0 float bool;
+#X text 232 282 1 if lists are same \, 0 if they are different.;
+#X text 206 199 compare this list with the stored list;
+#X text 232 140 all arguments together form a list being stored;
+#X text 208 223 same as all arguments together;
+#X connect 6 1 17 0;
+#X connect 14 1 15 0;
diff --git a/externals/gridflow/doc/flow_classes/listappend-help.pd b/externals/gridflow/doc/flow_classes/listappend-help.pd
new file mode 100644
index 00000000..266738e8
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/listappend-help.pd
@@ -0,0 +1,49 @@
+#N canvas 624 22 632 469 10;
+#X obj 103 420 listappend;
+#X obj 175 420 listelement;
+#X obj 253 420 listfind;
+#X obj 313 420 listflatten;
+#X obj 391 420 listprepend;
+#X obj 469 420 listreverse;
+#X obj 547 420 listsublist;
+#X msg 90 110 1 3 hello 8 13;
+#X msg 258 107 1 12 a b c d e f g h i j k l;
+#X obj 91 184 display;
+#X msg 267 128 200 201 202 203 204 205 206;
+#X obj 90 152 listappend 1 2 3 4 5 6 7;
+#X text 11 35 The [listappend] combines two lists together. It takes
+the initial list (List1)(passed as an argument or to inlet 1) and appends
+to it the list passed to inlet 0 (List0). [listappend] combines List0
+followed by List1 in a new list.;
+#X obj 0 0 doc_h;
+#X obj 3 274 doc_i 2;
+#X obj 3 358 doc_o 1;
+#X obj 3 212 doc_c n;
+#X obj 3 420 doc_also;
+#X obj 14 304 doc_ii 0;
+#X obj 14 326 doc_ii 1;
+#X obj 14 388 doc_oo 0;
+#X obj 14 242 doc_cc any;
+#X obj 97 304 doc_m i0 list;
+#X obj 97 326 doc_m i1 list;
+#X obj 97 388 doc_m o0 list;
+#X obj 0 440 doc_f;
+#X obj 97 242 doc_m cany <any>;
+#X text 232 242 all arguments together form the list to be appended
+;
+#X text 232 304 a list that the stored list will be appended to.;
+#X text 232 326 same as all args together;
+#X connect 7 0 11 0;
+#X connect 8 0 11 1;
+#X connect 10 0 11 1;
+#X connect 11 0 9 0;
+#X connect 17 1 0 0;
+#X connect 17 1 1 0;
+#X connect 17 1 2 0;
+#X connect 17 1 3 0;
+#X connect 17 1 4 0;
+#X connect 17 1 5 0;
+#X connect 17 1 6 0;
+#X connect 22 1 28 0;
+#X connect 23 1 29 0;
+#X connect 26 1 27 0;
diff --git a/externals/gridflow/doc/flow_classes/listelement-help.pd b/externals/gridflow/doc/flow_classes/listelement-help.pd
new file mode 100644
index 00000000..e30f98da
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/listelement-help.pd
@@ -0,0 +1,39 @@
+#N canvas 604 22 632 523 10;
+#X floatatom 262 160 5 0 0 0 - - -;
+#X floatatom 281 106 5 0 0 0 - - -;
+#X obj 195 158 print;
+#X msg 195 81 1 3 hello 8 13;
+#X obj 195 129 listelement 0;
+#X text 10 32 Outputs one element from a list as selected by an integer.
+;
+#X text 232 238 An integer acts as an index \, it selects the position
+of an element in a list. The selected element is output \, for example:
+integer "0" selects and outputs the first element in a list \, integer
+"1" selects and outputs the second element in a list \, integers "-1"
+selects and outputs the last element in a list.;
+#X text 232 387 Changes the value of the argument i.e. changes the
+index into the list to get a different element.;
+#X obj 0 0 doc_h;
+#X obj 3 335 doc_i 2;
+#X obj 3 432 doc_o 1;
+#X obj 14 365 doc_ii 0;
+#X obj 14 387 doc_ii 1;
+#X obj 14 462 doc_oo 0;
+#X obj 3 208 doc_c 1;
+#X obj 14 238 doc_cc 0;
+#X obj 97 238 doc_m c0 float/int;
+#X obj 97 365 doc_m i0 list;
+#X obj 97 387 doc_m i1 float/int;
+#X text 232 462 The element selected by the index is sent to the outlet
+;
+#X obj 0 494 doc_f;
+#X text 232 365 a list of numbers or symbols.;
+#X obj 97 462 doc_m o0 >any>;
+#X connect 1 0 4 1;
+#X connect 3 0 4 0;
+#X connect 4 0 0 0;
+#X connect 4 0 2 0;
+#X connect 16 1 6 0;
+#X connect 17 1 21 0;
+#X connect 18 1 7 0;
+#X connect 22 1 19 0;
diff --git a/externals/gridflow/doc/flow_classes/listfind-help.pd b/externals/gridflow/doc/flow_classes/listfind-help.pd
new file mode 100644
index 00000000..de83d33c
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/listfind-help.pd
@@ -0,0 +1,32 @@
+#N canvas 527 144 632 394 10;
+#X obj 0 0 doc_h;
+#X obj 0 365 doc_f;
+#X obj 44 66 listfind 2 3 5 7 11 13;
+#X floatatom 44 48 5 0 0 0 - - -;
+#X floatatom 44 85 5 0 0 0 - - -;
+#X text 214 54 find the position of an element (float or symbol) in
+a list \, or -1 if it is not found. in case of duplicate elements \,
+it only tells the position of the first occurrence.;
+#X obj 3 113 doc_c any;
+#X obj 14 143 doc_cc any;
+#X obj 97 143 doc_m cany <any>;
+#X obj 3 173 doc_i 1;
+#X obj 14 203 doc_ii 0;
+#X obj 97 203 doc_m i0 float;
+#X obj 97 238 doc_m i0 symbol;
+#X text 232 238 look for a symbol.;
+#X text 232 203 look for a float. this has the same gotchas as using
+[==] and [sel] \, about the precision of numbers.;
+#X obj 3 270 doc_o 1;
+#X obj 14 300 doc_oo 0;
+#X obj 97 300 doc_m o0 float int;
+#X text 232 300 nonnegative list index of first occurrence \, or -1
+if not found.;
+#X obj 3 345 doc_also;
+#X obj 103 345 listread;
+#X connect 2 0 4 0;
+#X connect 3 0 2 0;
+#X connect 11 1 14 0;
+#X connect 12 1 13 0;
+#X connect 17 1 18 0;
+#X connect 19 1 20 0;
diff --git a/externals/gridflow/doc/flow_classes/listflatten-help.pd b/externals/gridflow/doc/flow_classes/listflatten-help.pd
new file mode 100644
index 00000000..6f253a92
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/listflatten-help.pd
@@ -0,0 +1,39 @@
+#N canvas 630 27 632 433 10;
+#X obj 103 384 listappend;
+#X obj 253 384 listelement;
+#X obj 409 384 listfind;
+#X obj 547 384 listflatten;
+#X obj 175 384 listprepend;
+#X obj 331 384 listreverse;
+#X obj 469 384 listsublist;
+#X obj 225 153 display;
+#X obj 224 120 listflatten;
+#X msg 209 84 1 (2 (3 4 5) 6 7) 8;
+#X obj 210 187 display;
+#X obj 0 0 doc_h;
+#X obj 3 260 doc_i 1;
+#X obj 3 322 doc_o 1;
+#X obj 3 220 doc_c 0;
+#X obj 3 384 doc_also;
+#X obj 14 290 doc_ii 0;
+#X obj 14 352 doc_oo 0;
+#X obj 97 290 doc_m i0 list;
+#X obj 97 352 doc_m o0 list;
+#X obj 0 404 doc_f;
+#X text 232 290 a (usually) nested list.;
+#X text 232 352 Outputs the flattened (not nested) list.;
+#X text 7 30 Takes nested lists and places their contents into a single
+list in the same order. this is just like removing all parentheses
+from the literal and doing nothing else.;
+#X connect 8 0 7 0;
+#X connect 9 0 8 0;
+#X connect 9 0 10 0;
+#X connect 15 1 0 0;
+#X connect 15 1 4 0;
+#X connect 15 1 1 0;
+#X connect 15 1 5 0;
+#X connect 15 1 2 0;
+#X connect 15 1 6 0;
+#X connect 15 1 3 0;
+#X connect 18 1 21 0;
+#X connect 19 1 22 0;
diff --git a/externals/gridflow/doc/flow_classes/listlength-help.pd b/externals/gridflow/doc/flow_classes/listlength-help.pd
new file mode 100644
index 00000000..32e2512a
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/listlength-help.pd
@@ -0,0 +1,41 @@
+#N canvas 637 22 632 432 10;
+#X text 10 33 The [listlength] outputs the number of elements in the
+incoming list.;
+#X obj 103 383 listappend;
+#X obj 253 383 listelement;
+#X obj 409 383 listfind;
+#X obj 547 383 listflatten;
+#X obj 175 383 listprepend;
+#X obj 331 383 listreverse;
+#X obj 469 383 listsublist;
+#X floatatom 206 160 5 0 0 0 - - -;
+#X obj 139 158 print;
+#X msg 139 81 1 3 hello 8 13;
+#X obj 139 120 listlength;
+#X msg 246 96 1 12 a b c d e f g h i j k l;
+#X text 232 276 The length of the list passed to the left inlet will
+be returned in the outlet.;
+#X obj 0 0 doc_h;
+#X obj 3 206 doc_c 0;
+#X obj 3 246 doc_i 1;
+#X obj 3 321 doc_o 1;
+#X obj 3 383 doc_also 1;
+#X obj 14 276 doc_ii 0;
+#X obj 14 351 doc_oo 0;
+#X obj 97 276 doc_m i0 list;
+#X obj 97 351 doc_m o0 float int;
+#X obj 0 403 doc_f;
+#X text 232 351 the number of elements in the list.;
+#X connect 10 0 11 0;
+#X connect 11 0 8 0;
+#X connect 11 0 9 0;
+#X connect 12 0 11 0;
+#X connect 18 1 1 0;
+#X connect 18 1 5 0;
+#X connect 18 1 2 0;
+#X connect 18 1 6 0;
+#X connect 18 1 3 0;
+#X connect 18 1 7 0;
+#X connect 18 1 4 0;
+#X connect 21 1 13 0;
+#X connect 22 1 24 0;
diff --git a/externals/gridflow/doc/flow_classes/listprepend-help.pd b/externals/gridflow/doc/flow_classes/listprepend-help.pd
new file mode 100644
index 00000000..c71314af
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/listprepend-help.pd
@@ -0,0 +1,51 @@
+#N canvas 631 22 632 468 10;
+#X obj 103 419 listappend;
+#X obj 253 419 listelement;
+#X obj 409 419 listfind;
+#X obj 547 419 listflatten;
+#X obj 175 419 listprepend;
+#X obj 331 419 listreverse;
+#X obj 469 419 listsublist;
+#X msg 92 112 1 3 hello 8 13;
+#X msg 260 110 1 12 a b c d e f g h i j k l;
+#X obj 93 180 display;
+#X msg 269 131 200 201 202 203 204 205 206;
+#X obj 92 151 listprepend 1 2 3 4 5 6 7;
+#X text 232 387 Outputs the resulting list.;
+#X text 232 241 This optional argument can contain the initial list
+;
+#X text 8 35 The [listprepend] combines two lists together. It takes
+the initial list (List1)(passed as an argument or to inlet 1) and appends
+the list passed to inlet 0 (List0). [listprepend] combines List1 followed
+by List0 in a new list.;
+#X obj 0 0 doc_h;
+#X obj 3 273 doc_i 2;
+#X obj 3 357 doc_o 1;
+#X obj 3 211 doc_c n;
+#X obj 3 419 doc_also;
+#X obj 14 303 doc_ii 0;
+#X obj 14 325 doc_ii 1;
+#X obj 14 387 doc_oo 0;
+#X obj 14 241 doc_cc any;
+#X obj 97 303 doc_m i0 list;
+#X obj 97 325 doc_m i1 list;
+#X obj 97 387 doc_m o0 list;
+#X obj 0 439 doc_f;
+#X text 232 303 a list to be appended to initial list.;
+#X text 232 325 initial list to be appended to.;
+#X obj 97 241 doc_m cany <any>;
+#X connect 7 0 11 0;
+#X connect 8 0 11 1;
+#X connect 10 0 11 1;
+#X connect 11 0 9 0;
+#X connect 19 1 0 0;
+#X connect 19 1 4 0;
+#X connect 19 1 1 0;
+#X connect 19 1 5 0;
+#X connect 19 1 2 0;
+#X connect 19 1 6 0;
+#X connect 19 1 3 0;
+#X connect 24 1 28 0;
+#X connect 25 1 29 0;
+#X connect 26 1 12 0;
+#X connect 30 1 13 0;
diff --git a/externals/gridflow/doc/flow_classes/listread-help.pd b/externals/gridflow/doc/flow_classes/listread-help.pd
new file mode 100644
index 00000000..a970e607
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/listread-help.pd
@@ -0,0 +1,40 @@
+#N canvas 623 251 632 454 10;
+#X obj 0 0 doc_h;
+#X obj 0 425 doc_f;
+#X floatatom 44 48 5 0 0 0 - - -;
+#X floatatom 44 85 5 0 0 0 - - -;
+#X obj 3 143 doc_c any;
+#X obj 14 173 doc_cc any;
+#X obj 97 173 doc_m cany <any>;
+#X obj 3 203 doc_i 1;
+#X obj 14 233 doc_ii 0;
+#X obj 97 233 doc_m i0 float;
+#X obj 3 330 doc_o 1;
+#X obj 14 360 doc_oo 0;
+#X obj 97 360 doc_m o0 float int;
+#X text 232 360 nonnegative list index of first occurrence \, or -1
+if not found.;
+#X obj 3 405 doc_also;
+#X obj 103 405 listread;
+#X obj 44 66 listread 2 3 5 7 11 13;
+#X text 188 41 like [tabread] \, this outputs an element when given
+an index \, but unlike [tabread] \, this uses a list instead of an
+array.;
+#X obj 44 103 listfind 2 3 5 7 11 13;
+#X floatatom 44 122 5 0 0 0 - - -;
+#X text 188 88 a [listfind] with the same content cancels the effect
+of a [listread] when the input of [listread] is nonnegative and is
+smaller than the list's length.;
+#X text 232 233 lookup an element. if the index is nonnegative \, then
+it must be less than the list length \, else no output will be produced.
+if the index is negative \, then it must be greater than or equal to
+minus the list length \, and this counts from the end of the list:
+-1 will output the last element \, -2 will output the next to last
+\, etc.;
+#X connect 2 0 16 0;
+#X connect 3 0 18 0;
+#X connect 9 1 21 0;
+#X connect 12 1 13 0;
+#X connect 14 1 15 0;
+#X connect 16 0 3 0;
+#X connect 18 0 19 0;
diff --git a/externals/gridflow/doc/flow_classes/listreverse-help.pd b/externals/gridflow/doc/flow_classes/listreverse-help.pd
new file mode 100644
index 00000000..f5174d55
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/listreverse-help.pd
@@ -0,0 +1,13 @@
+#N canvas 659 137 632 262 10;
+#X obj 40 40 listreverse;
+#X obj 0 0 doc_h;
+#X obj 3 73 doc_c 0;
+#X obj 3 113 doc_i 1;
+#X obj 3 173 doc_o 1;
+#X obj 14 143 doc_ii 0;
+#X obj 14 203 doc_oo 0;
+#X obj 97 143 doc_m i0 list;
+#X obj 97 203 doc_m o0 list;
+#X text 119 34 Outputs the incoming list \, from last element to first
+element.;
+#X obj 0 233 doc_f;
diff --git a/externals/gridflow/doc/flow_classes/listsublist-help.pd b/externals/gridflow/doc/flow_classes/listsublist-help.pd
new file mode 100644
index 00000000..900328f5
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/listsublist-help.pd
@@ -0,0 +1,60 @@
+#N canvas 628 22 632 580 10;
+#X obj 103 531 listappend;
+#X obj 175 531 listelement;
+#X obj 253 531 listfind;
+#X obj 313 531 listflatten;
+#X obj 391 531 listprepend;
+#X obj 469 531 listreverse;
+#X msg 173 112 1 3 hello 8 13;
+#X msg 182 136 1 12 a b c d e f g h i j k l;
+#X obj 174 211 display;
+#X text 232 486 Outputs the sublist as specified by the inlets or the
+arguments.;
+#X text 9 33 The [listsublist] outputs consecutive elements of the
+list \, as selected by index (inlet 1 or arg 1) and length (inlet 2
+or arg 2). A negative index will start from the end of the list (like
+-1 means last element in the list).;
+#X floatatom 224 158 5 0 0 0 - - -;
+#X obj 0 0 doc_h;
+#X obj 3 350 doc_i 3;
+#X obj 3 456 doc_o 1;
+#X obj 3 253 doc_c 0..2;
+#X obj 3 531 doc_also;
+#X obj 14 380 doc_ii 0;
+#X obj 14 402 doc_ii 1;
+#X obj 14 424 doc_ii 2;
+#X obj 14 283 doc_cc 0;
+#X obj 14 305 doc_cc 1;
+#X obj 14 486 doc_oo 0;
+#X obj 547 531 listsublist;
+#X floatatom 267 158 5 0 0 0 - - -;
+#X obj 173 182 listsublist 2 3;
+#X text 232 283 The index in the list to start the sublist at.;
+#X text 232 305 The number of items wanted from the list starting at
+the index specified.;
+#X text 232 402 Index (See Argument 0);
+#X text 232 424 Number of items (See Argument 1);
+#X obj 97 283 doc_m c0 float/int;
+#X obj 97 305 doc_m c1 float/int;
+#X obj 97 380 doc_m i0 list;
+#X obj 97 402 doc_m i1 float int;
+#X obj 97 424 doc_m i2 float int;
+#X obj 97 486 doc_m o0 list;
+#X obj 0 551 doc_f;
+#X connect 6 0 25 0;
+#X connect 7 0 25 0;
+#X connect 11 0 25 1;
+#X connect 16 1 0 0;
+#X connect 16 1 1 0;
+#X connect 16 1 2 0;
+#X connect 16 1 3 0;
+#X connect 16 1 4 0;
+#X connect 16 1 5 0;
+#X connect 16 1 23 0;
+#X connect 24 0 25 2;
+#X connect 25 0 8 0;
+#X connect 30 1 26 0;
+#X connect 31 1 27 0;
+#X connect 33 1 28 0;
+#X connect 34 1 29 0;
+#X connect 35 1 9 0;
diff --git a/externals/gridflow/doc/flow_classes/norecurse-help.pd b/externals/gridflow/doc/flow_classes/norecurse-help.pd
new file mode 100644
index 00000000..d0207c97
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/norecurse-help.pd
@@ -0,0 +1,16 @@
+#N canvas 335 118 632 297 10;
+#X obj 0 0 doc_h;
+#X obj 3 80 doc_c;
+#X obj 0 268 doc_f;
+#X obj 76 48 norecurse;
+#X text 237 45 this will stop any control-recursion.;
+#X obj 3 120 doc_i 1;
+#X obj 3 208 doc_o 1;
+#X obj 14 150 doc_ii 0;
+#X obj 14 238 doc_oo 0;
+#X obj 97 150 doc_m i0 <any>;
+#X obj 97 238 doc_m o0 <any>;
+#X text 232 150 any incoming message will be copied as-is to the output.
+but only if a message is not currently "being sent" by this same object.
+thus this prevents any "strange loops".;
+#X connect 9 1 11 0;
diff --git a/externals/gridflow/doc/flow_classes/parallel_port-help.pd b/externals/gridflow/doc/flow_classes/parallel_port-help.pd
new file mode 100644
index 00000000..9cb8916d
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/parallel_port-help.pd
@@ -0,0 +1,96 @@
+#N canvas 188 22 632 673 10;
+#X floatatom 7 380 5 0 0 0 - - -;
+#X floatatom 71 348 5 0 0 0 - - -;
+#X floatatom 136 323 5 0 0 0 - - -;
+#X obj 7 34 tgl 15 0 empty empty empty 17 7 0 10 -24198 -1 -1 0 1;
+#X text 215 206 * my system resets the owner of the printer port to
+'root.lp' so I need to issue as root 'chown myuser.lp';
+#X text 215 50 * you will need : a paper clip (or a 'high tech' solid
+core 22-18 awg wire) an led a button;
+#X text 215 176 * consult http://en.wikipedia.org/wiki/Parallel_Port
+for the pinouts + more;
+#X text 215 255 7 6 5 4 3 2 1 0 bit number;
+#X text 215 269 9 8 7 6 5 4 3 2 pin number;
+#X text 215 237 layout of bit to pin numbers;
+#X text 18 32 <-- This will send a 0 or a 1 to the first pin;
+#X text 14 243 Will accept values from 0-255;
+#X obj 7 132 tgl 15 0 empty empty empty 0 -6 0 8 -260818 -1 -1 0 1
+;
+#X obj 26 132 tgl 15 0 empty empty empty 0 -6 0 8 -260818 -1 -1 0 1
+;
+#X obj 45 132 tgl 15 0 empty empty empty 0 -6 0 8 -260818 -1 -1 0 1
+;
+#X obj 64 132 tgl 15 0 empty empty empty 0 -6 0 8 -260818 -1 -1 0 1
+;
+#X obj 83 132 tgl 15 0 empty empty empty 0 -6 0 8 -260818 -1 -1 0 1
+;
+#X obj 102 132 tgl 15 0 empty empty empty 0 -6 0 8 -260818 -1 -1 0
+1;
+#X obj 121 132 tgl 15 0 empty empty empty 0 -6 0 8 -260818 -1 -1 0
+1;
+#X obj 140 132 tgl 15 0 empty empty empty 0 -6 0 8 -260818 -1 -1 0
+1;
+#X obj 7 229 nbx 5 14 -1e+37 1e+37 0 0 empty empty empty 0 -6 0 10
+-241291 -1 -1 0 256;
+#X obj 7 191 #fold +;
+#X obj 7 210 #to_float;
+#X obj 7 172 # << (0 1 2 3 4 5 6 7);
+#X obj 7 153 #pack 8 \, \, \, \, \, \, \, \, \, \, \, \, \, \, \, \,
+;
+#X text 19 274 takes the port as argument;
+#X text 44 -1 The cheapest digital i/o interface;
+#X obj 7 293 parallel_port /dev/lp0;
+#X obj 7 63 metro 1;
+#X text 215 286 Flags : PERRORP (active low) \, PSELECD (active high)
+\, POUTPA (active high) \, PACK (active low) \, PBUSY (active high)
+;
+#X obj 0 0 doc_h;
+#X text 215 80 1: break the paper clip in two and connect pin 11 (Busy)
+to pin 24 (GND) and pin 12 (Paper-Out) to 25 (GND). Those pins are
+normally 1 and grounding them opens the port for messages.;
+#X text 215 138 2: connect the led between pins 2 (Data0) and 23 (GND)
+;
+#X text 215 156 3: connect a button between pin 10 and 22 (GND);
+#X obj 3 416 doc_c 1;
+#X obj 3 478 doc_i 1;
+#X obj 14 508 doc_ii 0;
+#X obj 14 446 doc_cc 0;
+#X obj 0 644 doc_f;
+#X text 177 322 parallel port flags;
+#X text 110 348 status (pin 10);
+#X text 51 379 reserved for future use;
+#X obj 3 540 doc_o 3;
+#X obj 14 570 doc_oo 0;
+#X obj 14 590 doc_oo 1;
+#X obj 14 612 doc_oo 2;
+#X obj 97 612 doc_m o2 float;
+#X obj 97 590 doc_m o1 float;
+#X obj 97 570 doc_m o0 <none>;
+#X obj 97 508 doc_m i0 float;
+#X obj 97 446 doc_m c0 symbol;
+#X text 232 446 device name (Linux parallel port interface);
+#X text 232 508 bytes to send;
+#X text 232 590 status;
+#X text 232 612 flags;
+#X connect 3 0 28 0;
+#X connect 12 0 24 0;
+#X connect 13 0 24 1;
+#X connect 14 0 24 2;
+#X connect 15 0 24 3;
+#X connect 16 0 24 4;
+#X connect 17 0 24 5;
+#X connect 18 0 24 6;
+#X connect 19 0 24 7;
+#X connect 20 0 27 0;
+#X connect 21 0 22 0;
+#X connect 22 0 20 0;
+#X connect 23 0 21 0;
+#X connect 24 0 23 0;
+#X connect 27 0 0 0;
+#X connect 27 1 1 0;
+#X connect 27 2 2 0;
+#X connect 28 0 12 0;
+#X connect 46 1 54 0;
+#X connect 47 1 53 0;
+#X connect 49 1 52 0;
+#X connect 50 1 51 0;
diff --git a/externals/gridflow/doc/flow_classes/pingpong-help.pd b/externals/gridflow/doc/flow_classes/pingpong-help.pd
new file mode 100644
index 00000000..17b44f36
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/pingpong-help.pd
@@ -0,0 +1,27 @@
+#N canvas 680 0 632 383 10;
+#X obj 0 0 doc_h;
+#X obj 3 294 doc_o 1;
+#X text 148 44 Transforms linear counting (0 \, 1 \, 2 \, 3 \, 4 \,
+...) into a back-and-forth counting (0 \, 1 \, 2 \, 1 \, 0 \, ...)
+from 0 to a specified upper bound.;
+#X obj 34 47 pingpong;
+#X obj 14 324 doc_oo 0;
+#X obj 3 109 doc_c 1;
+#X obj 3 171 doc_i 2;
+#X obj 14 139 doc_cc 0;
+#X obj 14 201 doc_ii 0;
+#X obj 14 262 doc_ii 1;
+#X obj 97 139 doc_m c0 float;
+#X obj 97 262 doc_m i1 float;
+#X text 232 262 same as arg 0;
+#X text 232 139 "top";
+#X obj 97 201 doc_m i0 float;
+#X text 232 201 a value to be transformed. If \, for example \, top=10
+\, then values 0 thru 10 are left unchanged \, values 11 thru 19 are
+mapped to 9 thru 1 respectively \, and 20 thru 30 are mapped to 0 thru
+10 \, and so on.;
+#X obj 97 324 doc_m o0 float;
+#X obj 0 354 doc_f;
+#X connect 10 1 13 0;
+#X connect 11 1 12 0;
+#X connect 14 1 15 0;
diff --git a/externals/gridflow/doc/flow_classes/plotter_control-help.pd b/externals/gridflow/doc/flow_classes/plotter_control-help.pd
new file mode 100644
index 00000000..944a0e53
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/plotter_control-help.pd
@@ -0,0 +1,79 @@
+#N canvas 576 39 632 605 10;
+#X obj 22 162 r foo;
+#X msg 427 236 print_from_ascii $*;
+#X msg 427 115 print hello_world;
+#X msg 154 117 pu;
+#X msg 154 165 pd;
+#X msg 155 268 sp 0;
+#X msg 154 217 pa 120 160;
+#X obj 427 187 unix_time;
+#X obj 427 167 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 14 318 comport 0 9600;
+#X obj 6 192 plotter_control;
+#X obj 23 221 print hpgl_commands;
+#X obj 427 259 s foo;
+#X text 194 117 pen up;
+#X text 194 165 pen down;
+#X obj 427 137 s foo;
+#X text 238 217 move to absolute position;
+#N canvas 0 22 450 300 draw_a_rectangle 0;
+#X msg 31 156 pu \, sp 0;
+#X msg 138 191 pd \, pa \$2 \$1;
+#X msg 129 100 sp 5 \, pu \, pa 0 0 \, other si 320 320;
+#X obj 115 252 s foo;
+#X msg 138 134 0 0 \, 0 1 \, 1 1 \, 1 0 \, 0 0;
+#X obj 31 35 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 31 52 t a a a;
+#X obj 138 153 # * (110 320);
+#X obj 138 172 #to_list;
+#X connect 0 0 3 0;
+#X connect 1 0 3 0;
+#X connect 2 0 3 0;
+#X connect 4 0 7 0;
+#X connect 5 0 6 0;
+#X connect 6 0 0 0;
+#X connect 6 1 4 0;
+#X connect 6 2 2 0;
+#X connect 7 0 8 0;
+#X connect 8 0 1 0;
+#X restore 427 291 pd draw_a_rectangle;
+#X text 74 343 use the comport object to interface to the plotter;
+#X obj 155 290 s foo;
+#X obj 154 239 s foo;
+#X obj 154 187 s foo;
+#X obj 154 139 s foo;
+#X text 198 270 (0...6) remove/change the pen;
+#X obj 0 0 doc_h;
+#X obj 3 379 doc_c 0;
+#X obj 3 419 doc_i 1;
+#X obj 3 494 doc_o 1;
+#X obj 14 524 doc_oo 0;
+#X obj 14 449 doc_ii 0;
+#X text 10 32 This object produces HPGL instructions in ASCII form
+that can be sent to the comport object in order to control an HPGL
+compatible plotter.;
+#X obj 0 576 doc_f;
+#X obj 427 211 #to_list;
+#X obj 97 449 doc_m i0 <hpgl>;
+#X obj 97 524 doc_m o0 float;
+#X text 232 524 serialised hpgl (as ascii codes);
+#X text 232 449 hpgl stream (note: most other hpgl inlets don't support
+lowercase);
+#X obj 3 556 doc_also;
+#X obj 103 556 plotter_parser;
+#X connect 0 0 10 0;
+#X connect 1 0 12 0;
+#X connect 2 0 15 0;
+#X connect 3 0 22 0;
+#X connect 4 0 21 0;
+#X connect 5 0 19 0;
+#X connect 6 0 20 0;
+#X connect 7 0 32 0;
+#X connect 8 0 7 0;
+#X connect 10 0 11 0;
+#X connect 32 0 1 0;
+#X connect 33 1 36 0;
+#X connect 34 1 35 0;
+#X connect 37 1 38 0;
diff --git a/externals/gridflow/doc/flow_classes/plotter_parser-help.pd b/externals/gridflow/doc/flow_classes/plotter_parser-help.pd
new file mode 100644
index 00000000..637d8211
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/plotter_parser-help.pd
@@ -0,0 +1,116 @@
+#N canvas 663 22 632 620 10;
+#X obj 195 161 plotter_parser;
+#X obj 195 63 until;
+#X obj 195 46 bng 15 250 50 0 empty empty empty 17 7 0 10 -24198 -1
+-1;
+#X obj 128 46 tgl 15 0 empty empty empty 17 7 0 10 -24198 -1 -1 0 1
+;
+#X msg 202 87 rewind;
+#X obj 297 159 print bogus;
+#X obj 195 275 loadbang;
+#X obj 206 204 print command;
+#X obj 127 245 #store;
+#X obj 209 233 loadbang;
+#X obj 206 185 spigot;
+#X obj 252 186 tgl 15 0 empty empty empty 17 7 0 10 -241291 -1 -1 0
+1;
+#X obj 13 330 fps;
+#X obj 286 48 bng 15 250 50 0 empty empty empty 17 7 0 10 -258699 -1
+-1;
+#X obj 128 63 metro 1;
+#X obj 195 109 #in grid plotter_parser_old.pd.hpgl \, headerless \,
+type b;
+#X obj 326 302 #pack;
+#X obj 356 286 nbx 5 14 -1e+37 1e+37 0 1 empty empty empty 0 -8 0 10
+-241291 -1 -1 0 256;
+#X obj 326 270 nbx 5 14 -1e+37 1e+37 0 1 empty empty empty 0 -8 0 10
+-241291 -1 -1 -1000 256;
+#X obj 326 353 #pack;
+#X obj 356 337 nbx 5 14 -1e+37 1e+37 0 1 empty empty empty 0 -8 0 10
+-241291 -1 -1 10333 256;
+#X obj 326 321 nbx 5 14 -1e+37 1e+37 0 1 empty empty empty 0 -8 0 10
+-241291 -1 -1 7000 256;
+#X obj 128 82 t b b;
+#X obj 104 282 gf.oneshot;
+#X obj 127 226 t b b;
+#X obj 13 349 nbx 5 14 -1e+37 1e+37 0 0 empty empty empty 0 -8 0 10
+-225271 -1 -1 0 256;
+#X obj 13 282 gf.oneshot;
+#X obj 31 149 bng 15 250 50 0 empty empty empty 17 7 0 10 -24198 -1
+-1;
+#X obj 31 166 t b b;
+#X obj 123 315 #draw_hpgl;
+#X obj 13 311 #out window;
+#X obj 125 166 f;
+#X obj 150 166 + 1;
+#X obj 125 185 sel;
+#X msg 209 252 600 800 3 b #;
+#X msg 195 294 3 b # 255 255 255;
+#X obj 150 185 % 8;
+#X obj 0 0 doc_h;
+#X obj 3 385 doc_c 0;
+#X obj 3 425 doc_i 1;
+#X obj 3 487 doc_o 2;
+#X obj 14 455 doc_ii 0;
+#X obj 14 517 doc_oo 0;
+#X obj 14 539 doc_oo 1;
+#X obj 0 591 doc_f;
+#X obj 3 571 doc_also;
+#X obj 103 571 plotter_control;
+#X obj 97 539 doc_m o1 float;
+#X text 232 539 unknown bytes;
+#X obj 97 455 doc_m i0 float;
+#X obj 97 517 doc_m o0 <hpgl>;
+#X text 232 455 bytes that are supposed to form HPGL commands;
+#X text 232 517 HPGL commands;
+#X connect 0 0 10 0;
+#X connect 0 0 29 2;
+#X connect 0 1 5 0;
+#X connect 1 0 15 0;
+#X connect 2 0 1 0;
+#X connect 3 0 14 0;
+#X connect 4 0 15 0;
+#X connect 6 0 35 0;
+#X connect 8 0 23 0;
+#X connect 8 0 26 0;
+#X connect 9 0 34 0;
+#X connect 10 0 7 0;
+#X connect 11 0 10 1;
+#X connect 12 0 25 0;
+#X connect 13 0 4 0;
+#X connect 13 0 34 0;
+#X connect 14 0 22 0;
+#X connect 15 0 0 0;
+#X connect 15 1 1 1;
+#X connect 15 1 3 0;
+#X connect 15 1 27 0;
+#X connect 16 0 29 3;
+#X connect 17 0 16 1;
+#X connect 18 0 16 0;
+#X connect 19 0 29 4;
+#X connect 20 0 19 1;
+#X connect 21 0 19 0;
+#X connect 22 0 15 0;
+#X connect 22 1 15 0;
+#X connect 23 0 29 0;
+#X connect 24 0 8 0;
+#X connect 24 1 23 1;
+#X connect 24 1 31 0;
+#X connect 26 0 30 0;
+#X connect 27 0 28 0;
+#X connect 28 0 8 0;
+#X connect 28 1 26 1;
+#X connect 29 0 8 1;
+#X connect 29 1 24 0;
+#X connect 30 0 12 0;
+#X connect 31 0 32 0;
+#X connect 31 0 33 0;
+#X connect 32 0 36 0;
+#X connect 33 0 27 0;
+#X connect 34 0 8 1;
+#X connect 35 0 29 1;
+#X connect 36 0 31 1;
+#X connect 45 1 46 0;
+#X connect 47 1 48 0;
+#X connect 49 1 51 0;
+#X connect 50 1 52 0;
diff --git a/externals/gridflow/doc/flow_classes/range-help.pd b/externals/gridflow/doc/flow_classes/range-help.pd
new file mode 100644
index 00000000..12415511
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/range-help.pd
@@ -0,0 +1,28 @@
+#N canvas 680 0 632 393 10;
+#X obj 0 0 doc_h;
+#X obj 3 99 doc_c 0..;
+#X obj 3 304 doc_o 1..;
+#X obj 14 169 doc_ii 0;
+#X text 232 169 a value to be sent to one of the outlets. The first
+outlet is for values smaller than the first argument \; else the second
+outlet is for values smaller than the second argument \; and so on
+\; and the last outlet is for values greater or equal to the last argument.
+;
+#X obj 14 334 doc_oo any;
+#X obj 97 334 doc_m oany float;
+#X obj 97 169 doc_m i0 float;
+#X obj 3 139 doc_i 1..;
+#X obj 14 169 doc_ii other;
+#X obj 97 270 doc_m iother float;
+#X text 232 270 sets the corresponding separator in the separator list.
+;
+#X obj 0 364 doc_f;
+#X obj 256 53 moses 1;
+#X obj 164 53 range 1 2 3;
+#X text 241 52 =;
+#X obj 306 53 moses 2;
+#X obj 356 53 moses 3;
+#X connect 7 1 4 0;
+#X connect 10 1 11 0;
+#X connect 13 1 16 0;
+#X connect 16 1 17 0;
diff --git a/externals/gridflow/doc/flow_classes/receives-help.pd b/externals/gridflow/doc/flow_classes/receives-help.pd
new file mode 100644
index 00000000..6284c1f9
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/receives-help.pd
@@ -0,0 +1,38 @@
+#N canvas 335 118 632 409 10;
+#X obj 0 0 doc_h;
+#X obj 0 380 doc_f;
+#X obj 3 93 doc_c 0..;
+#X obj 14 123 doc_cc 0;
+#X obj 14 165 doc_cc other;
+#X obj 97 123 doc_m c0 symbol;
+#X obj 97 165 doc_m cother symbol;
+#X text 232 123 the prefix that is going to be common to all receive-symbols.
+if omitted \, the blank symbol will be used (thus no prefix).;
+#X text 232 165 the suffix of each receive symbol that will be registered.
+;
+#X obj 3 195 doc_i 1;
+#X obj 3 296 doc_o 2;
+#X obj 14 225 doc_ii 0;
+#X obj 14 326 doc_oo 0;
+#X obj 14 348 doc_oo 1;
+#X obj 97 225 doc_m i0 list;
+#X text 232 225 list of symbols to register receive-symbols for. they
+will be prefixed. sending such a message unregisters all previous receive-symbols
+registered by this box (which may be reregistered immediately... if
+this is what you're doing);
+#X text 232 326 the message received;
+#X obj 97 326 doc_m o0 <any>;
+#X obj 97 348 doc_m o1 symbol;
+#X text 232 348 the receive-symbol that this message was received as.
+;
+#X obj 85 53 receives \$0- a b c;
+#X text 206 52 =;
+#X obj 223 54 r \$0-a;
+#X obj 265 54 r \$0-b;
+#X obj 307 54 r \$0-c;
+#X text 356 52 and more;
+#X connect 5 1 7 0;
+#X connect 6 1 8 0;
+#X connect 14 1 15 0;
+#X connect 17 1 16 0;
+#X connect 18 1 19 0;
diff --git a/externals/gridflow/doc/flow_classes/route2-help.pd b/externals/gridflow/doc/flow_classes/route2-help.pd
new file mode 100644
index 00000000..c2dceaa5
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/route2-help.pd
@@ -0,0 +1,33 @@
+#N canvas 412 190 632 485 10;
+#X obj 11 140 route2 blah foo bar;
+#X msg 29 39 blah blah blah;
+#X msg 29 62 foo 42;
+#X msg 29 86 bar 3.14159;
+#X obj 140 160 display;
+#X obj 97 180 display;
+#X obj 54 200 display;
+#X obj 12 220 display;
+#X msg 29 114 pas rapport;
+#X text 176 29 just like [route];
+#X text 177 46 but preserves message as-is;
+#X obj 0 0 doc_h;
+#X obj 3 253 doc_c n;
+#X obj 3 313 doc_i 1;
+#X obj 3 373 doc_o n;
+#X obj 14 343 doc_ii 0;
+#X obj 14 403 doc_oo nonlast;
+#X obj 14 426 doc_oo last;
+#X obj 14 283 doc_cc any;
+#X obj 0 456 doc_f;
+#X obj 97 402 doc_m ononlast <any>;
+#X obj 97 426 doc_m olast <any>;
+#X obj 97 343 doc_m i0 <any>;
+#X obj 97 283 doc_m cany symbol;
+#X connect 0 0 7 0;
+#X connect 0 1 6 0;
+#X connect 0 2 5 0;
+#X connect 0 3 4 0;
+#X connect 1 0 0 0;
+#X connect 2 0 0 0;
+#X connect 3 0 0 0;
+#X connect 8 0 0 0;
diff --git a/externals/gridflow/doc/flow_classes/seq_fold-help.pd b/externals/gridflow/doc/flow_classes/seq_fold-help.pd
new file mode 100644
index 00000000..fd21cebf
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/seq_fold-help.pd
@@ -0,0 +1,46 @@
+#N canvas 536 114 632 525 10;
+#X obj 125 126 seq_fold;
+#X msg 125 65 2 \, 3 \, 5 \, 7 \, end;
+#X obj 125 93 route end;
+#X obj 150 150 +;
+#X obj 126 179 display;
+#X obj 0 0 doc_h;
+#X obj 3 222 doc_c 0;
+#X obj 3 262 doc_i 4;
+#X obj 14 292 doc_ii 0;
+#X obj 14 314 doc_ii 1;
+#X obj 14 336 doc_ii 2;
+#X obj 14 358 doc_ii 3;
+#X obj 3 390 doc_o 3;
+#X obj 14 420 doc_oo 0;
+#X obj 14 442 doc_oo 1;
+#X obj 14 464 doc_oo 2;
+#X obj 0 496 doc_f;
+#X obj 97 292 doc_m i0 bang;
+#X obj 97 314 doc_m i1 <any>;
+#X obj 97 336 doc_m i2 <any>;
+#X obj 97 358 doc_m i3 <any>;
+#X obj 97 420 doc_m o0 <any>;
+#X obj 97 442 doc_m o1 <any>;
+#X obj 97 464 doc_m o2 <any>;
+#X text 232 442 to outside left inlet;
+#X text 232 464 to outside right inlet;
+#X text 232 420 final result;
+#X text 232 358 from outside outlet;
+#X text 232 336 seed;
+#X text 232 292 output the final result;
+#X text 232 314 sequence of values to be folded;
+#X connect 0 0 4 0;
+#X connect 0 1 3 0;
+#X connect 0 2 3 1;
+#X connect 1 0 2 0;
+#X connect 2 0 0 0;
+#X connect 2 1 0 1;
+#X connect 3 0 0 3;
+#X connect 17 1 29 0;
+#X connect 18 1 30 0;
+#X connect 19 1 28 0;
+#X connect 20 1 27 0;
+#X connect 21 1 26 0;
+#X connect 22 1 24 0;
+#X connect 23 1 25 0;
diff --git a/externals/gridflow/doc/flow_classes/shunt-help.pd b/externals/gridflow/doc/flow_classes/shunt-help.pd
new file mode 100644
index 00000000..d2828f23
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/shunt-help.pd
@@ -0,0 +1,70 @@
+#N canvas 673 22 632 642 10;
+#X floatatom 121 151 5 0 0 0 - - -;
+#X floatatom 163 151 5 0 0 0 - - -;
+#X floatatom 205 151 5 0 0 0 - - -;
+#X floatatom 247 151 5 0 0 0 - - -;
+#X floatatom 166 85 5 0 0 0 - - -;
+#X obj 210 85 hradio 15 1 0 4 empty empty empty 0 -6 0 8 -260818 -1
+-1 0;
+#X text 272 84 <-- select output here;
+#X text 65 84 vary this -->;
+#X obj 346 119 shunt;
+#X text 232 527 The integer passed to inlet 1 determines which outlet
+is active.;
+#X text 232 602 Outputs incoming message value according to the selector
+value.;
+#X text 7 29 The [shunt] routes any type of data to its active outlet.
+The number of outlets is defined by the argument at creation and the
+active outlet is defined by its right most inlet.;
+#X obj 0 0 doc_h;
+#X obj 3 286 doc_i 2;
+#X obj 3 572 doc_o n;
+#X obj 14 316 doc_ii 0;
+#X obj 14 527 doc_ii 1;
+#X obj 14 602 doc_oo any;
+#X obj 166 114 shunt 4;
+#X text 232 219 Defines the number of outlets desired. If [shunt] is
+created without an argument \, it will have 2 outlets.;
+#X text 232 254 Defines the initial active outlet.;
+#X obj 3 189 doc_c 2;
+#X obj 14 254 doc_cc 1;
+#X obj 14 219 doc_cc 0;
+#X obj 0 647 doc_f;
+#X obj 97 219 doc_m c0 float/int;
+#X obj 97 254 doc_m c1 float/int;
+#X obj 97 527 doc_m i1 float int;
+#X obj 97 602 doc_m oany <any>;
+#X obj 97 338 doc_m i0 index;
+#X obj 97 382 doc_m i0 mode;
+#X obj 97 316 doc_m i0 hi;
+#X obj 97 360 doc_m i0 lo;
+#X text 232 382 -2: going down \, pingpong;
+#X text 232 404 -1: going down \, cycling;
+#X obj 97 492 doc_m i0 <any>;
+#X text 232 426 0: not changing;
+#X text 232 448 1: going up \, cycling;
+#X text 232 470 2: going up \, pingpong;
+#X text 232 338 same as arg 1;
+#X text 232 360 min value for cycling and pingpong (default: 0);
+#X text 232 316 max value for cycling and pingpong (default: N-1);
+#X text 232 492 Incoming message can be Grids \, Symbols \, Floats
+\, Lists \, etc.;
+#X connect 4 0 18 0;
+#X connect 5 0 18 1;
+#X connect 18 0 0 0;
+#X connect 18 1 1 0;
+#X connect 18 2 2 0;
+#X connect 18 3 3 0;
+#X connect 25 1 19 0;
+#X connect 26 1 20 0;
+#X connect 27 1 9 0;
+#X connect 28 1 10 0;
+#X connect 29 1 39 0;
+#X connect 30 1 33 0;
+#X connect 30 1 34 0;
+#X connect 30 1 36 0;
+#X connect 30 1 37 0;
+#X connect 30 1 38 0;
+#X connect 31 1 41 0;
+#X connect 32 1 40 0;
+#X connect 35 1 42 0;
diff --git a/externals/gridflow/doc/flow_classes/systemtime-help.pd b/externals/gridflow/doc/flow_classes/systemtime-help.pd
new file mode 100644
index 00000000..7bcdbd51
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/systemtime-help.pd
@@ -0,0 +1,33 @@
+#N canvas 463 105 632 422 10;
+#X obj 0 0 doc_h;
+#X obj 3 187 doc_c;
+#X obj 0 393 doc_f;
+#X obj 3 373 doc_also;
+#X obj 103 373 cputime;
+#X obj 157 373 systemtime;
+#X text 186 108 What [usertime] and [systemtime] tell you together
+should add up to the amount that [cputime] tells you.;
+#X obj 3 311 doc_o 1;
+#X obj 3 227 doc_i 2;
+#X obj 14 257 doc_ii 0;
+#X obj 14 279 doc_ii 1;
+#X obj 14 341 doc_oo 0;
+#X obj 97 257 doc_m i0 bang;
+#X obj 97 279 doc_m i1 bang;
+#X obj 97 341 doc_m o0 float;
+#X text 232 257 reset timer;
+#X text 232 279 trigger output;
+#X text 232 341 value in milliseconds;
+#X text 188 38 While [cputime] gives you the total time spent in the
+pd process \, therefore excluding any time spent running any other
+programmes \, time spent running pd.tk \, and time spent doing nothing
+at all \, [systemtime] also excludes whatever is NOT run in the kernel.
+;
+#X text 188 142 In C language \, this is the "stime" feature of the
+times() command.;
+#X obj 61 66 systemtime;
+#X connect 3 1 4 0;
+#X connect 3 1 5 0;
+#X connect 12 1 15 0;
+#X connect 13 1 16 0;
+#X connect 14 1 17 0;
diff --git a/externals/gridflow/doc/flow_classes/tsctime-help.pd b/externals/gridflow/doc/flow_classes/tsctime-help.pd
new file mode 100644
index 00000000..e53730a5
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/tsctime-help.pd
@@ -0,0 +1,50 @@
+#N canvas 508 124 632 550 10;
+#X obj 0 0 doc_h;
+#X obj 3 302 doc_c;
+#X obj 0 521 doc_f;
+#X obj 3 501 doc_also;
+#X obj 3 426 doc_o 1;
+#X obj 3 342 doc_i 2;
+#X obj 14 372 doc_ii 0;
+#X obj 14 394 doc_ii 1;
+#X obj 14 456 doc_oo 0;
+#X obj 97 372 doc_m i0 bang;
+#X obj 97 394 doc_m i1 bang;
+#X obj 97 456 doc_m o0 float;
+#X text 232 372 reset timer;
+#X text 232 394 trigger output;
+#X obj 103 501 realtime;
+#X obj 11 96 tsctime;
+#X text 188 38 This is a super-high-resolution version of the [realtime]
+class that does not look at the ordinary clock of the operating system
+\, and instead uses the clock tick of the CPU itself. However \, if
+you have a variable-clock CPU \, this will give you some kind of virtual
+time.;
+#X msg 50 45 bang;
+#X msg 11 45 bang;
+#X floatatom 14 122 10 0 0 0 - - -;
+#X obj 78 100 realtime;
+#X floatatom 78 122 10 0 0 0 - - -;
+#X text 190 114 It's also possible that this has some other bugs related
+to scaling. However \, even if it gives you really weird values \,
+this object will give you very precise values in what is really the
+wrong scale.;
+#X text 192 171 if you are trying to measure real time with this \,
+you should disable any CPU energy saving that may change the CPU's
+clock speed. However \, if you want to measure CPU usage \, [tsctime]
+is the ONLY of the time-objects to allow you to measure CPU usage reliably
+while your clock speed changes.;
+#X text 192 255 in assembly language \, [tsctime] is called "RDTSC"
+\, and this is where [tsctime] got its name from.;
+#X text 232 456 value in "milliseconds" (or lousy imitation thereof...
+see intro text above.);
+#X connect 3 1 14 0;
+#X connect 9 1 12 0;
+#X connect 10 1 13 0;
+#X connect 11 1 25 0;
+#X connect 15 0 19 0;
+#X connect 17 0 15 1;
+#X connect 17 0 20 1;
+#X connect 18 0 15 0;
+#X connect 18 0 20 0;
+#X connect 20 0 21 0;
diff --git a/externals/gridflow/doc/flow_classes/unix_time-help.pd b/externals/gridflow/doc/flow_classes/unix_time-help.pd
new file mode 100644
index 00000000..6e499216
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/unix_time-help.pd
@@ -0,0 +1,50 @@
+#N canvas 679 22 632 619 10;
+#X obj 109 184 unix_time;
+#X obj 109 153 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 26 243 #to_list;
+#X obj 109 111 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0
+1;
+#X obj 27 321 display;
+#X obj 109 129 metro 500;
+#X text 32 302 <-- Ascii format for the date;
+#X obj 326 292 display;
+#X obj 141 242 display;
+#X obj 325 266 display;
+#X obj 324 241 sprintf %04d%02d%02d-%02d%02d%02d;
+#X obj 0 0 doc_h;
+#X obj 3 356 doc_c 0;
+#X obj 3 396 doc_i 1;
+#X obj 3 471 doc_o 3;
+#X obj 14 426 doc_ii 0;
+#X obj 14 501 doc_oo 0;
+#X obj 14 523 doc_oo 1;
+#X obj 14 545 doc_oo 2;
+#X text 9 32 This object returns the Unix timestamp. The first outlet
+does so with ASCII \, the second in seconds and the third outlet outputs
+the fractions of seconds up to 1/100 0 th of a second which is useful
+for creating filenames.;
+#X text 232 426 A bang at the left inlet will tell [unix_time] to get
+the current Unix timestamp and send it to the outlets.;
+#X text 232 501 Outputs the time and date in ASCII format.;
+#X text 232 523 Outputs the Unix timestamp in seconds.;
+#X text 232 545 Outputs the fractions of a second up to 10 microseconds
+(?) (actual precision is probably platform-dependent...);
+#X obj 97 426 doc_m i0 bang;
+#X obj 97 501 doc_m o0 list;
+#X obj 97 523 doc_m o1 list;
+#X obj 97 545 doc_m o2 list;
+#X obj 0 590 doc_f;
+#X connect 0 0 2 0;
+#X connect 0 1 8 0;
+#X connect 0 2 7 0;
+#X connect 0 2 10 0;
+#X connect 1 0 0 0;
+#X connect 2 0 4 0;
+#X connect 3 0 5 0;
+#X connect 5 0 1 0;
+#X connect 10 0 9 0;
+#X connect 24 1 20 0;
+#X connect 25 1 21 0;
+#X connect 26 1 22 0;
+#X connect 27 1 23 0;
diff --git a/externals/gridflow/doc/flow_classes/usertime-help.pd b/externals/gridflow/doc/flow_classes/usertime-help.pd
new file mode 100644
index 00000000..28d52a2c
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/usertime-help.pd
@@ -0,0 +1,33 @@
+#N canvas 508 124 632 412 10;
+#X obj 0 0 doc_h;
+#X obj 3 177 doc_c;
+#X obj 0 383 doc_f;
+#X obj 3 363 doc_also;
+#X obj 103 363 cputime;
+#X obj 157 363 systemtime;
+#X text 186 108 What [usertime] and [systemtime] tell you together
+should add up to the amount that [cputime] tells you.;
+#X obj 3 301 doc_o 1;
+#X obj 3 217 doc_i 2;
+#X obj 14 247 doc_ii 0;
+#X obj 14 269 doc_ii 1;
+#X obj 14 331 doc_oo 0;
+#X obj 97 247 doc_m i0 bang;
+#X obj 97 269 doc_m i1 bang;
+#X obj 97 331 doc_m o0 float;
+#X text 232 247 reset timer;
+#X text 232 269 trigger output;
+#X text 232 331 value in milliseconds;
+#X text 188 142 In C language \, this is the "utime" feature of the
+times() command.;
+#X obj 61 66 usertime;
+#X text 188 38 While [cputime] gives you the total time spent in the
+pd process \, therefore excluding any time spent running any other
+programmes \, time spent running pd.tk \, and time spent doing nothing
+at all \, [systemtime] also excludes whatever is run in the kernel.
+;
+#X connect 3 1 4 0;
+#X connect 3 1 5 0;
+#X connect 12 1 15 0;
+#X connect 13 1 16 0;
+#X connect 14 1 17 0;
diff --git a/externals/gridflow/doc/flow_classes/var.#-help.pd b/externals/gridflow/doc/flow_classes/var.#-help.pd
new file mode 100644
index 00000000..67f921ea
--- /dev/null
+++ b/externals/gridflow/doc/flow_classes/var.#-help.pd
@@ -0,0 +1,21 @@
+#N canvas 335 118 632 407 10;
+#X obj 0 0 doc_h;
+#X obj 0 378 doc_f;
+#X obj 125 58 var.#;
+#X text 189 44 somewhat like [#store] but designed to be most especially
+to grids what [f] is to floats and [symbol] is to symbols.;
+#X obj 3 218 doc_i 2;
+#X obj 3 318 doc_o 1;
+#X text 191 85 it was named that way because if you alias [f] to [var.f]
+\, and [s] to [var.s] \, then [var.\$1] will instantiate an object
+of that class-family. (this is related to the PureUnity project);
+#X obj 14 348 doc_oo 0;
+#X obj 14 288 doc_ii 1;
+#X obj 97 348 doc_m o0 grid;
+#X obj 97 288 doc_m i1 grid;
+#X obj 97 268 doc_m i0 grid;
+#X obj 97 248 doc_m i0 bang;
+#X obj 14 248 doc_ii 0;
+#X obj 14 188 doc_cc 0;
+#X obj 3 158 doc_c 0..1;
+#X obj 97 188 doc_m c0 grid;
diff --git a/externals/gridflow/doc/index.pd b/externals/gridflow/doc/index.pd
new file mode 100644
index 00000000..c508cff9
--- /dev/null
+++ b/externals/gridflow/doc/index.pd
@@ -0,0 +1,329 @@
+#N canvas 0 0 560 480 10 ;
+#X obj 140 50 # +;
+#X text 180 50 plain numeric operators on grids: + - * / etc;
+#X obj -4 82 #apply_colormap_channelwise;
+#X text 180 82 ;
+#X obj 56 114 #background_model;
+#X text 180 114 make mask from learning to distinguish background from foreground;
+#X obj 116 146 #border;
+#X text 180 146 add padding on sides of a grid;
+#X obj 116 178 #camera;
+#X text 180 178 control panel for opening cameras;
+#X obj 116 210 #cast i;
+#X text 180 210 convert grid from one number type to another;
+#X obj 104 242 #centroid;
+#X text 180 242 find centroid (weighted average) of the coordinates of a grid;
+#X obj 116 274 #change;
+#X text 180 274 send grid only if different from previous grid;
+#X obj 104 306 #checkers;
+#X text 180 306 make image of chequered background in two tones of grey;
+#X obj 128 338 #clip;
+#X text 180 338 min and max;
+#X obj 86 370 #cluster_avg;
+#X text 180 370 ;
+#X obj 4 402 #color;
+#X text 180 402 GUI for selecting a colour;
+#X obj 104 474 #contrast;
+#X text 180 474 adjust contrast in two different ways;
+#X obj 104 506 #convolve;
+#X text 180 506 compute convolution product of a grid (blur and edge-detection);
+#X obj 134 538 #dim;
+#X text 180 538 get the size (dimensions) of a grid;
+#X obj 80 570 #downscale_by;
+#X text 180 570 reduce the size of an image by a whole factor;
+#X obj 98 602 #draw_hpgl;
+#X text 180 602 ;
+#X obj 92 634 #draw_image;
+#X text 180 634 picture-in-picture;
+#X obj 86 666 #draw_points;
+#X text 180 666 (future use);
+#X obj 80 698 #draw_polygon;
+#X text 180 698 draw polygon in an image;
+#X obj 98 730 #draw_rect;
+#X text 180 730 draw a rectangle in an image;
+#X obj 86 762 #draw_slider;
+#X text 180 762 draw a slider in an image;
+#X obj 80 794 #edit_polygon;
+#X text 180 794 draw a polygon in an image and react to mouse events;
+#X obj 56 826 #extract_diagonal;
+#X text 180 826 ;
+#X obj 128 858 #fade;
+#X text 180 858 fade in exponential-decay fashion (linear recurrence);
+#X obj 104 890 #fade_lin;
+#X text 180 890 fade in piecewise-linear fashion;
+#X obj 104 922 #fastblur;
+#X text 180 922 speedy shortcut for rectangular blur;
+#X obj 134 954 #fft;
+#X text 180 954 compute forward or inverse one-or-two-dimensional complex FFT of a grid;
+#X obj 104 986 #finished;
+#X text 180 986 bang when grid transmission has ended;
+#X obj 116 1018 #fold +;
+#X text 180 1018 compute the sum of each row \, product of each row, and other similar operations;
+#X obj 98 1050 #for 0 4 1;
+#X text 180 1050 make a grid from all numbers or coordinates in a certain range;
+#X obj 104 1082 #from_pix;
+#X text 180 1082 convert pix (GEM) to grid;
+#X obj 122 1114 #gamma;
+#X text 180 1114 apply gamma correction;
+#X obj 122 1146 #grade;
+#X text 180 1146 make an index of the sorting of a grid;
+#X obj 56 1178 #greyscale_to_rgb;
+#X text 180 1178 convert greyscale to RGB;
+#X obj 122 1210 #hello;
+#X text 180 1210 make 7 colour bars;
+#X obj 104 1242 #hueshift;
+#X text 180 1242 apply hue shift by rotating the color wheel;
+#X obj 116 1274 #import;
+#X text 180 1274 convert float \, list, or symbol ASCII codes, to a grid;
+#X obj 92 1306 #import_pix;
+#X text 180 1306 old name of #from_pix;
+#X obj 140 1338 #in;
+#X text 180 1338 open file or device for reading or download;
+#X obj 122 1370 #inner;
+#X text 180 1370 scalar ("dot") product \, matrix product, tensor contraction, image channel remapping, etc.;
+#X obj 104 1402 #io.aalib;
+#X text 180 1402 open an aalib window;
+#X obj 98 1434 #io.dc1394;
+#X text 180 1434 open a faiawaia "DC" camera (not DV) using a Linux-compatible OS;
+#X obj 110 1466 #io.grid;
+#X text 180 1466 read or write a .grid file (GridFlow storage format);
+#X obj 110 1498 #io.jpeg;
+#X text 180 1498 read or write a .jpeg file;
+#X obj 110 1530 #io.mpeg;
+#X text 180 1530 read a .mpeg video file;
+#X obj 116 1562 #io.png;
+#X text 180 1562 read a .png image file;
+#X obj 116 1594 #io.ppm;
+#X text 180 1594 read or write a .pbm or .pgm or .ppm image file;
+#X obj 80 1626 #io.quicktime;
+#X text 180 1626 read a .mov video file (or perhaps .avi);
+#X obj 116 1658 #io.sdl;
+#X text 180 1658 open a SDL window;
+#X obj 86 1690 #io.videodev;
+#X text 180 1690 open a V4L1 device (Linux interface for video cameras and video digitisers);
+#X obj 116 1722 #io.x11;
+#X text 180 1722 open a X11 window;
+#X obj 128 1754 #join;
+#X text 180 1754 join two grids together along any dimension;
+#X obj 98 1786 #labelling;
+#X text 180 1786 tag connected pixels with region numbers in a two-tone single-channel image;
+#X obj 122 1818 #layer;
+#X text 180 1818 layer two same-sized images;
+#X obj 62 1850 #line_to_polygon;
+#X text 180 1850 convert line (as point pair) to polygon (rotated rectangle);
+#X obj 92 1882 #make_cross;
+#X text 180 1882 make cross-shaped polygon;
+#X obj 116 1914 #moment;
+#X text 180 1914 find 1st or 2nd order moment (weighted average or variance) of the coordinates of a grid;
+#X obj 80 1946 #moment_polar;
+#X text 180 1946 convert covariance matrix to the longest and shortest radius of an ellipse and a rotation angle;
+#X obj 56 1978 #motion_detection;
+#X text 180 1978 frame difference with some options;
+#X obj 122 2010 #mouse;
+#X text 180 2010 converts mouse events to reports of clicks \, drags, unclicks, motions, and separate buttons and wheel;
+#X obj 62 2042 #noise_gate_yuvs;
+#X text 180 2042 replaces dark pixels by black pixels in signed YUV images;
+#X obj 134 2074 #out;
+#X text 180 2074 open file or device for writing or upload;
+#X obj 110 2106 #outer +;
+#X text 180 2106 apply numeric operator on all possible combinations of elements of one grid with elements of another;
+#X obj 128 2138 #pack;
+#X text 180 2138 combine floats on separate inlets to make a grid;
+#X obj 86 2170 #perspective;
+#X text 180 2170 divide each point by its depth;
+#X obj 80 2202 #polygon_area;
+#X text 180 2202 find area of a polygon in square pixels;
+#X obj 44 2234 #polygon_comparator;
+#X text 180 2234 find similarity between two polygons independently of rotation \, by radial maps and FFT;
+#X obj 50 2266 #polygon_each_edge;
+#X text 180 2266 convert a polygon to a sequence of overlapping 2-sided polygons representing edges;
+#X obj 68 2298 #polygon_moment;
+#X text 180 2298 find average of all points inside of a polygon;
+#X obj 50 2330 #polygon_perimetre;
+#X text 180 2330 find perimetre of a polygon in pixels (euclidian);
+#X obj 44 2362 #polygon_radial_map;
+#X text 180 2362 find radius of a polygon from a given origin \, sampled at equally spaced angles;
+#X obj 98 2394 #posterize;
+#X text 180 2394 quantise pixel values;
+#X obj 122 2426 #print;
+#X text 180 2426 print to console;
+#X obj 122 2458 #ravel;
+#X text 180 2458 do #redim so that a grid keeps same number of elements but just one dimension;
+#X obj 116 2490 #record;
+#X text 180 2490 wrapper around [#in quicktime];
+#X obj 104 2522 #redim ();
+#X text 180 2522 change the size of a grid by restreaming contents into a new shape;
+#X obj 92 2554 #reinterval;
+#X text 180 2554 ;
+#X obj 86 2586 #remap_image;
+#X text 180 2586 apply object chain on pixel positions to make new image from chosen pixels of the input image;
+#X obj 110 2618 #reverse;
+#X text 180 2618 mirror image of a grid along a dimension;
+#X obj 56 2650 #rgb_to_greyscale;
+#X text 180 2650 convert RGB to greyscale;
+#X obj 86 2682 #rgb_to_rgba;
+#X text 180 2682 convert RGB to RGBA (but setting alpha to 0);
+#X obj 92 2714 #rgb_to_yuv;
+#X text 180 2714 convert RGB to unsigned YUV;
+#X obj 86 2746 #rgba_to_rgb;
+#X text 180 2746 convert RGBA to RGB;
+#X obj 116 2778 #rotate;
+#X text 180 2778 rotate points through two axes (or rotate pixels as points in a colorspace);
+#X obj 74 2810 #rotatificator;
+#X text 180 2810 make rotation matrix for any two dimensions chosen from a space of any number of dimensions;
+#X obj 92 2842 #saturation;
+#X text 180 2842 multiply chroma by some value;
+#X obj 104 2874 #scale_by;
+#X text 180 2874 reduce the size of an image by a whole factor;
+#X obj 104 2906 #scale_to;
+#X text 180 2906 scale an image from one size to any other size by deleting or duplicating rows and columns;
+#X obj 116 2938 #scan +;
+#X text 180 2938 compute the cumulative sums of each row \, and other similar operations;
+#X obj 104 2970 #seq_fold;
+#X text 180 2970 cascade the use of an object on all elements of an incoming grid message sequence;
+#X obj 122 3002 #slice;
+#X text 180 3002 crop an image using a start point (top left) and end point (bottom right);
+#X obj 104 3034 #solarize;
+#X text 180 3034 like pingpong but on all pixel values of a grid;
+#X obj 128 3066 #sort;
+#X text 180 3066 sort each row of a grid;
+#X obj 116 3098 #spread;
+#X text 180 3098 add noise to each vector (point or pixel);
+#X obj 122 3130 #store;
+#X text 180 3130 store image in RAM \, in-place picture-in-picture, and make lookups in various ways;
+#X obj 128 3162 #swap;
+#X text 180 3162 like [swap] for grids;
+#X obj 140 3194 #t;
+#X text 180 3194 like [t a a] for grids;
+#X obj 74 3226 #text_to_image;
+#X text 180 3226 use a fixed-width font grid to make a tiling of characters as specified by a text string;
+#X obj 104 3258 #to_float;
+#X text 180 3258 convert grid to sequence of floats;
+#X obj 110 3290 #to_list;
+#X text 180 3290 convert grid to list;
+#X obj 92 3322 #to_literal;
+#X text 180 3322 convert grid to grid-literal (list with a # sign);
+#X obj 116 3354 #to_pix;
+#X text 180 3354 convert grid to pix (GEM);
+#X obj 98 3386 #to_symbol;
+#X text 180 3386 convert grid of ASCII codes to symbol;
+#X obj 98 3418 #transpose;
+#X text 180 3418 swap two dimensions out of any \, in a grid;
+#X obj 128 3450 #type;
+#X text 180 3450 get a symbol representing the number type of a grid;
+#X obj 116 3482 #unpack;
+#X text 180 3482 split a grid into floats on separate outlets;
+#X obj 116 3514 #window;
+#X text 180 3514 a [#out window] that can be toggled to appear and disappear;
+#X obj 92 3546 #yuv_to_rgb;
+#X text 180 3546 convert unsigned YUV to RGB;
+#X obj 134 3578 args;
+#X text 180 3578 pick up the arguments of an abstraction instance \, including nested lists and init-messages;
+#X obj 128 3610 ascii;
+#X text 180 3610 write integer as decimal in ascii codes;
+#X obj 98 3642 ascii_to_f;
+#X text 180 3642 converts a list of ascii codes to a float;
+#X obj 86 3674 class_exists;
+#X text 180 3674 figure out whether a class has been loaded by pd;
+#X obj 116 3706 cv/#Add;
+#X text 180 3706 OpenCV addition;
+#X obj 116 3738 cv/#And;
+#X text 180 3738 OpenCV bitwise AND;
+#X obj 74 3770 cv/#ApproxPoly;
+#X text 180 3770 ;
+#X obj 62 3802 cv/#CornerHarris;
+#X text 180 3802 ;
+#X obj 116 3834 cv/#Div;
+#X text 180 3834 OpenCV division;
+#X obj 92 3866 cv/#Ellipse;
+#X text 180 3866 OpenCV draw ellipse;
+#X obj 32 3898 cv/#HaarDetectObjects;
+#X text 180 3898 OpenCV (future use);
+#X obj 98 3930 cv/#Invert;
+#X text 180 3930 OpenCV invert matrix;
+#X obj 98 3962 cv/#KMeans;
+#X text 180 3962 OpenCV K-Means clusteriser;
+#X obj 98 3994 cv/#Kalman;
+#X text 180 3994 OpenCV (future use);
+#X obj 116 4026 cv/#Mul;
+#X text 180 4026 OpenCV multiplication;
+#X obj 122 4058 cv/#Or;
+#X text 180 4058 OpenCV bitwise OR;
+#X obj 116 4090 cv/#SVD;
+#X text 180 4090 OpenCV singular value decomposition (eigendecomposition);
+#X obj 116 4122 cv/#Sub;
+#X text 180 4122 OpenCV subtraction;
+#X obj 116 4154 cv/#Xor;
+#X text 180 4154 OpenCV bitwise XOR;
+#X obj 116 4186 display;
+#X text 180 4186 print message or grid inside of the patch;
+#X obj 122 4218 expect;
+#X text 180 4218 currently does like list.== (will do more than that in the future);
+#X obj 140 4250 for;
+#X text 180 4250 make sequence of float messages for each number in a range with specified stepping;
+#X obj 116 4282 foreach;
+#X text 180 4282 convert a list to a sequence of atom messages;
+#X obj 140 4314 fps;
+#X text 180 4314 measure frames per second and make statistics;
+#X obj 110 4346 gf.error;
+#X text 180 4346 emit error message from the perspective of the current abstraction instance in its parent patch;
+#X obj 74 4378 gf.io_generate;
+#X text 180 4378 for internal use by #in and #out;
+#X obj 98 4410 gf.oneshot;
+#X text 180 4410 spigot that shuts itself down after each message;
+#X obj 62 4442 gf.suffix_lookup;
+#X text 180 4442 find the objectclass corresponding ;
+#X obj 74 4474 hpgl_find_bbox;
+#X text 180 4474 ;
+#X obj 62 4506 hpgl_font_render;
+#X text 180 4506 ;
+#X obj 116 4538 hpgl_op;
+#X text 180 4538 ;
+#X obj 44 4570 hpgl_track_position;
+#X text 180 4570 ;
+#X obj 62 4602 interval_overlap;
+#X text 180 4602 ;
+#X obj 134 4634 inv*;
+#X text 180 4634 swapped /;
+#X obj 134 4666 inv+;
+#X text 180 4666 swapped -;
+#X obj 116 4698 list.==;
+#X text 180 4698 test two lists of floats and/or symbols for equality;
+#X obj 110 4730 listfind;
+#X text 180 4730 find index of an element in a list;
+#X obj 92 4762 listflatten;
+#X text 180 4762 merge all nested lists together \, depth-first;
+#X obj 110 4794 listread;
+#X text 180 4794 find element at an index in a list;
+#X obj 92 4826 listreverse;
+#X text 180 4826 mirror image of a list;
+#X obj 104 4858 norecurse;
+#X text 180 4858 ;
+#X obj 80 4890 parallel_port;
+#X text 180 4890 send to and receive from a DB25 parallel port;
+#X obj 110 4922 pingpong;
+#X text 180 4922 turns value of a counter into a zigzag between 0 and a given value;
+#X obj 68 4954 plotter_control;
+#X text 180 4954 make HPGL commands;
+#X obj 74 4986 plotter_parser;
+#X text 180 4986 interprets ascii codes as HPGL commands and output them as messages;
+#X obj 128 5018 range;
+#X text 180 5018 multiple moses in cascade;
+#X obj 86 5050 receives \$0-;
+#X text 180 5050 multiple receives with common outlet and other outlet telling the name of intended destination;
+#X obj 122 5082 route2;
+#X text 180 5082 route messages but keep them intact (does not remove selector);
+#X obj 110 5114 seq_fold;
+#X text 180 5114 cascade the use of an object on all elements of an incoming message sequence;
+#X obj 128 5146 shunt;
+#X text 180 5146 demultiplexer: send input to separately specified outlet;
+#X obj 98 5178 systemtime;
+#X text 180 5178 time spent by process in kernel mode \, as measured by the OS;
+#X obj 116 5210 tsctime;
+#X text 180 5210 high-resolution real time \, as measured by the CPU;
+#X obj 104 5242 unix_time;
+#X text 180 5242 real time as measured by the OS \, including date;
+#X obj 110 5274 usertime;
+#X text 180 5274 time spent by process in non-kernel mode \, as measured by the OS;
+#X obj 128 5306 var.#;
+#X text 180 5306 like [f] for grids;
diff --git a/externals/gridflow/doc/locale/english.tcl b/externals/gridflow/doc/locale/english.tcl
new file mode 100644
index 00000000..87324620
--- /dev/null
+++ b/externals/gridflow/doc/locale/english.tcl
@@ -0,0 +1,210 @@
+# this file will not contain any aliases, just the canonical names
+
+proc say2 {k v} {
+ say [lindex $k 0] $v
+ foreach kk [lrange $k 1 end] {say $k "old name of $k : $v"}
+}
+
+proc say3 {k v} {
+ set kk [regsub ^# $k @]
+ say2 [list k kk] $v
+}
+
+category "Stuff"
+say # "plain numeric operators on grids: + - * / etc"
+say #border "add padding on sides of a grid"
+say #cast "convert grid from one number type to another"
+say #centroid "find centroid (weighted average) of the coordinates of a grid"
+say #convolve "compute convolution product of a grid (blur and edge-detection)"
+say #dim "get the size (dimensions) of a grid"
+say #downscale_by "reduce the size of an image by a whole factor"
+say #draw_image "picture-in-picture"
+say #draw_points "(future use)"
+
+category "Data Conversion"
+say #to_literal "convert grid to grid-literal (list with a # sign)"
+say #to_float "convert grid to sequence of floats"
+say #to_list "convert grid to list"
+say #to_pix "convert grid to pix (GEM)"
+say #to_symbol "convert grid of ASCII codes to symbol"
+
+category "Stuff"
+say #fft "compute forward or inverse one-or-two-dimensional complex FFT of a grid"
+say #finished "bang when grid transmission has ended"
+say #fold "compute the sum of each row, product of each row, and other similar operations"
+say #for "make a grid from all numbers or coordinates in a certain range"
+say #from_pix "convert pix (GEM) to grid"
+say #import_pix "old name of #from_pix"
+say #grade "make an index of the sorting of a grid"
+say #import "convert float, list, or symbol ASCII codes, to a grid"
+say #inner "scalar (\"dot\") product, matrix product, tensor contraction, image channel remapping, etc."
+
+category "Hardware and Files"
+say #camera "control panel for opening cameras"
+say #io.aalib "open an aalib window"
+say #io.dc1394 "open a faiawaia \"DC\" camera (not DV) using a Linux-compatible OS"
+say #io.grid "read or write a .grid file (GridFlow storage format)"
+say #io.jpeg "read or write a .jpeg file"
+say #io.mpeg "read a .mpeg video file"
+say #io.png "read a .png image file"
+say #io.ppm "read or write a .pbm or .pgm or .ppm image file"
+say #io.quicktime "read a .mov video file (or perhaps .avi)"
+say #io.sdl "open a SDL window"
+say #io.videodev "open a V4L1 device (Linux interface for video cameras and video digitisers)"
+say #io.x11 "open a X11 window"
+say parallel_port "send to and receive from a DB25 parallel port"
+say plotter_control "make HPGL commands"
+
+category "Stuff"
+say #labelling "tag connected pixels with region numbers in a two-tone single-channel image"
+say #layer "layer two same-sized images"
+say #moment "find 1st or 2nd order moment (weighted average or variance) of the coordinates of a grid"
+say #noise_gate_yuvs "replaces dark pixels by black pixels in signed YUV images"
+say #outer "apply numeric operator on all possible combinations of elements of one grid with elements of another"
+say #pack "combine floats on separate inlets to make a grid"
+say #perspective "divide each point by its depth"
+say #polygonize "(future use)"
+say #print "print to console"
+say #redim "change the size of a grid by restreaming contents into a new shape"
+say #reverse "mirror image of a grid along a dimension"
+say #rotatificator "make rotation matrix for any two dimensions chosen from a space of any number of dimensions"
+say #scale_by "reduce the size of an image by a whole factor"
+say #scan "compute the cumulative sums of each row, and other similar operations"
+say #store "store image in RAM, in-place picture-in-picture, and make lookups in various ways"
+say #transpose "swap two dimensions out of any, in a grid"
+say #type "get a symbol representing the number type of a grid"
+say #unpack "split a grid into floats on separate outlets"
+say #join "join two grids together along any dimension"
+
+category "Lists"
+say foreach "convert a list to a sequence of atom messages"
+say listfind "find index of an element in a list"
+say listread "find element at an index in a list"
+say listflatten "merge all nested lists together, depth-first"
+say listreverse "mirror image of a list"
+
+category "Stuff"
+say args "pick up the arguments of an abstraction instance, including nested lists and init-messages"
+say ascii "write integer as decimal in ascii codes"
+say class_exists "figure out whether a class has been loaded by pd"
+say display "print message or grid inside of the patch"
+say gf.error "emit error message from the perspective of the current abstraction instance in its parent patch"
+say gf.suffix_lookup "find the objectclass corresponding "
+say range "multiple moses in cascade"
+say receives "multiple receives with common outlet and other outlet telling the name of intended destination"
+say route2 "route messages but keep them intact (does not remove selector)"
+say send39 "backward-compatibility crutch for dynamic patching in pd 0.39"
+say shunt "demultiplexer: send input to separately specified outlet"
+say systemtime "time spent by process in kernel mode, as measured by the OS"
+say tsctime "high-resolution real time, as measured by the CPU"
+say unix_time "real time as measured by the OS, including date"
+say usertime "time spent by process in non-kernel mode, as measured by the OS"
+
+category "Stuff"
+say #apply_colormap_channelwise "apply color correction tables separately on each channel"
+say #background_model "make mask from learning to distinguish background from foreground"
+say #change "send grid only if different from previous grid"
+say #checkers "make image of chequered background in two tones of grey"
+say #clip "min and max"
+say #color "GUI for selecting a colour"
+say condition "Castonguay rectangle bounds-checking"
+say #contrast "adjust contrast in two different ways"
+say count "Castonguay counter"
+say #fade_lin "fade in piecewise-linear fashion"
+say #fade "fade in exponential-decay fashion (linear recurrence)"
+say #fastblur "speedy shortcut for rectangular blur"
+say for "make sequence of float messages for each number in a range with specified stepping"
+say fps "measure frames per second and make statistics"
+say #gamma "apply gamma correction"
+say gf.io_generate "for internal use by #in and #out"
+say #hueshift "apply hue shift by rotating the color wheel"
+
+say #in "open file or device for reading or download"
+say #out "open file or device for writing or upload"
+
+say inv* "swapped /"
+say inv+ "swapped -"
+
+say #moment_polar "convert covariance matrix to the longest and shortest radius of an ellipse and a rotation angle"
+say #motion_detection "frame difference with some options"
+say #mouse "converts mouse events to reports of clicks, drags, unclicks, motions, and separate buttons and wheel"
+say gf.oneshot "spigot that shuts itself down after each message"
+say pingpong "turns value of a counter into a zigzag between 0 and a given value"
+
+category "Polygons"
+say #polygon_area "find area of a polygon in square pixels"
+say #polygon_comparator "find similarity between two polygons independently of rotation, by radial maps and FFT"
+say #polygon_each_edge "convert a polygon to a sequence of overlapping 2-sided polygons representing edges"
+say #polygon_moment "find average of all points inside of a polygon"
+say #polygon_perimetre "find perimetre of a polygon in pixels (euclidian)"
+say #polygon_radial_map "find radius of a polygon from a given origin, sampled at equally spaced angles"
+say #line_to_polygon "convert line (as point pair) to polygon (rotated rectangle)"
+say #draw_rect "draw a rectangle in an image"
+say #draw_slider "draw a slider in an image"
+say #edit_polygon "draw a polygon in an image and react to mouse events"
+say #make_cross "make cross-shaped polygon"
+say #draw_polygon "draw polygon in an image"
+
+category "Stuff"
+say #posterize "quantise pixel values"
+say #ravel "do #redim so that a grid keeps same number of elements but just one dimension"
+say #record "wrapper around \[#in quicktime\]"
+say #remap_image "apply object chain on pixel positions to make new image from chosen pixels of the input image"
+say #rotate "rotate points through two axes (or rotate pixels as points in a colorspace)"
+say #saturation "multiply chroma by some value"
+say #scale_to "scale an image from one size to any other size by deleting or duplicating rows and columns"
+say #seq_fold "cascade the use of an object on all elements of an incoming grid message sequence"
+say seq_fold "cascade the use of an object on all elements of an incoming message sequence"
+say #slice "crop an image using a start point (top left) and end point (bottom right)"
+say #solarize "like pingpong but on all pixel values of a grid"
+say #sort "sort each row of a grid"
+say #spread "add noise to each vector (point or pixel)"
+say #swap "like \[swap\] for grids"
+say #text_to_image "use a fixed-width font grid to make a tiling of characters as specified by a text string"
+say #t "like \[t a a\] for grids"
+say var.# "like \[f\] for grids"
+
+category "Colorspace Conversion"
+say #rgb_to_yuv "convert RGB to unsigned YUV"
+say #yuv_to_rgb "convert unsigned YUV to RGB"
+say #rgb_to_rgba "convert RGB to RGBA (but setting alpha to 0)"
+say #rgba_to_rgb "convert RGBA to RGB"
+say #greyscale_to_rgb "convert greyscale to RGB"
+say #rgb_to_greyscale "convert RGB to greyscale"
+
+category "OpenCV"
+say cv/#Add "OpenCV addition"
+say cv/#Div "OpenCV division"
+say cv/#Mul "OpenCV multiplication"
+say cv/#Sub "OpenCV subtraction"
+say cv/#And "OpenCV bitwise AND"
+say cv/#Or "OpenCV bitwise OR"
+say cv/#Xor "OpenCV bitwise XOR"
+say cv/#Invert "OpenCV invert matrix"
+say cv/#SVD "OpenCV singular value decomposition (eigendecomposition)"
+say cv/#Ellipse "OpenCV draw ellipse"
+say cv/#KMeans "OpenCV K-Means clusteriser"
+say cv/#HaarDetectObjects "OpenCV (future use)"
+say cv/#Kalman "OpenCV (future use)"
+say cv/#ApproxPoly ""
+say cv/#CornerHarris ""
+
+category "Stuff"
+say ascii_to_f "converts a list of ascii codes to a float"
+say plotter_parser "interprets ascii codes as HPGL commands and output them as messages"
+say list.== "test two lists of floats and/or symbols for equality"
+say expect "currently does like list.== (will do more than that in the future)"
+say #hello "make 7 colour bars"
+say #window "a \[#out window\] that can be toggled to appear and disappear"
+
+say #apply_colormap_channelwise ""
+say #cluster_avg ""
+say #draw_hpgl ""
+say #extract_diagonal ""
+say #reinterval ""
+say hpgl_find_bbox ""
+say hpgl_font_render ""
+say hpgl_op ""
+say hpgl_track_position ""
+say interval_overlap ""
+say norecurse ""
diff --git a/externals/gridflow/doc/make_index.tcl b/externals/gridflow/doc/make_index.tcl
new file mode 100644
index 00000000..8b95003e
--- /dev/null
+++ b/externals/gridflow/doc/make_index.tcl
@@ -0,0 +1,29 @@
+proc say {k v} {set ::say($k) $v}
+proc category {k} {}
+source locale/english.tcl
+puts "#N canvas 0 0 560 480 10 ;"
+set y 50
+foreach k [lsort [array names ::say *]] {
+ set v $::say($k)
+ if {$k == "#"} {set k "# +"}
+ if {$k == "#fold"} {set k "#fold +"}
+ if {$k == "#scan"} {set k "#scan +"}
+ if {$k == "#outer"} {set k "#outer +"}
+ if {$k == "#cast"} {set k "#cast i"}
+ if {$k == "#for"} {set k "#for 0 4 1"}
+ if {$k == "#redim"} {set k "#redim ()"}
+ if {$k == "receives"} {set k "receives \$0-"}
+ if {$k == "send39"} {set k "send39 \$0-patchname"}
+ set w [string length $k]
+ regsub "\\$" $k "\\$" k
+ if {$w<3} {set w 3}
+ set w [expr {$w*6+2}]
+ if {$k == "#color"} {set w 156}
+ puts "#X obj [expr 160-$w] $y $k;"
+ regsub "," $v " \\, " v
+ regsub ";" $v " \\; " v
+ regsub "\\$" $v "\\$" v
+ puts "#X text 180 $y $v;"
+ if {$k == "#color"} {incr y 40}
+ incr y 32
+}
diff --git a/externals/gridflow/doc/moulinette.tcl b/externals/gridflow/doc/moulinette.tcl
new file mode 100644
index 00000000..952459b3
--- /dev/null
+++ b/externals/gridflow/doc/moulinette.tcl
@@ -0,0 +1,215 @@
+#!/usr/bin/env tclsh
+
+proc mset {vars list} {uplevel 1 "foreach {$vars} {$list} {break}"}
+proc p {text} {write [list #X text 10 $::y $text]; incr ::y 60}
+proc write {list} {
+ set v [join $list " "]
+ regsub -all "," $v " \\, " v
+ regsub -all ";" $v " \\; " v
+ regsub -all "\\$" $v "\\$" v
+ puts $::fh "$v;"
+}
+set oid 0
+proc obj {args} {write [concat [list #X obj ] $args]; incr ::oid}
+proc msg {args} {write [concat [list #X msg ] $args]; incr ::oid}
+proc text {args} {write [concat [list #X text] $args]; incr ::oid}
+
+set fh [open numop.pd w]
+write [list #N canvas 0 0 1024 768 10]
+set y 0
+set row 0
+set msgboxes {}
+set col1 96
+set col2 512
+set col3 768
+set col4 1024
+set rowsize 32
+
+obj 0 $y cnv 15 $col4 30 empty empty empty 20 12 0 14 20 -66577 0
+text 10 $y op name
+text $col1 $y description
+text $col2 $y "effect on pixels"
+text $col3 $y "effect on coords"
+incr y 32
+
+# onpixels = meaning in pixel context (pictures, palettes)
+# oncoords = meaning in spatial context (indexmaps, polygons)
+
+# for vecops, the two analogy-columns were labelled:
+# meaning in geometric context (indexmaps, polygons, in which each complex number is a point)
+# meaning in spectrum context (FFT) in which each number is a (cosine,sine) pair
+proc op {op desc {extra1 ""} {extra2 ""}} {
+ global y
+ if {$::row&1} {set bg -233280} {set bg -249792}
+ obj 0 $y cnv 15 $::col4 [expr $::rowsize-2] empty empty empty 20 12 0 14 $bg -66577 0
+ lappend ::msgboxes $::oid
+ msg 10 $y op $op
+ text $::col1 $y $desc
+ if {$extra1 != ""} {text $::col2 $y $extra1}
+ if {$extra2 != ""} {text $::col3 $y $extra2}
+ incr ::row
+ incr ::y $::rowsize
+}
+
+proc draw_columns {} {
+ obj [expr $::col1-1] 0 cnv 0 0 $::y empty empty empty -1 12 0 14 0 -66577 0
+ obj [expr $::col2-1] 0 cnv 0 0 $::y empty empty empty -1 12 0 14 0 -66577 0
+ obj [expr $::col3-1] 0 cnv 0 0 $::y empty empty empty -1 12 0 14 0 -66577 0
+}
+
+proc numbertype {op desc {extra1 ""} {extra2 ""}} {op $op $desc $extra1 $extra2}
+
+set sections {}
+proc section {desc} {
+ lappend ::sections [list $::y $desc]
+ incr ::y 20
+}
+
+section {numops}
+op {ignore} { A } {no effect} {no effect}
+op {put} { B } {replace by} {replace by}
+op {+} { A + B } {brightness, crossfade} {move, morph}
+op {-} { A - B } {brightness, motion detection} {move, motion detection}
+op {inv+} { B - A } {negate then contrast} {180 degree rotate then move}
+op {*} { A * B } {contrast} {zoom out}
+op {/} { A / B, rounded towards zero } {contrast} {zoom in}
+op {div} { A / B, rounded downwards } {contrast} {zoom in}
+op {inv*} { B / A, rounded towards zero }
+op {swapdiv} { B / A, rounded downwards }
+op {%} { A % B, modulo (goes with div) } {--} {tile}
+op {swap%} { B % A, modulo (goes with div) }
+op {rem} { A % B, remainder (goes with /) }
+op {swaprem} { B % A, remainder (goes with /) }
+op {gcd} {greatest common divisor}
+op {lcm} {least common multiple}
+op {|} { A or B, bitwise } {bright munchies} {bottomright munchies}
+op {^} { A xor B, bitwise } {symmetric munchies (fractal checkers)} {symmetric munchies (fractal checkers)}
+op {&} { A and B, bitwise } {dark munchies} {topleft munchies}
+op {<<} { A * (2**(B % 32)), which is left-shifting } {like *} {like *}
+op {>>} { A / (2**(B % 32)), which is right-shifting } {like /,div} {like /,div}
+op {||} { if A is zero then B else A }
+op {&&} { if A is zero then zero else B}
+op {min} { the lowest value in A,B } {clipping} {clipping (of individual points)}
+op {max} { the highest value in A,B } {clipping} {clipping (of individual points)}
+op {cmp} { -1 when A&lt;B; 0 when A=B; 1 when A&gt;B. }
+op {==} { is A equal to B ? 1=true, 0=false }
+op {!=} { is A not equal to B ? }
+op {>} { is A greater than B ? }
+op {<=} { is A not greater than B ? }
+op {<} { is A less than B ? }
+op {>=} {is A not less than B ? }
+op {sin*} { B * sin(A) in centidegrees } {--} {waves, rotations}
+op {cos*} { B * cos(A) in centidegrees } {--} {waves, rotations}
+op {atan} { arctan(A/B) in centidegrees } {--} {find angle to origin (part of polar transform)}
+op {tanh*} { B * tanh(A) in centidegrees } {smooth clipping} {smooth clipping (of individual points), neural sigmoid, fuzzy logic}
+op {log*} { B * log(A) (in base e) }
+op {gamma} { floor(pow(a/256.0,256.0/b)*256.0) } {gamma correction}
+op {**} { A**B, that is, A raised to power B } {gamma correction}
+op {abs-} { absolute value of (A-B) }
+op {rand} { randomly produces a non-negative number below A }
+op {sqrt} { square root of A, rounded downwards }
+op {sq-} { (A-B) times (A-B) }
+op {avg} { (A+B)/2 }
+op {hypot} { distance function: square root of (A*A+B*B) }
+op {clip+} { like A+B but overflow causes clipping instead of wrapping around (coming soon) }
+op {clip-} { like A-B but overflow causes clipping instead of wrapping around (coming soon) }
+op {erf*} { integral of e^(-x*x) dx ... (coming soon; what ought to be the scaling factor?) }
+op {weight} { number of "1" bits in an integer}
+op {sin} {sin(A-B) in radians, float only}
+op {cos} {cos(A-B) in radians, float only}
+op {atan2} {atan2(A,B) in radians, float only}
+op {tanh} {tanh(A-B) in radians, float only}
+op {exp} {exp(A-B) in radians, float only}
+op {log} {log(A-B) in radians, float only}
+
+section {vecops for complex numbers}
+op {C.* } {A*B}
+op {C.*conj} {A*conj(B)}
+op {C./ } {A/B}
+op {C./conj} {A/conj(B)}
+op {C.sq- } {(A-B)*(A-B)}
+op {C.abs- } {abs(A-B)}
+op {C.sin } {sin(A-B)}
+op {C.cos } {cos(A-B)}
+op {C.tanh } {tanh(A-B)}
+op {C.exp } {exp(A-B)}
+op {C.log } {log(A-B)}
+
+#section {vecops for other things}
+#op {cart2pol}
+#op {pol2cart}
+
+incr y 10
+set outletid $oid
+obj 10 $y outlet
+incr y 20
+
+foreach msgbox $msgboxes {write [list #X connect $msgbox 0 $outletid 0]}
+
+draw_columns
+
+foreach section $sections {
+ mset {y1 desc} $section
+ obj 0 $y1 cnv 15 $::col4 18 empty empty empty 20 12 0 14 -248881 -66577 0
+ text 10 $y1 $desc
+}
+
+p {
+ note: a centidegree is 0.01 degree. There are 36000 centidegrees in a circle.
+ Some angle operators use centidegrees, while some others use radians. To
+ convert degrees into centidegrees, multiply by 100.
+ To convert degrees into radians, divide by 57.2957 .
+ Thus, to convert centidegrees into radians, divide by 5729.57 .
+}
+
+close $fh
+set fh [open numtype.pd w]
+write [list #N canvas 0 0 1024 768 10]
+set y 0
+set row 0
+set oid 0
+set col1 192
+set col2 384
+set col3 608
+set col4 1024
+set rowsize 64
+
+obj 0 $y cnv 15 $col4 30 empty empty empty 20 12 0 14 20 -66577 0
+text 10 $y op names
+text $col1 $y range
+text $col2 $y precision
+text $col3 $y description
+incr y 32
+
+numbertype {b u8 uint8} {0 to 255} {1} {
+ unsigned 8-bit integer. this is the usual size of numbers taken from files and cameras, and
+ written to files and to windows. (however #in converts to int32 unless otherwise specified.)}
+numbertype {s i16 int16} {-32768 to 32767} {1}
+numbertype {i i32 int32} {-(1<<31) to (1<<31)-1} {1} {
+ signed 32-bit integer. this is used by default throughout GridFlow.
+}
+numbertype {l i64 int64} {-(1<<63) to (1<<63)-1} {1}
+numbertype {f f32 float32} {-(1<<128) to (1<<128)} {23 bits or 0.000012%}
+numbertype {d f64 float64} {-(1<<2048) to (1<<2048)} {52 bits or 0.000000000000022%}
+
+draw_columns
+
+p {High-performance computation requires precise and quite peculiar
+ definitions of numbers and their representation.}
+p {Inside most programs, numbers are written down as strings of
+ bits. A bit is either zero or one. Just like the decimal system
+ uses units, tens, hundreds, the binary system uses units, twos,
+ fours, eights, sixteens, and so on, doubling every time.}
+p {One notation, called integer allows for only integer values to be
+ written (no fractions). when it is unsigned, no negative values may
+ be written. when it is signed, one bit indicates whether the number
+ is positive or negative. Integer storage is usually fixed-size, so you have
+ bounds on the size of numbers, and if a result is too big it "wraps around", truncating the biggest
+ bits.}
+p {Another notation, called floating point (or float) stores numbers using
+ a fixed number of significant digits, and a scale factor that allows for huge numbers
+ and tiny fractions at once. Note that 1/3 has periodic digits, but even 0.1 has periodic digits,
+ in binary coding; so expect some slight roundings; the precision offered should be
+ sufficient for most purposes. Make sure the errors of rounding don't accumulate, though.}
+
+close $fh
diff --git a/externals/gridflow/doc/numop.pd b/externals/gridflow/doc/numop.pd
new file mode 100644
index 00000000..c1d8efbf
--- /dev/null
+++ b/externals/gridflow/doc/numop.pd
@@ -0,0 +1,327 @@
+#N canvas 0 0 1024 768 10;
+#X obj 0 0 cnv 15 1024 30 empty empty empty 20 12 0 14 20 -66577 0;
+#X text 10 0 op name;
+#X text 96 0 description;
+#X text 512 0 effect on pixels;
+#X text 768 0 effect on coords;
+#X obj 0 52 cnv 15 1024 30 empty empty empty 20 12 0 14 -249792 -66577 0;
+#X msg 10 52 op ignore;
+#X text 96 52 A ;
+#X text 512 52 no effect;
+#X text 768 52 no effect;
+#X obj 0 84 cnv 15 1024 30 empty empty empty 20 12 0 14 -233280 -66577 0;
+#X msg 10 84 op put;
+#X text 96 84 B ;
+#X text 512 84 replace by;
+#X text 768 84 replace by;
+#X obj 0 116 cnv 15 1024 30 empty empty empty 20 12 0 14 -249792 -66577 0;
+#X msg 10 116 op +;
+#X text 96 116 A + B ;
+#X text 512 116 brightness \, crossfade;
+#X text 768 116 move \, morph;
+#X obj 0 148 cnv 15 1024 30 empty empty empty 20 12 0 14 -233280 -66577 0;
+#X msg 10 148 op -;
+#X text 96 148 A - B ;
+#X text 512 148 brightness \, motion detection;
+#X text 768 148 move \, motion detection;
+#X obj 0 180 cnv 15 1024 30 empty empty empty 20 12 0 14 -249792 -66577 0;
+#X msg 10 180 op inv+;
+#X text 96 180 B - A ;
+#X text 512 180 negate then contrast;
+#X text 768 180 180 degree rotate then move;
+#X obj 0 212 cnv 15 1024 30 empty empty empty 20 12 0 14 -233280 -66577 0;
+#X msg 10 212 op *;
+#X text 96 212 A * B ;
+#X text 512 212 contrast;
+#X text 768 212 zoom out;
+#X obj 0 244 cnv 15 1024 30 empty empty empty 20 12 0 14 -249792 -66577 0;
+#X msg 10 244 op /;
+#X text 96 244 A / B \, rounded towards zero ;
+#X text 512 244 contrast;
+#X text 768 244 zoom in;
+#X obj 0 276 cnv 15 1024 30 empty empty empty 20 12 0 14 -233280 -66577 0;
+#X msg 10 276 op div;
+#X text 96 276 A / B \, rounded downwards ;
+#X text 512 276 contrast;
+#X text 768 276 zoom in;
+#X obj 0 308 cnv 15 1024 30 empty empty empty 20 12 0 14 -249792 -66577 0;
+#X msg 10 308 op inv*;
+#X text 96 308 B / A \, rounded towards zero ;
+#X obj 0 340 cnv 15 1024 30 empty empty empty 20 12 0 14 -233280 -66577 0;
+#X msg 10 340 op swapdiv;
+#X text 96 340 B / A \, rounded downwards ;
+#X obj 0 372 cnv 15 1024 30 empty empty empty 20 12 0 14 -249792 -66577 0;
+#X msg 10 372 op %;
+#X text 96 372 A % B \, modulo (goes with div) ;
+#X text 512 372 --;
+#X text 768 372 tile;
+#X obj 0 404 cnv 15 1024 30 empty empty empty 20 12 0 14 -233280 -66577 0;
+#X msg 10 404 op swap%;
+#X text 96 404 B % A \, modulo (goes with div) ;
+#X obj 0 436 cnv 15 1024 30 empty empty empty 20 12 0 14 -249792 -66577 0;
+#X msg 10 436 op rem;
+#X text 96 436 A % B \, remainder (goes with /) ;
+#X obj 0 468 cnv 15 1024 30 empty empty empty 20 12 0 14 -233280 -66577 0;
+#X msg 10 468 op swaprem;
+#X text 96 468 B % A \, remainder (goes with /) ;
+#X obj 0 500 cnv 15 1024 30 empty empty empty 20 12 0 14 -249792 -66577 0;
+#X msg 10 500 op gcd;
+#X text 96 500 greatest common divisor;
+#X obj 0 532 cnv 15 1024 30 empty empty empty 20 12 0 14 -233280 -66577 0;
+#X msg 10 532 op lcm;
+#X text 96 532 least common multiple;
+#X obj 0 564 cnv 15 1024 30 empty empty empty 20 12 0 14 -249792 -66577 0;
+#X msg 10 564 op |;
+#X text 96 564 A or B \, bitwise ;
+#X text 512 564 bright munchies;
+#X text 768 564 bottomright munchies;
+#X obj 0 596 cnv 15 1024 30 empty empty empty 20 12 0 14 -233280 -66577 0;
+#X msg 10 596 op ^;
+#X text 96 596 A xor B \, bitwise ;
+#X text 512 596 symmetric munchies (fractal checkers);
+#X text 768 596 symmetric munchies (fractal checkers);
+#X obj 0 628 cnv 15 1024 30 empty empty empty 20 12 0 14 -249792 -66577 0;
+#X msg 10 628 op &;
+#X text 96 628 A and B \, bitwise ;
+#X text 512 628 dark munchies;
+#X text 768 628 topleft munchies;
+#X obj 0 660 cnv 15 1024 30 empty empty empty 20 12 0 14 -233280 -66577 0;
+#X msg 10 660 op <<;
+#X text 96 660 A * (2**(B % 32)) \, which is left-shifting ;
+#X text 512 660 like *;
+#X text 768 660 like *;
+#X obj 0 692 cnv 15 1024 30 empty empty empty 20 12 0 14 -249792 -66577 0;
+#X msg 10 692 op >>;
+#X text 96 692 A / (2**(B % 32)) \, which is right-shifting ;
+#X text 512 692 like / \, div;
+#X text 768 692 like / \, div;
+#X obj 0 724 cnv 15 1024 30 empty empty empty 20 12 0 14 -233280 -66577 0;
+#X msg 10 724 op ||;
+#X text 96 724 if A is zero then B else A ;
+#X obj 0 756 cnv 15 1024 30 empty empty empty 20 12 0 14 -249792 -66577 0;
+#X msg 10 756 op &&;
+#X text 96 756 if A is zero then zero else B;
+#X obj 0 788 cnv 15 1024 30 empty empty empty 20 12 0 14 -233280 -66577 0;
+#X msg 10 788 op min;
+#X text 96 788 the lowest value in A \, B ;
+#X text 512 788 clipping;
+#X text 768 788 clipping (of individual points);
+#X obj 0 820 cnv 15 1024 30 empty empty empty 20 12 0 14 -249792 -66577 0;
+#X msg 10 820 op max;
+#X text 96 820 the highest value in A \, B ;
+#X text 512 820 clipping;
+#X text 768 820 clipping (of individual points);
+#X obj 0 852 cnv 15 1024 30 empty empty empty 20 12 0 14 -233280 -66577 0;
+#X msg 10 852 op cmp;
+#X text 96 852 -1 when A&lt \; B \; 0 when A=B \; 1 when A&gt \; B. ;
+#X obj 0 884 cnv 15 1024 30 empty empty empty 20 12 0 14 -249792 -66577 0;
+#X msg 10 884 op ==;
+#X text 96 884 is A equal to B ? 1=true \, 0=false ;
+#X obj 0 916 cnv 15 1024 30 empty empty empty 20 12 0 14 -233280 -66577 0;
+#X msg 10 916 op !=;
+#X text 96 916 is A not equal to B ? ;
+#X obj 0 948 cnv 15 1024 30 empty empty empty 20 12 0 14 -249792 -66577 0;
+#X msg 10 948 op >;
+#X text 96 948 is A greater than B ? ;
+#X obj 0 980 cnv 15 1024 30 empty empty empty 20 12 0 14 -233280 -66577 0;
+#X msg 10 980 op <=;
+#X text 96 980 is A not greater than B ? ;
+#X obj 0 1012 cnv 15 1024 30 empty empty empty 20 12 0 14 -249792 -66577 0;
+#X msg 10 1012 op <;
+#X text 96 1012 is A less than B ? ;
+#X obj 0 1044 cnv 15 1024 30 empty empty empty 20 12 0 14 -233280 -66577 0;
+#X msg 10 1044 op >=;
+#X text 96 1044 is A not less than B ? ;
+#X obj 0 1076 cnv 15 1024 30 empty empty empty 20 12 0 14 -249792 -66577 0;
+#X msg 10 1076 op sin*;
+#X text 96 1076 B * sin(A) in centidegrees ;
+#X text 512 1076 --;
+#X text 768 1076 waves \, rotations;
+#X obj 0 1108 cnv 15 1024 30 empty empty empty 20 12 0 14 -233280 -66577 0;
+#X msg 10 1108 op cos*;
+#X text 96 1108 B * cos(A) in centidegrees ;
+#X text 512 1108 --;
+#X text 768 1108 waves \, rotations;
+#X obj 0 1140 cnv 15 1024 30 empty empty empty 20 12 0 14 -249792 -66577 0;
+#X msg 10 1140 op atan;
+#X text 96 1140 arctan(A/B) in centidegrees ;
+#X text 512 1140 --;
+#X text 768 1140 find angle to origin (part of polar transform);
+#X obj 0 1172 cnv 15 1024 30 empty empty empty 20 12 0 14 -233280 -66577 0;
+#X msg 10 1172 op tanh*;
+#X text 96 1172 B * tanh(A) in centidegrees ;
+#X text 512 1172 smooth clipping;
+#X text 768 1172 smooth clipping (of individual points) \, neural sigmoid \, fuzzy logic;
+#X obj 0 1204 cnv 15 1024 30 empty empty empty 20 12 0 14 -249792 -66577 0;
+#X msg 10 1204 op log*;
+#X text 96 1204 B * log(A) (in base e) ;
+#X obj 0 1236 cnv 15 1024 30 empty empty empty 20 12 0 14 -233280 -66577 0;
+#X msg 10 1236 op gamma;
+#X text 96 1236 floor(pow(a/256.0 \, 256.0/b)*256.0) ;
+#X text 512 1236 gamma correction;
+#X obj 0 1268 cnv 15 1024 30 empty empty empty 20 12 0 14 -249792 -66577 0;
+#X msg 10 1268 op **;
+#X text 96 1268 A**B \, that is \, A raised to power B ;
+#X text 512 1268 gamma correction;
+#X obj 0 1300 cnv 15 1024 30 empty empty empty 20 12 0 14 -233280 -66577 0;
+#X msg 10 1300 op abs-;
+#X text 96 1300 absolute value of (A-B) ;
+#X obj 0 1332 cnv 15 1024 30 empty empty empty 20 12 0 14 -249792 -66577 0;
+#X msg 10 1332 op rand;
+#X text 96 1332 randomly produces a non-negative number below A ;
+#X obj 0 1364 cnv 15 1024 30 empty empty empty 20 12 0 14 -233280 -66577 0;
+#X msg 10 1364 op sqrt;
+#X text 96 1364 square root of A \, rounded downwards ;
+#X obj 0 1396 cnv 15 1024 30 empty empty empty 20 12 0 14 -249792 -66577 0;
+#X msg 10 1396 op sq-;
+#X text 96 1396 (A-B) times (A-B) ;
+#X obj 0 1428 cnv 15 1024 30 empty empty empty 20 12 0 14 -233280 -66577 0;
+#X msg 10 1428 op avg;
+#X text 96 1428 (A+B)/2 ;
+#X obj 0 1460 cnv 15 1024 30 empty empty empty 20 12 0 14 -249792 -66577 0;
+#X msg 10 1460 op hypot;
+#X text 96 1460 distance function: square root of (A*A+B*B) ;
+#X obj 0 1492 cnv 15 1024 30 empty empty empty 20 12 0 14 -233280 -66577 0;
+#X msg 10 1492 op clip+;
+#X text 96 1492 like A+B but overflow causes clipping instead of wrapping around (coming soon) ;
+#X obj 0 1524 cnv 15 1024 30 empty empty empty 20 12 0 14 -249792 -66577 0;
+#X msg 10 1524 op clip-;
+#X text 96 1524 like A-B but overflow causes clipping instead of wrapping around (coming soon) ;
+#X obj 0 1556 cnv 15 1024 30 empty empty empty 20 12 0 14 -233280 -66577 0;
+#X msg 10 1556 op erf*;
+#X text 96 1556 integral of e^(-x*x) dx ... (coming soon \; what ought to be the scaling factor?) ;
+#X obj 0 1588 cnv 15 1024 30 empty empty empty 20 12 0 14 -249792 -66577 0;
+#X msg 10 1588 op weight;
+#X text 96 1588 number of "1" bits in an integer;
+#X obj 0 1620 cnv 15 1024 30 empty empty empty 20 12 0 14 -233280 -66577 0;
+#X msg 10 1620 op sin;
+#X text 96 1620 sin(A-B) in radians \, float only;
+#X obj 0 1652 cnv 15 1024 30 empty empty empty 20 12 0 14 -249792 -66577 0;
+#X msg 10 1652 op cos;
+#X text 96 1652 cos(A-B) in radians \, float only;
+#X obj 0 1684 cnv 15 1024 30 empty empty empty 20 12 0 14 -233280 -66577 0;
+#X msg 10 1684 op atan2;
+#X text 96 1684 atan2(A \, B) in radians \, float only;
+#X obj 0 1716 cnv 15 1024 30 empty empty empty 20 12 0 14 -249792 -66577 0;
+#X msg 10 1716 op tanh;
+#X text 96 1716 tanh(A-B) in radians \, float only;
+#X obj 0 1748 cnv 15 1024 30 empty empty empty 20 12 0 14 -233280 -66577 0;
+#X msg 10 1748 op exp;
+#X text 96 1748 exp(A-B) in radians \, float only;
+#X obj 0 1780 cnv 15 1024 30 empty empty empty 20 12 0 14 -249792 -66577 0;
+#X msg 10 1780 op log;
+#X text 96 1780 log(A-B) in radians \, float only;
+#X obj 0 1832 cnv 15 1024 30 empty empty empty 20 12 0 14 -233280 -66577 0;
+#X msg 10 1832 op C.* ;
+#X text 96 1832 A*B;
+#X obj 0 1864 cnv 15 1024 30 empty empty empty 20 12 0 14 -249792 -66577 0;
+#X msg 10 1864 op C.*conj;
+#X text 96 1864 A*conj(B);
+#X obj 0 1896 cnv 15 1024 30 empty empty empty 20 12 0 14 -233280 -66577 0;
+#X msg 10 1896 op C./ ;
+#X text 96 1896 A/B;
+#X obj 0 1928 cnv 15 1024 30 empty empty empty 20 12 0 14 -249792 -66577 0;
+#X msg 10 1928 op C./conj;
+#X text 96 1928 A/conj(B);
+#X obj 0 1960 cnv 15 1024 30 empty empty empty 20 12 0 14 -233280 -66577 0;
+#X msg 10 1960 op C.sq- ;
+#X text 96 1960 (A-B)*(A-B);
+#X obj 0 1992 cnv 15 1024 30 empty empty empty 20 12 0 14 -249792 -66577 0;
+#X msg 10 1992 op C.abs- ;
+#X text 96 1992 abs(A-B);
+#X obj 0 2024 cnv 15 1024 30 empty empty empty 20 12 0 14 -233280 -66577 0;
+#X msg 10 2024 op C.sin ;
+#X text 96 2024 sin(A-B);
+#X obj 0 2056 cnv 15 1024 30 empty empty empty 20 12 0 14 -249792 -66577 0;
+#X msg 10 2056 op C.cos ;
+#X text 96 2056 cos(A-B);
+#X obj 0 2088 cnv 15 1024 30 empty empty empty 20 12 0 14 -233280 -66577 0;
+#X msg 10 2088 op C.tanh ;
+#X text 96 2088 tanh(A-B);
+#X obj 0 2120 cnv 15 1024 30 empty empty empty 20 12 0 14 -249792 -66577 0;
+#X msg 10 2120 op C.exp ;
+#X text 96 2120 exp(A-B);
+#X obj 0 2152 cnv 15 1024 30 empty empty empty 20 12 0 14 -233280 -66577 0;
+#X msg 10 2152 op C.log ;
+#X text 96 2152 log(A-B);
+#X obj 10 2194 outlet;
+#X connect 6 0 245 0;
+#X connect 11 0 245 0;
+#X connect 16 0 245 0;
+#X connect 21 0 245 0;
+#X connect 26 0 245 0;
+#X connect 31 0 245 0;
+#X connect 36 0 245 0;
+#X connect 41 0 245 0;
+#X connect 46 0 245 0;
+#X connect 49 0 245 0;
+#X connect 52 0 245 0;
+#X connect 57 0 245 0;
+#X connect 60 0 245 0;
+#X connect 63 0 245 0;
+#X connect 66 0 245 0;
+#X connect 69 0 245 0;
+#X connect 72 0 245 0;
+#X connect 77 0 245 0;
+#X connect 82 0 245 0;
+#X connect 87 0 245 0;
+#X connect 92 0 245 0;
+#X connect 97 0 245 0;
+#X connect 100 0 245 0;
+#X connect 103 0 245 0;
+#X connect 108 0 245 0;
+#X connect 113 0 245 0;
+#X connect 116 0 245 0;
+#X connect 119 0 245 0;
+#X connect 122 0 245 0;
+#X connect 125 0 245 0;
+#X connect 128 0 245 0;
+#X connect 131 0 245 0;
+#X connect 134 0 245 0;
+#X connect 139 0 245 0;
+#X connect 144 0 245 0;
+#X connect 149 0 245 0;
+#X connect 154 0 245 0;
+#X connect 157 0 245 0;
+#X connect 161 0 245 0;
+#X connect 165 0 245 0;
+#X connect 168 0 245 0;
+#X connect 171 0 245 0;
+#X connect 174 0 245 0;
+#X connect 177 0 245 0;
+#X connect 180 0 245 0;
+#X connect 183 0 245 0;
+#X connect 186 0 245 0;
+#X connect 189 0 245 0;
+#X connect 192 0 245 0;
+#X connect 195 0 245 0;
+#X connect 198 0 245 0;
+#X connect 201 0 245 0;
+#X connect 204 0 245 0;
+#X connect 207 0 245 0;
+#X connect 210 0 245 0;
+#X connect 213 0 245 0;
+#X connect 216 0 245 0;
+#X connect 219 0 245 0;
+#X connect 222 0 245 0;
+#X connect 225 0 245 0;
+#X connect 228 0 245 0;
+#X connect 231 0 245 0;
+#X connect 234 0 245 0;
+#X connect 237 0 245 0;
+#X connect 240 0 245 0;
+#X connect 243 0 245 0;
+#X obj 95 0 cnv 0 0 2214 empty empty empty -1 12 0 14 0 -66577 0;
+#X obj 511 0 cnv 0 0 2214 empty empty empty -1 12 0 14 0 -66577 0;
+#X obj 767 0 cnv 0 0 2214 empty empty empty -1 12 0 14 0 -66577 0;
+#X obj 0 32 cnv 15 1024 18 empty empty empty 20 12 0 14 -248881 -66577 0;
+#X text 10 32 numops;
+#X obj 0 1812 cnv 15 1024 18 empty empty empty 20 12 0 14 -248881 -66577 0;
+#X text 10 1812 vecops for complex numbers;
+#X text 10 2214
+ note: a centidegree is 0.01 degree. There are 36000 centidegrees in a circle.
+ Some angle operators use centidegrees \, while some others use radians. To
+ convert degrees into centidegrees \, multiply by 100.
+ To convert degrees into radians \, divide by 57.2957 .
+ Thus \, to convert centidegrees into radians \, divide by 5729.57 .
+;
diff --git a/externals/gridflow/doc/numtype.pd b/externals/gridflow/doc/numtype.pd
new file mode 100644
index 00000000..ce1cdc2f
--- /dev/null
+++ b/externals/gridflow/doc/numtype.pd
@@ -0,0 +1,56 @@
+#N canvas 0 0 1024 768 10;
+#X obj 0 0 cnv 15 1024 30 empty empty empty 20 12 0 14 20 -66577 0;
+#X text 10 0 op names;
+#X text 192 0 range;
+#X text 384 0 precision;
+#X text 608 0 description;
+#X obj 0 32 cnv 15 1024 62 empty empty empty 20 12 0 14 -249792 -66577 0;
+#X msg 10 32 op b u8 uint8;
+#X text 192 32 0 to 255;
+#X text 384 32 1;
+#X text 608 32
+ unsigned 8-bit integer. this is the usual size of numbers taken from files and cameras \, and
+ written to files and to windows. (however #in converts to int32 unless otherwise specified.);
+#X obj 0 96 cnv 15 1024 62 empty empty empty 20 12 0 14 -233280 -66577 0;
+#X msg 10 96 op s i16 int16;
+#X text 192 96 -32768 to 32767;
+#X text 384 96 1;
+#X obj 0 160 cnv 15 1024 62 empty empty empty 20 12 0 14 -249792 -66577 0;
+#X msg 10 160 op i i32 int32;
+#X text 192 160 -(1<<31) to (1<<31)-1;
+#X text 384 160 1;
+#X text 608 160
+ signed 32-bit integer. this is used by default throughout GridFlow.
+;
+#X obj 0 224 cnv 15 1024 62 empty empty empty 20 12 0 14 -233280 -66577 0;
+#X msg 10 224 op l i64 int64;
+#X text 192 224 -(1<<63) to (1<<63)-1;
+#X text 384 224 1;
+#X obj 0 288 cnv 15 1024 62 empty empty empty 20 12 0 14 -249792 -66577 0;
+#X msg 10 288 op f f32 float32;
+#X text 192 288 -(1<<128) to (1<<128);
+#X text 384 288 23 bits or 0.000012%;
+#X obj 0 352 cnv 15 1024 62 empty empty empty 20 12 0 14 -233280 -66577 0;
+#X msg 10 352 op d f64 float64;
+#X text 192 352 -(1<<2048) to (1<<2048);
+#X text 384 352 52 bits or 0.000000000000022%;
+#X obj 191 0 cnv 0 0 416 empty empty empty -1 12 0 14 0 -66577 0;
+#X obj 383 0 cnv 0 0 416 empty empty empty -1 12 0 14 0 -66577 0;
+#X obj 607 0 cnv 0 0 416 empty empty empty -1 12 0 14 0 -66577 0;
+#X text 10 416 High-performance computation requires precise and quite peculiar
+ definitions of numbers and their representation.;
+#X text 10 476 Inside most programs \, numbers are written down as strings of
+ bits. A bit is either zero or one. Just like the decimal system
+ uses units \, tens \, hundreds \, the binary system uses units \, twos \,
+ fours \, eights \, sixteens \, and so on \, doubling every time.;
+#X text 10 536 One notation \, called integer allows for only integer values to be
+ written (no fractions). when it is unsigned \, no negative values may
+ be written. when it is signed \, one bit indicates whether the number
+ is positive or negative. Integer storage is usually fixed-size \, so you have
+ bounds on the size of numbers \, and if a result is too big it "wraps around" \, truncating the biggest
+ bits.;
+#X text 10 596 Another notation \, called floating point (or float) stores numbers using
+ a fixed number of significant digits \, and a scale factor that allows for huge numbers
+ and tiny fractions at once. Note that 1/3 has periodic digits \, but even 0.1 has periodic digits \,
+ in binary coding \; so expect some slight roundings \; the precision offered should be
+ sufficient for most purposes. Make sure the errors of rounding don't accumulate \, though.;
diff --git a/externals/gridflow/doc/stuff.txt b/externals/gridflow/doc/stuff.txt
new file mode 100644
index 00000000..2a495735
--- /dev/null
+++ b/externals/gridflow/doc/stuff.txt
@@ -0,0 +1,144 @@
+Grid Literals
+ In every grid-accepting inlet, a list may be sent instead; if
+ it consists only of integers, it will be converted to a
+ one-dimensional grid. Else it may contain a single "#" sign and
+ integers on both sides of it, where the ones to the left of it are
+ fed as arguments to an imaginary [#redim] object and the one to the
+ right of it are fed through that [#redim].
+ In every grid-accepting inlet, an integer or float may also be sent;
+ it will be converted to a zero-dimensional grid (a scalar).
+
+Grid Protocol
+ a grid has an associated number type that defines what are the possible values for its elements
+ (and how much space it takes). the default is int32.
+ a single-dimensional grid of 3 elements (a triplet) is called dim(3). a
+ three-dimensional grid of 240 rows of 320 columns of triplets is called
+ dim(240,320,3).
+ There is a sequence in which elements of a Grid are stored and
+ transmitted. Dimension 0 is called "first" and dimension N-1 is
+ called "last". They are called so because if you select a
+ position in the first dimension of a grid, the selected part is of the same
+ shape minus the first dimension; so in dim(240,320,3) if you select
+ row 51 (or whichever valid row number), you get a dim(320,3). if you select
+ a subpart two more times you get to a single number.
+ At each such level, elements are sent/stored in their numeric order,
+ and are numbered using natural numbers starting at 0. This ordering usually
+ does not matter, but sometimes it does. Most notably, [#import], [#export] and [#redim] care about it.
+ On the other hand, order of dimensions usually does matter; this is
+ what distinguishes rows from columns and channels, for example.
+ Most objects care about the distinction.
+ A grid with only 1 element in a given dimension is different from one
+ lacking that dimension; it won't have the same meaning. You can use this
+ property to your advantage sometimes.
+ Zero-dimensional grids exist. They are called dim(). They can only contain
+ a single number.
+Picture Protocol
+ This section is useful if you want to know what a picture is in terms of a grid.
+ A picture is a three-dimensional Grid: 0:rows 1:columns 2:channels
+
+Channels for the RGB color model are: 0:red 1:green 2:blue
+ Because Grids are made of 32-bit integers, a three-channel picture uses
+ 96 bpp (bits per pixel), and have to be downscaled to 24 bpp (or 16 bpp)
+ for display. That huge amount of slack is there because when you create
+ your own effects you often have intermediate results that need to be of
+ higher precision than a normal picture. Especially, results of multiplications
+ are big and should not overflow before you divide them back to normal;
+ and similarly, you can have negative values all over, as long as you take
+ care of them before they get to the display.
+ In the final conversion, high bits are just ignored. This means: black is
+ 0, maximum is 255, and values wrap like with % 256. If you want to
+ clip them, you may use [# max 0] and [# min 255] objects.
+
+The following are called VecOps because each operation happens between more than just two numbers.
+A first kind of VecOp are those that arise when a pair of numbers (A0,A1) is considered as a single number A0+A1*sqrt(-1).
+If you need complex numbers but don't know yet how they work, learn them using a math tutorial and then those VecOps will begin to seem familiar.
+All the complex number operators are only for floats.
+TODO: fill the last two columns of this table.
+
+Synchronisation
+
+In GridFlow you cannot send two grids in different inlets at the
+same time. You have to use [#finished] together with (possibly) [fork] and [#store],
+which can be cumbersome. If you don't do this, the result is undefined
+behaviour (or crash!).
+There are two exceptions: [#store] and # allow right-inlet grids to be buffered if an operation is occuring on left inlet. This
+should make many programs simpler.
+
+
+Introduction
+
+ The philosophy that guides PureData is a simple but powerful one:
+ the software must first provide the user with generic tools
+ rather than imposing pre-cooked effects. In other words the user
+ should have total freedom.
+
+ GridFlow follows that philosophy: it first defines elementary
+ mathematical operations. Those can in turn be used as simple
+ visual effects or be combined to produce more complex effects.
+
+ The strategy followed by most video plugins for PureData and MAX/MSP, is
+ to provide the user first with constructs for manipulating video
+ streams at a fairly high level. The strategy put forward by GridFlow
+ is different.
+
+ It can be said that in all those video plugins there are three layers:
+ the first, the low level, is not accessible to non-programmers (and fairly
+ difficult of access even to programmers); the second, mathematical, where
+ one needs not to be a C++ programmer, but still requires a good
+ understanding of how numbers and pixels and colours and geometry work; and
+ a third level that looks more like the software an artist would like to
+ use.
+
+ In other video plugins there is a fairly low emphasis on the second
+ layer. In GridFlow that layer is very strong and opens many possibilities.
+ Even though the third layer in GridFlow is not as developed as it could,
+ the second layer may be used to produce third-layer object classes much
+ more quickly.
+
+ GridFlow provides a unifying view of multimedia information. Several
+ kinds of data -- raster graphics in any number of channels, coordinate
+ transforms, matrices, vectors -- may all be represented by Grids
+ (also known as multi-dimensional arrays). Grids exist in several ways: they
+ are usually streamed from object to object, but they can also be stored in
+ memory, stored into a file, sent through the network.
+
+ Here is an example of how things work in GridFlow. (if you want more
+ information, consult the rest of this manual)
+
+ A picture is a three-dimensional Grid:
+ 0 : rows
+ 1 : columns
+ 2 : channels
+
+ Pictures come in all sorts of heights and widths. The channels, however,
+ are more limited in number. Usually it's three: Red, Green, Blue.
+
+ A coordinate transform, when specified pixel by pixel, may be a
+ three-dimensional Grid in which the two "channels" are Y and X,
+ representing row-and-column positions in a separate picture.
+
+ Other shapes of grids could be designed to represent various things;
+ for example, configuration for blur effects. Grids could be useful for
+ things not directly related to raster pictures (e.g. sound recordings).
+ Those are all kinds of things you could actually develop _within_ the
+ PureData / GridFlow framework. You don't need to wait for me.
+
+
+GridFlow Release
+
+dir=gridflow-0.9.6; tag=gridflow_0_9_6
+svn copy svn+ssh://gridflow.ca/home/svn/gridflow/trunk svn+ssh://gridflow.ca/home/svn/gridflow/tags/$tag/
+svn export svn+ssh://gridflow.ca/home/svn/gridflow/tags/$tag/ $dir
+chmod -R go=u-w $dir && tar cfzvv $dir.tar.gz $dir && rm -rf $dir
+scp $dir.tar.gz gridflow@artengine.ca:public_html/download
+mv $dir.tar.gz /home/matju/GridFlow
+cd doc/homepage; pico index.html; make install
+
+download somewhere else and try to compile
+pd-announce mlist : post release
+
+Committed revision 4239.
+Warning: 'post-commit' hook failed with error output:
+/home/svn/gridflow/hooks/post-commit: line 49: /home/svn/gridflow/hooks/svn-mailer.log: Permission denied
+
+svn copy svn+ssh://gridflow.ca/home/svn/gridflow/tags/$tag/ https://pure-data.svn.sourceforge.net/svnroot/pure-data/trunk/externals/gridflow/
diff --git a/externals/gridflow/doc/tutorials/gf_sampling_quantization.pd b/externals/gridflow/doc/tutorials/gf_sampling_quantization.pd
new file mode 100644
index 00000000..4f60217d
--- /dev/null
+++ b/externals/gridflow/doc/tutorials/gf_sampling_quantization.pd
@@ -0,0 +1,57 @@
+#N canvas 740 0 704 805 10;
+#X obj 2 5 cnv 15 650 15 empty empty empty 20 12 0 14 -228992 -66577
+0;
+#X obj 2 -30 cnv 15 700 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X obj 0 741 cnv 15 700 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X text 14 746 GridFlow 0.9.1;
+#X text 7 -23 Principles of new media;
+#X text 218 152 <-- reduces the size of the image;
+#X text 5 3 1.1 sampling;
+#X obj 4 314 cnv 15 650 15 empty empty empty 20 12 0 14 -228992 -66577
+0;
+#X text 7 313 1.2 quantization;
+#X text 330 85 <-- change the resampling factor (1 to 8);
+#X obj 55 80 #in;
+#X obj 55 32 tgl 15 0 empty empty empty 17 7 0 10 -4034 -1 -1 1 1;
+#X obj 75 259 #out window \, title sampling;
+#X obj 55 204 #scale_by;
+#X obj 202 86 hradio 15 1 0 8 empty empty empty 0 -8 0 10 -257985 -1
+-1 0;
+#X obj 202 108 + 1;
+#X obj 202 130 t a a;
+#X text 218 152 <-- reduces the size of the image;
+#X msg 123 55 open babbage.jpg;
+#X obj 55 419 #out window \, title quantization;
+#X text 230 53 <-- open image first;
+#X floatatom 124 365 5 0 0 0 - - -;
+#X obj 24 449 #downscale_by 32 smoothly;
+#X obj 25 518 display;
+#X obj 34 470 #out window \, title really_small_window;
+#X text 133 385 <-- reduces the number of possible pixel values;
+#X text 121 201 <-- increases the image size by the same factor \,
+letting us see the loss of information from the original image;
+#X obj 55 152 #downscale_by \, smoothly;
+#X obj 127 343 hsl 128 15 2 16 0 0 empty empty empty -2 -8 0 10 -257985
+-1 -1 3300 1;
+#X obj 55 54 metro 100;
+#X obj 55 385 #posterize 2;
+#X text 262 342 <-- number of tones per channel;
+#X connect 10 0 27 0;
+#X connect 11 0 29 0;
+#X connect 13 0 12 0;
+#X connect 13 0 30 0;
+#X connect 14 0 15 0;
+#X connect 15 0 16 0;
+#X connect 16 0 27 1;
+#X connect 16 1 13 1;
+#X connect 18 0 10 0;
+#X connect 21 0 30 1;
+#X connect 22 0 23 0;
+#X connect 22 0 24 0;
+#X connect 27 0 13 0;
+#X connect 28 0 21 0;
+#X connect 29 0 10 0;
+#X connect 30 0 19 0;
+#X connect 30 0 22 0;
diff --git a/externals/gridflow/doc/tutorials/gf_tutorial_grid_1.pd b/externals/gridflow/doc/tutorials/gf_tutorial_grid_1.pd
new file mode 100644
index 00000000..e86ff88f
--- /dev/null
+++ b/externals/gridflow/doc/tutorials/gf_tutorial_grid_1.pd
@@ -0,0 +1,25 @@
+#N canvas 363 183 701 242 10;
+#X obj 2 5 cnv 15 430 15 empty empty empty 20 12 0 14 -228992 -66577
+0;
+#X obj 2 -30 cnv 15 700 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X text 5 5 1.1 What is a grid?;
+#X text 7 -23 1 Introduction to Grids;
+#X obj 0 178 cnv 15 700 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X obj 523 56 bng 15 250 50 0 empty empty empty 0 -6 0 8 -24198 -1
+-1;
+#X obj 537 119 #out window;
+#X obj 537 88 #in david.jpg;
+#X text 14 183 GridFlow 0.9.0;
+#X text 5 28 A grid is composed of rows and columns that contain numeric
+data. GridFlow usually interprets images as three-dimensional grids
+with rows (height) and columns (width). Each channel is a single colour
+\, usually red \, green and blue (RGB). The channels make up the colour
+information of an image. Videos are also interpreted as grids since
+each frame is a still image.;
+#X text 5 125 GridFlow objects that accept or produce grids are identified
+by the number sign "#" (a mini grid). From now on \, the term "grid"
+is used to identify an image or video.;
+#X connect 5 0 7 0;
+#X connect 7 0 6 0;
diff --git a/externals/gridflow/doc/tutorials/gf_tutorial_grid_2.pd b/externals/gridflow/doc/tutorials/gf_tutorial_grid_2.pd
new file mode 100644
index 00000000..59aecb1a
--- /dev/null
+++ b/externals/gridflow/doc/tutorials/gf_tutorial_grid_2.pd
@@ -0,0 +1,64 @@
+#N canvas 376 138 1022 422 10;
+#X obj 1 14 cnv 15 460 15 empty empty empty 20 12 0 14 -228992 -66577
+0;
+#X text 4 14 1.2 How to create a grid.;
+#X obj 1 14 cnv 15 430 15 empty empty empty 20 12 0 14 -228992 -66577
+0;
+#X text 5 14 1.2 Creating a grid using the [#import] object.;
+#X text 5 40 GridFlow can create a grid from a list of numbers. The
+[#import] object permits you to set the desired amount of rows and
+columns. A message box must be connected to tell the grid which numbers
+to display.;
+#X text 6 109 Steps to create a grid:;
+#X text 7 134 1 - Create a list of numbers using a message box (the
+numbers must be seperated by a space). The list can have as many numbers
+as you want but only the amount defined by [#import] will be displayed.
+As you click on the message box the numbers will appear in the grid.
+Note how the numbers are positioned in the grid from left to right
+and from the top to the bottom.;
+#X text 7 229 2 - Create the [#import] object and indicate the parameters
+you want as grid dimensions. By indicating 3 3 in brackets following
+[#import] \, you are creating a grid that has 3 rows and 3 columns.
+A 3 by 3 grid will displays 9 numbers.;
+#X text 8 291 3 - Connect the objects to a [display] object or a [print]
+object to see the resulting grid. You can alter your grid without actually
+seeing the image.;
+#X obj 1 -30 cnv 15 1020 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X obj 1 -30 cnv 15 780 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X text 6 -23 1 Introduction to Grids;
+#X obj 1 356 cnv 15 1020 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X obj 479 285 display;
+#X msg 547 154 reset;
+#X obj 476 15 cnv 15 545 15 empty empty empty 20 12 0 14 -228992 -66577
+0;
+#X obj 476 15 cnv 15 430 15 empty empty empty 20 12 0 14 -228992 -66577
+0;
+#X obj 673 50 cnv 15 15 15 empty empty empty 20 12 0 14 -259603 -66577
+0;
+#X obj 478 223 cnv 15 92 15 empty empty empty 20 12 0 14 -241291 -66577
+0;
+#X obj 478 222 #import (3 3);
+#X msg 478 51 1 2 3 4 5 6 7 8 9;
+#X msg 535 99 1 2 3 4;
+#X text 483 15 1.2 Patch example.;
+#X text 610 155 <-- resets the grid to only display the numbers from
+the list;
+#X obj 652 217 cnv 15 15 15 empty empty empty 20 12 0 14 -259603 -66577
+0;
+#X text 610 97 <-- click here three times to see how [#import] only
+outputs a grid once it recieves the number of values associated with
+its dimensions;
+#X text 590 217 <-- step 2: click here to create a grid that has 3
+rows and 3 columns (try changing these numbers to alter the dimensions
+of the grid).;
+#X text 592 287 <-- the display object outputs results.;
+#X text 611 50 <-- step 1: click here to view the numbers from the
+list in a grid.;
+#X text 9 363 GridFlow 0.9.0;
+#X connect 14 0 19 0;
+#X connect 19 0 13 0;
+#X connect 20 0 19 0;
+#X connect 21 0 19 0;
diff --git a/externals/gridflow/doc/tutorials/gf_tutorial_grid_3.pd b/externals/gridflow/doc/tutorials/gf_tutorial_grid_3.pd
new file mode 100644
index 00000000..4e5e5778
--- /dev/null
+++ b/externals/gridflow/doc/tutorials/gf_tutorial_grid_3.pd
@@ -0,0 +1,30 @@
+#N canvas 106 132 652 402 10;
+#X obj 7 11 cnv 15 640 15 empty empty empty 20 12 0 14 -228992 -66577
+0;
+#X text 10 11 1.2 How to create a grid.;
+#X obj 7 11 cnv 15 430 15 empty empty empty 20 12 0 14 -228992 -66577
+0;
+#X text 11 11 1.3 Creating a grid using the [# + 0] object.;
+#X obj 7 -29 cnv 15 640 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X text 12 -22 1 Introduction to Grids;
+#X obj 279 117 cnv 15 15 15 empty empty empty 20 12 0 14 -259603 -66577
+0;
+#X text 216 255 <-- the display object outputs results.;
+#X text 217 116 <-- step 1: click on either message box to view the
+numbers from the list in a grid.;
+#X text 9 36 The [# + 0] object works like [#import] but allows you
+to put your grid parameters and values into one message box instead
+of having to insert them into the object box.;
+#X obj 5 337 cnv 15 640 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X msg 16 113 3 3 # 6 1 3 6 3 324 6 3 4;
+#X msg 37 159 3 3 # 1 0 0 0;
+#X obj 17 254 display;
+#X obj 16 204 cnv 15 37 15 empty empty empty 20 12 0 14 -241291 -66577
+0;
+#X obj 16 203 # + 0;
+#X text 14 345 GridFlow 0.8.4;
+#X connect 11 0 15 0;
+#X connect 12 0 15 0;
+#X connect 15 0 13 0;
diff --git a/externals/gridflow/doc/tutorials/gf_tutorial_image_1.pd b/externals/gridflow/doc/tutorials/gf_tutorial_image_1.pd
new file mode 100644
index 00000000..1c0fa483
--- /dev/null
+++ b/externals/gridflow/doc/tutorials/gf_tutorial_image_1.pd
@@ -0,0 +1,65 @@
+#N canvas 523 65 902 461 10;
+#X obj 4 323 cnv 15 900 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X obj 5 -67 cnv 15 430 15 empty empty empty 20 12 0 14 -228992 -66577
+0;
+#X obj 5 -106 cnv 15 900 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X obj 5 -106 cnv 15 780 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X text 12 -99 2 Introduction to Images;
+#X obj 450 -67 cnv 15 430 15 empty empty empty 20 12 0 14 -228992 -66577
+0;
+#X text 453 -67 1.2 How to create a grid.;
+#X obj 450 -67 cnv 15 430 15 empty empty empty 20 12 0 14 -228992 -66577
+0;
+#X obj 112 167 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 621 48 cnv 15 15 15 empty empty empty 20 12 0 14 -259603 -66577
+0;
+#X obj 621 100 cnv 15 15 15 empty empty empty 20 12 0 14 -259603 -66577
+0;
+#X text 557 99 <-- step #2 : click here to update the image;
+#X text 556 47 <-- step #1 : click here to load the image;
+#X text 8 169 step 3: Add a;
+#X text 7 136 step 2: Create [#in] object;
+#X text 8 202 step 4: Create a [#out window];
+#X text 6 98 step 1:;
+#X obj 450 264 cnv 15 25 15 empty empty empty 20 12 0 14 -260818 -66577
+0;
+#X text 449 264 Tip:;
+#X text 485 263 Remember \, as with the rest of PD \, you can obtain
+information regarding specific objects by right-clicking on it. Try
+this for [#in].;
+#X text 6 250 GridFlow accepts several image formats including .jpg
+\, .png \, .tiff.;
+#X text 449 213 The [#out window] object must be deleted in order to
+close the display window the image is in.;
+#X text 8 -46 The following steps outline the items that you need to
+open a grid. Whether it be an image or a video you want to open theses
+four steps are necessary.;
+#X text 8 2 In order for GridFlow to recognize your media files by
+file name you have to put them in the "images" folder (located within
+the GridFlow directory). Another way to locate an image is to specify
+the path to where it is saved on your hard drive in the message box.
+;
+#X text 452 -46 To view the image you must initialize the patch. Click
+on the message box \, and then on the bang (this must be done in the
+run mode). The image will appear in a display window \, off to the
+side of the patch. Sometimes the display window opens behind the patch
+\, try moving the patch if the display seems to be missing.;
+#X text 459 -66 2.1 Patch Example;
+#X text 8 -68 2.1 Opening an Image;
+#X obj 450 140 cnv 15 22 15 empty empty empty 20 12 0 14 -241291 -66577
+0;
+#X obj 450 180 #out window;
+#X msg 450 48 open b001.jpg;
+#X obj 534 99 bng 15 250 50 0 empty empty empty 0 -6 0 8 -24198 -1
+-1;
+#X obj 450 139 #in;
+#X text 62 113 extension you want to open;
+#X text 63 99 Create message box [open< with the file name and;
+#X text 11 329 GridFlow 0.9.0;
+#X connect 29 0 31 0;
+#X connect 30 0 31 0;
+#X connect 31 0 28 0;
diff --git a/externals/gridflow/doc/tutorials/gf_tutorial_image_2.pd b/externals/gridflow/doc/tutorials/gf_tutorial_image_2.pd
new file mode 100644
index 00000000..affb33b7
--- /dev/null
+++ b/externals/gridflow/doc/tutorials/gf_tutorial_image_2.pd
@@ -0,0 +1,63 @@
+#N canvas 257 0 660 624 10;
+#X obj 3 -37 cnv 15 653 15 empty empty empty 20 12 0 14 -228992 -66577
+0;
+#X obj 3 -72 cnv 15 653 30 empty empty empty 20 12 0 14 -233017 -355
+0;
+#X obj 3 517 cnv 15 653 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X obj 268 271 cnv 15 15 15 empty empty empty 20 12 0 14 -259603 -66577
+0;
+#X obj 152 134 cnv 15 15 15 empty empty empty 20 12 0 14 -259603 -66577
+0;
+#X text 88 133 <-- step #2 : start the metro;
+#X obj 203 363 cnv 15 15 15 empty empty empty 20 12 0 14 -259603 -66577
+0;
+#X obj 246 465 cnv 15 20 15 empty empty empty 20 12 0 14 -260818 -66577
+0;
+#X text 111 159 the metro refreshes the display window so you don't
+have to reload the grid every time it's altered.;
+#X text 204 271 <-- step #1 : load the image;
+#X text 245 464 Tip: try replacing this number box with a slider.;
+#X text 139 363 <-- step #3 : change the grid's vertical parameters
+;
+#X obj 247 405 cnv 15 15 15 empty empty empty 20 12 0 14 -259603 -66577
+0;
+#X text 15 -38 2.2 Resizing an image;
+#X text 10 82 [# pack] lets you resize grids by altering the vertical
+and horizontal parameters.;
+#X text 10 34 If you want to make your image four times its size \,
+you would have to insert a 4 into the object \; [#scale_by 4].;
+#X text 9 -10 [#scale_by] resizes grids by multiplying its parameters
+(width and height). To resize an image proportionatly a specific scaling
+size must be identified within the object.;
+#X text 183 405 <-- step #4 : change the grid's horizontal parameters
+;
+#X text 17 -67 2 Introduction to Images;
+#X obj 16 177 metro 10;
+#X obj 16 135 tgl 15 0 empty empty empty 0 -6 0 8 -24198 -1 -1 0 1
+;
+#X floatatom 74 368 5 1 4 0 - - -;
+#X obj 16 482 #out window;
+#X obj 53 295 #in;
+#X msg 53 272 load bluemarble.jpg;
+#X obj 74 431 #pack 2;
+#X obj 16 319 #store;
+#X obj 16 319 #store;
+#X obj 53 249 loadbang;
+#X obj 17 458 cnv 15 63 15 empty empty empty 20 12 0 14 -241291 -66577
+0;
+#X obj 16 457 #scale_by;
+#X floatatom 118 406 5 0 0 0 - - -;
+#X text 11 524 GridFlow 0.8.4;
+#X connect 19 0 26 0;
+#X connect 19 0 27 0;
+#X connect 20 0 19 0;
+#X connect 21 0 25 0;
+#X connect 23 0 26 1;
+#X connect 23 0 27 1;
+#X connect 24 0 23 0;
+#X connect 25 0 30 1;
+#X connect 27 0 30 0;
+#X connect 28 0 24 0;
+#X connect 30 0 22 0;
+#X connect 31 0 25 1;
diff --git a/externals/gridflow/doc/tutorials/gf_tutorial_image_3.pd b/externals/gridflow/doc/tutorials/gf_tutorial_image_3.pd
new file mode 100644
index 00000000..03d8c056
--- /dev/null
+++ b/externals/gridflow/doc/tutorials/gf_tutorial_image_3.pd
@@ -0,0 +1,84 @@
+#N canvas 0 87 993 482 10;
+#X obj 6 38 cnv 15 430 15 empty empty empty 20 12 0 14 -228992 -66577
+0;
+#X obj 6 3 cnv 15 1000 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X obj 5 149 cnv 15 430 15 empty empty empty 20 12 0 14 -228992 -66577
+0;
+#X obj 530 134 bng 15 250 50 0 empty empty empty 0 -6 0 8 -24198 -1
+-1;
+#X obj 484 163 #in;
+#X obj 484 191 cnv 15 42 17 empty empty empty 20 12 0 14 -241291 -66577
+0;
+#X text 8 180 In this section we will introduce some very basic functions
+of the numeric operator \, one of the most common methods used for
+image transformation.;
+#X text 7 69 GridFlow performs high level grid processing \; in other
+words its main function is the manipulation of images and video. There
+are several ways to modify images in GridFlow \, some are very basic
+while others are more advanced.;
+#X text 9 234 Numeric Operators (numop): transform grids by applying
+a mathematical operation to each pixel value.;
+#X obj 6 455 cnv 15 1000 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X text 18 37 2.3 Image Manipulation;
+#X text 17 148 Image Manipulation Using Numeric Operators;
+#X text 8 277 To transform a grid the numop must first be given an
+argument. That argument will be applied to every pixel in the grid.
+The following three examples show some ways to give the numop an argument.
+;
+#X obj 460 38 cnv 15 430 15 empty empty empty 20 12 0 14 -228992 -66577
+0;
+#X text 465 62 Altering a grid by placing an argument directly into
+the numop object.;
+#X obj 560 343 cnv 15 42 17 empty empty empty 20 12 0 14 -241291 -66577
+0;
+#X obj 561 382 display;
+#X msg 483 278 1 2 3 4 5 6 7 8 9;
+#X obj 483 307 #import (3 3);
+#X obj 484 382 display;
+#X obj 10 38 cnv 15 430 15 empty empty empty 20 12 0 14 -228992 -66577
+0;
+#X text 22 37 2.3 Image Manipulation;
+#X obj 10 38 cnv 15 430 15 empty empty empty 20 12 0 14 -228992 -66577
+0;
+#X text 22 37 2.3 Image Manipulation;
+#X obj 672 103 cnv 15 15 15 empty empty empty 20 12 0 14 -259603 -66577
+0;
+#X obj 11 352 cnv 15 20 15 empty empty empty 20 12 0 14 -260818 -66577
+0;
+#X text 422 361 --->;
+#X text 608 103 <-- step #1 : click here to load the image;
+#X obj 672 133 cnv 15 15 15 empty empty empty 20 12 0 14 -259603 -66577
+0;
+#X obj 624 189 cnv 15 15 15 empty empty empty 20 12 0 14 -259603 -66577
+0;
+#X text 608 133 <-- step #2 : click here to view the image;
+#X text 658 201 the value (42);
+#X text 560 188 <-- step #3 : try altering the argument by changing
+;
+#X obj 691 276 cnv 15 15 15 empty empty empty 20 12 0 14 -259603 -66577
+0;
+#X obj 691 342 cnv 15 15 15 empty empty empty 20 12 0 14 -259603 -66577
+0;
+#X text 627 276 <-- step #1 : click here to load the grid;
+#X text 20 8 2 Introduction to Images;
+#X text 472 37 2.3 Patch Example 1;
+#X text 9 352 Tip: To understand how pixels are affected by the numop
+test out this numeric grid patch. Each grid value that is output is
+multiplied by 42;
+#X obj 484 220 #out window;
+#X obj 484 191 # * 42;
+#X text 727 360 by changing the value (42);
+#X text 628 342 <-- step #2 : try altering the argument;
+#X obj 560 343 # * 42;
+#X text 14 463 GridFlow 0.8.4;
+#X msg 484 106 open working.jpg;
+#X connect 3 0 4 0;
+#X connect 4 0 40 0;
+#X connect 17 0 18 0;
+#X connect 18 0 19 0;
+#X connect 18 0 43 0;
+#X connect 40 0 39 0;
+#X connect 43 0 16 0;
+#X connect 45 0 4 0;
diff --git a/externals/gridflow/doc/tutorials/gf_tutorial_image_4.pd b/externals/gridflow/doc/tutorials/gf_tutorial_image_4.pd
new file mode 100644
index 00000000..ca6eae3f
--- /dev/null
+++ b/externals/gridflow/doc/tutorials/gf_tutorial_image_4.pd
@@ -0,0 +1,49 @@
+#N canvas 240 75 554 435 10;
+#X obj 23 -109 #in;
+#X obj 95 -59 cnv 15 25 17 empty empty empty 20 12 0 14 -241291 -66577
+0;
+#X obj 95 -84 cnv 15 25 17 empty empty empty 20 12 0 14 -241291 -66577
+0;
+#X obj 96 -34 cnv 15 25 17 empty empty empty 20 12 0 14 -241291 -66577
+0;
+#X msg 95 -59 67;
+#X msg 95 -84 2;
+#X msg 96 -34 199;
+#X text 146 -153 <--;
+#X text 145 -82 <--;
+#X text 145 -59 <--;
+#X text 145 -37 <--;
+#X obj 58 -148 bng 15 250 50 0 empty empty empty 0 -6 0 8 -24198 -1
+-1;
+#X obj 4 -299 cnv 15 550 15 empty empty empty 20 12 0 14 -228992 -66577
+0;
+#X obj 4 -334 cnv 15 550 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X obj 5 69 cnv 15 550 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X text 18 -329 2 Introduction to Images;
+#X text 15 -301 2.3 Patch Example 2;
+#X text 12 -269 Altering a grid by sending numop an argument using
+a message box. This method allows you to send the numop several different
+arguments.;
+#X obj 209 -206 cnv 15 15 15 empty empty empty 20 12 0 14 -259603 -66577
+0;
+#X obj 210 -152 cnv 15 15 15 empty empty empty 20 12 0 14 -259603 -66577
+0;
+#X text 145 -206 <-- step #2 : click here to load the image;
+#X text 174 -153 Step #3: click on the bang to see the updated image
+;
+#X obj 215 -59 cnv 15 15 15 empty empty empty 20 12 0 14 -259603 -66577
+0;
+#X text 179 -59 step #1 : click on one of the arguments;
+#X text 14 77 GridFlow 0.8.4;
+#X obj 23 33 #out window;
+#X msg 23 -206 open working.jpg;
+#X obj 23 -35 # * 1;
+#X connect 0 0 27 0;
+#X connect 4 0 27 1;
+#X connect 5 0 27 1;
+#X connect 6 0 27 1;
+#X connect 11 0 0 0;
+#X connect 26 0 0 0;
+#X connect 27 0 25 0;
diff --git a/externals/gridflow/doc/tutorials/gf_tutorial_image_5.pd b/externals/gridflow/doc/tutorials/gf_tutorial_image_5.pd
new file mode 100644
index 00000000..a0226c88
--- /dev/null
+++ b/externals/gridflow/doc/tutorials/gf_tutorial_image_5.pd
@@ -0,0 +1,52 @@
+#N canvas 559 20 560 533 10;
+#X obj 2 37 cnv 15 550 15 empty empty empty 20 12 0 14 -228992 -66577
+0;
+#X obj 2 2 cnv 15 550 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X obj 2 501 cnv 15 550 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X text 16 7 2 Introduction to Images;
+#X text 14 36 2.3 Patch Example 3;
+#X text 2 58 Altering a grid using numop with slider and metro. This
+combination allows you to scroll through values and modify a grid in
+real time.;
+#X obj 19 338 cnv 15 38 17 empty empty empty 20 12 0 14 -241291 -66577
+0;
+#X obj 225 207 cnv 15 15 15 empty empty empty 20 12 0 14 -259603 -66577
+0;
+#X obj 280 294 cnv 15 15 15 empty empty empty 20 12 0 14 -259603 -66577
+0;
+#X text 314 306 the slider;
+#X obj 223 122 cnv 15 15 15 empty empty empty 20 12 0 14 -259603 -66577
+0;
+#X obj 224 162 cnv 15 15 15 empty empty empty 20 12 0 14 -259603 -66577
+0;
+#X obj 21 252 #in;
+#X obj 54 295 hsl 128 15 0 255 0 0 empty empty empty -2 -6 0 8 -260818
+-1 -1 0 1;
+#X obj 53 228 metro 33.3;
+#X obj 53 206 tgl 15 0 empty empty empty 0 -6 0 8 -24198 -1 -1 1 1
+;
+#X floatatom 72 326 5 0 0 0 - - -;
+#X obj 50 165 bng 15 250 50 0 empty empty empty 0 -6 0 8 -24198 -1
+-1;
+#X obj 21 398 #out window;
+#X msg 21 121 open scissors.jpg;
+#X obj 21 338 # + 0;
+#X text 159 122 <-- step #1 : click here to load the image;
+#X text 161 206 <-- step #2 : start the metro;
+#X text 160 162 <-- step #2 : click here to view the image;
+#X text 223 184 or;
+#X text 216 294 <-- step #3 : try altering the argument by using;
+#X text 11 509 GridFlow 0.9.0;
+#X text 4 443 These examples use the [# +] numop. There are several
+numeric operators \; they can be found in the numeric operator help
+patch (right click on the [# + 0] and select help to view them).;
+#X connect 12 0 20 0;
+#X connect 13 0 16 0;
+#X connect 13 0 20 1;
+#X connect 14 0 12 0;
+#X connect 15 0 14 0;
+#X connect 17 0 12 0;
+#X connect 19 0 12 0;
+#X connect 20 0 18 0;
diff --git a/externals/gridflow/doc/tutorials/gf_tutorial_image_6.pd b/externals/gridflow/doc/tutorials/gf_tutorial_image_6.pd
new file mode 100644
index 00000000..e595e5b1
--- /dev/null
+++ b/externals/gridflow/doc/tutorials/gf_tutorial_image_6.pd
@@ -0,0 +1,66 @@
+#N canvas 130 10 767 676 10;
+#X obj 7 -69 cnv 15 760 15 empty empty empty 20 12 0 14 -228992 -66577
+0;
+#X obj 2 425 cnv 15 760 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X obj 4 -220 cnv 15 760 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X text 18 -215 2 Introduction to Images;
+#X obj 5 -183 cnv 15 760 15 empty empty empty 20 12 0 14 -228992 -66577
+0;
+#X text 12 -155 When an image is represented as a grid every pixel
+value will vary between 0 and 255 Colour wrapping occurs when the result
+of an operation on the pixel value is higher than 255 Values above
+255 are counted from 0 For example: if a pixel has a red value of 240
+and 20 is added to it \, you get 5 instead of displaying 260 (240 +
+20 - 255 = 5).;
+#X text 17 -184 2.4 Colour Wrapping;
+#X text 15 -69 2.4 [#clip];
+#X text 11 -44 The [#clip] object is used with numops in order to set
+a lower and upper range to pixel values. This allows you to avoid over
+saturating the colours of your grid.;
+#X obj 163 83 cnv 15 15 15 empty empty empty 20 12 0 14 -259603 -66577
+0;
+#X obj 19 254 cnv 15 38 17 empty empty empty 20 12 0 14 -241291 -66577
+0;
+#X obj 53 161 hsl 128 15 0 255 0 0 empty empty empty -2 -6 0 8 -260818
+-1 -1 0 1;
+#X obj 20 56 tgl 15 0 empty empty empty 0 -6 0 8 -24198 -1 -1 0 1;
+#X obj 50 353 #clip;
+#X obj 20 78 metro 33.3;
+#X obj 75 185 #color;
+#X obj 20 385 #out window;
+#X obj 20 314 shunt;
+#X obj 50 288 tgl 15 0 empty empty empty 0 -6 0 8 -24198 -1 -1 0 1
+;
+#X obj 3 107 bng 15 250 50 0 empty empty empty 0 -6 0 8 -24198 -1 -1
+;
+#X text 296 211 channel at a time;
+#X text 268 196 <-- use colour specific sliders to add values to one
+;
+#X obj 147 288 cnv 15 15 15 empty empty empty 20 12 0 14 -259603 -66577
+0;
+#X text 179 288 click here to redirect the flow of data using the [shunt]
+object and see the effect of [#clip];
+#X text 100 83 <-- step #1 : start the metro;
+#X text 199 160 <-- use slider to add values to all channels at once
+;
+#X text 9 432 GridFlow 0.8.4;
+#X obj 20 136 #store;
+#X obj 66 136 #in sewing.jpg;
+#X obj 20 254 # + 0;
+#X obj 66 117 loadbang;
+#X text 84 288 <-- step #2 :;
+#X connect 11 0 29 1;
+#X connect 12 0 14 0;
+#X connect 13 0 16 0;
+#X connect 14 0 27 0;
+#X connect 15 0 29 1;
+#X connect 17 0 16 0;
+#X connect 17 1 13 0;
+#X connect 18 0 17 1;
+#X connect 19 0 27 0;
+#X connect 27 0 29 0;
+#X connect 28 0 27 1;
+#X connect 29 0 17 0;
+#X connect 30 0 28 0;
diff --git a/externals/gridflow/doc/tutorials/gf_tutorial_image_7.pd b/externals/gridflow/doc/tutorials/gf_tutorial_image_7.pd
new file mode 100644
index 00000000..d7704291
--- /dev/null
+++ b/externals/gridflow/doc/tutorials/gf_tutorial_image_7.pd
@@ -0,0 +1,36 @@
+#N canvas 79 206 438 353 10;
+#X obj 2 -37 cnv 15 430 15 empty empty empty 20 12 0 14 -228992 -66577
+0;
+#X obj 2 -72 cnv 15 430 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X obj 3 244 cnv 15 430 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X text 4 -15 To convert an image to greyscale use [#rgb_to_greyscale].
+It converts a colour information into a black to white gradient.;
+#X obj 12 207 cnv 15 25 15 empty empty empty 20 12 0 14 -260818 -66577
+0;
+#X text 11 207 Tip:;
+#X text 48 201 If you have trouble opening this image refer back to
+previous tutorials.;
+#X text 16 -67 2 Introduction to Images;
+#X text 16 -37 2.5 Greyscale;
+#X obj 14 125 cnv 15 110 16 empty empty empty 20 12 0 14 -241291 -66577
+0;
+#X obj 15 71 #in;
+#X obj 27 51 bng 15 250 50 0 empty empty empty 0 -6 0 8 -24198 -1 -1
+;
+#X msg 15 27 open working.jpg;
+#X text 11 252 GridFlow 0.9.0;
+#X obj 15 124 #rgb_to_greyscale;
+#X obj 15 145 #greyscale_to_rgb;
+#X obj 15 172 #out window \, title greyscale;
+#X obj 157 91 #out window \, title original;
+#X obj 15 94 t a a;
+#X text 124 144 [#out window] still only accepts rgb images;
+#X connect 10 0 18 0;
+#X connect 11 0 10 0;
+#X connect 12 0 10 0;
+#X connect 14 0 15 0;
+#X connect 15 0 16 0;
+#X connect 18 0 14 0;
+#X connect 18 1 17 0;
diff --git a/externals/gridflow/doc/tutorials/gf_tutorial_image_8.pd b/externals/gridflow/doc/tutorials/gf_tutorial_image_8.pd
new file mode 100644
index 00000000..1697e73b
--- /dev/null
+++ b/externals/gridflow/doc/tutorials/gf_tutorial_image_8.pd
@@ -0,0 +1,61 @@
+#N canvas 29 52 836 433 10;
+#X obj 3 347 cnv 15 830 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X obj 4 -18 cnv 15 830 15 empty empty empty 20 12 0 14 -228992 -66577
+0;
+#X obj 4 -52 cnv 15 830 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X text 11 -46 2 Introduction to Images;
+#X text 10 -18 2.6 Remap Image;
+#X obj 261 229 cnv 15 25 15 empty empty empty 20 12 0 14 -260818 -66577
+0;
+#X text 260 229 Tip:;
+#X text 290 228 This is a numeric operator. Right click on it for more
+information or go back to the tutorial about the numeric operator.
+;
+#X obj 272 77 cnv 15 15 15 empty empty empty 20 12 0 14 -259603 -66577
+0;
+#X obj 321 188 cnv 15 15 15 empty empty empty 20 12 0 14 -259603 -66577
+0;
+#X text 355 200 number box to transform image;
+#X obj 21 267 cnv 15 85 15 empty empty empty 20 12 0 14 -241291 -66577
+0;
+#X obj 20 77 bng 15 250 50 0 empty empty empty 0 -6 0 8 -24198 -1 -1
+;
+#X obj 20 166 #in;
+#X obj 20 104 t b b;
+#X obj 99 290 #print;
+#X obj 191 128 bng 15 250 50 0 empty empty empty 0 -6 0 8 -24198 -1
+-1;
+#X floatatom 210 189 5 0 0 0 - - -;
+#X obj 180 152 #for (0 0) (240 320) (1 1);
+#X obj 180 102 metro 100;
+#X obj 180 77 tgl 15 0 empty empty empty 0 -6 0 8 -24198 -1 -1 1 1
+;
+#X obj 20 266 #remap_image;
+#X obj 180 227 # / 1;
+#X obj 20 315 #out window;
+#X text 231 228 <--;
+#X text 11 354 GridFlow 0.8.4;
+#X msg 50 135 open working.jpg;
+#X obj 110 77 cnv 15 15 15 empty empty empty 20 12 0 14 -259603 -66577
+0;
+#X text 12 7 Each numeric operator applies unique effects to a grid.
+The standard effect changes when numop is used in combination with
+the [#remap_image] object.;
+#X text 46 75 <-- step #1;
+#X text 207 77 <-- step #2 : start the metro;
+#X text 258 188 <-- step #3 : click and drag cursor over;
+#X connect 12 0 14 0;
+#X connect 13 0 21 0;
+#X connect 14 0 13 0;
+#X connect 14 1 26 0;
+#X connect 16 0 18 0;
+#X connect 17 0 22 1;
+#X connect 18 0 22 0;
+#X connect 19 0 18 0;
+#X connect 20 0 19 0;
+#X connect 21 0 23 0;
+#X connect 21 1 15 0;
+#X connect 22 0 21 1;
+#X connect 26 0 13 0;
diff --git a/externals/gridflow/doc/tutorials/gf_tutorial_image_9.pd b/externals/gridflow/doc/tutorials/gf_tutorial_image_9.pd
new file mode 100644
index 00000000..b7684734
--- /dev/null
+++ b/externals/gridflow/doc/tutorials/gf_tutorial_image_9.pd
@@ -0,0 +1,65 @@
+#N canvas 157 13 867 556 10;
+#X obj -14 522 cnv 15 862 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X obj -14 34 cnv 15 865 15 empty empty empty 20 12 0 14 -228992 -66577
+0;
+#X obj -14 -1 cnv 15 870 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X text -9 5 2 Introduction to Images;
+#X text -9 33 2.6 [#convolve];
+#X obj 147 258 #store;
+#X obj 147 362 # / 9;
+#X msg 297 372 3 3 # 1 1 1 1 1 1 1 1 1;
+#X obj -5 353 #out window;
+#X obj -5 160 #in;
+#X obj 147 177 tgl 15 0 empty empty empty 0 -6 0 8 -24198 -1 -1 0 1
+;
+#X obj -5 119 loadbang;
+#X obj 147 206 metro 33.3667;
+#X obj -5 218 t a;
+#X obj 147 335 #convolve \, seed 4;
+#X obj 297 339 loadbang;
+#X obj 297 445 display;
+#X obj 147 411 #clip;
+#X obj 529 390 cnv 15 15 15 empty empty empty 20 12 0 14 -259603 -66577
+0;
+#X obj 228 141 cnv 15 15 15 empty empty empty 20 12 0 14 -259603 -66577
+0;
+#X obj 229 175 cnv 15 15 15 empty empty empty 20 12 0 14 -259603 -66577
+0;
+#X text 164 140 <-- step #1 : load image;
+#X text 166 175 <-- step #3 : start metro;
+#X obj 297 316 cnv 15 110 15 empty empty empty 20 12 0 14 -241291 -66577
+0;
+#X text 331 316 Blurs;
+#X text 562 389 apply effect by selecting a message box;
+#X text 202 253 <-- The [#store] object stores the last grid that [#convolve]
+was applied to. Everytime time the metro bangs \, [#convolve] is applied
+to the grid retained in this object \, therefore applying effect on
+top of effect.;
+#X text 465 390 <-- step #2 :;
+#X text -8 529 GridFlow 0.9.0;
+#X text -18 502 ((Source convolve.pd : Copyright Mathieu Bouchard 2002)
+;
+#X msg 296 415 3 3 # 4 0 -1 3 1 0 0 0 4;
+#X text -9 55 [#convolve] allows you to apply preset effects such as
+blur \, edge sharpen and emboss onto a grid. In this example you can
+create two different kinds of "blurs" on an image.;
+#X msg -5 140 load working.jpg;
+#X obj 147 387 # abs-;
+#X connect 5 0 14 0;
+#X connect 6 0 33 0;
+#X connect 7 0 14 1;
+#X connect 9 0 13 0;
+#X connect 10 0 12 0;
+#X connect 11 0 32 0;
+#X connect 12 0 5 0;
+#X connect 13 0 5 1;
+#X connect 13 0 8 0;
+#X connect 14 0 6 0;
+#X connect 15 0 7 0;
+#X connect 17 0 13 0;
+#X connect 30 0 14 1;
+#X connect 30 0 16 0;
+#X connect 32 0 9 0;
+#X connect 33 0 17 0;
diff --git a/externals/gridflow/doc/tutorials/gf_tutorial_intro.pd b/externals/gridflow/doc/tutorials/gf_tutorial_intro.pd
new file mode 100644
index 00000000..9113ebb0
--- /dev/null
+++ b/externals/gridflow/doc/tutorials/gf_tutorial_intro.pd
@@ -0,0 +1,86 @@
+#N canvas 160 16 884 589 10;
+#X obj 5 6 cnv 15 870 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X obj 5 550 cnv 15 870 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X obj 6 46 cnv 15 430 15 empty empty empty 20 12 0 14 -179884 -66577
+0;
+#X obj 4 232 cnv 15 430 145 empty empty empty 20 12 0 14 -179884 -66577
+0;
+#X obj 25 271 pddp_open pure-data-1;
+#X obj 25 294 pddp_open pure-data-2;
+#X obj 25 317 pddp_open pure-data-3;
+#X obj 25 340 pddp_open pure-data-4;
+#X text 200 271 Pure-Data Introduction;
+#X text 200 294 GUI Objects for Interaction;
+#X text 200 317 Creating your first patch;
+#X text 200 340 Control: metro \, random & counter;
+#X obj 444 233 cnv 15 430 145 empty empty empty 20 12 0 14 -179884
+-66577 0;
+#X obj 5 391 cnv 15 430 145 empty empty empty 20 12 0 14 -179884 -66577
+0;
+#X obj 25 416 pddp_open pure-data-5;
+#X obj 25 439 pddp_open pure-data-6;
+#X text 200 439 The powerful message object;
+#X obj 25 462 pddp_open pure-data-7;
+#X text 200 462 More about lists;
+#X text 200 485 Nesting collections of objects;
+#X text 200 416 Connectionless communications;
+#X obj 25 485 pddp_open pure-data-8;
+#X text 200 509 Using GUI's in abstractions;
+#X obj 25 509 pddp_open pure-data-9;
+#X obj 445 391 cnv 15 430 145 empty empty empty 20 12 0 14 -179884
+-66577 0;
+#X obj 468 271 pddp_open GridFlow-1;
+#X obj 468 294 pddp_open GridFlow-2;
+#X obj 468 317 pddp_open GridFlow-3;
+#X obj 468 340 pddp_open GridFlow-4;
+#X text 642 319 Introduction to video;
+#X obj 446 46 cnv 15 430 15 empty empty empty 20 12 0 14 -179884 -66577
+0;
+#X text 645 477 Interfacing with sensors;
+#X obj 467 426 pddp_open GridFlow-6;
+#X obj 467 452 pddp_open GridFlow-7;
+#X text 451 236 2 Introduction to GridFlow;
+#X obj 448 236 cnv 15 15 15 empty empty empty 20 12 0 14 -262144 -66577
+0;
+#X text 451 236 2 Introduction to GridFlow;
+#X obj 8 395 cnv 15 15 15 empty empty empty 20 12 0 14 -262144 -66577
+0;
+#X obj 449 395 cnv 15 15 15 empty empty empty 20 12 0 14 -262144 -66577
+0;
+#X obj 7 235 cnv 15 15 15 empty empty empty 20 12 0 14 -262144 -66577
+0;
+#X text 452 395 4 Intermediate GridFlow;
+#X text 10 235 1 Introduction to Pure-Data;
+#X text 11 395 3 Intermediate Pure-Data;
+#X text 582 563 Stephanie Brodeur and Darsha Hewitt 2006;
+#X text 451 46 What is GridFlow?;
+#X text 500 550 What is GridFlow? and GridFlow tutorials developed
+by;
+#X text 453 84 GridFlow is a plug-in for PureData that introduces the
+grid (#) data type into the PD environment. GridFlow allows you to
+work with live video \, still images and video files in a real-time
+environment.;
+#X text 11 46 What is PureData (aka PD)?;
+#X text 14 85 PureData is an open-source patching environment for multi-media
+(audio+image). PureData is a programming language where you create
+relationships by connecting visual boxes (rather than typing complex
+commands).;
+#X text 454 144 This section deals with the particular objects related
+to GridFlow. GridFlow uses the usual PD "control" objects \, as well
+as a set of GridFlow specific objects.;
+#X text 15 141 A basic understanding of PureData is useful when using
+GridFlow. If you are new to the PureData programming environment it
+is recommended that you follow the Introduction to PureData before
+you move onto the GridFlow tutorials.;
+#X text 10 13 Welcome to PureData;
+#X text 13 551 What is PureData? and PureData tutorials copyright Ben
+Bogart 2005 \; (See COPYING.TXT for details);
+#X text 642 340 Introduction to live video;
+#X text 641 273 Introduction to grids;
+#X text 639 296 Introduction to images;
+#X text 653 480;
+#X obj 467 477 pddp_open GridFlow-8;
+#X text 646 451 Motion detection;
+#X text 646 426 Advanced video effects;
diff --git a/externals/gridflow/doc/tutorials/grid-intro.pd b/externals/gridflow/doc/tutorials/grid-intro.pd
new file mode 100644
index 00000000..fdbfdbbf
--- /dev/null
+++ b/externals/gridflow/doc/tutorials/grid-intro.pd
@@ -0,0 +1,10 @@
+#N canvas 0 0 476 213 10;
+#X text 29 30 GridFlow is a plug-in for PureData that introduces the
+grid (#) data type into the PD environment. GridFlow allows you to
+work with live video \, still images and video files in a rel-time
+environment.;
+#X text 32 97 This section deals with the particular objects related
+to GridFlow. GridFlow uses the usual PD "control" objects \, as well
+as a set of GridFlow specific objects. Before we get into the tutorials
+we will explain the grid "#" \, the most important concept in GridFlow.
+;
diff --git a/externals/gridflow/doc/tutorials/pure-data-1.pd b/externals/gridflow/doc/tutorials/pure-data-1.pd
new file mode 100644
index 00000000..7be2a91a
--- /dev/null
+++ b/externals/gridflow/doc/tutorials/pure-data-1.pd
@@ -0,0 +1,71 @@
+#N canvas 221 110 894 498 10;
+#N canvas 0 22 450 300 this 0;
+#X obj 192 128 inlet;
+#X obj 192 171 outlet;
+#X text 8 7 If you're looking at this you're just going to confuse
+yourself!;
+#X connect 0 0 1 0;
+#X restore 499 380 pd this is an object;
+#X text 509 358 <- This is a connection;
+#X msg 499 319 10;
+#X text 13 348 Objects are like filters \, they change the way messages
+flow through them.;
+#X text 13 153 You can think of a patch as plumbing. The way water
+flows through the plumbing of your house \, messages flow through the
+connections in your patch. Objects change the flow of the messages
+to allow different things to happen. Messages always go into objects
+at the top \, called the inlet \, and always come out at the bottom
+\, called the outlet. In PD messages flow from top to bottom.;
+#X text 458 236 This is a very simple example of a patch \, the message
+"10" can be sent through the "pd this is an object" and can be seen
+being passed out the outlet.;
+#X floatatom 499 416 5 0 0 0 - - -;
+#X text 539 415 <- This number box shows the float message;
+#X text 553 334 and watch the output!;
+#X obj 8 6 cnv 15 870 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X obj 8 46 cnv 15 430 15 empty empty empty 20 12 0 14 -179884 -66577
+0;
+#X text 13 252 You can work with PD in two ways \, the first is in
+"edit mode". Edit-mode is where you create your patch by adding objects
+and the connections between them. "Run mode" is when you're done with
+the construction of your patch \, and you wish to send messages through
+it. In run-mode your cursor is an arrow (as it is right now since we
+are in run-mode) \, in edit-mode your cursor is a pointing hand.;
+#X text 458 136 Messages are what allow objects to communicate with
+one and other. Messages can change the way an object acts \, and/or
+express the work the object is doing. Messages come in different types.
+They can contain words \, numbers and groups of these. The main types
+of messages we will be dealing with are floats (numbers). You can click
+on a message \, when in run-mode \, to send it through your patch.
+;
+#X obj 448 46 cnv 15 430 15 empty empty empty 20 12 0 14 -179884 -66577
+0;
+#X obj 448 290 cnv 15 430 15 empty empty empty 20 12 0 14 -179884 -66577
+0;
+#X obj 8 447 cnv 15 870 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X text 668 449 Copyright Ben Bogart 2005 \; (See COPYING.TXT for details)
+;
+#X text 12 20 DESCRIPTION: What is a patch? An object? A message?;
+#N canvas 0 22 466 316 META 0;
+#X text 12 5 CATEGORY: tutorial;
+#X text 12 15 KEYWORDS: metaphor object message GUI introduction;
+#X restore 16 453 pd META;
+#X text 457 67 GUI objects allow you to interact with your PD patch
+as it is running. They allow you to change what your patch is doing
+without reconnecting the objects. The simplest GUI object is the "Message"
+that simply contains a message you want to send in your patch.;
+#X text 453 290 A patch that connects a GUI to an object to a second
+GUI.;
+#X text 531 320 <- This GUI sends a float message (click on it);
+#X text 13 66 When working with PD you are dealing primarily with objects
+\, GUI (Graphical User Interface) objects \, connections and messages.
+These are the building blocks of PD programming. When you connect objects
+\, GUI objects \, and messages you are creating a "patch". Patching
+is making something complex out of smaller building blocks.;
+#X text 13 46 The "patch" \, "objects" and "connections";
+#X text 453 46 "GUI objects" and "messages";
+#X text 12 8 1 Introduction to Pure-Data & its Metaphors;
+#X connect 0 0 6 0;
+#X connect 2 0 0 0;
diff --git a/externals/gridflow/doc/tutorials/pure-data-2.pd b/externals/gridflow/doc/tutorials/pure-data-2.pd
new file mode 100644
index 00000000..151af26f
--- /dev/null
+++ b/externals/gridflow/doc/tutorials/pure-data-2.pd
@@ -0,0 +1,73 @@
+#N canvas 197 100 899 548 10;
+#X obj 8 6 cnv 15 870 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X obj 8 46 cnv 15 430 15 empty empty empty 20 12 0 14 -179884 -66577
+0;
+#X obj 448 46 cnv 15 430 15 empty empty empty 20 12 0 14 -179884 -66577
+0;
+#X obj 8 497 cnv 15 870 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X text 668 499 Copyright Ben Bogart 2005 \; (See COPYING.TXT for details)
+;
+#N canvas 0 22 470 320 META 0;
+#X text 12 5 CATEGORY: tutorial;
+#X text 12 15 KEYWORDS: GUI slider toggle number message introduction
+;
+#X restore 16 503 pd META;
+#X text 12 20 DESCRIPTION: Message \, slider \, toggle \, bang and
+number;
+#X msg 93 145 hello world;
+#X obj 93 168 print;
+#X text 181 146 <- Click on this message;
+#X text 18 74 Messages control the behavior of objects and it is the
+objects that change what a patch does. The first object we're going
+to learn is "print". All "print" does is print out the messages you
+send it to the terminal:;
+#X text 19 197 TIP: If you forget what an object does you can always
+double-click (on a mac) or right-click (on a PC) and then choose "help".
+;
+#X text 19 250 In this tutorial we will use two different types of
+objects: "objects" (of which "print" is an example) and GUI objects
+\, (of which "message" is an example). GUI objects allow you to interact
+with your patch \, control PD and change parameters of objects. We
+are going to learn four types of GUI objects (but there are many more):
+Slider \, Toggle \, Bang \, and Number.;
+#X obj 76 355 hsl 300 30 0 127 0 0 empty empty This_is_a_HSlider_(Horizontal)
+10 15 1 10 -262144 -1 -1 0 1;
+#X obj 73 393 print;
+#X text 21 421 This "hslider" is connected to the print object. This
+way we can see what messages the "hslider" sends. Try clicking and
+dragging in the Slider. You can change the scale (and other properties)
+of some GUI Objects by double-clicking (mac) or right-clicking (pc)
+and choosing "properties".;
+#X text 13 46 The "message" and "hslider" GUI Objects:;
+#X text 453 46 "toggle" \, "bang" \, "number";
+#X obj 519 176 tgl 30 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0
+1;
+#X obj 629 176 bng 30 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 629 210 print Bang;
+#X obj 519 210 print Toggle;
+#X obj 739 210 print Number;
+#X floatatom 739 192 5 0 0 0 - - -;
+#X text 466 76 "slider" \, "toggle" and "number" all send messages
+made up of floats (numbers). "bang" is a special case and it only sends
+the message "bang". Below we're using an argument to the print object
+that tags each message sent to the terminal. This way when we have
+multiple "print" objects in one patch we can differenciate thier output.
+;
+#X text 465 268 "toggle" sends the message "1" or "0" \, "bang" always
+sends "bang" and if you click and drag on the "number" you can see
+it acts a lot like a Slider. With "number" you can also click once
+\, and then type a number to send.;
+#X text 467 335 TIP: You can send floating point numbers by holding
+down the SHIFT key as you click and drag on the "number".;
+#X text 467 375 There are other types of GUI objects not covered here.
+See the guis-about.pd PDDP patch:;
+#X text 12 8 2 PD Introduction - Some Useful GUI Objects in Pure-Data
+;
+#X connect 7 0 8 0;
+#X connect 13 0 14 0;
+#X connect 18 0 21 0;
+#X connect 19 0 20 0;
+#X connect 23 0 22 0;
diff --git a/externals/gridflow/doc/tutorials/pure-data-3.pd b/externals/gridflow/doc/tutorials/pure-data-3.pd
new file mode 100644
index 00000000..729b2dc7
--- /dev/null
+++ b/externals/gridflow/doc/tutorials/pure-data-3.pd
@@ -0,0 +1,70 @@
+#N canvas 261 121 900 544 10;
+#X obj 8 6 cnv 15 870 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X obj 8 46 cnv 15 430 15 empty empty empty 20 12 0 14 -179884 -66577
+0;
+#X obj 448 366 cnv 15 430 15 empty empty empty 20 12 0 14 -179884 -66577
+0;
+#X obj 8 497 cnv 15 870 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X text 668 499 Copyright Ben Bogart 2005 \; (See COPYING.TXT for details)
+;
+#N canvas 0 22 474 324 META 0;
+#X text 12 5 CATEGORY: tutorial;
+#X text 12 15 KEYWORDS: patch first connecting placing place connect
+;
+#X restore 16 503 pd META;
+#X text 12 20 DESCRIPTION: Using PD to create your first patch;
+#X text 13 46 Adding Objects:;
+#X text 19 75 In order to create a patch you need to first place objects
+and GUI objects \, and second make connections between these objects.
+To place an object you need to be in "edit-mode". You should now be
+in run mode \, so please go to the "Edit" pull-down menu and choose
+"Edit mode" at the bottom. You should see your cursor change from an
+arrow to a pointing hand.;
+#X text 19 175 SHORTCUT: You can press "Control" and "e" simultaneously
+in order to toggle (switch) between edit and Run modes.;
+#X obj 448 386 cnv 15 430 100 empty empty empty 20 12 0 14 -233017
+-66577 0;
+#X floatatom 506 406 5 0 0 0 - - -;
+#X text 19 355 SHORTCUT: You can press "Control" and "3" simultaneously
+in order to place a number. All shortcuts are listed next to the items
+in the "Put" menu.;
+#X text 453 366 Patch work area:;
+#X text 19 215 Once you are in "edit-mode" you are now free to place
+objects. To place an object go to the "Put" pull-down menu and choose
+"Number". Once you have chosen this menu item you will see that a "number"
+gui is attached to your mouse pointer. In order to place the number
+into the patch move your pointer to the grey area to the right (in
+the "Patch work area" -> Click once to release it from your mouse.
+Note that the number is coloured blue. The blue colour shows that an
+item in your patch is selected. To unselect any item simply click once
+on the blank (white) space between items.;
+#X obj 520 440 print;
+#X obj 448 156 cnv 15 430 15 empty empty empty 20 12 0 14 -179884 -66577
+0;
+#X text 453 156 Connecting Objects:;
+#X text 19 411 Next we're going to place the familar "print" object
+beneath the "number" GUI. Press "Control" and "1" to place an object
+box. Again the object gets attached to your mouse and again click once
+to place it in the patch area somewhere under the "number".;
+#X text 459 41 While the number box is still selected (coloured blue)
+you can see a flashing cursor. Type the word "print" into the object
+box. The object will retain a dashed line while you type. In order
+to create the object you simply need to unselect \, by clicking somewhere
+outside the object. Note that once you have clicked to create the object
+the dashed line turns solid and an inlet (small rectangle) gets drawn
+around the word "print". The objects have now been created!;
+#X text 459 185 All connections between objects in PD are created from
+outlet to inlet (top to bottom). To start making a connection move
+your hand-pointer over the outlet of the "number" gui. When over the
+outlet your pointer will change to a circle. When you see the circle
+press and hold the mouse button. As you drag (holding the mouse button
+down) the pointer you see a line being drawn from the outlet to your
+pointer. To attach this connection to another object drag your mouse
+to an inlet of another object. The pointer will again change to a circle
+and at this point you can release the mouse button. Once released the
+objects are now connected! To play with your patch go back into run-mode
+and click and drag on the number-box while watching the terminal.;
+#X text 12 8 3 PD Introduction - Creating your first patch;
+#X connect 11 0 15 0;
diff --git a/externals/gridflow/doc/tutorials/pure-data-4.pd b/externals/gridflow/doc/tutorials/pure-data-4.pd
new file mode 100644
index 00000000..4d38f41d
--- /dev/null
+++ b/externals/gridflow/doc/tutorials/pure-data-4.pd
@@ -0,0 +1,87 @@
+#N canvas 183 61 890 531 10;
+#X obj 8 6 cnv 15 870 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X obj 8 96 cnv 15 430 15 empty empty empty 20 12 0 14 -179884 -66577
+0;
+#X obj 8 487 cnv 15 870 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X text 668 489 Copyright Ben Bogart 2005 \; (See COPYING.TXT for details)
+;
+#N canvas 0 22 478 328 META 0;
+#X text 12 5 CATEGORY: tutorial;
+#X text 12 15 KEYWORDS: metro counter random;
+#X restore 16 493 pd META;
+#X text 12 20 DESCRIPTION: Learning "metro" \, "counter" & "random"
+;
+#X text 13 96 Using the "metro" object:;
+#X text 21 47 In this section we will learn three new objects \, "metro"
+\, "counter" \, and "random". Metro sends a bang at regular intervals
+\, just like a metronome.;
+#X obj 164 142 metro 250;
+#X obj 164 123 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0
+1;
+#X obj 164 163 bng 15 100 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X floatatom 222 123 5 0 0 0 - - -;
+#X text 21 187 You can turn a Metro on and off by sending it a "1"
+or "0" message. Because a toggle sends 0/1 messages \, we can simply
+connect it directly. Metro also accepts an argument (words or numbers
+wirtten after the object name). This argument is how fast the metro
+should send out bangs (in milliseconds). You can always change the
+speed of the metro by sending it number messages through the rightmost
+inlet.;
+#X obj 8 306 cnv 15 430 15 empty empty empty 20 12 0 14 -179884 -66577
+0;
+#X text 13 306 Using the "random" object:;
+#X text 21 277 For more info see the metro-help.pd patch.;
+#X obj 168 385 bng 15 100 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 168 425 print;
+#X obj 168 404 random 100;
+#X floatatom 233 385 5 0 0 0 - - -;
+#X text 20 327 The Random object returns a number between 0 and the
+(number) argument when it receives a bang message in the leftmost inlet.
+You can also change the upper limit by sending a message to the rightmost
+inlet.;
+#X obj 448 46 cnv 15 430 15 empty empty empty 20 12 0 14 -179884 -66577
+0;
+#X text 453 46 Using the "random" object:;
+#X obj 559 154 bng 15 100 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X floatatom 590 154 3 1 3 0 - - -;
+#X floatatom 621 174 3 0 0 0 - - -;
+#X floatatom 652 194 3 0 0 0 - - -;
+#X obj 652 234 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X floatatom 559 234 8 0 0 0 - - -;
+#X obj 559 213 counter 0 10 1;
+#X text 21 447 For more info see the random-help.pd patch.;
+#X text 461 77 "counter" is simply an object that counts. It can count
+up \, count down and count up and then down. Where it starts and where
+it stops are all definable. This is the counter that in included with
+Gem \, it is not compatible with other counter objects.;
+#X text 461 274 The first argument for counter is the lower limit (number
+to start counting at). The second is the upper limit to count to. The
+third argument is the direction in which to count. "1" means forward
+\, "2" means backward and "3" means forward and then backward. You
+can also use the three rightmost inlets to change the behaviour of
+counter. The rightmost inlet is the upper limit \, the second right-most
+the lower limit \, and the third right-most as the direction. The rightmost
+outlet sends out a bang message when the counter loops.;
+#X text 681 193 Rightmost inlet;
+#X text 651 173 Second Rightmost inlet;
+#X text 621 153 Third Rightmost inlet;
+#X text 461 407 For more info see the counter-help.pd patch.;
+#X text 12 8 4 Introduction to PD - More objects;
+#X connect 8 0 10 0;
+#X connect 9 0 8 0;
+#X connect 11 0 8 1;
+#X connect 16 0 18 0;
+#X connect 18 0 17 0;
+#X connect 19 0 18 1;
+#X connect 23 0 29 0;
+#X connect 24 0 29 1;
+#X connect 25 0 29 2;
+#X connect 26 0 29 3;
+#X connect 29 0 28 0;
+#X connect 29 1 27 0;
diff --git a/externals/gridflow/doc/tutorials/pure-data-5.pd b/externals/gridflow/doc/tutorials/pure-data-5.pd
new file mode 100644
index 00000000..dc357bb1
--- /dev/null
+++ b/externals/gridflow/doc/tutorials/pure-data-5.pd
@@ -0,0 +1,108 @@
+#N canvas -235 0 891 673 10;
+#X obj 8 6 cnv 15 870 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X obj 8 46 cnv 15 430 15 empty empty empty 20 12 0 14 -179884 -66577
+0;
+#X obj 8 627 cnv 15 870 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X text 668 629 Copyright Ben Bogart 2005 \; (See COPYING.TXT for details)
+;
+#N canvas 0 22 482 332 META 0;
+#X text 12 5 CATEGORY: tutorial;
+#X text 12 15 KEYWORDS: send receive netsend netreceive cordless communication
+network TCP/IP UDP internet;
+#X restore 16 633 pd META;
+#X obj 448 46 cnv 15 430 15 empty empty empty 20 12 0 14 -179884 -66577
+0;
+#X text 12 20 DESCRIPTION: Communicating between objects w/out connections
+;
+#X text 13 46 "send" & "receive";
+#X obj 86 223 send invisible-link;
+#X obj 86 248 receive invisible-link;
+#X floatatom 86 273 5 0 0 0 - - -;
+#X msg 86 198 10;
+#X floatatom 266 273 5 0 0 0 - - -;
+#X floatatom 266 203 5 0 0 0 - - -;
+#X obj 266 223 s invisible-link2;
+#X obj 266 248 r invisible-link2;
+#X obj 102 483 r send-from-number;
+#X floatatom 102 508 5 0 0 0 - - -;
+#X floatatom 102 462 5 0 0 0 - - send-from-number;
+#X floatatom 242 462 5 0 0 0 - - -;
+#X obj 242 483 s send-to-number2;
+#X floatatom 242 508 5 0 0 0 - send-to-number2 -;
+#X text 19 385 Note: Many GUI objects have built-in send and receive
+objects. The tag names are specified in the GUI properties. Remeber
+to get the GUI properties Right-Click or Control-Click on the GUI object
+and select "Properties".;
+#X text 453 46 "netsend" & "netreceive";
+#X text 19 575 For more info see: send-help.pd \, receive-help.pd \,
+netsend-help.pd and netreceive-help.pd;
+#X text 459 75 While "send" and "receive" allow you to send messages
+without connecting objects with patch-cords "netsend" and "netreceive"
+do the same but communicate between objects using TCP/IP the internet
+protocol. This means that you can send messages from a patch running
+on one machine to a second patch running on a second machine on the
+same network \, or even over the internet.;
+#X text 19 545 You can also send messages using UDP rather than TCP/IP.
+See "more info" below for details.;
+#X obj 589 292 netreceive 8001;
+#X text 459 185 The first argument of "netreceive" is the port the
+netrecive should listen on. "netsend" can connect to this port from
+other machines. "netreceive" has two outlets. The first outlet sends
+out the messages it receives over network \, and the second argument
+send a "1" when netsend is connected and "0" when netsend disconnects.
+;
+#X obj 589 318 print;
+#X obj 689 318 tgl 16 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1
+1;
+#X obj 503 563 netsend;
+#X text 459 355 "netsend" is controlled using three messages: "connect"
+\, "disconnect" and "send". "connect" has two arguments \, the host
+or IP and the port number you wish to connect to. There needs to be
+a "netreceive" listening on the port you connect to. "disconnect" drops
+the current connection. "send" sends any arguments to the "netreceive"
+over the network. The single outlet of "netsend" prints "1" when a
+connection is made and "0" when the connection is lost.;
+#X obj 503 586 tgl 16 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1
+1;
+#X msg 503 486 connect localhost 8001;
+#X msg 516 511 disconnect;
+#X msg 525 537 send hello from the internet;
+#X text 602 510 Close connection;
+#X text 673 486 Connect to this machine;
+#X text 733 536 Send message;
+#X text 19 75 In some cases you will want to send messages without
+connecting objects. You may be sending one message to many different
+places that would make connections too laborious. "send" and "receive"
+both have a single argument. This argument is the tag name for the
+communication. "send" will always send any messages it gets in it inlet
+to any number of "receive" objects in a patch with the same tag name.
+"s" and "r" can be used in the place of "send" and "receive".;
+#X obj 86 336 s broadcast;
+#X floatatom 86 317 5 0 0 0 - - -;
+#X obj 176 316 r broadcast;
+#X floatatom 176 339 5 0 0 0 - - -;
+#X obj 266 316 r broadcast;
+#X floatatom 266 339 5 0 0 0 - - -;
+#X text 12 8 5 Intermediate Pure-Data - send and receive;
+#X msg 585 598 send \$1;
+#X floatatom 584 567 5 0 0 0 - - -;
+#X text 651 596 send variables to another computer;
+#X connect 9 0 10 0;
+#X connect 11 0 8 0;
+#X connect 13 0 14 0;
+#X connect 15 0 12 0;
+#X connect 16 0 17 0;
+#X connect 19 0 20 0;
+#X connect 27 0 29 0;
+#X connect 27 1 30 0;
+#X connect 31 0 33 0;
+#X connect 34 0 31 0;
+#X connect 35 0 31 0;
+#X connect 36 0 31 0;
+#X connect 42 0 41 0;
+#X connect 43 0 44 0;
+#X connect 45 0 46 0;
+#X connect 48 0 31 0;
+#X connect 49 0 48 0;
diff --git a/externals/gridflow/doc/tutorials/pure-data-6.pd b/externals/gridflow/doc/tutorials/pure-data-6.pd
new file mode 100644
index 00000000..01e6dcd7
--- /dev/null
+++ b/externals/gridflow/doc/tutorials/pure-data-6.pd
@@ -0,0 +1,92 @@
+#N canvas 304 98 891 675 10;
+#X obj 8 6 cnv 15 870 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X obj 8 627 cnv 15 870 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X text 668 629 Copyright Ben Bogart 2005 \; (See COPYING.TXT for details)
+;
+#N canvas 0 22 486 336 META 0;
+#X text 12 5 CATEGORY: tutorial;
+#X text 12 15 KEYWORDS: message comma semicolon dollersign receive
+list;
+#X restore 16 633 pd META;
+#X text 12 20 DESCRIPTION: Advanced uses for the message object;
+#X text 19 45 In Pure-Data there are two distinct concepts with the
+name "message". Messages are the data that gets send in PD from object
+to object. There is also the Messsage object that contains a message
+you want to send. The message object is the first GUI object we covered
+in this tutorial. The message is not the only way to send messages
+in a patch \, since all GUI objects also send messages. So what makes
+the message object different? The message object can sent messages
+of any type \, where a number for example can only send float (number)
+messages. There are a number of powerful features in the message object.
+We are familar with the "usual" way of using the message object:;
+#X msg 163 208 hello;
+#X msg 212 208 bye;
+#X obj 196 238 print messages;
+#X text 459 556 Note: It is a very common mistake to confuse the message
+object with an object box. The object box is framed in a rectangle.
+The message object has a notch removed from the right edge.;
+#X obj 106 385 print messages;
+#X msg 106 358 hello \, bye;
+#X text 19 305 You can send multiple messages in succession from a
+single message box by using a comma " \, " between the messages. The
+messages get send from left to right.;
+#X obj 8 276 cnv 15 430 15 empty empty empty 20 12 0 14 -179884 -66577
+0;
+#X obj 8 416 cnv 15 430 15 empty empty empty 20 12 0 14 -179884 -66577
+0;
+#X text 13 416 Semicolon in message boxes;
+#X text 13 276 Comma in message boxes;
+#X text 19 445 Just like you can specify receive tags directly in GUI
+objects you can also use a message box to send a message directly to
+a particular "receive".;
+#X obj 34 536 r myreceive;
+#X floatatom 34 560 5 0 0 0 - - -;
+#X text 189 360 Click to send both messages;
+#X text 136 502 send "10" to receive tag "myreceive";
+#X text 19 585 For more info see: message-help.pd 04.messages.pd 10.more.messages.pd
+;
+#X msg 34 498 \; myreceive 10;
+#X obj 448 46 cnv 15 430 15 empty empty empty 20 12 0 14 -179884 -66577
+0;
+#X text 453 46 Dollarsign in message boxes;
+#X msg 534 175 \$1 \$1 \$1;
+#X msg 534 154 10;
+#X text 459 75 In messages there are placeholders that start with "$".
+These placeholders are variables that get replaced with messages you
+send to the message box. In the example below we have a single message
+"10". Each "$1" in the message box gets replaced with the message "10".
+;
+#X text 601 175 \$1 placeholder gets replaced;
+#X text 570 154 message sent to message box;
+#X msg 534 304 list 1 2;
+#X text 600 304 a list with items "1" and "2";
+#X msg 534 325 \$2 \$1;
+#X text 584 325 \$1 becomes "1" and \$2 becomes "2";
+#X obj 534 347 print reverse-list;
+#X text 459 235 The "$1" placeholder refers to the first element of
+the list the message box gets from its inlet. We can use this to use
+a message box to reverse the order of elements (called atoms) in a
+list.;
+#X text 459 385 In this case the list "1 2" has two elements (called
+atoms) when this list gets sent to the inlet of a message box its atoms
+are available to the message box through the $ variables. \$1 gets
+replaced with the first element \, \$2 the second and so on.;
+#X obj 534 197 print repeated-message;
+#X obj 480 511 print complex-message;
+#X msg 480 468 list Fred Marcus;
+#X text 607 468 a list with two symbol atoms;
+#X msg 480 489 Hi \$1. \, Ya know \$2?;
+#X text 623 489 Becomes: "Hi Fred \, Ya know Marcus?";
+#X text 12 8 6 Intermediate Pure-Data - Using the message object;
+#X connect 6 0 8 0;
+#X connect 7 0 8 0;
+#X connect 11 0 10 0;
+#X connect 18 0 19 0;
+#X connect 26 0 38 0;
+#X connect 27 0 26 0;
+#X connect 31 0 33 0;
+#X connect 33 0 35 0;
+#X connect 40 0 42 0;
+#X connect 42 0 39 0;
diff --git a/externals/gridflow/doc/tutorials/pure-data-7.pd b/externals/gridflow/doc/tutorials/pure-data-7.pd
new file mode 100644
index 00000000..0d8360ec
--- /dev/null
+++ b/externals/gridflow/doc/tutorials/pure-data-7.pd
@@ -0,0 +1,106 @@
+#N canvas 280 89 936 678 10;
+#X obj 8 6 cnv 15 870 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X obj 8 627 cnv 15 870 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X text 668 629 Copyright Ben Bogart 2005 \; (See COPYING.TXT for details)
+;
+#N canvas 0 22 482 332 META 0;
+#X text 12 5 CATEGORY: tutorial;
+#X text 12 15 KEYWORDS: send receive netsend netreceive cordless communication
+network TCP/IP UDP internet;
+#X restore 16 633 pd META;
+#X obj 8 266 cnv 15 430 15 empty empty empty 20 12 0 14 -179884 -66577
+0;
+#X text 13 266 "pack" object;
+#X msg 96 543 2;
+#X msg 45 521 1;
+#X obj 45 588 print mylist;
+#X text 12 20 DESCRIPTION: Using pack \, unpack and route with lists
+;
+#X text 19 75 In the Pure-Data introduction we discussed the three
+different types of data in PD. These are floats (numbers) \, symbols
+(words) and lists (groups of floats and words). Floats and symbols
+are known as atoms. Atoms are single elements \, they do not contain
+spaces or other special characters. Atoms can be grouped into lists.
+;
+#X obj 8 46 cnv 15 430 15 empty empty empty 20 12 0 14 -179884 -66577
+0;
+#X text 13 46 What is a list?;
+#X msg 145 216 list one two three;
+#X obj 145 239 print this is a list;
+#X text 19 155 Lists can be created in a number of ways \, but we are
+going to cover the two most common ways of creating lists. The most
+simple way to create a list is to type the list into a message box
+starting with the word (symbol) "list":;
+#X text 19 295 The "pack" object is the second most common way to create
+a list. "pack" allows you to take individual atoms and combine them
+into a single list. "pack" accepts a number of arguments. Each argument
+defines the type of atom in the resulting list. The "f" argument creates
+an inlet that accepts float atoms. The "s" argument creates an inlet
+accepts symbol atoms. The number of arguments is the same as the number
+of elements in the resultant list.;
+#X text 19 405 "pack" is the first object we are going to learn that
+has a "cold" inlet. Some control objects in PD have "hot" and "cold"
+inlets. When you send a message to a "cold" inlet the object does not
+generate any output (it does not send any messages). When "hot" inlets
+get messages then the object does generate output. The leftmost inlet
+is always the "hot" inlet and all other inlets are "cold" or in some
+cases all inlets are "hot";
+#X text 75 521 sets the first atom "1" and then sends the list;
+#X text 132 543 sets the second atom "2";
+#X obj 45 566 pack f f;
+#X text 459 45 Note that if you do not set the second and onwards atoms
+via thier "cold" inlets and you generate the list by setting the first
+atom via the "hot" inlet then all float atoms will be set to "0" and
+all symbol atoms will be set to "symbol" in the resultant list.;
+#X obj 448 126 cnv 15 430 15 empty empty empty 20 12 0 14 -179884 -66577
+0;
+#X text 453 126 "unpack" object;
+#X obj 596 241 unpack f f f;
+#X msg 596 219 list 1 2 3;
+#X floatatom 596 294 5 0 0 0 - - -;
+#X floatatom 635 277 5 0 0 0 - - -;
+#X floatatom 675 262 5 0 0 0 - - -;
+#X text 639 293 First Atom;
+#X text 678 277 Second Atom;
+#X text 718 261 Third Atom;
+#X text 459 156 The "unpack" object is very similar to the "pack" object
+except it works in reverse. "unpack" takes a list and splits it up
+into a number of atoms. It uses the same arguments as "pack" but generates
+outlets rather than inlets.;
+#X obj 448 319 cnv 15 430 15 empty empty empty 20 12 0 14 -179884 -66577
+0;
+#X text 453 319 "route" object;
+#X text 459 349 The "route" object sorts lists based on the first atom
+of the list. It as a number of float or symbol arguments. For each
+argument "route" creates one outlet. "route" also creates one additional
+rightmost outlet for rejections. For each list route gets it compares
+the first atom to all its arguments. If the first atom matches one
+of the arguments it the rest of the list \, without the first atom
+\, gets send through the outlet corresponding to that argument. If
+the first atom of the list does not match any arguments the entire
+list \, including the first atom \, gets sent out the rejection outlet.
+;
+#X msg 688 493 rejection 1;
+#X obj 685 553 print rejection;
+#X msg 538 493 o1 2;
+#X msg 613 493 o2 3;
+#X obj 613 531 route o1 o2;
+#X obj 613 593 print o1;
+#X obj 649 573 print o2;
+#X text 12 8 7 Intermediate Pure-Data - Working with lists;
+#X connect 6 0 20 1;
+#X connect 7 0 20 0;
+#X connect 13 0 14 0;
+#X connect 20 0 8 0;
+#X connect 24 0 26 0;
+#X connect 24 1 27 0;
+#X connect 24 2 28 0;
+#X connect 25 0 24 0;
+#X connect 36 0 40 0;
+#X connect 38 0 40 0;
+#X connect 39 0 40 0;
+#X connect 40 0 41 0;
+#X connect 40 1 42 0;
+#X connect 40 2 37 0;
diff --git a/externals/gridflow/doc/tutorials/pure-data-8.pd b/externals/gridflow/doc/tutorials/pure-data-8.pd
new file mode 100644
index 00000000..aa95c087
--- /dev/null
+++ b/externals/gridflow/doc/tutorials/pure-data-8.pd
@@ -0,0 +1,89 @@
+#N canvas 238 94 891 621 10;
+#X obj 8 6 cnv 15 870 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X obj 8 577 cnv 15 870 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X text 668 579 Copyright Ben Bogart 2005 \; (See COPYING.TXT for details)
+;
+#N canvas 0 22 482 332 META 0;
+#X text 12 5 CATEGORY: tutorial;
+#X text 12 15 KEYWORDS: send receive netsend netreceive cordless communication
+network TCP/IP UDP internet;
+#X restore 16 583 pd META;
+#X obj 8 46 cnv 15 430 15 empty empty empty 20 12 0 14 -179884 -66577
+0;
+#X text 12 20 DESCRIPTION: nested patches using abstractions & subpatches
+;
+#X text 13 46 What is an abstraction?;
+#X text 23 76 Since objects are very simple in Pure-Data doing complex
+tasks often leads to very complex patches. Often it is useful to use
+the same bit of patching you do for one project for another. Pure-Data
+has a facility to "nest" \, that is to take a number of objects in
+a collection and place them into a group that looks like a single object.
+This is also handy to make a complex patch look simple and clear by
+hiding the nitty-gritty details. There are two types of these collections
+\, the subpatch and the abstraction.;
+#X obj 8 216 cnv 15 430 15 empty empty empty 20 12 0 14 -179884 -66577
+0;
+#X text 13 216 The subpatch;
+#X text 23 246 Subpatches are collections of objects that get "hidden"
+inside a container that looks like a normal PD object. Subpatches are
+created by creating an object box \, and typing the word "pd" followed
+by whatever you want to describe the contents of the subpatch. Subpatches
+are saved at the same time as the "parent" patch. Here is a subpatch:
+;
+#N canvas 0 22 460 310 subpatch 0;
+#X obj 30 34 inlet;
+#X obj 30 77 outlet;
+#X text 99 35 This is inside the subpatch.;
+#X connect 0 0 1 0;
+#X restore 178 359 pd subpatch;
+#X floatatom 178 336 5 0 0 0 - - -;
+#X floatatom 178 387 5 0 0 0 - - -;
+#X text 23 416 To open a subpatch simply click once on the subpatch
+in run-mode or control-click (or right-click) and select open in edit-mode.
+Both subpatches and abstractions communicate with the parent patch
+through special objects called "inlet" and "outlet" for each "inlet"
+in a subpatch or abstraction an inlet is created on the subpatch. This
+example has one inlet and one outlet.;
+#X obj 448 46 cnv 15 430 15 empty empty empty 20 12 0 14 -179884 -66577
+0;
+#X text 453 46 The abstraction;
+#X text 463 76 Abstractions are very similar to subpatches. They are
+collections of objects that are "hidden" inside PD objects \, and they
+both use "inlet" and "outlet" objects to communicate with the parent
+patch. The difference between subpatches and abstractions is that abstractions
+are saved in a separate file from the parent. This means when you save
+the parent patch containing abstractions the abstractions are not saved.
+The abstractions are saved as separate files so that they can be used
+in multiple patches. A second feature that exists in abstractions and
+not in subpatches is the ability to use arguments. "send" and "receive"
+can be used inside abstractions to send data without connections (patch-cords).
+;
+#X obj 682 253 r output;
+#X obj 682 277 print;
+#X obj 564 253 abstraction 1 2;
+#X text 463 316 To create an abstraction all you need to do is create
+a new PD patch ("File" -> "New"). Create the contents of the abstraction
+and then save it in the same directory as the patch you want to use
+it in. In this case the abstraction is saved as "abstraction.pd". Once
+saved you can easily embed the abstraction simply by typing its name
+\, without the .pd extension \, into an object box.;
+#X obj 448 416 cnv 15 430 15 empty empty empty 20 12 0 14 -179884 -66577
+0;
+#X text 453 416 Dollarsign in object boxes;
+#X text 463 446 If you open the above example you will see that the
+familiar "pack" object has a number of "$" arguments. The "$" arguments
+in a object box differ entirely from the "$" used in message objects.
+When you use a "$" in an object box inside an abstraction the values
+get replaced with the arguments to that abstraction. In the case above
+the "pack" object's first argument "$1" gets replaced with the first
+argument of the abstraction "1" "$2" gets replaced with the second
+argument "2".;
+#X text 23 536 For more info see: 12.PART2.subpatch.pd 14.dollersign.pd
+;
+#X text 12 8 8 Intermediate Pure-Data - Using abstractions and subpacthes
+;
+#X connect 11 0 13 0;
+#X connect 12 0 11 0;
+#X connect 18 0 19 0;
diff --git a/externals/gridflow/doc/tutorials/pure-data-9.pd b/externals/gridflow/doc/tutorials/pure-data-9.pd
new file mode 100644
index 00000000..e5188ee0
--- /dev/null
+++ b/externals/gridflow/doc/tutorials/pure-data-9.pd
@@ -0,0 +1,43 @@
+#N canvas 291 108 450 562 10;
+#X obj 8 6 cnv 15 430 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X obj 8 517 cnv 15 430 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X text 228 519 Copyright Ben Bogart 2005 \; (See COPYING.TXT for details)
+;
+#N canvas 0 22 486 336 META 0;
+#X text 12 5 CATEGORY: tutorial;
+#X text 12 15 KEYWORDS: GOP graph parent abstraction nesting ui interface
+;
+#X restore 16 523 pd META;
+#X obj 8 46 cnv 15 430 15 empty empty empty 20 12 0 14 -179884 -66577
+0;
+#X text 12 20 DESCRIPTION: Using Graph on Parent abstractions;
+#X text 13 46 What is Graph on Parent?;
+#X text 13 76 Graph on Parent is a feature of PD that allows you to
+show the GUI objects contained in an abstraction on the parent patch.
+This means that you can create abstractions that not only include a
+collection of objects but can also include a user interface. To use
+graph on parent you simply need to create an abstraction the usual
+way but before saving it you need should Control-Click (Right-Click)
+on the background (white area) in the abstraction and choose "properties".
+From the properties menu check the "graph on parent" option. Now when
+you save the patch and embed it in a second patch all GUI objects will
+be visible.;
+#X obj 154 250 gop_abstraction;
+#X text 13 331 In this simple example there is only one GUI object
+\, a slider. Inside the abstraction the slider is connected to an inlet
+and an outlet. If you move the slider you can see the result in the
+outlet. If you set a value in the inlet with the number GUI you can
+see the position of the slider change.;
+#X floatatom 154 231 5 0 0 0 - - -;
+#X floatatom 154 297 5 0 0 0 - - -;
+#X text 13 421 Note you can change the size of the abstractions bounding
+box by Control-Click (Right-Click) on the abstraction and choose "properties".
+The size of the bounding-box is specified by the "screen width" and
+"screen height".;
+#X text 13 487 For more info see:;
+#X text 12 8 9 Intermediate Pure-Data - Using GUI's in abstractions
+;
+#X connect 8 0 11 0;
+#X connect 10 0 8 0;
diff --git a/externals/gridflow/examples/binary_operations.pd b/externals/gridflow/examples/binary_operations.pd
new file mode 100644
index 00000000..cf4df98a
--- /dev/null
+++ b/externals/gridflow/examples/binary_operations.pd
@@ -0,0 +1,73 @@
+#N canvas 401 211 734 490 10;
+#X text 163 212 posterize;
+#X obj 99 187 tgl 15 0 empty empty empty 0 -6 0 8 -241291 -1 -1 0 1
+;
+#X obj 143 187 hsl 59 15 2 8 0 0 empty empty empty -2 -6 0 8 -260818
+-1 -1 0 1;
+#X obj 65 103 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 87 361 # ^;
+#X obj 135 336 hsl 137 15 0 255 0 0 empty empty empty -2 -6 0 8 -260818
+-1 -1 0 1;
+#X obj 99 237 tgl 15 0 empty empty empty 0 -6 0 8 -241291 -1 -1 0 1
+;
+#X text 124 144 negative;
+#X obj 39 121 #in;
+#X text 146 361 munchies (XOR effect) in the colour domain;
+#X obj 39 187 shunt 2;
+#X obj 39 338 shunt 2;
+#X text 157 297 color wrapping;
+#X obj 88 261 # %;
+#X obj 98 338 tgl 15 0 empty empty empty 0 -6 0 8 -241291 -1 -1 0 1
+;
+#X obj 87 164 # inv+ 255;
+#X obj 99 142 tgl 15 0 empty empty empty 0 -6 0 8 -241291 -1 -1 0 1
+;
+#X obj 65 54 tgl 15 0 empty empty empty 0 -6 0 8 -24198 -1 -1 0 1;
+#X obj 89 304 # /;
+#X obj 39 142 shunt 2;
+#X obj 39 423 #out window;
+#X obj 88 283 # * 255;
+#X obj 166 265 hsl 137 15 0 255 0 0 empty empty empty -2 -6 0 8 -260818
+-1 -1 0 1;
+#X obj 39 237 shunt 2;
+#X text 88 105 image loader;
+#X msg 65 121 open r001.jpg \, bang;
+#X obj 65 78 metro 33.3667;
+#X obj 87 212 #posterize;
+#X obj 8 456 cnv 15 720 30 empty empty empty 20 12 0 14 -200249 -66577
+0;
+#X text 16 463 GridFlow 0.8.0;
+#X obj 8 5 cnv 15 720 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X text 11 5 binary_operations.pd;
+#X text 222 143 <-- try various combinations of checkboxes and settings.
+then click on the image loader to see the result.;
+#X text 11 19 Copyright Mathieu Bouchard;
+#X connect 1 0 10 1;
+#X connect 2 0 27 1;
+#X connect 3 0 25 0;
+#X connect 4 0 20 0;
+#X connect 5 0 4 1;
+#X connect 6 0 23 1;
+#X connect 8 0 19 0;
+#X connect 10 0 23 0;
+#X connect 10 1 27 0;
+#X connect 11 0 20 0;
+#X connect 11 1 4 0;
+#X connect 13 0 21 0;
+#X connect 14 0 11 1;
+#X connect 15 0 10 0;
+#X connect 16 0 19 1;
+#X connect 17 0 26 0;
+#X connect 18 0 11 0;
+#X connect 19 0 10 0;
+#X connect 19 1 15 0;
+#X connect 21 0 18 0;
+#X connect 22 0 18 1;
+#X connect 22 0 13 1;
+#X connect 23 0 11 0;
+#X connect 23 1 13 0;
+#X connect 25 0 8 0;
+#X connect 26 0 3 0;
+#X connect 27 0 23 0;
diff --git a/externals/gridflow/examples/blob.pd b/externals/gridflow/examples/blob.pd
new file mode 100644
index 00000000..c131ded5
--- /dev/null
+++ b/externals/gridflow/examples/blob.pd
@@ -0,0 +1,106 @@
+#N canvas 19 81 792 575 10;
+#X floatatom 398 265 5 0 0 0 - - -;
+#X obj 368 225 r move;
+#X obj 56 129 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X msg 56 162 240 320 3 # 0;
+#X msg 461 407 300;
+#X obj 398 392 # * 300;
+#X obj 261 475 # cos*;
+#X msg 461 369 1600;
+#X msg 513 299 25;
+#X obj 368 263 +;
+#X msg 513 318 100;
+#X obj 505 244 hsl 128 15 100 2600 0 1 empty empty empty -2 -6 0 8
+-260818 -1 -1 2297 1;
+#X text 314 474 make circular orbit of variable radius;
+#X floatatom 502 261 5 0 0 0 - - -;
+#X msg 461 388 800;
+#X text 294 375 frequency of the orbit;
+#X text 501 229 increment;
+#X msg 368 244 1;
+#X obj 58 108 s move;
+#X obj 73 128 loadbang;
+#X obj 19 50 tgl 15 0 empty empty empty 0 -6 0 8 -24198 -1 -1 1 1;
+#X obj 75 427 #out window;
+#X obj 186 236 # +;
+#X obj 437 345 # + 50;
+#X text 394 250 counter;
+#X obj 19 91 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 19 354 #store;
+#X text 65 147 blank image to start with;
+#X text 212 237 translate the square;
+#X text 546 297 make a wavy radius (50-100) \; the 1100 is its frequency
+\; tune it for fun and profit.;
+#X obj 19 108 t b b;
+#X obj 368 282 t a a a;
+#X msg 186 198 4 2 # -1 -1 -1 1 1 1 1 -1;
+#X obj 8 541 cnv 15 780 30 empty empty empty 20 12 0 14 -200249 -66577
+0;
+#X text 16 548 GridFlow 0.8.0;
+#X obj 8 12 cnv 15 780 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X text 21 12 Blob.pd;
+#X msg 514 337 10;
+#X obj 437 307 # * 1000;
+#X obj 101 265 #color;
+#X obj 101 221 loadbang;
+#X text 385 432 duplicate the angle \; make the 2nd 90 degrees apart
+(required for a circle \; else it'll be an oval or a line);
+#X text 21 25 Copyright 2002 Mathieu Bouchard and Alexandre Castonguay
+;
+#X text 185 182 a 2x2 square's coordinates;
+#X text 228 218 scale factor;
+#X obj 186 217 # * 8;
+#X obj 75 402 #solarize;
+#X text 400 49 This is the classic "Shadebob" effect of the demoscene
+;
+#X msg 101 243 12 24 36;
+#X text 6 331 superimpose the light of many squares;
+#X obj 437 326 # cos* 100;
+#X obj 261 444 #outer + (0 9000);
+#X obj 75 354 #draw_polygon + (3 #);
+#X obj 261 494 # + (120 160);
+#X obj 19 72 metro 33.367;
+#X connect 0 0 9 1;
+#X connect 1 0 17 0;
+#X connect 2 0 3 0;
+#X connect 3 0 26 1;
+#X connect 4 0 5 1;
+#X connect 5 0 51 0;
+#X connect 6 0 53 0;
+#X connect 7 0 5 1;
+#X connect 8 0 50 1;
+#X connect 9 0 0 0;
+#X connect 9 0 31 0;
+#X connect 10 0 50 1;
+#X connect 11 0 13 0;
+#X connect 13 0 38 1;
+#X connect 14 0 5 1;
+#X connect 17 0 9 0;
+#X connect 19 0 2 0;
+#X connect 20 0 54 0;
+#X connect 22 0 52 2;
+#X connect 23 0 6 1;
+#X connect 25 0 30 0;
+#X connect 26 0 52 0;
+#X connect 30 0 26 0;
+#X connect 30 1 18 0;
+#X connect 31 0 32 0;
+#X connect 31 1 5 0;
+#X connect 31 2 38 0;
+#X connect 32 0 45 0;
+#X connect 37 0 50 1;
+#X connect 38 0 50 0;
+#X connect 39 0 52 1;
+#X connect 40 0 48 0;
+#X connect 45 0 22 0;
+#X connect 46 0 21 0;
+#X connect 48 0 39 0;
+#X connect 50 0 23 0;
+#X connect 51 0 6 0;
+#X connect 52 0 26 1;
+#X connect 52 0 46 0;
+#X connect 53 0 22 1;
+#X connect 54 0 25 0;
diff --git a/externals/gridflow/examples/bounce.pd b/externals/gridflow/examples/bounce.pd
new file mode 100644
index 00000000..46421cad
--- /dev/null
+++ b/externals/gridflow/examples/bounce.pd
@@ -0,0 +1,32 @@
+#N canvas 0 0 450 300 10;
+#X obj 34 284 #out window;
+#X floatatom 48 71 5 0 0 0 - - -;
+#X obj 34 16 metro 30;
+#X obj 6 19 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1;
+#X obj 34 42 f;
+#X obj 95 34 + 1;
+#X msg 34 265 set_geometry \$1 \$2 200 200;
+#X obj 34 93 t f f;
+#X obj 34 246 pack 0 0;
+#X obj 64 136 expr $f1-int($f1);
+#X obj 64 156 expr 2*if($f1>=.5 \, $f1 \, (1-$f1));
+#X obj 64 176 expr $f1*400;
+#X obj 64 115 / 200;
+#X obj 95 53 % 1000;
+#X obj 34 206 expr 400-200*abs(sin($f1/3.1416/5));
+#X connect 2 0 4 0;
+#X connect 3 0 2 0;
+#X connect 4 0 5 0;
+#X connect 4 0 1 0;
+#X connect 4 0 7 0;
+#X connect 5 0 13 0;
+#X connect 6 0 0 0;
+#X connect 7 0 14 0;
+#X connect 7 1 12 0;
+#X connect 8 0 6 0;
+#X connect 9 0 10 0;
+#X connect 10 0 11 0;
+#X connect 11 0 8 1;
+#X connect 12 0 9 0;
+#X connect 13 0 4 1;
+#X connect 14 0 8 0;
diff --git a/externals/gridflow/examples/cellular_1d.pd b/externals/gridflow/examples/cellular_1d.pd
new file mode 100644
index 00000000..5fa34551
--- /dev/null
+++ b/externals/gridflow/examples/cellular_1d.pd
@@ -0,0 +1,170 @@
+#N canvas 104 110 783 543 10;
+#X obj 33 103 loadbang;
+#X obj 124 361 tgl 15 0 empty empty empty 0 -6 0 8 -260818 -1 -1 0
+1;
+#X obj 139 361 tgl 15 0 empty empty empty 0 -6 0 8 -260818 -1 -1 1
+1;
+#X obj 154 361 tgl 15 0 empty empty empty 0 -6 0 8 -260818 -1 -1 1
+1;
+#X obj 169 361 tgl 15 0 empty empty empty 0 -6 0 8 -260818 -1 -1 0
+1;
+#X obj 184 361 tgl 15 0 empty empty empty 0 -6 0 8 -260818 -1 -1 1
+1;
+#X obj 199 361 tgl 15 0 empty empty empty 0 -6 0 8 -260818 -1 -1 0
+1;
+#X obj 214 361 tgl 15 0 empty empty empty 0 -6 0 8 -260818 -1 -1 1
+1;
+#X obj 229 361 tgl 15 0 empty empty empty 0 -6 0 8 -260818 -1 -1 0
+1;
+#X obj 124 452 nbx 5 14 -1e+37 1e+37 0 0 empty empty empty 0 -6 0 10
+-241291 -1 -1 86 256;
+#X obj -1 215 bng 15 250 50 0 empty empty empty 0 -6 0 8 -24198 -1
+-1;
+#X msg 17 312 1 256 # 1;
+#X msg 33 122 1 256 # 2;
+#X obj -1 77 tgl 15 0 empty empty empty 0 -6 0 8 -24198 -1 -1 1 1;
+#X text 92 465 characteristic number;
+#X obj 221 166 nbx 2 14 1 99 0 0 empty empty empty 0 -6 0 10 -241291
+-1 -1 1 256;
+#X text 79 141 randomizer;
+#X text 246 360 specify behaviour here;
+#X text 24 234 compute new state;
+#X text 245 233 make scrollie;
+#X text 297 263 convert bit matrix to rgb image;
+#X text 243 246 (window height = 128);
+#X obj 159 74 bng 15 250 50 0 empty empty empty 0 -6 0 8 -24198 -1
+-1;
+#X obj 172 324 loadbang;
+#X obj 75 182 t a a;
+#X obj 444 53 loadbang;
+#X msg 329 54 3 # 0;
+#X msg 505 55 3 # 255;
+#X text 370 55 background;
+#X text 558 57 foreground;
+#X obj 17 272 t a a;
+#X obj 33 141 # rand;
+#X obj 17 214 #store;
+#X obj 17 292 #finished;
+#X obj 17 332 # <<;
+#X obj 17 352 # &;
+#X obj 17 372 # != 0;
+#X obj 124 414 #fold +;
+#X obj 124 433 #export;
+#X obj 159 91 #for 0 256 1;
+#X obj 159 110 # == 128;
+#X obj 281 296 #store;
+#X obj 329 74 #color;
+#X obj 505 74 #color;
+#X obj 423 135 #pack 6;
+#X obj 17 252 #convolve (1 3 # 1 2 4);
+#X obj 124 395 # << (0 1 2 3 4 5 6 7);
+#X obj -4 510 cnv 15 780 30 empty empty empty 20 12 0 14 -200249 -66577
+0;
+#X text 4 517 GridFlow 0.8.0;
+#X obj -7 0 cnv 15 780 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X obj 281 334 #out window;
+#X text -3 15 Copyright 2002 Mathieu Bouchard;
+#X text -3 1 Cellular_1d;
+#X text 253 166 <-- number of new lines per frame;
+#X text 178 73 <-- make single dot;
+#X text 100 123 restart;
+#X obj 281 277 #outer ignore (0);
+#X obj 327 296 #redim (2 3);
+#X obj 329 134 #unpack 3;
+#X obj 505 134 #unpack 3;
+#X obj 159 129 #redim (1 256);
+#X obj 281 315 #scale_by 2;
+#N canvas 79 42 450 300 make_scrollie 0;
+#X obj 41 30 inlet one_line;
+#X obj 290 30 inlet number_of_lines;
+#X obj 42 258 outlet grid;
+#X obj 205 205 loadbang;
+#X msg 205 224 1 256 # 0;
+#X msg 256 87 \$1 256;
+#X msg 142 82 set \$1;
+#X obj 156 125 t a a;
+#X obj 156 144 #finished;
+#X obj 142 167 #for 1 128 1;
+#X obj 142 205 #store;
+#X obj 142 224 @join 0;
+#X obj 142 62 max 1;
+#X obj 142 186 #outer ignore (0);
+#X obj 156 106 #import (1 256);
+#X connect 0 0 14 0;
+#X connect 1 0 12 0;
+#X connect 3 0 4 0;
+#X connect 4 0 10 1;
+#X connect 5 0 14 1;
+#X connect 6 0 9 0;
+#X connect 7 0 8 0;
+#X connect 7 1 11 1;
+#X connect 8 0 9 0;
+#X connect 9 0 13 0;
+#X connect 10 0 11 0;
+#X connect 11 0 10 1;
+#X connect 11 0 2 0;
+#X connect 12 0 6 0;
+#X connect 12 0 5 0;
+#X connect 13 0 10 0;
+#X connect 14 0 7 0;
+#X restore 114 182 pd make_scrollie;
+#X obj 17 76 metro 33.3667;
+#X obj 124 376 #pack 8 \, \, \, \, \, \, \, \, \,;
+#X connect 0 0 12 0;
+#X connect 1 0 64 0;
+#X connect 2 0 64 1;
+#X connect 3 0 64 2;
+#X connect 4 0 64 3;
+#X connect 5 0 64 4;
+#X connect 6 0 64 5;
+#X connect 7 0 64 6;
+#X connect 8 0 64 7;
+#X connect 9 0 35 1;
+#X connect 10 0 32 0;
+#X connect 11 0 34 0;
+#X connect 12 0 31 0;
+#X connect 13 0 63 0;
+#X connect 15 0 62 1;
+#X connect 22 0 39 0;
+#X connect 23 0 2 0;
+#X connect 23 0 3 0;
+#X connect 23 0 7 0;
+#X connect 23 0 5 0;
+#X connect 24 0 32 1;
+#X connect 24 1 62 0;
+#X connect 25 0 26 0;
+#X connect 25 0 27 0;
+#X connect 26 0 42 0;
+#X connect 27 0 43 0;
+#X connect 30 0 33 0;
+#X connect 30 1 34 1;
+#X connect 31 0 24 0;
+#X connect 32 0 45 0;
+#X connect 33 0 11 0;
+#X connect 34 0 35 0;
+#X connect 35 0 36 0;
+#X connect 36 0 24 0;
+#X connect 37 0 38 0;
+#X connect 38 0 9 0;
+#X connect 39 0 40 0;
+#X connect 40 0 60 0;
+#X connect 41 0 61 0;
+#X connect 42 0 58 0;
+#X connect 43 0 59 0;
+#X connect 44 0 57 0;
+#X connect 45 0 30 0;
+#X connect 46 0 37 0;
+#X connect 56 0 41 0;
+#X connect 57 0 41 1;
+#X connect 58 0 44 0;
+#X connect 58 1 44 1;
+#X connect 58 2 44 2;
+#X connect 59 0 44 3;
+#X connect 59 1 44 4;
+#X connect 59 2 44 5;
+#X connect 60 0 24 0;
+#X connect 61 0 50 0;
+#X connect 62 0 56 0;
+#X connect 63 0 32 0;
+#X connect 64 0 46 0;
diff --git a/externals/gridflow/examples/color_correction.pd b/externals/gridflow/examples/color_correction.pd
new file mode 100644
index 00000000..93b1d9fe
--- /dev/null
+++ b/externals/gridflow/examples/color_correction.pd
@@ -0,0 +1,151 @@
+#N canvas 37 349 672 521 10;
+#X text 360 136 sigma (extremes);
+#X obj 134 465 #out window;
+#X text 361 211 linear (contrast);
+#X obj 134 404 shunt 2;
+#N canvas 1 96 188 188 color 0;
+#X obj 25 105 # inv+;
+#X obj 25 67 # inv+ 255;
+#X obj 85 86 inlet;
+#X obj 25 31 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 25 12 inlet;
+#X obj 25 86 #outer <;
+#X obj 25 124 # & 255;
+#X obj 25 48 #for 0 256 1;
+#X obj 25 143 outlet;
+#X connect 0 0 6 0;
+#X connect 1 0 5 0;
+#X connect 2 0 5 1;
+#X connect 3 0 7 0;
+#X connect 4 0 3 0;
+#X connect 5 0 0 0;
+#X connect 6 0 8 0;
+#X connect 7 0 1 0;
+#X restore 194 425 pd color correction graph generator;
+#X obj 59 285 #in;
+#X text 360 284 constant (brightness);
+#N canvas 352 112 370 429 color-correction 0;
+#X obj 23 191 # + 128;
+#X obj 23 172 # /;
+#X obj 23 95 # *;
+#X obj 89 270 # +;
+#X obj 77 95 # max 32;
+#X obj 77 134 # tanh* 512;
+#X obj 23 57 # gamma;
+#X obj 77 114 # << 5;
+#X obj 23 76 # - 128;
+#X obj 23 153 # tanh* 65535;
+#X obj 23 115 # >> 2;
+#X obj 95 232 inlet linear;
+#X obj 114 270 inlet constant;
+#X obj 49 232 # *>>8;
+#X obj 77 76 inlet sigma;
+#X obj 67 38 inlet gamma;
+#X obj 23 19 inlet image;
+#X obj 89 308 outlet image;
+#X obj 89 289 #clip;
+#X connect 0 0 13 0;
+#X connect 1 0 0 0;
+#X connect 2 0 10 0;
+#X connect 3 0 18 0;
+#X connect 4 0 2 1;
+#X connect 4 0 7 0;
+#X connect 5 0 1 1;
+#X connect 6 0 8 0;
+#X connect 7 0 5 0;
+#X connect 8 0 2 0;
+#X connect 9 0 1 0;
+#X connect 10 0 9 0;
+#X connect 11 0 13 1;
+#X connect 12 0 3 1;
+#X connect 13 0 3 0;
+#X connect 14 0 4 0;
+#X connect 15 0 6 1;
+#X connect 16 0 6 0;
+#X connect 18 0 17 0;
+#X restore 176 314 pd color-correction;
+#X obj 134 425 #store;
+#X obj 29 45 tgl 15 0 empty empty empty 0 -6 0 8 -24198 -1 -1 1 1;
+#X obj 29 81 #for 0 256 1;
+#X obj 168 340 #finished;
+#X obj 29 62 metro 33.3667;
+#X obj 59 247 loadbang;
+#X obj 256 92 vradio 15 1 0 3 empty empty empty 0 -6 0 8 -241291 -1
+-1 0;
+#X text 277 93 regular;
+#X text 276 108 solarize;
+#X text 277 122 solarize 2;
+#X obj 29 119 shunt 3;
+#X obj 29 173 t a;
+#X obj 119 174 # sin* 255;
+#X obj 120 155 # / 255;
+#X obj 120 136 # * 18000;
+#X obj 190 391 vradio 15 1 0 2 empty empty empty 0 -6 0 8 -241291 -1
+-1 0;
+#X text 209 391 see picture;
+#X text 209 406 see graph;
+#X obj 8 221 spigot;
+#X obj 57 222 tgl 15 0 empty empty empty 0 -6 0 8 -241291 -1 -1 0 1
+;
+#X text 13 204 enable stream;
+#X text 361 60 gamma (midtones);
+#X msg 254 183 3 # 256;
+#X obj 253 163 loadbang;
+#X msg 238 212 3 # 0;
+#X obj 8 310 #camera;
+#X obj 362 77 #color 0 1024 1;
+#X obj 362 152 #color 0 1024 1;
+#X obj 362 226 #color 0 1024 1;
+#X obj 362 298 #color -256 256 1;
+#X obj 51 140 #solarize;
+#X obj 134 445 #apply_colormap_channelwise;
+#X obj 2 2 cnv 15 720 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X text 15 15 Copyright 2002 Mathieu Bouchard;
+#X obj 2 487 cnv 15 720 30 empty empty empty 20 12 0 14 -200249 -66577
+0;
+#X text 15 2 color_correction.pd;
+#X obj 29 100 #outer ignore (3 #);
+#X text 10 494 GridFlow 0.8.3;
+#X msg 59 266 load bluemarble.jpg;
+#X connect 3 0 8 0;
+#X connect 3 1 4 0;
+#X connect 4 0 1 0;
+#X connect 5 0 8 1;
+#X connect 7 0 11 0;
+#X connect 7 0 4 1;
+#X connect 7 0 39 1;
+#X connect 8 0 39 0;
+#X connect 9 0 12 0;
+#X connect 10 0 44 0;
+#X connect 11 0 3 0;
+#X connect 12 0 10 0;
+#X connect 12 0 26 0;
+#X connect 13 0 46 0;
+#X connect 14 0 18 1;
+#X connect 18 0 19 0;
+#X connect 18 1 38 0;
+#X connect 18 2 22 0;
+#X connect 19 0 7 0;
+#X connect 20 0 19 0;
+#X connect 21 0 20 0;
+#X connect 22 0 21 0;
+#X connect 23 0 3 1;
+#X connect 26 0 33 0;
+#X connect 27 0 26 1;
+#X connect 30 0 34 0;
+#X connect 30 0 36 0;
+#X connect 31 0 30 0;
+#X connect 31 0 32 0;
+#X connect 32 0 37 0;
+#X connect 32 0 35 0;
+#X connect 33 0 8 1;
+#X connect 34 0 7 1;
+#X connect 35 0 7 2;
+#X connect 36 0 7 3;
+#X connect 37 0 7 4;
+#X connect 38 0 19 0;
+#X connect 39 0 1 0;
+#X connect 44 0 18 0;
+#X connect 46 0 5 0;
diff --git a/externals/gridflow/examples/color_detect.pd b/externals/gridflow/examples/color_detect.pd
new file mode 100644
index 00000000..91610cdb
--- /dev/null
+++ b/externals/gridflow/examples/color_detect.pd
@@ -0,0 +1,218 @@
+#N canvas 562 75 668 715 10;
+#X obj 14 262 # > 0;
+#X obj 68 284 # + 128;
+#X obj 383 135 hsl 222 15 0 442 0 0 empty empty tolerance 8 8 0 8 -260818
+-1 -1 10300 1;
+#X obj 224 530 #out window;
+#X obj 68 262 # tanh* 127;
+#X obj 86 2 #store;
+#X obj 277 177 tgl 15 1 empty empty empty 0 -6 0 8 -261689 -258699
+-1 1 1;
+#X obj 31 -64 tgl 15 0 empty empty empty 0 -6 0 8 -24198 -1 -1 1 1
+;
+#X obj 14 179 # inv+;
+#X obj 14 284 # << 8;
+#X obj 14 160 #fold +;
+#X obj 315 360 loadbang;
+#X obj 298 398 #checkers;
+#X obj 224 468 # +;
+#X obj 224 445 # *;
+#X obj 297 446 # *;
+#X obj 224 489 # >> 8;
+#X obj 297 424 # inv+ 256;
+#X obj 271 490 # min 255;
+#X obj 298 362 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 380 76 #color;
+#X obj 72 22 s image;
+#X obj 240 426 r image;
+#X text 374 46 select a point in the color cube \; and a radius of
+accepted similarity.;
+#X obj 277 196 #pack 3;
+#X obj 299 177 tgl 15 1 empty empty empty 0 -6 0 8 -225271 -24198 -1
+1 1;
+#X obj 321 177 tgl 15 1 empty empty empty 0 -6 0 8 -228992 -62784 -1
+1 1;
+#X text 271 161 enable selection on:;
+#X text 339 178 all three = select sphere in color cube \; pick two
+= select circle in a color square \; pick one = select range in one
+channel;
+#X text 377 360 make background;
+#X obj 57 217 # inv+;
+#X obj 295 229 vradio 15 1 0 2 empty empty empty 0 -6 0 8 -241291 -66577
+-1 0;
+#X text 314 228 erase nonselected;
+#X text 314 245 erase selected;
+#X obj 295 269 vradio 15 1 0 2 empty empty empty 0 -6 0 8 -241291 -66577
+-1 1;
+#X text 317 268 strict;
+#X text 316 284 fuzzy;
+#X obj 296 325 vradio 15 1 0 2 empty empty empty 0 -6 0 8 -241291 -66577
+-1 0;
+#X text 318 324 see filtered image on checkers;
+#X text 318 339 see opacity mask;
+#X obj 224 406 t a a;
+#N canvas 414 518 450 216 color 0;
+#X obj 25 3 inlet bang;
+#X obj 26 182 outlet image;
+#X obj 26 144 # min 255;
+#X obj 26 163 # max 0;
+#X obj 178 31 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 25 25 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 178 88 #outer + ( 0 0 9000 );
+#X obj 48 24 t b b;
+#X obj 26 81 #outer * ( 1 0 0 );
+#X obj 26 105 # +;
+#X obj 178 132 # + ( 0 128 128 );
+#X obj 178 48 #for 0 320 1;
+#X obj 179 67 # * 113;
+#X obj 26 62 #outer + ( 320 # 0 );
+#X obj 26 43 #for -120 360 2;
+#X obj 178 155 #redim ( 240 320 3 );
+#X obj 178 109 # cos* ( 0 128 128 );
+#X obj 26 124 #yuv_to_rgb;
+#X connect 0 0 7 0;
+#X connect 2 0 3 0;
+#X connect 3 0 1 0;
+#X connect 4 0 11 0;
+#X connect 5 0 14 0;
+#X connect 6 0 16 0;
+#X connect 7 0 5 0;
+#X connect 7 1 4 0;
+#X connect 8 0 9 0;
+#X connect 9 0 17 0;
+#X connect 10 0 15 0;
+#X connect 11 0 12 0;
+#X connect 12 0 6 0;
+#X connect 13 0 8 0;
+#X connect 14 0 13 0;
+#X connect 15 0 9 1;
+#X connect 16 0 10 0;
+#X connect 17 0 2 0;
+#X restore 133 21 pd color panorama;
+#X obj 133 2 loadbang;
+#X obj 210 -53 vradio 15 1 0 2 empty empty empty 0 -6 0 8 -241291 -66577
+-1 1;
+#X text 229 -54 on video;
+#X text 229 -38 on color panorama;
+#X floatatom 336 136 5 0 0 0 - - -;
+#X obj 76 240 # *>>8 256;
+#X obj 338 302 hsl 129 15 4 4096 1 1 empty empty empty -2 -6 0 8 -260818
+-1 -1 7000 1;
+#X floatatom 295 302 5 0 0 0 - - -;
+#X obj 58 87 #rgb_to_yuv;
+#X obj 90 55 vradio 15 1 0 2 empty empty empty 0 -6 0 8 -241291 -1
+-1 0;
+#X text 107 55 RGB;
+#X text 107 70 YUV;
+#X text 141 55 warning: in YUV mode \,;
+#X text 140 81 green slider = U chroma;
+#X text 147 94 blue slider = V chroma;
+#X text 154 68 red slider = Y luma;
+#X obj 31 -39 metro 33.3667;
+#X obj 31 22 t a a;
+#X obj 31 1 #camera;
+#X obj 332 446 spigot;
+#X obj 379 447 tgl 15 0 empty empty empty 0 -6 0 8 -241291 -1 -1 0
+1;
+#X text 398 448 recurrent layering;
+#X obj 224 511 t a;
+#X obj 14 141 # &;
+#X obj 40 141 # inv+;
+#X obj 36 397 # >> 6;
+#X obj 14 198 shunt 2;
+#X obj 14 241 shunt 2;
+#X obj 14 55 shunt 2;
+#X obj 14 306 shunt 2;
+#X obj 68 308 tgl 15 0 empty empty empty 0 -6 0 8 -241291 -1 -1 0 1
+;
+#X text 87 302 sort-of feather;
+#X obj 224 385 shunt 2;
+#X text 87 317 (8x8 square blur on mask);
+#X obj 31 -18 shunt 2;
+#X obj 36 377 # + 32;
+#X obj -2 561 cnv 15 740 30 empty empty empty 20 12 0 14 -200249 -66577
+0;
+#X text 6 568 GridFlow 0.8.0;
+#X obj 1 -118 cnv 15 740 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X text 14 -118 color_detect.pd;
+#X text 13 -105 Copyright 2001-2004 Mathieu Bouchard;
+#X obj 14 122 # sq-;
+#X obj 61 179 # sq-;
+#X obj 36 337 #convolve (8 1 # 1);
+#X obj 36 357 #convolve (1 8 # 1);
+#X obj 14 457 #outer ignore (3 # 0);
+#X obj 298 379 #for (0 0) (240 320) (1 1);
+#X connect 0 0 9 0;
+#X connect 1 0 71 0;
+#X connect 2 0 46 0;
+#X connect 4 0 1 0;
+#X connect 5 0 59 0;
+#X connect 6 0 24 0;
+#X connect 7 0 58 0;
+#X connect 8 0 68 0;
+#X connect 9 0 71 0;
+#X connect 10 0 8 0;
+#X connect 11 0 19 0;
+#X connect 12 0 15 1;
+#X connect 13 0 16 0;
+#X connect 14 0 13 0;
+#X connect 15 0 13 1;
+#X connect 16 0 64 0;
+#X connect 17 0 15 0;
+#X connect 18 0 64 0;
+#X connect 19 0 88 0;
+#X connect 20 0 83 1;
+#X connect 22 0 14 1;
+#X connect 24 0 66 0;
+#X connect 25 0 24 1;
+#X connect 26 0 24 2;
+#X connect 30 0 69 0;
+#X connect 31 0 68 1;
+#X connect 34 0 69 1;
+#X connect 37 0 74 1;
+#X connect 40 0 14 0;
+#X connect 40 1 17 0;
+#X connect 41 0 5 1;
+#X connect 42 0 41 0;
+#X connect 43 0 76 1;
+#X connect 46 0 84 0;
+#X connect 47 0 4 0;
+#X connect 48 0 49 0;
+#X connect 49 0 47 1;
+#X connect 50 0 83 0;
+#X connect 51 0 70 1;
+#X connect 58 0 76 0;
+#X connect 59 0 70 0;
+#X connect 59 1 21 0;
+#X connect 60 0 59 0;
+#X connect 61 0 15 1;
+#X connect 62 0 61 1;
+#X connect 64 0 3 0;
+#X connect 64 0 61 0;
+#X connect 65 0 10 0;
+#X connect 66 0 65 1;
+#X connect 67 0 87 0;
+#X connect 68 0 69 0;
+#X connect 68 1 30 0;
+#X connect 69 0 0 0;
+#X connect 69 1 47 0;
+#X connect 70 0 83 0;
+#X connect 70 1 50 0;
+#X connect 71 0 87 0;
+#X connect 71 1 85 0;
+#X connect 72 0 71 1;
+#X connect 74 0 40 0;
+#X connect 74 1 18 0;
+#X connect 76 0 60 0;
+#X connect 76 1 5 0;
+#X connect 77 0 67 0;
+#X connect 83 0 65 0;
+#X connect 84 0 8 1;
+#X connect 85 0 86 0;
+#X connect 86 0 77 0;
+#X connect 87 0 74 0;
+#X connect 88 0 12 0;
diff --git a/externals/gridflow/examples/convolve.pd b/externals/gridflow/examples/convolve.pd
new file mode 100644
index 00000000..4b6aeb67
--- /dev/null
+++ b/externals/gridflow/examples/convolve.pd
@@ -0,0 +1,90 @@
+#N canvas 17 90 652 511 10;
+#X obj 40 102 bng 15 250 50 0 empty empty empty 0 -6 0 8 -24198 -1
+-1;
+#X obj 40 220 #store;
+#X obj 136 306 # / 9;
+#X obj 31 300 #out window;
+#X obj 78 175 #in;
+#X obj 40 66 tgl 15 0 empty empty empty 0 -6 0 8 -24198 -1 -1 0 1;
+#X text 351 75 step 1: select one of those six grids;
+#X obj 78 135 loadbang;
+#X obj 40 83 metro 33.3667;
+#X obj 78 197 t a;
+#X obj 136 287 #convolve \, seed 4;
+#X obj 352 95 loadbang;
+#X text 13 239 feedback loop;
+#X obj 136 325 shunt 2;
+#X obj 191 327 tgl 15 0 empty empty empty 0 -6 0 8 -241291 -1 -1 0
+1;
+#X msg 307 205 0;
+#X obj 183 365 # + 128;
+#X msg 317 365 1;
+#X obj 31 319 fps;
+#X obj 31 338 print;
+#X obj 5 481 cnv 15 780 30 empty empty empty 20 12 0 14 -200249 -66577
+0;
+#X text 13 488 GridFlow 0.8.0;
+#X text 13 488 GridFlow 0.8.0;
+#X obj 7 5 cnv 15 780 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X text 20 18 Copyright 2002 Mathieu Bouchard;
+#X text 20 5 convolve.pd;
+#X text 526 282 Laplacian masks;
+#X text 416 352 Sharpen;
+#X text 527 107 Blurs;
+#X obj 183 346 # << 4;
+#X msg 78 155 open babbage.jpg \, bang;
+#X obj 136 344 # abs-;
+#X obj 136 392 #clip;
+#X msg 416 370 3 3 # -1 -1 -1 -1 17;
+#X msg 416 325 3 3 # -1 -1 -1 -1 8;
+#X msg 419 302 3 3 # 0 1 0 1 -4 1 0 1 0;
+#X msg 413 246 1 3 # 0 9 -9;
+#X msg 413 227 1 3 # 0 2 -2;
+#X msg 401 127 3 3 # 1 1 1 1 1 1 1 1 1;
+#X msg 407 147 3 3 # 4 0 0 0 1 0 0 0 4;
+#X msg 397 187 3 3 # 2 2 2 2 -7 2 2 2 2;
+#X msg 402 207 3 3 # 0 4 0 4 9 -4 0 -4 0;
+#X text 420 170 Simple edge detection;
+#X obj 134 197 display;
+#X obj 277 186 t a b;
+#X obj 287 346 t a b;
+#X obj 210 217 # +;
+#X connect 0 0 1 0;
+#X connect 1 0 10 0;
+#X connect 2 0 13 0;
+#X connect 3 0 18 0;
+#X connect 4 0 9 0;
+#X connect 5 0 8 0;
+#X connect 7 0 30 0;
+#X connect 8 0 0 0;
+#X connect 9 0 1 1;
+#X connect 9 0 3 0;
+#X connect 10 0 2 0;
+#X connect 11 0 38 0;
+#X connect 13 0 31 0;
+#X connect 13 1 29 0;
+#X connect 14 0 13 1;
+#X connect 15 0 14 0;
+#X connect 16 0 32 0;
+#X connect 17 0 14 0;
+#X connect 18 0 19 0;
+#X connect 29 0 16 0;
+#X connect 30 0 4 0;
+#X connect 31 0 32 0;
+#X connect 32 0 9 0;
+#X connect 33 0 44 0;
+#X connect 34 0 45 0;
+#X connect 35 0 45 0;
+#X connect 36 0 45 0;
+#X connect 37 0 44 0;
+#X connect 38 0 44 0;
+#X connect 39 0 44 0;
+#X connect 40 0 44 0;
+#X connect 41 0 44 0;
+#X connect 44 0 46 0;
+#X connect 44 1 15 0;
+#X connect 45 0 46 0;
+#X connect 45 1 17 0;
+#X connect 46 0 10 1;
+#X connect 46 0 43 0;
diff --git a/externals/gridflow/examples/cross_fade.pd b/externals/gridflow/examples/cross_fade.pd
new file mode 100644
index 00000000..c612e1db
--- /dev/null
+++ b/externals/gridflow/examples/cross_fade.pd
@@ -0,0 +1,76 @@
+#N canvas 344 101 680 501 10;
+#X obj 13 229 # *>>8;
+#X text 40 253 first picture plus a fraction of the difference;
+#X obj 13 251 # +;
+#X obj 13 210 #store;
+#X obj 211 157 # inv+;
+#X obj 68 271 tgl 15 0 empty empty empty 0 -6 0 8 -241291 -1 -1 0 1
+;
+#X text 12 372 note: the #layer/#join objects can make the crossfade
+process simpler but it's still not faster.;
+#X obj 13 46 tgl 15 0 empty empty empty 0 -6 0 8 -24198 -1 -1 1 1;
+#X obj 264 130 #in;
+#X obj 13 191 #finished;
+#X text 85 271 click to clip out-of-range colours;
+#X text 60 229 multiply by a N/256 fraction;
+#X obj 211 111 #in;
+#X obj 13 353 #out window;
+#X text 61 213 keep the difference between both pictures;
+#X obj 249 91 t b b;
+#X obj 249 72 loadbang;
+#X obj 13 270 shunt 2;
+#X obj 13 82 float;
+#X obj 25 101 nbx 5 14 -1e+37 1e+37 0 0 empty empty empty 0 -6 0 10
+-262144 -1 -1 2784 256;
+#X obj 52 82 + 4;
+#X obj 13 117 pingpong 256;
+#X obj 21 136 hsl 129 15 0 256 0 0 empty empty empty -2 -6 0 8 -260818
+-1 -1 11200 1;
+#X text 11 406 also #draw_image/#join is a possibility;
+#X obj 0 1 cnv 15 680 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X text 14 14 Copyright 2002 Mathieu Bouchard;
+#X text 14 -2 cross_fade.pd;
+#X obj 0 469 cnv 15 680 30 empty empty empty 20 12 0 14 -200249 -66577
+0;
+#X text 8 477 GridFlow 0.8.0;
+#X obj 57 308 #clip;
+#X msg 237 111 load b001.jpg;
+#X msg 289 130 load r001.jpg;
+#X obj 264 149 #cast s;
+#X obj 211 130 #cast s;
+#X obj 13 172 t a a;
+#X obj 13 63 metro 33.3667;
+#X obj 57 289 #cast i;
+#X obj 13 153 #cast s;
+#X connect 0 0 2 0;
+#X connect 2 0 17 0;
+#X connect 3 0 0 0;
+#X connect 4 0 3 1;
+#X connect 5 0 17 1;
+#X connect 7 0 35 0;
+#X connect 8 0 32 0;
+#X connect 9 0 3 0;
+#X connect 12 0 33 0;
+#X connect 15 0 30 0;
+#X connect 15 1 31 0;
+#X connect 16 0 15 0;
+#X connect 17 0 13 0;
+#X connect 17 1 36 0;
+#X connect 18 0 19 0;
+#X connect 18 0 20 0;
+#X connect 18 0 21 0;
+#X connect 20 0 18 1;
+#X connect 21 0 22 0;
+#X connect 21 0 37 0;
+#X connect 29 0 13 0;
+#X connect 30 0 12 0;
+#X connect 31 0 8 0;
+#X connect 32 0 4 1;
+#X connect 33 0 4 0;
+#X connect 33 0 2 1;
+#X connect 34 0 9 0;
+#X connect 34 1 0 1;
+#X connect 35 0 18 0;
+#X connect 36 0 29 0;
+#X connect 37 0 34 0;
diff --git a/externals/gridflow/examples/doodle.pd b/externals/gridflow/examples/doodle.pd
new file mode 100644
index 00000000..8999b273
--- /dev/null
+++ b/externals/gridflow/examples/doodle.pd
@@ -0,0 +1,51 @@
+#N canvas 0 0 450 427 10;
+#X obj 22 22 metro 33.3667;
+#X obj 1 22 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1;
+#X obj 183 74 t b l;
+#X obj 270 93 loadbang;
+#X msg 222 74 put_at ( \$1 \$2 0 );
+#X msg 270 112 0 192 255;
+#X obj 22 133 #scale_by 8;
+#X obj 22 262 #out window;
+#X obj 22 295 #mouse;
+#X obj 22 314 # / 8;
+#X obj 22 333 #export_list;
+#X obj 183 93 #store;
+#X obj 270 131 #color;
+#X obj 22 114 #store (64 64 3 #);
+#X obj 200 225 #for (0 0) (8 8) (1 1);
+#X obj 200 263 #fold &;
+#X obj 211 203 loadbang;
+#X obj 189 205 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X msg 196 168 0 0;
+#X obj 22 167 #draw_image *>>8 \, tile 1;
+#X obj 200 244 # !=;
+#X obj 200 282 # * 128;
+#X obj 200 301 #outer + (3 # 127);
+#X connect 0 0 13 0;
+#X connect 1 0 0 0;
+#X connect 2 0 11 0;
+#X connect 2 1 4 0;
+#X connect 3 0 5 0;
+#X connect 4 0 13 1;
+#X connect 5 0 12 0;
+#X connect 5 0 18 0;
+#X connect 6 0 19 0;
+#X connect 7 0 8 0;
+#X connect 8 0 9 0;
+#X connect 8 1 9 0;
+#X connect 9 0 10 0;
+#X connect 10 0 2 0;
+#X connect 11 0 13 1;
+#X connect 12 0 11 1;
+#X connect 13 0 6 0;
+#X connect 14 0 20 0;
+#X connect 15 0 21 0;
+#X connect 16 0 14 0;
+#X connect 17 0 14 0;
+#X connect 18 0 19 2;
+#X connect 19 0 7 0;
+#X connect 20 0 15 0;
+#X connect 21 0 22 0;
+#X connect 22 0 19 1;
diff --git a/externals/gridflow/examples/drag_rectangle.pd b/externals/gridflow/examples/drag_rectangle.pd
new file mode 100644
index 00000000..4d5bd6b7
--- /dev/null
+++ b/externals/gridflow/examples/drag_rectangle.pd
@@ -0,0 +1,106 @@
+#N canvas 420 110 647 484 10;
+#X obj 274 73 tgl 15 0 empty empty empty 0 -6 0 8 -24198 -1 -1 1 1
+;
+#X obj 274 197 #out window;
+#X obj 64 224 hsl 128 15 0 319 0 0 x1_o x1_i empty -2 -8 1 10 -262144
+-1 -1 8560 1;
+#X obj 64 76 hsl 128 15 0 319 0 0 x0_o x0_i empty 0 8 1 10 -262144
+-66577 -258699 5215 0;
+#X obj 46 93 vsl 15 128 239 0 0 0 y0_o y0_i empty 0 -8 1 10 -262144
+-1 -1 10840 1;
+#X obj 194 93 vsl 15 128 239 0 0 0 y1_o y1_i empty 0 -8 1 10 -262144
+-1 -1 7439 1;
+#N canvas 463 375 452 302 make_rectangle 0;
+#X obj 27 16 inlet;
+#X text 25 -3 image;
+#X obj 93 17 inlet;
+#X text 92 0 start pos;
+#X obj 172 18 inlet;
+#X text 172 1 end pos;
+#X obj 27 244 outlet;
+#X text 27 264 image;
+#X obj 125 81 #export_list;
+#X msg 95 135 4 2 # \$1 \$2 \$1 \$4 \$3 \$4 \$3 \$2;
+#X obj 27 177 #draw_polygon >> (1 1 1) (4 2 #);
+#X obj 90 37 #unpack;
+#X obj 154 42 #unpack;
+#X obj 125 62 #pack 4;
+#X connect 0 0 10 0;
+#X connect 2 0 11 0;
+#X connect 4 0 12 0;
+#X connect 8 0 9 0;
+#X connect 9 0 10 2;
+#X connect 10 0 6 0;
+#X connect 11 0 13 0;
+#X connect 11 1 13 1;
+#X connect 12 0 13 2;
+#X connect 12 1 13 3;
+#X connect 13 0 8 0;
+#X restore 274 177 pd make_rectangle;
+#X obj 274 123 metro 33.3667;
+#X text 21 75 start;
+#X text 198 224 end;
+#X obj 371 103 loadbang;
+#X obj 274 152 #store;
+#X obj 436 105 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 358 197 #mouse \, ...;
+#X obj 421 145 loadbang;
+#X msg 421 164 0 0;
+#X obj 385 241 t a;
+#X obj 90 402 #out window;
+#X obj 129 301 t b a;
+#X obj 90 366 #store;
+#X msg 91 323 set ( \$1 \$2 );
+#X obj 370 123 #in b001.jpg;
+#X text 73 115 drag the mouse;
+#X text 99 100 step 2:;
+#X text 82 131 inside the;
+#X text 80 146 first window;
+#X text 261 55 step 1: turn on;
+#X text 95 384 cropping (to 2nd window);
+#X obj 2 453 cnv 15 640 30 empty empty empty 20 12 0 14 -200249 -66577
+0;
+#X text 10 460 GridFlow 0.8.0;
+#X text 10 460 GridFlow 0.8.0;
+#X obj 3 3 cnv 15 640 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X text 16 16 Copyright 2002 Mathieu Bouchard;
+#X text 16 3 drag_rectangle.pd;
+#X obj 90 347 #for (0 0) (0 0) (1 1);
+#X obj 358 359 unpack;
+#X obj 493 354 unpack;
+#X obj 395 378 s x0_i;
+#X obj 493 392 s y1_i;
+#X obj 530 373 s x1_i;
+#X obj 358 397 s y0_i;
+#X connect 0 0 7 0;
+#X connect 1 0 13 0;
+#X connect 6 0 1 0;
+#X connect 7 0 11 0;
+#X connect 10 0 21 0;
+#X connect 11 0 6 0;
+#X connect 12 0 21 0;
+#X connect 13 0 6 1;
+#X connect 13 0 20 0;
+#X connect 13 0 16 0;
+#X connect 13 0 35 0;
+#X connect 13 1 16 0;
+#X connect 13 2 16 0;
+#X connect 13 2 18 0;
+#X connect 14 0 15 0;
+#X connect 15 0 6 1;
+#X connect 15 0 6 2;
+#X connect 16 0 6 2;
+#X connect 16 0 36 0;
+#X connect 18 0 34 0;
+#X connect 18 1 34 1;
+#X connect 19 0 17 0;
+#X connect 20 0 34 0;
+#X connect 21 0 11 1;
+#X connect 21 0 19 1;
+#X connect 34 0 19 0;
+#X connect 35 0 40 0;
+#X connect 35 1 37 0;
+#X connect 36 0 38 0;
+#X connect 36 1 39 0;
diff --git a/externals/gridflow/examples/eclipse.pd b/externals/gridflow/examples/eclipse.pd
new file mode 100644
index 00000000..068b1e7d
--- /dev/null
+++ b/externals/gridflow/examples/eclipse.pd
@@ -0,0 +1,77 @@
+#N canvas 246 45 635 533 10;
+#X floatatom 342 279 5 0 0 0 - - -;
+#X obj 61 -35 tgl 15 0 empty empty empty 0 -6 0 8 -24198 -1 -1 1 1
+;
+#X obj 294 237 loadbang;
+#X floatatom 294 281 5 0 0 0 - - -;
+#X obj 38 17 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 61 -6 metro 33.3667;
+#X text 289 214 size of subimages;
+#X obj 61 17 #camera;
+#X obj 61 91 #finished;
+#X obj 61 183 # /;
+#X obj 61 202 # *;
+#X obj 61 229 #store;
+#X obj 61 294 #out window;
+#X obj 294 299 #pack 2;
+#X obj 127 219 #store;
+#X obj 127 196 # *;
+#X obj 1 418 cnv 15 640 30 empty empty empty 20 12 0 14 -200249 -66577
+0;
+#X obj 3 -85 cnv 15 640 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X text 121 17 <-- open this;
+#X text 16 -85 eclipse.pd;
+#X obj 61 72 t a a;
+#X obj 61 110 t b b;
+#X obj 61 332 print;
+#X obj 61 313 fps detailed;
+#X text 9 425 GridFlow 0.8.3;
+#X msg 294 259 6;
+#X msg 342 259 8;
+#X obj 294 318 # inv* (240 320);
+#X text 16 -72 Copyright 2002 \, 2006 Mathieu Bouchard;
+#X obj 164 114 #for (0 0) (240 320) (1 1);
+#X obj 61 164 #store;
+#X obj 127 174 #store;
+#X obj 61 275 #clip;
+#X obj 164 95 loadbang;
+#X obj 61 256 # *>>8;
+#X obj 61 36 #gamma 600;
+#X text 183 145 this is actually like #remap_image but faster;
+#X connect 0 0 13 1;
+#X connect 1 0 5 0;
+#X connect 2 0 26 0;
+#X connect 2 0 25 0;
+#X connect 3 0 13 0;
+#X connect 4 0 7 0;
+#X connect 5 0 7 0;
+#X connect 7 0 35 0;
+#X connect 8 0 21 0;
+#X connect 9 0 10 0;
+#X connect 10 0 11 0;
+#X connect 11 0 34 0;
+#X connect 12 0 23 0;
+#X connect 13 0 15 1;
+#X connect 13 0 27 0;
+#X connect 14 0 34 1;
+#X connect 15 0 14 0;
+#X connect 20 0 8 0;
+#X connect 20 1 11 1;
+#X connect 20 1 14 1;
+#X connect 21 0 30 0;
+#X connect 21 1 31 0;
+#X connect 23 0 22 0;
+#X connect 25 0 3 0;
+#X connect 26 0 0 0;
+#X connect 27 0 9 1;
+#X connect 27 0 10 1;
+#X connect 29 0 30 1;
+#X connect 29 0 31 1;
+#X connect 30 0 9 0;
+#X connect 31 0 15 0;
+#X connect 32 0 12 0;
+#X connect 33 0 29 0;
+#X connect 34 0 32 0;
+#X connect 35 0 20 0;
diff --git a/externals/gridflow/examples/epicycloid.pd b/externals/gridflow/examples/epicycloid.pd
new file mode 100644
index 00000000..000bc8c0
--- /dev/null
+++ b/externals/gridflow/examples/epicycloid.pd
@@ -0,0 +1,125 @@
+#N canvas 301 73 904 550 10;
+#X text 158 43 epicycloid;
+#X text 168 56 x(t) = (R+r) cos(t) - p*cos((R+r)t/r);
+#X text 168 69 y(t) = (R+r) sin(t) - p*sin((R+r)t/r);
+#X obj 24 273 #draw_polygon put 1;
+#X obj 24 292 #out window;
+#X obj -22 68 tgl 15 0 empty empty empty 0 -6 0 8 -24198 -1 -1 0 1
+;
+#X obj 297 428 pack f f f f;
+#X msg 297 447 \$2 \$1 \$4 \$1 \$4 \$3 \$2 \$3;
+#X text 304 403 x;
+#X text 364 405 y;
+#X text 391 407 y+1;
+#X text 327 405 x+1;
+#X floatatom 303 381 5 0 0 0 - - -;
+#X obj 345 379 + 1;
+#X floatatom 390 382 5 0 0 0 - - -;
+#X obj 432 379 + 1;
+#X obj 303 358 t f f;
+#X obj 390 361 t f f;
+#X obj -16 108 s met;
+#X obj 258 428 r met;
+#X obj 388 197 hsl 128 15 5 100 0 1 empty empty empty -2 -6 0 8 -24198
+-1 -1 5500 1;
+#X obj 515 238 hsl 128 15 -100 100 0 1 empty empty empty -2 -6 0 8
+-44926 -1 -1 4000 1;
+#X obj 665 263 hsl 128 15 -150 150 0 1 empty empty empty -2 -6 0 8
+-258699 -1 -1 3200 1;
+#X text 313 155 t = valeur en angles de 0 a 360;
+#X obj 385 241 t f f;
+#X obj 512 270 t f f;
+#X obj 662 283 t f f;
+#X obj 303 217 * 6.28319;
+#X obj 303 196 / 360;
+#X floatatom 303 178 5 0 0 0 - - -;
+#X obj 303 236 t f f;
+#X obj -22 273 #store;
+#X obj -14 129 loadbang;
+#X obj 390 323 expr ($f2+$f3)*sin($f1) - $f4*sin(($f2+$f3)*$f1/$f3)
+;
+#X obj 303 302 expr ($f2+$f3)*cos($f1) - $f4*cos(($f2+$f3)*$f1/$f3)
+;
+#X obj 303 135 + 1;
+#X msg 303 111 1;
+#X floatatom 335 138 5 0 0 0 - - -;
+#X msg 335 119 0;
+#X text 366 122 reset count;
+#X text 100 147 reset image;
+#X text 470 216 r = Rayon du deuxieme cercle -100 a 100;
+#X obj 390 342 + 150;
+#X obj 303 339 + 150;
+#X floatatom 397 223 5 0 0 0 - - -;
+#X floatatom 563 263 5 0 0 0 - - -;
+#X floatatom 712 286 5 0 0 0 - - -;
+#X obj -22 85 metro 1;
+#X obj 25 68 hsl 128 15 0 15 0 0 empty empty empty -2 -6 0 8 -260818
+-1 -1 0 1;
+#X text 360 178 R = Rayon du premier cercle 5 a 100;
+#X obj -38 515 cnv 15 900 30 empty empty empty 20 12 0 14 -200249 -66577
+0;
+#X text -29 522 GridFlow 0.8.0;
+#X text -29 522 GridFlow 0.8.0;
+#X obj -35 5 cnv 15 800 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X obj 88 213 #color;
+#X obj 88 175 loadbang;
+#X msg 88 194 230 224 0;
+#X msg -14 148 300 300 3 # 0;
+#X text -22 18 Copyright 2004 Alexandre Castonguay;
+#X text -22 5 epicycloid.pd;
+#X text 51 128 start with a blank \, black image;
+#X text 660 248 deuxieme cercle - 150 a 150;
+#X text 660 233 p = distance du centre du;
+#X obj 297 466 #import (4 2);
+#X connect 3 0 4 0;
+#X connect 3 0 31 1;
+#X connect 5 0 47 0;
+#X connect 6 0 7 0;
+#X connect 7 0 63 0;
+#X connect 12 0 6 0;
+#X connect 13 0 6 2;
+#X connect 14 0 6 1;
+#X connect 15 0 6 3;
+#X connect 16 0 12 0;
+#X connect 16 1 13 0;
+#X connect 17 0 14 0;
+#X connect 17 1 15 0;
+#X connect 19 0 6 0;
+#X connect 20 0 24 0;
+#X connect 20 0 44 0;
+#X connect 21 0 25 0;
+#X connect 21 0 45 0;
+#X connect 22 0 26 0;
+#X connect 22 0 46 0;
+#X connect 24 0 34 1;
+#X connect 24 1 33 1;
+#X connect 25 0 34 2;
+#X connect 25 1 33 2;
+#X connect 26 0 34 3;
+#X connect 26 1 33 3;
+#X connect 27 0 30 0;
+#X connect 28 0 27 0;
+#X connect 29 0 28 0;
+#X connect 30 0 34 0;
+#X connect 30 1 33 0;
+#X connect 31 0 3 0;
+#X connect 32 0 57 0;
+#X connect 33 0 42 0;
+#X connect 34 0 43 0;
+#X connect 35 0 37 0;
+#X connect 35 0 29 0;
+#X connect 36 0 35 0;
+#X connect 37 0 35 1;
+#X connect 38 0 37 0;
+#X connect 42 0 17 0;
+#X connect 43 0 16 0;
+#X connect 47 0 18 0;
+#X connect 47 0 31 0;
+#X connect 47 0 36 0;
+#X connect 48 0 47 1;
+#X connect 54 0 3 1;
+#X connect 55 0 56 0;
+#X connect 56 0 54 0;
+#X connect 57 0 31 1;
+#X connect 63 0 3 2;
diff --git a/externals/gridflow/examples/feedback_fractal.pd b/externals/gridflow/examples/feedback_fractal.pd
new file mode 100644
index 00000000..abb70e80
--- /dev/null
+++ b/externals/gridflow/examples/feedback_fractal.pd
@@ -0,0 +1,147 @@
+#N canvas 609 30 779 549 10;
+#N canvas 0 0 450 300 experimental 0;
+#X obj 32 212 outlet 0;
+#X obj 39 81 @for ( 0 0 ) ( 256 256 ) ( 1 1 );
+#X obj 39 55 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 207 64 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 206 87 @for ( 0 0 ) ( 256 256 ) ( 1 1 );
+#X obj 206 109 @ >> ( 4 6 );
+#X obj 39 104 @ << ( 4 2 );
+#X obj 198 140 @inner & ^ 1 ( 2 2 # 85 170 170 85 );
+#X obj 39 126 @ +;
+#X obj 39 33 inlet;
+#X connect 1 0 6 0;
+#X connect 2 0 1 0;
+#X connect 3 0 4 0;
+#X connect 4 0 5 0;
+#X connect 5 0 8 1;
+#X connect 6 0 8 0;
+#X connect 8 0 0 0;
+#X connect 9 0 2 0;
+#X restore 545 260 pd experimental features;
+#X text 515 193 Choose Julia Mapping or Rotation;
+#X obj 31 53 tgl 15 0 empty empty empty 0 -6 0 8 -24198 -1 -1 1 1;
+#X obj 414 145 bng 15 250 50 0 empty empty empty 0 -6 0 8 -24198 -1
+-1;
+#X text 135 196 apply transform (with feedback);
+#X floatatom 430 363 5 0 0 0 - - -;
+#X floatatom 518 387 5 0 0 0 - - -;
+#X text 434 375 zoom;
+#X text 518 397 move x;
+#X msg 518 368 -45;
+#X msg 430 344 128;
+#X obj 119 197 bng 15 250 50 0 empty empty empty 0 -6 0 8 -24198 -1
+-1;
+#X obj 444 119 bng 15 250 50 0 empty empty empty 0 -6 0 8 -24198 -1
+-1;
+#X obj 497 193 tgl 15 0 empty empty empty 0 -6 0 8 -241291 -1 -1 0
+1;
+#X floatatom 472 387 5 0 0 0 - - -;
+#X text 471 398 move y;
+#X msg 472 368 193;
+#X obj 31 80 metro 33.3667;
+#X obj 442 191 shunt 2;
+#X obj 77 365 loadbang;
+#X obj 414 91 t b b;
+#X obj 414 67 loadbang;
+#X obj 31 338 t a;
+#X obj 131 220 loadbang;
+#X obj 131 239 bng 15 250 50 0 empty empty empty 0 -6 0 8 -24198 -1
+-1;
+#X obj 119 317 t a;
+#X obj 31 108 t b b;
+#X obj 73 109 float;
+#X obj 73 128 + 1;
+#X obj 84 148 nbx 5 14 -1e+37 1e+37 0 0 empty empty empty 0 -6 0 10
+-262144 -1 -1 57 256;
+#X obj 486 323 t b;
+#X text 149 240 reset transform;
+#X obj 99 128 mod 60;
+#X obj 73 168 sel 59;
+#X obj 31 200 #store;
+#X obj 31 276 # << 7;
+#X obj 31 295 #fade 10;
+#X obj 31 314 # >> 7;
+#X obj 31 422 #store;
+#X obj 31 451 #out window;
+#X obj 414 478 # -;
+#X obj 438 454 # - 128;
+#X obj 414 390 # /;
+#X obj 414 296 #store;
+#X obj 442 172 #for ( -128 -128 ) ( 128 128 ) ( 1 1 );
+#X obj 442 210 @complex_sq;
+#X obj 485 229 #inner (2 2 # 120 30 -30 120);
+#X obj -13 0 cnv 15 780 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X obj -15 518 cnv 15 780 30 empty empty empty 20 12 0 14 -200249 -66577
+0;
+#X text -7 525 GridFlow 0.8.0;
+#X text -7 525 GridFlow 0.8.0;
+#X text 0 0 feedback_fractal.pd;
+#X text 0 13 Copyright 2001 Mathieu Bouchard;
+#X obj 131 258 #for (0 0) (256 256) (1 1);
+#X obj 119 298 #store;
+#X obj 119 279 #store;
+#X obj 77 422 #cast b;
+#X obj 77 403 #in;
+#X msg 77 384 load teapot.png;
+#X obj 438 432 #pack;
+#X text 431 145 apply coords;
+#X text 462 118 apply type of transform;
+#X connect 0 0 43 1;
+#X connect 2 0 17 0;
+#X connect 3 0 43 0;
+#X connect 5 0 42 1;
+#X connect 6 0 59 1;
+#X connect 9 0 6 0;
+#X connect 10 0 5 0;
+#X connect 11 0 55 0;
+#X connect 12 0 44 0;
+#X connect 13 0 18 1;
+#X connect 14 0 59 0;
+#X connect 16 0 14 0;
+#X connect 17 0 26 0;
+#X connect 18 0 45 0;
+#X connect 18 1 46 0;
+#X connect 19 0 58 0;
+#X connect 20 0 3 0;
+#X connect 20 1 12 0;
+#X connect 20 1 30 0;
+#X connect 21 0 20 0;
+#X connect 22 0 38 0;
+#X connect 23 0 24 0;
+#X connect 24 0 53 0;
+#X connect 25 0 34 1;
+#X connect 25 0 54 1;
+#X connect 26 0 34 0;
+#X connect 26 1 27 0;
+#X connect 27 0 28 0;
+#X connect 28 0 29 0;
+#X connect 28 0 32 0;
+#X connect 28 0 33 0;
+#X connect 30 0 10 0;
+#X connect 30 0 16 0;
+#X connect 30 0 9 0;
+#X connect 32 0 27 1;
+#X connect 33 0 11 0;
+#X connect 34 0 35 0;
+#X connect 35 0 36 0;
+#X connect 36 0 37 0;
+#X connect 37 0 22 0;
+#X connect 38 0 39 0;
+#X connect 40 0 55 1;
+#X connect 41 0 40 1;
+#X connect 42 0 40 0;
+#X connect 43 0 42 0;
+#X connect 44 0 18 0;
+#X connect 45 0 43 1;
+#X connect 46 0 43 1;
+#X connect 53 0 34 1;
+#X connect 53 0 54 1;
+#X connect 54 0 25 0;
+#X connect 55 0 54 0;
+#X connect 56 0 38 1;
+#X connect 57 0 56 0;
+#X connect 58 0 57 0;
diff --git a/externals/gridflow/examples/fire.pd b/externals/gridflow/examples/fire.pd
new file mode 100644
index 00000000..f9aa2ea8
--- /dev/null
+++ b/externals/gridflow/examples/fire.pd
@@ -0,0 +1,300 @@
+#N canvas 588 0 632 527 10;
+#X obj 377 355 loadbang;
+#X text 243 362 palette generator;
+#X obj 100 383 fps detailed;
+#X obj 264 400 #for 0 256 1;
+#X obj 19 240 #store;
+#X obj 100 402 print;
+#X msg 56 200 \$1 \$2 # 0;
+#X obj 264 379 #finished;
+#X obj 19 35 tgl 15 0 empty empty empty 0 -6 0 8 -24198 -1 -1 0 1;
+#X obj 200 39 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 332 379 t a a;
+#X text 258 62 height width;
+#X obj 100 364 #out window;
+#X text 97 308 applying palette;
+#N canvas 127 200 450 300 circle 0;
+#X obj 47 146 #fold +;
+#X obj 47 203 # << 7;
+#X obj 47 165 # >> 6;
+#X obj 47 184 # == 10;
+#X obj 47 15 inlet size;
+#X obj 47 222 outlet matrix;
+#X obj 77 108 inlet pos;
+#X obj 47 53 t b a;
+#X obj 47 127 # sq-;
+#X obj 47 79 #for (0 0) (0 0) (1 1);
+#X obj 90 53 #export_list;
+#X connect 0 0 2 0;
+#X connect 1 0 5 0;
+#X connect 2 0 3 0;
+#X connect 3 0 1 0;
+#X connect 4 0 7 0;
+#X connect 6 0 8 1;
+#X connect 7 0 9 0;
+#X connect 7 1 10 0;
+#X connect 8 0 0 0;
+#X connect 9 0 8 0;
+#X connect 10 0 9 1;
+#X restore 222 200 pd circle generator;
+#N canvas 498 387 361 260 baseline 0;
+#X obj 18 116 #fold +;
+#X obj 127 148 - 4;
+#X obj 18 56 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 18 135 # ==;
+#X obj 127 129 listelement 0;
+#X text 93 10 line generator;
+#X obj 18 154 # << 7;
+#X obj 127 110 #export_list;
+#X obj 18 9 inlet size;
+#X obj 18 173 outlet matrix;
+#X obj 18 33 t a a;
+#X text 154 150 four pixels from bottom;
+#X obj 18 78 #for (0 0) (0 0) (1 1);
+#X obj 18 97 # & (-1 0);
+#X connect 0 0 3 0;
+#X connect 1 0 3 1;
+#X connect 2 0 12 0;
+#X connect 3 0 6 0;
+#X connect 4 0 1 0;
+#X connect 6 0 9 0;
+#X connect 7 0 4 0;
+#X connect 8 0 10 0;
+#X connect 10 0 2 0;
+#X connect 10 1 7 0;
+#X connect 10 1 12 1;
+#X connect 12 0 13 0;
+#X connect 13 0 0 0;
+#X restore 200 220 pd baseline generator;
+#X text 45 183 make blank image;
+#X text 26 223 feedback loop;
+#X obj 377 393 #color 0 800 1;
+#X msg 377 374 600 200 75;
+#X obj 220 38 loadbang;
+#N canvas 624 360 400 289 fire 0;
+#X obj 174 180 #store;
+#X obj 61 196 #export_list;
+#X obj 6 65 # >> 2;
+#X obj 6 235 # & 255;
+#X obj 6 103 # / 80;
+#X msg 174 138 \$1 1 # 256;
+#X obj 174 97 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 174 78 route grid;
+#X obj 60 155 inlet;
+#X obj 274 146 # + 32;
+#X obj 60 177 #dim;
+#X obj 6 214 # +;
+#X obj 6 258 outlet 0;
+#X msg 274 101 256 \$2 # 64;
+#X obj 6 84 # *;
+#X obj 6 7 inlet image;
+#X obj 274 79 inlet size;
+#X text 102 8 this fire algorithm;
+#X text 101 22 was designed by matju in 1994;
+#X text 264 167 makes a cache of;
+#X text 264 180 random numbers;
+#X obj 174 159 # rand;
+#X obj 274 123 # rand;
+#X obj 6 46 #convolve (3 3 # 1 0 0 0 1 0 1 1 1);
+#X obj 174 115 list;
+#X obj 6 26 t a a;
+#X obj 160 215 display;
+#X connect 0 0 14 1;
+#X connect 1 0 24 1;
+#X connect 2 0 14 0;
+#X connect 3 0 12 0;
+#X connect 4 0 11 0;
+#X connect 5 0 21 0;
+#X connect 6 0 24 0;
+#X connect 7 0 6 0;
+#X connect 8 0 11 1;
+#X connect 8 0 10 0;
+#X connect 8 0 26 0;
+#X connect 9 0 0 1;
+#X connect 10 0 1 0;
+#X connect 11 0 3 0;
+#X connect 13 0 22 0;
+#X connect 14 0 4 0;
+#X connect 15 0 25 0;
+#X connect 16 0 13 0;
+#X connect 21 0 0 0;
+#X connect 22 0 9 0;
+#X connect 23 0 2 0;
+#X connect 24 0 5 0;
+#X connect 25 0 23 0;
+#X connect 25 1 7 0;
+#X restore 65 240 pd fire generator;
+#X text 166 108 note: reset the size if you change the generator;
+#X obj 19 67 metro 33.3667;
+#X obj 5 -4 cnv 15 620 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X text 15 -4 fire.pd;
+#X obj 5 483 cnv 15 620 30 empty empty empty 20 12 0 14 -200249 -66577
+0;
+#X text 13 491 GridFlow 0.8.0;
+#X obj 139 402 route position;
+#N canvas 268 301 442 406 cursor 0;
+#X obj 107 48 listsublist 0 2;
+#X obj 107 10 inlet;
+#X obj 132 151 listsublist 0 48;
+#X obj 30 49 t a a;
+#X obj 30 284 outlet;
+#X obj 30 151 listappend 0 0;
+#X obj 107 29 #export_list;
+#X obj 30 79 # -;
+#X obj 115 86 #finished;
+#X obj 115 105 #store (0 0);
+#X obj 30 170 #redim (25 2);
+#X obj 30 189 # sq-;
+#X obj 30 208 #fold +;
+#X obj 30 227 # sqrt;
+#X obj 30 246 #fold +;
+#X obj 30 265 # / 5;
+#X obj 30 9 r metro;
+#X obj 30 131 #export_list;
+#X obj 30 29 list;
+#X connect 0 0 18 1;
+#X connect 1 0 6 0;
+#X connect 2 0 5 1;
+#X connect 3 0 7 0;
+#X connect 3 1 9 1;
+#X connect 5 0 2 0;
+#X connect 5 0 10 0;
+#X connect 6 0 0 0;
+#X connect 7 0 8 0;
+#X connect 7 0 17 0;
+#X connect 8 0 9 0;
+#X connect 9 0 7 1;
+#X connect 10 0 11 0;
+#X connect 11 0 12 0;
+#X connect 12 0 13 0;
+#X connect 13 0 14 0;
+#X connect 14 0 15 0;
+#X connect 15 0 4 0;
+#X connect 16 0 18 0;
+#X connect 17 0 5 0;
+#X connect 18 0 3 0;
+#X restore 371 162 pd cursor motion detector;
+#X obj 139 460 s cursor;
+#X msg 20 341 hidecursor;
+#N canvas 238 140 484 503 fuzzy 0;
+#X obj 47 281 outlet;
+#X obj 47 68 #for (0 0) (0 0) (1 1);
+#X obj 47 13 inlet size;
+#X obj 47 32 t b a;
+#X obj 86 32 #export_list;
+#X obj 47 91 # sq-;
+#X obj 47 262 # - 10;
+#X obj 47 243 # max 10;
+#X obj 47 224 # min 255;
+#X obj 47 205 # + 64;
+#X obj 47 186 # tanh* 64;
+#X obj 47 167 # << 8;
+#X obj 47 148 # inv+ 2;
+#X obj 47 129 # >> 2;
+#X obj 104 125 inlet radius;
+#X obj 229 89 inlet pos;
+#X obj 47 110 #fold +;
+#X connect 1 0 5 0;
+#X connect 2 0 3 0;
+#X connect 3 0 1 0;
+#X connect 3 1 4 0;
+#X connect 4 0 1 1;
+#X connect 5 0 16 0;
+#X connect 6 0 0 0;
+#X connect 7 0 6 0;
+#X connect 8 0 7 0;
+#X connect 9 0 8 0;
+#X connect 10 0 9 0;
+#X connect 11 0 10 0;
+#X connect 12 0 11 0;
+#X connect 13 0 12 0;
+#X connect 14 0 12 1;
+#X connect 15 0 5 1;
+#X connect 16 0 13 0;
+#X restore 276 181 pd fuzzy disk seed generator;
+#X text 177 440 #scale_by compensation;
+#X msg 139 421 \$1 \$2;
+#X obj 99 345 #scale_by 2;
+#X obj 139 440 # / 2;
+#X text 15 294 (height \, width \, 1) grid = grey image;
+#X text 16 260 (height \, width) grid = matrix;
+#X obj 200 123 shunt 3;
+#X obj 253 125 hradio 15 1 0 3 empty empty empty 0 -6 0 8 -241291 -1
+-1 0;
+#X obj 501 203 r cursor;
+#X obj 501 223 t a;
+#X obj 58 86 spigot;
+#X obj 19 86 t b b;
+#X obj 115 86 tgl 15 0 empty empty empty 0 -6 0 8 -241291 -1 -1 1 1
+;
+#X obj 49 105 s metro;
+#X obj 67 277 #outer ignore (0);
+#X text 15 9 Copyright 2001 \, 2005 Mathieu Bouchard;
+#X msg 200 62 120 160;
+#X obj 500 247 display;
+#X obj 99 326 #store;
+#X obj 264 422 #outer gamma;
+#X obj 204 90 list;
+#X obj 115 67 loadbang;
+#X obj 71 27 f;
+#X obj 96 27 + 1;
+#X obj 71 46 sel 100;
+#X floatatom 128 48 5 0 0 0 - - -;
+#X connect 0 0 19 0;
+#X connect 2 0 5 0;
+#X connect 3 0 52 0;
+#X connect 4 0 21 0;
+#X connect 6 0 4 1;
+#X connect 7 0 3 0;
+#X connect 8 0 23 0;
+#X connect 9 0 49 0;
+#X connect 10 0 7 0;
+#X connect 10 1 52 1;
+#X connect 12 0 2 0;
+#X connect 12 0 28 0;
+#X connect 14 0 21 1;
+#X connect 15 0 21 1;
+#X connect 18 0 10 0;
+#X connect 19 0 18 0;
+#X connect 20 0 49 0;
+#X connect 21 0 4 1;
+#X connect 21 0 47 0;
+#X connect 23 0 44 0;
+#X connect 28 0 34 0;
+#X connect 29 0 32 1;
+#X connect 31 0 12 0;
+#X connect 32 0 21 1;
+#X connect 34 0 36 0;
+#X connect 35 0 12 0;
+#X connect 36 0 30 0;
+#X connect 39 0 15 0;
+#X connect 39 1 14 0;
+#X connect 39 2 32 0;
+#X connect 40 0 39 1;
+#X connect 41 0 42 0;
+#X connect 42 0 29 0;
+#X connect 42 0 14 1;
+#X connect 42 0 32 2;
+#X connect 42 0 50 0;
+#X connect 43 0 53 0;
+#X connect 44 0 4 0;
+#X connect 44 1 43 0;
+#X connect 44 1 46 0;
+#X connect 45 0 43 1;
+#X connect 47 0 51 0;
+#X connect 49 0 6 0;
+#X connect 49 0 21 2;
+#X connect 49 0 53 1;
+#X connect 51 0 35 0;
+#X connect 52 0 51 1;
+#X connect 53 0 39 0;
+#X connect 54 0 45 0;
+#X connect 55 0 56 0;
+#X connect 55 0 57 0;
+#X connect 56 0 55 1;
+#X connect 57 0 8 0;
+#X connect 57 1 58 0;
diff --git a/externals/gridflow/examples/frequency_mask.pd b/externals/gridflow/examples/frequency_mask.pd
new file mode 100644
index 00000000..c5a08b52
--- /dev/null
+++ b/externals/gridflow/examples/frequency_mask.pd
@@ -0,0 +1,160 @@
+#N canvas 608 0 612 689 10;
+#X obj 33 12 tgl 15 0 empty empty empty 17 7 0 10 -24198 -1 -1 0 1
+;
+#X obj 33 432 t a a;
+#X obj 33 457 # -;
+#X obj 33 476 t a a;
+#X obj 33 501 # -;
+#X obj 33 520 t a a;
+#X obj 33 545 # -;
+#X obj 33 612 #clip;
+#X obj 33 631 #out window;
+#X obj 33 593 # + 128;
+#X obj 33 574 # << 2;
+#X obj 33 650 fps;
+#X floatatom 33 669 5 0 0 0 - - -;
+#X obj 33 212 #fft \, real;
+#X obj 33 193 #cast f;
+#X obj 33 250 #fft \, real \, sign 1;
+#X obj 33 269 #cast i;
+#X obj 33 288 # / 76800;
+#X obj 314 55 # sq-;
+#X obj 314 74 #fold +;
+#X obj 314 169 #out window;
+#X obj 314 17 #cast i;
+#X obj 314 112 #clip;
+#X obj 314 150 #remap_image;
+#X obj 402 150 # - (120 160);
+#X obj 33 29 metro 10;
+#X obj 314 93 # sqrt;
+#X obj 314 36 # / 277;
+#X text 42 398 2nd derivative effects;
+#X text 42 412 chosen because they emphasise noise;
+#X obj 33 357 shunt;
+#X obj 79 544 #convolve (3 3 # 0 1 0 1 -4 1);
+#X obj 72 358 tgl 15 0 empty empty empty 17 7 0 10 -241291 -1 -1 0
+1;
+#X obj 314 131 #gamma 768;
+#X obj 63 86 #greyscale_to_rgb;
+#X obj 33 48 #camera 0 \, size 240 320;
+#X obj 314 188 #mouse \, \, \, \,;
+#X obj 439 230 sel 1;
+#X obj 478 230 sel 1;
+#X msg 478 249 0;
+#X msg 439 249 1;
+#X obj 346 307 pack 0 0 0;
+#X obj 33 231 # * (2 f # 1 0);
+#X obj 65 333 #out window;
+#X obj 33 307 #clip;
+#X obj 304 473 #inner (1 0);
+#X obj 304 492 # * 255;
+#X obj 304 454 #cast i;
+#X obj 314 211 t b a;
+#X obj 249 230 gf.oneshot;
+#X obj 33 67 shunt;
+#X obj 72 68 tgl 15 0 empty empty empty 17 7 0 10 -241291 -1 -1 0 1
+;
+#X obj 456 304 display;
+#X obj 33 112 t a b;
+#X obj 304 530 #out window \, title mask;
+#X msg 346 326 put_at ( \$1 \$2 0 0 ) \, 1 1 3 2 f # \$3 \$3;
+#X obj 239 302 #unpack;
+#X obj 239 264 # * -1;
+#X obj 239 283 # % (240 320);
+#X obj 308 372 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 325 370 loadbang;
+#X obj 239 321 pack 0 0 0;
+#X obj 304 435 #store (240 320 3 2 f # 1);
+#X obj 439 273 t a;
+#X msg 339 408 reassign \, 240 320 3 2 f # 1;
+#X obj 309 389 t b b;
+#X obj 344 230 # + (120 160);
+#X obj 344 258 #unpack;
+#X obj 304 511 #remap_image;
+#X obj 392 511 # - (120 160);
+#X connect 0 0 25 0;
+#X connect 1 0 2 1;
+#X connect 1 1 2 0;
+#X connect 2 0 3 0;
+#X connect 3 0 4 1;
+#X connect 3 1 4 0;
+#X connect 4 0 5 0;
+#X connect 5 0 6 1;
+#X connect 5 1 6 0;
+#X connect 6 0 10 0;
+#X connect 7 0 8 0;
+#X connect 8 0 11 0;
+#X connect 9 0 7 0;
+#X connect 10 0 9 0;
+#X connect 11 0 12 0;
+#X connect 13 0 21 0;
+#X connect 13 0 42 0;
+#X connect 14 0 13 0;
+#X connect 15 0 16 0;
+#X connect 16 0 17 0;
+#X connect 17 0 44 0;
+#X connect 18 0 19 0;
+#X connect 19 0 26 0;
+#X connect 20 0 36 0;
+#X connect 21 0 27 0;
+#X connect 22 0 33 0;
+#X connect 23 0 20 0;
+#X connect 23 1 24 0;
+#X connect 24 0 23 1;
+#X connect 25 0 35 0;
+#X connect 26 0 22 0;
+#X connect 27 0 18 0;
+#X connect 30 0 1 0;
+#X connect 30 1 31 0;
+#X connect 31 0 10 0;
+#X connect 32 0 30 1;
+#X connect 33 0 23 0;
+#X connect 34 0 53 0;
+#X connect 35 0 50 0;
+#X connect 36 0 48 0;
+#X connect 36 1 48 0;
+#X connect 36 4 37 0;
+#X connect 36 6 38 0;
+#X connect 37 0 40 0;
+#X connect 38 0 39 0;
+#X connect 39 0 63 0;
+#X connect 40 0 63 0;
+#X connect 41 0 55 0;
+#X connect 41 0 52 0;
+#X connect 42 0 15 0;
+#X connect 44 0 43 0;
+#X connect 44 0 30 0;
+#X connect 45 0 46 0;
+#X connect 46 0 68 0;
+#X connect 47 0 45 0;
+#X connect 48 0 49 1;
+#X connect 48 1 66 0;
+#X connect 49 0 62 0;
+#X connect 50 0 53 0;
+#X connect 50 1 34 0;
+#X connect 51 0 50 1;
+#X connect 53 0 14 0;
+#X connect 53 1 49 0;
+#X connect 55 0 62 1;
+#X connect 56 0 61 0;
+#X connect 56 1 61 1;
+#X connect 57 0 58 0;
+#X connect 58 0 56 0;
+#X connect 59 0 65 0;
+#X connect 60 0 65 0;
+#X connect 61 0 55 0;
+#X connect 62 0 42 1;
+#X connect 62 0 47 0;
+#X connect 63 0 61 2;
+#X connect 63 0 41 2;
+#X connect 64 0 62 1;
+#X connect 65 0 62 0;
+#X connect 65 1 64 0;
+#X connect 66 0 57 0;
+#X connect 66 0 67 0;
+#X connect 67 0 41 0;
+#X connect 67 1 41 1;
+#X connect 68 0 54 0;
+#X connect 68 1 69 0;
+#X connect 69 0 68 1;
diff --git a/externals/gridflow/examples/game_of_life.pd b/externals/gridflow/examples/game_of_life.pd
new file mode 100644
index 00000000..8be32882
--- /dev/null
+++ b/externals/gridflow/examples/game_of_life.pd
@@ -0,0 +1,92 @@
+#N canvas 429 0 654 368 10;
+#X obj 36 46 tgl 15 0 empty empty empty 0 -6 0 8 -24198 -1 -1 0 1;
+#X obj 31 237 #out window;
+#X text 48 122 this is the feedback loop;
+#X obj 143 50 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 262 87 loadbang;
+#X obj 141 103 #store;
+#X obj 161 68 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 31 275 print;
+#X obj 31 256 fps detailed;
+#X obj 31 143 t a a;
+#X text 179 68 next;
+#N canvas 0 0 450 632 game 1;
+#X obj 28 64 inlet matrix;
+#X obj 28 141 outlet matrix;
+#X text 18 14 this part at the left defines the rule of the game (this
+is my own rewriting of the rules. it is equivalent to the original
+but faster to compute.);
+#X obj 28 83 # << (b # 1);
+#X obj 28 122 # < (b # 3);
+#X obj 28 103 #convolve (3 3 b # 0 0 0 0 1) \, op >> \, seed (b # 251)
+;
+#X text 26 173 This is about the fastest you can get in GridFlow. This
+solution uses all the advanced dirty tricks you can imagine (and perhaps
+some you can't).;
+#X text 26 221 First I changed the convolution to use << so that *1
+becomes <<0 and *2 becomes <<1 \, because << is faster than *. Then
+I changed << to >> so that \, with a preceding <<1 \, <<0 becomes >>1
+and <<1 becomes >>0. This is because #convolve knows that >>0 is doing
+nothing (just like *1) and we want to have as many of those do-nothing
+operations because they all get removed.;
+#X text 25 322 Then the check for whether the result is 5 \, 6 or 7
+is reduced to a subtraction of 5 \, and a check for whether the result
+is 0 \, 1 or 2 This can be made by a single < by using the "b" (uint8)
+type \, in which negative numbers don't exist (-1 = 255). I can include
+the subtraction in the #convolve by using the seed \, but -5 can't
+be written with a b type \, so you need to write 256-5 = 251 instead.
+;
+#X text 25 423 Those are all optional accelerations. You may want to
+undo a few of those so that you have a patch that is more tweakable
+\, but then you'd realise that it is the nature of the game of life
+to not be very tweakable. This is one of the most sensitive formulas
+you can find: most any change will completely destroy the pattern \,
+changing it into either an explosion of noise or sudden death. There
+are some difficult-to-find interesting tweaks \, but so far \, none
+of them has given rich results like the game of life has.;
+#X text 25 548 The original (3 3 # 2 2 2 2 1 2 2 2 2) is itself a shortcut
+I devised so that I don't have to have separate rules for lit cells
+and unlit cells. This is the only shortcut I'd keep in all versions
+of this patch no matter how much tweaking I'd do.;
+#X connect 0 0 3 0;
+#X connect 3 0 5 0;
+#X connect 4 0 1 0;
+#X connect 5 0 4 0;
+#X restore 31 102 pd game of life;
+#X text 260 60 init with a random map;
+#X text 261 72 10% white dots;
+#X text 33 169 convert this 1-bit matrix to standard RGB \; 1 becomes
+-1 becomes 255 \, but 0 stays 0;
+#X obj 53 45 metro 5;
+#X obj 5 329 cnv 15 640 30 empty empty empty 20 12 0 14 -200249 -66577
+0;
+#X obj 7 5 cnv 15 640 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X text 20 5 game_of_life.pd;
+#X text 20 18 Copyright 2001 Mathieu Bouchard;
+#X obj 262 125 # rand (b #);
+#X obj 262 144 # == (b # 0);
+#X msg 262 106 240 320 b # 10;
+#X obj 31 199 # inv+ (b # 0);
+#X obj 31 218 #outer ignore (3 b #);
+#X obj 161 49 for 0 100 1;
+#X text 13 336 GridFlow 0.9.5;
+#X connect 0 0 15 0;
+#X connect 1 0 8 0;
+#X connect 3 0 25 0;
+#X connect 4 0 22 0;
+#X connect 5 0 11 0;
+#X connect 6 0 5 0;
+#X connect 8 0 7 0;
+#X connect 9 0 23 0;
+#X connect 9 1 5 1;
+#X connect 11 0 9 0;
+#X connect 15 0 5 0;
+#X connect 20 0 21 0;
+#X connect 21 0 9 0;
+#X connect 22 0 20 0;
+#X connect 23 0 24 0;
+#X connect 24 0 1 0;
+#X connect 25 0 6 0;
diff --git a/externals/gridflow/examples/game_of_life_gem.pd b/externals/gridflow/examples/game_of_life_gem.pd
new file mode 100644
index 00000000..5032ca9e
--- /dev/null
+++ b/externals/gridflow/examples/game_of_life_gem.pd
@@ -0,0 +1,291 @@
+#N canvas 608 0 588 612 10;
+#X obj 368 33 loadbang;
+#X obj 23 48 gemhead;
+#N canvas 610 247 578 360 GOL 0;
+#X text 48 122 this is the feedback loop;
+#X obj 143 50 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 161 49 for 0 10 1;
+#X obj 262 87 loadbang;
+#X obj 141 103 #store;
+#X obj 161 68 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 31 143 fork;
+#X text 179 68 next;
+#N canvas 0 0 450 210 game 0;
+#X obj 28 64 inlet matrix;
+#X obj 28 141 outlet matrix;
+#X text 18 14 this part at the left defines the rule of the game (this
+is my own rewriting of the rules. it is equivalent to the original
+but faster to compute.);
+#X obj 28 83 # << (b # 1);
+#X obj 28 122 # < (b # 3);
+#X obj 28 103 #convolve (3 3 b # 0 0 0 0 1) \, op >> \, seed (b # 251)
+;
+#X connect 0 0 3 0;
+#X connect 3 0 5 0;
+#X connect 4 0 1 0;
+#X connect 5 0 4 0;
+#X restore 31 102 pd game of life;
+#X text 260 60 init with a random map;
+#X obj 5 329 cnv 15 780 30 empty empty empty 20 12 0 14 -200249 -66577
+0;
+#X text 13 336 GridFlow 0.8.0;
+#X text 13 336 GridFlow 0.8.0;
+#X obj 7 5 cnv 15 780 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X text 20 5 game_of_life.pd;
+#X text 20 18 Copyright 2001 Mathieu Bouchard;
+#X obj 262 165 # rand (b #);
+#X obj 262 184 # == (b # 0);
+#X obj 24 41 inlet metro;
+#X obj 22 69 route bang reset;
+#X obj 31 295 outlet RGB;
+#X obj 31 181 #cast i;
+#X obj 31 238 #clip;
+#X obj 41 257 #apply_colormap_channelwise;
+#X obj 207 239 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 31 200 # << 10;
+#X obj 234 238 #for 0 256 1;
+#X obj 234 257 #outer gamma (3 # 333 555 999);
+#X text 261 72 20% white dots;
+#X obj 31 162 #outer ignore (4 b #);
+#X obj 279 117 t b b;
+#X obj 31 276 #scale_by;
+#X msg 261 146 128 128 b # 5;
+#X obj 31 219 #fade (16 4 1 1);
+#X connect 1 0 2 0;
+#X connect 2 0 5 0;
+#X connect 3 0 30 0;
+#X connect 4 0 8 0;
+#X connect 5 0 4 0;
+#X connect 6 0 29 0;
+#X connect 6 1 4 1;
+#X connect 8 0 6 0;
+#X connect 16 0 17 0;
+#X connect 17 0 6 0;
+#X connect 18 0 19 0;
+#X connect 19 0 4 0;
+#X connect 19 1 32 0;
+#X connect 21 0 25 0;
+#X connect 22 0 31 0;
+#X connect 24 0 26 0;
+#X connect 25 0 33 0;
+#X connect 26 0 27 0;
+#X connect 27 0 23 1;
+#X connect 29 0 21 0;
+#X connect 30 0 32 0;
+#X connect 30 1 26 0;
+#X connect 31 0 20 0;
+#X connect 32 0 16 0;
+#X connect 33 0 22 0;
+#X restore 144 363 pd GOL;
+#X obj 127 278 tgl 15 0 empty empty empty 0 -6 0 8 -24198 -1 -1 0 1
+;
+#X msg 154 336 reset;
+#X obj 23 429 rotateXYZ;
+#X obj 32 406 #unpack 3;
+#X obj 32 349 # +;
+#X obj 57 349 t a;
+#X obj 32 368 #cast f;
+#X obj 32 387 # / (f # 100);
+#X floatatom 108 67 5 0 0 0 - - -;
+#X obj 76 48 bang;
+#X obj 108 48 fps \, period 5;
+#X obj 23 215 pix_texture;
+#X obj 285 516 #out window;
+#X obj 285 63 gemhead 74;
+#X obj 53 158 tgl 15 0 empty empty empty 0 -6 0 8 -241291 -1 -1 0 1
+;
+#X msg 53 172 yflip \$1;
+#X obj 285 312 t a b;
+#X obj 360 133 vsl 15 128 0 512 0 0 empty empty empty 0 -8 0 8 -241291
+-1 -1 3175 1;
+#X obj 375 133 vsl 15 128 0 512 0 0 empty empty empty 0 -8 0 8 -241291
+-1 -1 3175 1;
+#X obj 414 133 vsl 15 128 0 512 0 0 empty empty empty 0 -8 0 8 -241291
+-1 -1 6350 1;
+#X obj 429 133 vsl 15 128 0 512 0 0 empty empty empty 0 -8 0 8 -241291
+-1 -1 6350 1;
+#X msg 324 312 snap;
+#X obj 360 110 #unpack;
+#X obj 413 110 #unpack;
+#X obj 285 364 pix_snap;
+#X obj 350 267 #pack;
+#X obj 404 267 #pack;
+#X obj 300 404 tgl 15 0 empty empty empty 0 -6 0 8 -241291 -1 -1 0
+1;
+#X msg 300 418 yflip \$1;
+#X msg 360 90 128 128;
+#X msg 413 91 256 256;
+#X obj 23 528 cube 4;
+#X obj 179 298 + 1;
+#X obj 154 317 sel 0;
+#X obj 154 298 f;
+#X msg 307 437 help;
+#X obj 407 289 #to_list;
+#X obj 347 289 #to_list;
+#X obj 23 196 #to_pix;
+#X obj 4 1 cnv 15 500 18 empty empty empty 20 12 0 14 -228992 -66577
+0;
+#X text 5 1 [#to_pix];
+#X text 401 2 GridFlow 0.9.3;
+#X obj 62 106 separator;
+#X obj 23 106 t a a;
+#X msg 368 52 create \, 1 \, lighting 1;
+#X msg 32 330 60 42 30;
+#X obj 144 277 metro 33.3667;
+#X floatatom 204 317 5 0 0 0 - - -;
+#N canvas 0 0 450 300 lighting 0;
+#X obj 22 28 inlet gem;
+#X obj 152 210 light;
+#X obj 282 210 light;
+#X obj 22 47 t a a a;
+#X obj 66 66 separator;
+#X obj 44 85 separator;
+#X obj 22 210 light;
+#X obj 133 251 loadbang;
+#X obj 22 191 translateXYZ 0 4 4;
+#X obj 152 191 translateXYZ 4 0 4;
+#X obj 282 191 translateXYZ 4 4 0;
+#X msg 61 210 1 0 0;
+#X msg 191 210 0 1 0;
+#X msg 321 210 0 0 1;
+#X connect 0 0 3 0;
+#X connect 3 0 8 0;
+#X connect 3 1 5 0;
+#X connect 3 2 4 0;
+#X connect 4 0 10 0;
+#X connect 5 0 9 0;
+#X connect 7 0 11 0;
+#X connect 7 0 12 0;
+#X connect 7 0 13 0;
+#X connect 8 0 6 0;
+#X connect 9 0 1 0;
+#X connect 10 0 2 0;
+#X connect 11 0 6 1;
+#X connect 12 0 1 1;
+#X connect 13 0 2 1;
+#X restore 62 125 pd lighting;
+#X obj 23 509 color 1 1 1;
+#X obj 144 382 # inv+ 255;
+#X obj 368 71 gemwin 29.97;
+#X obj 23 457 shunt;
+#X obj 62 458 tgl 15 0 empty empty empty 17 7 0 10 -24198 -1 -1 1 1
+;
+#N canvas 0 0 450 300 eight_cubes 0;
+#X obj 33 29 inlet gem;
+#X obj 33 48 t a a;
+#X obj 163 48 separator;
+#X obj 33 86 t a;
+#X obj 33 105 t a a;
+#X obj 163 105 separator;
+#X obj 33 143 t a;
+#X obj 33 162 t a a;
+#X obj 163 162 separator;
+#X obj 33 200 t a;
+#X obj 33 219 cube 2;
+#X obj 33 67 translateXYZ 4 0 0;
+#X obj 33 124 translateXYZ 0 4 0;
+#X obj 33 181 translateXYZ 0 0 4;
+#X obj 163 181 translateXYZ 0 0 -4;
+#X obj 163 124 translateXYZ 0 -4 0;
+#X obj 163 67 translateXYZ -4 0 0;
+#X connect 0 0 1 0;
+#X connect 1 0 11 0;
+#X connect 1 1 2 0;
+#X connect 2 0 16 0;
+#X connect 3 0 4 0;
+#X connect 4 0 12 0;
+#X connect 4 1 5 0;
+#X connect 5 0 15 0;
+#X connect 6 0 7 0;
+#X connect 7 0 13 0;
+#X connect 7 1 8 0;
+#X connect 8 0 14 0;
+#X connect 9 0 10 0;
+#X connect 11 0 3 0;
+#X connect 12 0 6 0;
+#X connect 13 0 9 0;
+#X connect 14 0 9 0;
+#X connect 15 0 6 0;
+#X connect 16 0 3 0;
+#X restore 53 476 pd eight_cubes;
+#X obj 285 482 #remap_image;
+#X obj 204 298 % 256;
+#X obj 390 463 % 32;
+#X obj 23 239 translateXYZ 0 0 -7;
+#X obj 285 457 #import_pix;
+#X obj 374 482 # ^;
+#X connect 0 0 47 0;
+#X connect 0 0 32 0;
+#X connect 0 0 33 0;
+#X connect 1 0 12 0;
+#X connect 1 0 46 0;
+#X connect 2 0 53 0;
+#X connect 3 0 49 0;
+#X connect 4 0 2 0;
+#X connect 5 0 55 0;
+#X connect 6 0 5 1;
+#X connect 6 1 5 2;
+#X connect 6 2 5 3;
+#X connect 7 0 8 0;
+#X connect 7 0 9 0;
+#X connect 8 0 7 1;
+#X connect 9 0 10 0;
+#X connect 10 0 6 0;
+#X connect 12 0 13 0;
+#X connect 13 0 11 0;
+#X connect 14 0 61 0;
+#X connect 16 0 19 0;
+#X connect 17 0 18 0;
+#X connect 18 0 41 0;
+#X connect 19 0 27 0;
+#X connect 19 1 24 0;
+#X connect 20 0 28 0;
+#X connect 21 0 28 1;
+#X connect 22 0 29 0;
+#X connect 23 0 29 1;
+#X connect 24 0 27 0;
+#X connect 25 0 20 0;
+#X connect 25 1 21 0;
+#X connect 26 0 22 0;
+#X connect 26 1 23 0;
+#X connect 27 0 62 0;
+#X connect 28 0 40 0;
+#X connect 29 0 39 0;
+#X connect 30 0 31 0;
+#X connect 31 0 62 0;
+#X connect 32 0 25 0;
+#X connect 33 0 26 0;
+#X connect 35 0 59 0;
+#X connect 36 0 4 0;
+#X connect 37 0 35 0;
+#X connect 37 0 36 0;
+#X connect 38 0 62 0;
+#X connect 39 0 27 2;
+#X connect 40 0 27 1;
+#X connect 41 0 14 0;
+#X connect 45 0 51 0;
+#X connect 46 0 41 0;
+#X connect 46 1 45 0;
+#X connect 47 0 54 0;
+#X connect 48 0 7 0;
+#X connect 49 0 2 0;
+#X connect 49 0 37 0;
+#X connect 49 0 48 0;
+#X connect 52 0 34 0;
+#X connect 53 0 41 1;
+#X connect 55 0 52 0;
+#X connect 55 1 57 0;
+#X connect 56 0 55 1;
+#X connect 58 0 15 0;
+#X connect 58 1 63 0;
+#X connect 59 0 37 1;
+#X connect 59 0 50 0;
+#X connect 59 0 60 0;
+#X connect 60 0 63 1;
+#X connect 61 0 5 0;
+#X connect 62 0 58 0;
+#X connect 63 0 58 1;
diff --git a/externals/gridflow/examples/heat.pd b/externals/gridflow/examples/heat.pd
new file mode 100644
index 00000000..d4511be1
--- /dev/null
+++ b/externals/gridflow/examples/heat.pd
@@ -0,0 +1,173 @@
+#N canvas 592 228 741 486 10;
+#X obj 228 23 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#N canvas 199 246 450 453 heat 0;
+#X obj 129 23 inlet mask;
+#X obj 22 42 t a a;
+#X obj 22 224 # +;
+#X obj 22 23 inlet heatmap;
+#X obj 24 394 outlet heatmap;
+#X obj 241 154 #greyscale_to_rgb;
+#X obj 241 175 #out window;
+#X obj 22 80 #store;
+#X obj 22 61 #finished;
+#X obj 52 167 # + 128;
+#X obj 52 186 # >> 8;
+#X obj 52 134 # *;
+#X obj 52 103 #convolve (3 3 # 0 1 0 1 -4 1);
+#X obj 52 205 # + 2;
+#X obj 52 225 # >> 4;
+#X connect 0 0 11 1;
+#X connect 1 0 8 0;
+#X connect 1 1 7 1;
+#X connect 1 1 12 0;
+#X connect 2 0 4 0;
+#X connect 3 0 1 0;
+#X connect 5 0 6 0;
+#X connect 7 0 2 0;
+#X connect 8 0 7 0;
+#X connect 9 0 10 0;
+#X connect 10 0 13 0;
+#X connect 11 0 9 0;
+#X connect 12 0 11 0;
+#X connect 13 0 14 0;
+#X connect 14 0 2 1;
+#X restore 27 81 pd heat;
+#X obj 27 61 #store;
+#X obj 94 42 loadbang;
+#X obj 27 16 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1
+;
+#X obj 27 363 #out window;
+#X obj 227 157 #greyscale_to_rgb;
+#X obj 227 138 # >> 2;
+#X obj 48 23 s metro;
+#X obj 27 382 #mouse \, ...;
+#X obj 120 382 # >> 1;
+#X obj 27 344 #scale_by 2;
+#X msg 94 61 240 320 1 # 0;
+#N canvas 205 52 520 286 finger 0;
+#X obj 28 62 shunt 2;
+#X msg 289 71 4 2 # 0 0 0 1 1 1 1 0;
+#X obj 289 90 # * 8;
+#X obj 289 109 # - 4;
+#X obj 289 128 # +;
+#X obj 28 23 inlet;
+#X obj 28 142 outlet;
+#X obj 289 14 inlet position;
+#X obj 72 23 inlet button;
+#X obj 289 33 #export_list;
+#X obj 289 52 t b a;
+#X obj 72 81 #draw_polygon + (4000);
+#X connect 0 0 6 0;
+#X connect 0 1 11 0;
+#X connect 1 0 2 0;
+#X connect 2 0 3 0;
+#X connect 3 0 4 0;
+#X connect 4 0 11 2;
+#X connect 5 0 0 0;
+#X connect 7 0 9 0;
+#X connect 8 0 0 1;
+#X connect 9 0 10 0;
+#X connect 10 0 1 0;
+#X connect 10 1 4 1;
+#X connect 11 0 6 0;
+#X restore 27 163 pd finger;
+#X obj 15 436 fps detailed;
+#X obj 16 456 display;
+#X obj 27 119 shunt 2;
+#X obj 90 104 f;
+#X obj 115 104 + 1;
+#X obj 27 100 t a b;
+#X obj 140 123 ==;
+#X obj 140 104 % 4;
+#N canvas 340 133 341 379 render 0;
+#X obj 12 285 # +;
+#X obj 26 23 inlet heatmap;
+#X obj 12 323 outlet rgb;
+#X obj 123 23 inlet mask;
+#X obj 26 53 t a a;
+#X obj 26 80 #inner (1 3 # 2 4 6) \, op >>;
+#X obj 82 161 t a a;
+#X obj 88 189 # -;
+#X obj 88 227 # + 128;
+#X obj 12 304 #clip;
+#X obj 88 208 # << 6;
+#X obj 26 108 shunt 2;
+#X obj 79 109 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1
+;
+#X connect 0 0 9 0;
+#X connect 1 0 4 0;
+#X connect 3 0 0 1;
+#X connect 4 0 5 0;
+#X connect 5 0 11 0;
+#X connect 6 0 7 1;
+#X connect 6 1 7 0;
+#X connect 7 0 10 0;
+#X connect 8 0 0 0;
+#X connect 9 0 2 0;
+#X connect 10 0 8 0;
+#X connect 11 0 0 0;
+#X connect 11 1 6 0;
+#X connect 12 0 11 1;
+#X restore 28 271 pd render;
+#X obj 295 232 #fold +;
+#X obj 295 251 #fold +;
+#X obj 295 289 #fold +;
+#X obj 245 23 loadbang;
+#X obj 227 100 # max;
+#X obj 227 81 # << 1;
+#X obj 227 119 # min 256;
+#X obj 227 62 # - 40;
+#X obj 295 270 # / 320;
+#X obj 295 308 # / 240;
+#X obj 295 327 #export;
+#X floatatom 294 356 5 0 0 0 - - -;
+#X obj 27 42 metro 12;
+#X text 542 3 heat propagation simulation;
+#X text 396 43 use a greyscale image here;
+#X text 493 17 Copyright 2005 by Mathieu Bouchard;
+#X text 396 57 as a heat conduction map;
+#X obj 227 43 #in pmask.png;
+#X connect 0 0 40 0;
+#X connect 1 0 19 0;
+#X connect 2 0 1 0;
+#X connect 3 0 12 0;
+#X connect 4 0 35 0;
+#X connect 5 0 9 0;
+#X connect 5 0 14 0;
+#X connect 6 0 22 1;
+#X connect 7 0 6 0;
+#X connect 9 0 10 0;
+#X connect 9 1 10 0;
+#X connect 9 4 13 1;
+#X connect 10 0 13 2;
+#X connect 11 0 5 0;
+#X connect 12 0 2 1;
+#X connect 13 0 2 1;
+#X connect 13 0 22 0;
+#X connect 14 0 15 0;
+#X connect 16 0 2 1;
+#X connect 16 1 13 0;
+#X connect 17 0 18 0;
+#X connect 18 0 21 0;
+#X connect 19 0 16 0;
+#X connect 19 1 17 0;
+#X connect 20 0 16 1;
+#X connect 21 0 17 1;
+#X connect 21 0 20 0;
+#X connect 22 0 11 0;
+#X connect 23 0 24 0;
+#X connect 24 0 31 0;
+#X connect 25 0 32 0;
+#X connect 26 0 40 0;
+#X connect 27 0 29 0;
+#X connect 28 0 27 0;
+#X connect 29 0 1 1;
+#X connect 29 0 7 0;
+#X connect 30 0 28 0;
+#X connect 31 0 25 0;
+#X connect 32 0 33 0;
+#X connect 33 0 34 0;
+#X connect 35 0 2 0;
+#X connect 35 0 8 0;
+#X connect 40 0 30 0;
diff --git a/externals/gridflow/examples/hello-world.pd b/externals/gridflow/examples/hello-world.pd
new file mode 100644
index 00000000..6b8306a3
--- /dev/null
+++ b/externals/gridflow/examples/hello-world.pd
@@ -0,0 +1,39 @@
+#N canvas 580 223 489 466 10;
+#X obj 21 68 # / 320;
+#X obj 21 188 # * 255;
+#X obj 21 154 # != 0;
+#X obj 21 -11 bng 15 250 50 0 empty empty empty 0 -6 0 8 -24198 -1
+-1;
+#X obj 21 100 # inv+ 7;
+#X obj 21 16 #for 0 320 1;
+#X obj 21 49 # * 7;
+#X obj 21 -33 loadbang;
+#X text 41 -11 make one line:;
+#X text 29 32 numbers 0 to 319;
+#X text 30 85 numbers 0 to 6 repeated 45 or 46 times;
+#X text 31 117 numbers 7 down to 1 ...;
+#X text 28 173 3*1-bit rgb image line;
+#X text 28 206 3*8-bit rgb image line;
+#X text 150 224 repeat line 240 times;
+#X obj 2 -84 cnv 15 500 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X text 15 -85 hello-world.pd;
+#X obj 21 135 #outer & (2 4 1);
+#X obj 21 223 #redim (240 320 3);
+#X obj 1 348 cnv 15 500 30 empty empty empty 20 12 0 14 -200249 -66577
+0;
+#X text 8 354 GridFlow 0.8.0;
+#X text 8 354 GridFlow 0.8.0;
+#X text 15 -71 Copyright 2001 Mathieu Bouchard;
+#X obj 21 281 #out window;
+#X text 64 321 this is also covered by a new class named [#hello];
+#X connect 0 0 4 0;
+#X connect 1 0 18 0;
+#X connect 2 0 1 0;
+#X connect 3 0 5 0;
+#X connect 4 0 17 0;
+#X connect 5 0 6 0;
+#X connect 6 0 0 0;
+#X connect 7 0 3 0;
+#X connect 17 0 2 0;
+#X connect 18 0 23 0;
diff --git a/externals/gridflow/examples/image_stats.pd b/externals/gridflow/examples/image_stats.pd
new file mode 100644
index 00000000..b53220fd
--- /dev/null
+++ b/externals/gridflow/examples/image_stats.pd
@@ -0,0 +1,62 @@
+#N canvas 308 151 716 426 10;
+#X obj 214 261 print total_value;
+#X obj 473 191 #dim;
+#X obj 42 220 #export_list;
+#X obj 278 231 print number_of_values;
+#X obj 473 229 print number_of_dimensions;
+#X obj 473 210 #export;
+#X obj 205 181 #fold +;
+#X obj 205 301 /;
+#X obj 205 219 #fold +;
+#X obj 42 239 print total_pixel;
+#X obj 205 147 t a a;
+#X obj 265 118 #in;
+#X obj 420 166 print dimensions;
+#X obj 205 320 print average_value;
+#X obj 205 238 #export;
+#X obj 205 200 #fold +;
+#X obj 420 147 #export_list;
+#X obj 420 128 #dim;
+#X obj 278 174 #dim;
+#X obj 278 212 #export;
+#X msg 291 55 open bluemarble.jpg \, bang;
+#X msg 291 75 open teapot.png \, bang;
+#X msg 291 95 open r001.jpg \, bang;
+#X obj 5 394 cnv 15 720 30 empty empty empty 20 12 0 14 -200249 -66577
+0;
+#X text 13 401 GridFlow 0.8.0;
+#X text 13 401 GridFlow 0.8.0;
+#X obj 7 5 cnv 15 720 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X text 15 18 Copyright 2001 Mathieu Bouchard;
+#X text 15 4 image_stats.pd;
+#X obj 42 201 #fold + \, seed (3 #);
+#X obj 42 182 #fold + \, seed (3 #);
+#X text 480 54 <-- click on one of these;
+#X obj 278 193 #fold *;
+#X connect 1 0 5 0;
+#X connect 2 0 9 0;
+#X connect 5 0 4 0;
+#X connect 6 0 15 0;
+#X connect 7 0 13 0;
+#X connect 8 0 14 0;
+#X connect 10 0 6 0;
+#X connect 10 0 30 0;
+#X connect 10 1 18 0;
+#X connect 11 0 10 0;
+#X connect 11 0 17 0;
+#X connect 14 0 0 0;
+#X connect 14 0 7 0;
+#X connect 15 0 8 0;
+#X connect 16 0 12 0;
+#X connect 17 0 16 0;
+#X connect 17 0 1 0;
+#X connect 18 0 32 0;
+#X connect 19 0 3 0;
+#X connect 19 0 7 1;
+#X connect 20 0 11 0;
+#X connect 21 0 11 0;
+#X connect 22 0 11 0;
+#X connect 29 0 2 0;
+#X connect 30 0 29 0;
+#X connect 32 0 19 0;
diff --git a/externals/gridflow/examples/instant_blur.pd b/externals/gridflow/examples/instant_blur.pd
new file mode 100644
index 00000000..15195879
--- /dev/null
+++ b/externals/gridflow/examples/instant_blur.pd
@@ -0,0 +1,142 @@
+#N canvas 477 0 743 530 10;
+#X obj 13 204 #cast f;
+#X obj 13 280 #cast i;
+#X obj 50 59 #in teapot.png;
+#X obj 193 46 loadbang;
+#X obj 13 223 #fft;
+#X obj 13 356 #out window;
+#X obj 293 270 #fft;
+#X obj 293 289 # / (f # 256);
+#X text 244 331 B->RGB;
+#X obj 348 23 #for (-128 -128) (128 128) (1 1);
+#X obj 175 65 t b b;
+#X obj 175 48 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 50 40 bng 15 250 50 0 empty empty empty 0 -6 0 8 -24198 -1 -1
+;
+#X obj 293 213 #t;
+#X obj 318 232 #fold +;
+#X obj 318 213 #ravel;
+#X obj 13 337 #gamma 512;
+#X obj 13 375 fps;
+#X floatatom 13 394 5 0 0 0 - - -;
+#X obj 175 26 metro 33.3667;
+#X obj 175 9 tgl 15 0 empty empty empty 0 -6 0 8 -24198 -1 -1 0 1;
+#X obj 348 61 # sq- 128;
+#X obj 234 443 #out window;
+#X obj 234 367 #cast i;
+#X obj 348 80 #fold +;
+#X obj 348 99 #cast f;
+#X obj 13 78 #store;
+#X obj 234 348 # * (f # 255);
+#X obj 13 137 #remap_image;
+#X obj 111 118 # - 128;
+#X obj 111 156 # + 128;
+#X floatatom 164 139 5 0 0 0 - - -;
+#X obj 111 137 # *>>8;
+#X obj 13 261 #fft \, sign 1;
+#X obj 385 224 #import () f;
+#X obj 13 242 # C.*;
+#X obj 293 232 # /;
+#X obj 385 125 loadbang;
+#X obj 13 318 #inner (2 # 1 0);
+#X obj 293 251 #outer * (3 2 f # 1 0);
+#X obj 13 185 #outer & (-1 0);
+#X obj 67 39 loadbang;
+#X obj 385 167 f;
+#X obj 293 115 t b b;
+#X obj 234 405 #remap_image;
+#X obj 330 405 # + 128;
+#X msg 164 120 256;
+#X obj 164 101 loadbang;
+#X obj 435 167 mod 150;
+#X obj 410 167 - 1;
+#X obj 385 186 - 75;
+#X obj 293 194 # <=;
+#X obj 234 424 #outer ignore (3 #);
+#X obj 385 205 expr pow($f1 \, 4)/666;
+#X obj 348 42 # & 255;
+#X obj 293 134 #store;
+#X obj 348 4 loadbang;
+#X obj 331 23 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
+-1;
+#X msg 385 144 75;
+#X obj 13 299 # >> 8;
+#X obj 463 391 # **;
+#X obj 463 353 t a a;
+#X obj 463 372 # put (f # 0.99);
+#X obj 570 334 # inv* (f # 1);
+#X floatatom 570 299 5 0 0 0 - - -;
+#X obj 570 315 #import () f;
+#X obj 570 353 # inv+ (f # 1);
+#X connect 0 0 4 0;
+#X connect 1 0 59 0;
+#X connect 2 0 26 1;
+#X connect 3 0 11 0;
+#X connect 4 0 35 0;
+#X connect 5 0 17 0;
+#X connect 6 0 7 0;
+#X connect 7 0 35 1;
+#X connect 9 0 54 0;
+#X connect 10 0 26 0;
+#X connect 10 1 43 0;
+#X connect 11 0 10 0;
+#X connect 12 0 2 0;
+#X connect 13 0 36 0;
+#X connect 13 0 27 0;
+#X connect 13 1 15 0;
+#X connect 14 0 36 1;
+#X connect 15 0 14 0;
+#X connect 16 0 5 0;
+#X connect 17 0 18 0;
+#X connect 19 0 11 0;
+#X connect 20 0 19 0;
+#X connect 21 0 24 0;
+#X connect 23 0 44 0;
+#X connect 24 0 25 0;
+#X connect 25 0 55 1;
+#X connect 26 0 28 0;
+#X connect 27 0 23 0;
+#X connect 28 0 40 0;
+#X connect 28 1 29 0;
+#X connect 29 0 32 0;
+#X connect 30 0 28 1;
+#X connect 31 0 32 1;
+#X connect 32 0 30 0;
+#X connect 33 0 1 0;
+#X connect 34 0 51 1;
+#X connect 35 0 33 0;
+#X connect 36 0 39 0;
+#X connect 37 0 58 0;
+#X connect 38 0 16 0;
+#X connect 39 0 6 0;
+#X connect 40 0 0 0;
+#X connect 41 0 2 0;
+#X connect 42 0 49 0;
+#X connect 42 0 50 0;
+#X connect 43 0 55 0;
+#X connect 43 1 42 0;
+#X connect 44 0 52 0;
+#X connect 44 1 45 0;
+#X connect 45 0 44 1;
+#X connect 46 0 31 0;
+#X connect 47 0 46 0;
+#X connect 48 0 42 1;
+#X connect 49 0 48 0;
+#X connect 50 0 53 0;
+#X connect 51 0 13 0;
+#X connect 52 0 22 0;
+#X connect 53 0 34 0;
+#X connect 54 0 21 0;
+#X connect 55 0 51 0;
+#X connect 56 0 9 0;
+#X connect 57 0 9 0;
+#X connect 58 0 42 0;
+#X connect 59 0 38 0;
+#X connect 61 0 62 0;
+#X connect 61 1 60 1;
+#X connect 62 0 60 0;
+#X connect 63 0 66 0;
+#X connect 64 0 65 0;
+#X connect 65 0 63 0;
+#X connect 66 0 62 1;
diff --git a/externals/gridflow/examples/linear_transform.pd b/externals/gridflow/examples/linear_transform.pd
new file mode 100644
index 00000000..d8f9923d
--- /dev/null
+++ b/externals/gridflow/examples/linear_transform.pd
@@ -0,0 +1,225 @@
+#N canvas 415 64 784 587 10;
+#X text 359 43 click here to go in manual mode;
+#X floatatom 141 311 5 0 0 0 - - -;
+#X obj 27 374 # >> 11;
+#X obj 27 139 #store;
+#X obj 183 291 hsl 128 15 -4096 4096 0 0 empty empty empty -2 -6 0
+8 -260818 -1 -1 0 1;
+#X obj 505 208 * 3;
+#X obj 183 310 hsl 128 15 -4096 4096 0 0 empty empty empty -2 -6 0
+8 -260818 -1 -1 0 1;
+#X floatatom 141 257 5 0 0 0 - - -;
+#X msg 444 238 10000;
+#X obj 27 59 tgl 15 0 empty empty empty 0 -6 0 8 -24198 -1 -1 1 1;
+#X obj 183 253 hsl 128 15 -4096 4096 0 0 empty empty empty -2 -6 0
+8 -260818 -1 -1 0 1;
+#X obj 77 138 loadbang;
+#X text 180 234 linear transform;
+#X obj 27 395 # + 128;
+#X floatatom 141 275 5 0 0 0 - - -;
+#X floatatom 141 293 5 0 0 0 - - -;
+#X obj 183 272 hsl 128 15 -4096 4096 0 0 empty empty empty -2 -6 0
+8 -260818 -1 -1 0 1;
+#X obj 428 260 vsl 15 128 0 35999 0 0 empty empty empty 0 -8 0 8 -260818
+-1 -1 8220 1;
+#X obj 444 259 vsl 15 128 -32768 32768 0 0 empty empty empty 0 -8 0
+8 -260818 -1 -1 5796 1;
+#X obj 313 82 % 36000;
+#X obj 444 219 loadbang;
+#X text 432 185 rotozoomer;
+#X obj 505 227 # sin* 100;
+#X obj 288 43 shunt 2;
+#X obj 152 416 loadbang;
+#X obj 27 448 #store;
+#X obj 27 469 #out window;
+#X obj 343 44 tgl 15 0 empty empty empty 0 -6 0 8 -241291 -1 -1 0 1
+;
+#X obj 88 334 #pack 4;
+#X obj 27 95 t b b;
+#X obj 313 63 + 100;
+#X obj 505 246 # inv* 100000;
+#X obj 505 265 #export;
+#X obj 83 426 #camera;
+#X obj 152 454 #in;
+#X obj 83 406 spigot;
+#X obj 131 407 tgl 15 0 empty empty empty 0 -6 0 8 -241291 -1 -1 0
+1;
+#X obj 27 353 #inner;
+#X obj 88 237 loadbang;
+#X obj 27 488 fps detailed;
+#X obj 27 507 print;
+#X obj 2 0 cnv 15 780 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X text 21 13 Copyright 2002 Mathieu Bouchard;
+#X text 21 0 convolve.pd;
+#X obj 2 0 cnv 15 780 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X text 21 0 linear_transform.pd;
+#X obj 77 157 #for (-128 -128) (128 128) (1 1);
+#X obj 428 416 #outer + (9000 18000 0 9000);
+#X text 21 13 Copyright 2001 Mathieu Bouchard;
+#X obj 2 549 cnv 15 780 30 empty empty empty 20 12 0 14 -200249 -66577
+0;
+#X text 10 556 GridFlow 0.8.0;
+#X text 10 556 GridFlow 0.8.0;
+#X obj 27 76 metro 33.3667;
+#X obj 89 353 #redim (2 2);
+#X obj 333 335 #export;
+#X obj 333 316 # % 36000;
+#N canvas 0 0 450 300 scratch 0;
+#X obj 40 38 inlet;
+#X obj 40 245 outlet;
+#X obj 40 57 route keypress;
+#X msg 40 76 \$4;
+#X msg 40 115 -1;
+#X msg 79 115 1;
+#X obj 40 182 +;
+#X obj 40 207 int;
+#X obj 72 185 nbx 8 14 -1e+37 1e+37 0 0 empty empty empty 0 -6 0 10
+-262144 -1 -1 0 256;
+#X obj 40 226 #fade 2;
+#X obj 65 207 inlet;
+#X obj 40 139 * 1500;
+#X obj 40 95 route Left Right;
+#X connect 0 0 2 0;
+#X connect 2 0 3 0;
+#X connect 3 0 12 0;
+#X connect 4 0 11 0;
+#X connect 5 0 11 0;
+#X connect 6 0 7 1;
+#X connect 6 0 8 0;
+#X connect 7 0 9 0;
+#X connect 8 0 6 1;
+#X connect 9 0 1 0;
+#X connect 10 0 7 0;
+#X connect 11 0 6 0;
+#X connect 12 0 4 0;
+#X connect 12 1 5 0;
+#X restore 333 297 pd scratch;
+#N canvas 0 0 304 312 scratch2 0;
+#X obj 30 23 inlet;
+#X obj 46 263 outlet;
+#X obj 30 42 route keypress;
+#X msg 30 90 \$4;
+#X msg 69 130 1;
+#X obj 45 197 +;
+#X obj 46 218 int;
+#X obj 71 199 nbx 8 14 -1e+37 1e+37 0 0 empty empty empty 0 -6 0 10
+-262144 -1 -1 0 256;
+#X obj 46 243 #fade 2;
+#X obj 71 218 inlet;
+#X obj 30 109 route Up Down;
+#X msg 30 130 -1;
+#X obj 30 70 t l l;
+#X msg 129 62 \$3;
+#X obj 129 81 & 1;
+#X obj 129 100 sel 0 1;
+#X obj 49 161 *;
+#X msg 130 120 1000;
+#X msg 168 120 5;
+#X connect 0 0 2 0;
+#X connect 2 0 12 0;
+#X connect 3 0 10 0;
+#X connect 4 0 16 0;
+#X connect 5 0 6 1;
+#X connect 5 0 7 0;
+#X connect 6 0 8 0;
+#X connect 7 0 5 1;
+#X connect 8 0 1 0;
+#X connect 9 0 6 0;
+#X connect 10 0 11 0;
+#X connect 10 1 4 0;
+#X connect 11 0 16 0;
+#X connect 12 0 3 0;
+#X connect 12 1 13 0;
+#X connect 13 0 14 0;
+#X connect 14 0 15 0;
+#X connect 15 0 17 0;
+#X connect 15 1 18 0;
+#X connect 16 0 5 0;
+#X connect 17 0 16 1;
+#X connect 18 0 16 1;
+#X restore 336 367 pd scratch2;
+#X obj 336 386 #export;
+#X obj 336 405 / 10000;
+#X obj 336 424 exp;
+#X obj 505 373 t b;
+#X msg 152 435 load teapot.png;
+#X obj 288 82 f;
+#X msg 393 172 6666;
+#X obj 328 273 spigot;
+#X obj 385 255 tgl 15 0 empty empty empty 17 7 0 10 -241291 -1 -1 0
+1;
+#X obj 344 465 spigot;
+#X obj 342 489 display;
+#X obj 428 435 # sin*;
+#X obj 462 497 display;
+#X connect 1 0 28 3;
+#X connect 2 0 13 0;
+#X connect 3 0 37 0;
+#X connect 4 0 15 0;
+#X connect 5 0 22 0;
+#X connect 6 0 1 0;
+#X connect 7 0 28 0;
+#X connect 8 0 18 0;
+#X connect 9 0 52 0;
+#X connect 10 0 7 0;
+#X connect 11 0 46 0;
+#X connect 13 0 25 0;
+#X connect 14 0 28 1;
+#X connect 15 0 28 2;
+#X connect 16 0 14 0;
+#X connect 17 0 47 0;
+#X connect 18 0 61 0;
+#X connect 18 0 69 1;
+#X connect 19 0 63 1;
+#X connect 20 0 8 0;
+#X connect 22 0 31 0;
+#X connect 23 0 63 0;
+#X connect 24 0 62 0;
+#X connect 25 0 26 0;
+#X connect 26 0 39 0;
+#X connect 26 0 65 0;
+#X connect 27 0 23 1;
+#X connect 28 0 53 0;
+#X connect 29 0 3 0;
+#X connect 29 1 23 0;
+#X connect 29 1 35 0;
+#X connect 29 1 56 1;
+#X connect 29 1 57 1;
+#X connect 30 0 19 0;
+#X connect 31 0 32 0;
+#X connect 32 0 61 0;
+#X connect 32 0 18 0;
+#X connect 33 0 25 1;
+#X connect 34 0 25 1;
+#X connect 35 0 33 0;
+#X connect 36 0 35 1;
+#X connect 37 0 2 0;
+#X connect 38 0 28 0;
+#X connect 39 0 40 0;
+#X connect 46 0 3 1;
+#X connect 47 0 69 0;
+#X connect 52 0 29 0;
+#X connect 53 0 37 1;
+#X connect 55 0 54 0;
+#X connect 56 0 55 0;
+#X connect 57 0 58 0;
+#X connect 58 0 59 0;
+#X connect 59 0 60 0;
+#X connect 60 0 67 0;
+#X connect 61 0 17 0;
+#X connect 62 0 34 0;
+#X connect 63 0 30 0;
+#X connect 63 0 17 0;
+#X connect 63 0 5 0;
+#X connect 64 0 17 0;
+#X connect 65 0 56 0;
+#X connect 65 0 57 0;
+#X connect 66 0 65 1;
+#X connect 66 0 67 1;
+#X connect 67 0 18 0;
+#X connect 67 0 68 0;
+#X connect 67 0 69 1;
+#X connect 69 0 53 0;
+#X connect 69 0 70 0;
diff --git a/externals/gridflow/examples/markov.pd b/externals/gridflow/examples/markov.pd
new file mode 100644
index 00000000..d6bbe262
--- /dev/null
+++ b/externals/gridflow/examples/markov.pd
@@ -0,0 +1,133 @@
+#N canvas 238 57 825 641 10;
+#X obj 70 203 dac~;
+#X obj 71 141 osc~;
+#X obj 71 103 mtof;
+#X obj 71 122 t f b;
+#X obj 105 142 line~;
+#X obj 70 160 *~;
+#X obj 74 86 hsl 128 15 0 127 0 0 empty empty empty -2 -6 0 8 -262144
+-1 -1 6700 1;
+#X obj 70 179 *~ 0.1;
+#X obj 33 6 key;
+#X obj 409 139 messageprepend set;
+#X obj 497 110 t l;
+#X msg 409 89 list \$1;
+#X obj 409 109 listprepend;
+#X msg 481 84 list;
+#X obj 97 7 loadbang;
+#X obj 34 29 listfind;
+#X obj 34 48 sel -1;
+#X obj 71 67 + 60;
+#X msg 114 28 list 113 50 119 51 101 114 53 116 54 121 55 117 105 57
+111 48 112 91 61 93 127;
+#X obj 409 69 key;
+#X msg 111 123 0.7 \, 0 400;
+#X floatatom 105 68 5 0 0 0 - - -;
+#X msg 200 180 list \$1;
+#X obj 275 199 listsublist 0 2;
+#X obj 200 199 listappend;
+#X obj 483 388 display;
+#X msg 270 264 1;
+#X msg 305 240 put_at ( \$2 \$1 );
+#X obj 166 319 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 75 309 f;
+#X obj 39 410 #store;
+#X obj 97 393 #fold +;
+#X obj 96 417 display;
+#X obj 275 219 t l l l;
+#X msg 184 279 bang;
+#X obj 8 387 #finished;
+#X floatatom 99 311 5 0 0 0 - - -;
+#X obj 90 288 t f;
+#X obj 17 262 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1
+;
+#X msg 192 299 list \$1;
+#X obj 46 366 t a a;
+#X obj 39 502 #scan +;
+#X obj 200 157 spigot;
+#X obj 82 440 # rand;
+#X obj 80 472 display;
+#X obj 38 546 # <;
+#X obj 50 595 #fold +;
+#X obj 280 512 display;
+#X obj 132 596 #export;
+#X obj 248 157 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0
+1;
+#X obj 104 329 + 60;
+#X obj 148 368 spigot;
+#X obj 199 367 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0
+1;
+#X obj 17 286 metro 100;
+#X obj 50 617 display;
+#X obj 67 568 display;
+#X obj 90 537 display;
+#X obj 191 322 #store (17 17 #) \, op +;
+#X text 536 12 This will be an example of Markov Chains;
+#X text 536 27 But it's not too clean yet;
+#X connect 1 0 5 0;
+#X connect 2 0 3 0;
+#X connect 3 0 1 0;
+#X connect 3 1 20 0;
+#X connect 4 0 5 1;
+#X connect 5 0 7 0;
+#X connect 6 0 2 0;
+#X connect 7 0 0 0;
+#X connect 7 0 0 1;
+#X connect 8 0 15 0;
+#X connect 10 0 12 1;
+#X connect 11 0 12 0;
+#X connect 12 0 10 0;
+#X connect 12 0 9 0;
+#X connect 13 0 12 1;
+#X connect 14 0 18 0;
+#X connect 15 0 16 0;
+#X connect 16 1 17 0;
+#X connect 16 1 42 0;
+#X connect 17 0 6 0;
+#X connect 17 0 21 0;
+#X connect 18 0 15 1;
+#X connect 19 0 11 0;
+#X connect 20 0 4 0;
+#X connect 22 0 24 0;
+#X connect 23 0 24 1;
+#X connect 23 0 33 0;
+#X connect 24 0 23 0;
+#X connect 26 0 57 1;
+#X connect 27 0 57 1;
+#X connect 28 0 57 0;
+#X connect 29 0 39 0;
+#X connect 30 0 41 0;
+#X connect 30 0 47 0;
+#X connect 31 0 32 0;
+#X connect 31 0 43 0;
+#X connect 33 0 34 0;
+#X connect 33 1 26 0;
+#X connect 33 2 27 0;
+#X connect 34 0 57 0;
+#X connect 35 0 30 0;
+#X connect 36 0 50 0;
+#X connect 37 0 29 1;
+#X connect 37 0 36 0;
+#X connect 38 0 53 0;
+#X connect 39 0 57 0;
+#X connect 40 0 35 0;
+#X connect 40 1 30 1;
+#X connect 40 1 31 0;
+#X connect 41 0 45 0;
+#X connect 41 0 56 0;
+#X connect 42 0 22 0;
+#X connect 43 0 44 0;
+#X connect 43 0 45 1;
+#X connect 45 0 46 0;
+#X connect 45 0 55 0;
+#X connect 46 0 48 0;
+#X connect 46 0 54 0;
+#X connect 48 0 37 0;
+#X connect 49 0 42 1;
+#X connect 50 0 6 0;
+#X connect 51 0 40 0;
+#X connect 52 0 51 1;
+#X connect 53 0 29 0;
+#X connect 57 0 25 0;
+#X connect 57 0 51 0;
diff --git a/externals/gridflow/examples/mechanics.pd b/externals/gridflow/examples/mechanics.pd
new file mode 100644
index 00000000..944dcb7c
--- /dev/null
+++ b/externals/gridflow/examples/mechanics.pd
@@ -0,0 +1,121 @@
+#N canvas 491 20 624 716 10;
+#X obj 188 65 # rand;
+#X obj 81 97 #store;
+#X obj 188 8 loadbang;
+#X obj 134 120 #transpose;
+#X obj 64 8 tgl 17 0 empty empty empty 0 -6 0 8 -24198 -1 -1 0 1;
+#X obj 81 171 #inner \, op sq- \, fold +;
+#X msg 139 56 1;
+#X msg 100 56 0;
+#X obj 81 120 shunt 2;
+#X obj 81 29 t b b b b;
+#X obj 27 244 #transpose 1 3;
+#X obj 27 282 #fold +;
+#X obj 27 357 # inv*;
+#X obj 159 424 # +;
+#X msg 188 27 bang;
+#X obj 12 648 #out window;
+#X obj 12 29 t b b;
+#X obj 12 667 fps detailed;
+#X obj 190 471 # inv+;
+#X obj 279 235 # + 1;
+#X obj 279 216 # * -2;
+#X obj 185 424 # *;
+#X msg 261 76 7 2 # 0;
+#X obj 12 574 # min 255;
+#X obj 81 8 metro 40;
+#X obj 350 598 #dim;
+#X msg 350 636 \$1;
+#X msg 349 674 \$1 2;
+#X obj 350 617 #export_list;
+#X obj 287 500 t a a;
+#X obj 350 655 * 6;
+#X obj 27 225 #outer sq-;
+#X msg 188 46 7 2 # 5760 7680;
+#X obj 240 521 # / 16;
+#X obj 27 322 # >> 8;
+#X obj 46 496 display;
+#X obj 190 452 # >> 8;
+#X obj 74 357 # << 8;
+#X obj 27 263 # * (2 2 # 1 0 0 1);
+#X obj 81 190 #outer ignore (2 #);
+#X obj 279 178 # abs- (2880 3840);
+#X obj 279 197 # >= (2880 3840);
+#X obj 290 460 # min (36000 48000);
+#X obj 290 479 # max (0 0);
+#X obj 240 541 #inner (2 6 2 # 1 0 1 0 1 0 1 0 1 0 0 0 0 1 0 1 0 1
+0 1 0 1 0 0);
+#X obj 240 573 # + (6 2 # -8 -8 -8 8 8 8 8 -8 -8 -8 180 240);
+#X obj 12 555 # *>>8 (232 242 252);
+#X obj 12 536 #draw_polygon + \, color (3 # 130);
+#X obj 12 517 #store (360 480 3 # 0);
+#X obj 28 376 #fold + \, seed (2 #);
+#X obj 231 613 #redim (42 2);
+#X text 310 8 This was supposed to be some kind of;
+#X text 310 24 Newtonian physics simulation;
+#X text 310 42 But it doesn't quite work;
+#X connect 0 0 1 1;
+#X connect 1 0 8 0;
+#X connect 2 0 14 0;
+#X connect 3 0 5 1;
+#X connect 3 0 31 1;
+#X connect 4 0 24 0;
+#X connect 5 0 39 0;
+#X connect 6 0 8 1;
+#X connect 7 0 8 1;
+#X connect 8 0 5 0;
+#X connect 8 0 31 0;
+#X connect 8 1 3 0;
+#X connect 8 1 18 1;
+#X connect 8 1 40 0;
+#X connect 9 0 16 0;
+#X connect 9 1 7 0;
+#X connect 9 2 1 0;
+#X connect 9 3 6 0;
+#X connect 10 0 38 0;
+#X connect 11 0 34 0;
+#X connect 12 0 49 0;
+#X connect 13 0 21 1;
+#X connect 13 0 36 0;
+#X connect 14 0 32 0;
+#X connect 14 0 22 0;
+#X connect 15 0 17 0;
+#X connect 16 0 48 0;
+#X connect 16 1 1 0;
+#X connect 18 0 29 0;
+#X connect 19 0 21 0;
+#X connect 20 0 19 0;
+#X connect 21 0 13 1;
+#X connect 22 0 13 1;
+#X connect 22 0 21 1;
+#X connect 23 0 15 0;
+#X connect 23 0 48 1;
+#X connect 24 0 9 0;
+#X connect 25 0 28 0;
+#X connect 26 0 30 0;
+#X connect 27 0 50 1;
+#X connect 28 0 26 0;
+#X connect 29 0 1 1;
+#X connect 29 0 33 0;
+#X connect 29 1 25 0;
+#X connect 30 0 27 0;
+#X connect 31 0 10 0;
+#X connect 32 0 0 0;
+#X connect 33 0 44 0;
+#X connect 34 0 12 0;
+#X connect 36 0 18 0;
+#X connect 36 0 35 0;
+#X connect 37 0 12 1;
+#X connect 38 0 11 0;
+#X connect 39 0 37 0;
+#X connect 40 0 41 0;
+#X connect 41 0 20 0;
+#X connect 42 0 43 0;
+#X connect 43 0 29 0;
+#X connect 44 0 45 0;
+#X connect 45 0 50 0;
+#X connect 46 0 23 0;
+#X connect 47 0 46 0;
+#X connect 48 0 47 0;
+#X connect 49 0 13 0;
+#X connect 50 0 47 2;
diff --git a/externals/gridflow/examples/motion_detect.pd b/externals/gridflow/examples/motion_detect.pd
new file mode 100644
index 00000000..c0d00178
--- /dev/null
+++ b/externals/gridflow/examples/motion_detect.pd
@@ -0,0 +1,44 @@
+#N canvas 564 180 494 470 10;
+#X obj 32 -33 tgl 15 0 empty empty empty 0 -6 0 8 -24198 -1 -1 0 1
+;
+#X obj 37 193 #downscale_by ( 15 20 ) smoothly;
+#X obj 37 219 #scale_by ( 32 32 );
+#X obj 37 251 #out window;
+#X obj 32 42 t a a;
+#X obj 37 68 # -;
+#X obj 37 91 @! abs;
+#X obj 37 114 # * 8;
+#X obj 37 140 # - 64;
+#X obj 61 291 fps detailed;
+#X obj 61 311 print;
+#X obj 32 -6 metro 33.3667;
+#X obj 32 18 #camera;
+#X obj 37 165 #clip;
+#X obj -15 353 cnv 15 500 30 empty empty empty 20 12 0 14 -200249 -66577
+0;
+#X text -7 360 GridFlow 0.8.0;
+#X text -7 360 GridFlow 0.8.0;
+#X obj -13 -85 cnv 15 500 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X text -5 -85 motion_detect.pd;
+#X text -6 -72 Copyright 2001 Mathieu Bouchard;
+#X obj 181 253 display;
+#X text 127 79 This patch demonstrates the basis of motion detection.
+The substraction of two subsequent frames after [t a a]. It then downscales
+and rescales the image \, breaking it down into larger regions that
+can be monitored for changes.;
+#X connect 0 0 11 0;
+#X connect 1 0 2 0;
+#X connect 1 0 20 0;
+#X connect 2 0 3 0;
+#X connect 3 0 9 0;
+#X connect 4 0 5 1;
+#X connect 4 1 5 0;
+#X connect 5 0 6 0;
+#X connect 6 0 7 0;
+#X connect 7 0 8 0;
+#X connect 8 0 13 0;
+#X connect 9 0 10 0;
+#X connect 11 0 12 0;
+#X connect 12 0 4 0;
+#X connect 13 0 1 0;
diff --git a/externals/gridflow/examples/multiblob.pd b/externals/gridflow/examples/multiblob.pd
new file mode 100644
index 00000000..22abdfb3
--- /dev/null
+++ b/externals/gridflow/examples/multiblob.pd
@@ -0,0 +1,205 @@
+#N canvas 575 0 647 688 10;
+#X obj 24 11 tgl 15 0 empty empty empty 17 7 0 10 -24198 -1 -1 0 1
+;
+#X obj 9 51 bng 15 250 50 0 empty empty empty 17 7 0 10 -24198 -1 -1
+;
+#X obj 128 47 print;
+#N canvas 474 566 363 100 erosion 0;
+#X obj 13 15 inlet binary_grid;
+#X obj 13 72 outlet binary_grid;
+#X obj 13 34 #convolve (3 3 # 1);
+#X obj 13 53 # > 5;
+#X connect 0 0 2 0;
+#X connect 2 0 3 0;
+#X connect 3 0 1 0;
+#X restore 24 257 pd erosion;
+#X obj 41 10 bng 15 250 50 0 empty empty empty 17 7 0 10 -24198 -1
+-1;
+#X obj 24 630 #out window \, set_geometry 0 0 240 320;
+#X obj 24 124 t a a;
+#X obj 172 344 # +;
+#X obj 172 393 #clip;
+#X text 560 -17 7.7 fps;
+#X text 560 -5 8.2 fps;
+#X text 560 7 8.5 fps;
+#X text 555 18 10.3 fps;
+#X obj 172 325 #greyscale_to_rgb;
+#X text 555 30 12.7 fps;
+#X obj 24 86 shunt;
+#X obj 44 69 tgl 15 0 empty empty empty 17 7 0 10 -241291 -1 -1 0 1
+;
+#X obj 63 86 s end;
+#X obj 31 570 r end;
+#X text 555 42 13.4 fps;
+#X obj 24 28 metro 66.7333;
+#X text 556 55 14.9 fps yuv;
+#X text 556 67 17 fps y;
+#X obj 24 591 shunt;
+#X obj 61 592 tgl 15 0 empty empty empty 17 7 0 10 -241291 -1 -1 0
+1;
+#X obj 44 611 #scale_by 2;
+#X obj 513 214 != 0;
+#X obj 440 141 spigot;
+#X obj 172 257 spigot;
+#X obj 24 445 #finished;
+#X obj 97 363 spigot;
+#X obj 109 341 >= 100;
+#X obj 97 382 s pos;
+#X obj 53 363 spigot;
+#X obj 53 382 s vari;
+#N canvas 357 365 450 300 contour2 0;
+#X obj 24 27 inlet;
+#X obj 24 46 #convolve (3 3 # 0 -1 0 -1 4 -1);
+#X obj 24 84 outlet;
+#X obj 24 65 # << 8;
+#X connect 0 0 1 0;
+#X connect 1 0 3 0;
+#X connect 3 0 2 0;
+#X restore 172 306 pd contour2;
+#X obj 24 276 #t;
+#X obj 82 504 tgl 15 0 empty empty empty 17 7 0 10 -241291 -1 -1 1
+1;
+#X obj 109 504 tgl 15 0 empty empty empty 17 7 0 10 -241291 -1 -1 1
+1;
+#X obj 513 192 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 1
+1;
+#X obj 511 168 loadbang;
+#X obj 128 28 fps detailed \, period 10;
+#X obj 94 483 loadbang;
+#X obj 24 50 #camera 0;
+#X text 12 -30 Copyright 2007 by Mathieu Bouchard;
+#X obj 24 143 #rgb_to_greyscale;
+#X obj 49 164 nbx 5 14 -1e+37 1e+37 0 1 empty empty empty 0 -8 0 10
+-232961 -1 -1 152 256;
+#X text 12 -19 Originally made for a show with Andree Prefontaine and
+Michal Seta;
+#X obj 24 162 # >;
+#X obj 60 296 #labelling;
+#X obj 24 296 t a a;
+#N canvas 772 226 450 385 show_labelling 0;
+#X obj 25 21 inlet bitmap;
+#X obj 170 288 inlet background_layer;
+#X obj 25 346 outlet image;
+#X obj 65 293 #seq_fold;
+#X obj 138 150 #moment_polar;
+#X obj 78 221 #make_cross;
+#X obj 226 150 #cast i;
+#X obj 138 169 + 9000;
+#X obj 78 274 # +;
+#X msg 78 169 0 0;
+#X obj 78 150 #finished;
+#X obj 226 169 # / 2;
+#N canvas 536 310 450 300 make_ellipse 0;
+#X obj 23 29 inlet;
+#X obj 120 30 inlet;
+#X obj 23 204 outlet;
+#X obj 23 48 bang;
+#X obj 23 105 #outer + (0 9000);
+#X obj 23 124 # cos*;
+#X obj 23 67 #for 0 24 1;
+#X obj 23 86 # * 1500;
+#X connect 0 0 3 0;
+#X connect 1 0 5 1;
+#X connect 3 0 6 0;
+#X connect 4 0 5 0;
+#X connect 5 0 2 0;
+#X connect 6 0 7 0;
+#X connect 7 0 4 0;
+#X restore 194 224 pd make_ellipse;
+#X obj 97 109 spigot;
+#X obj 226 188 shunt;
+#X obj 192 30 inlet enable;
+#X obj 97 128 t a a;
+#X obj 103 274 r pos;
+#X obj 97 90 r vari;
+#X obj 78 188 shunt;
+#X obj 339 183 inlet ellipse;
+#X obj 88 322 #draw_polygon put (255 0 0);
+#X obj 78 255 #rotate;
+#X connect 0 0 3 0;
+#X connect 1 0 3 2;
+#X connect 3 0 2 0;
+#X connect 3 1 21 0;
+#X connect 3 2 21 2;
+#X connect 4 0 7 0;
+#X connect 4 1 6 0;
+#X connect 5 0 22 0;
+#X connect 6 0 11 0;
+#X connect 7 0 22 1;
+#X connect 8 0 3 1;
+#X connect 9 0 19 0;
+#X connect 10 0 9 0;
+#X connect 11 0 14 0;
+#X connect 12 0 22 0;
+#X connect 13 0 16 0;
+#X connect 14 0 5 1;
+#X connect 14 1 12 1;
+#X connect 15 0 13 1;
+#X connect 16 0 10 0;
+#X connect 16 1 4 0;
+#X connect 17 0 8 1;
+#X connect 18 0 13 0;
+#X connect 19 0 5 0;
+#X connect 19 1 12 0;
+#X connect 20 0 14 1;
+#X connect 20 0 19 1;
+#X connect 21 0 3 3;
+#X connect 22 0 8 0;
+#X restore 24 521 pd show_labelling;
+#X text 130 504 ellipse mode;
+#X obj 171 280 t a a;
+#X obj 173 369 # +;
+#X obj 259 365 #inner (1 3 # 200 200 200);
+#X obj 259 384 # & (-1 -1 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0);
+#X text 347 403 make little dots;
+#X connect 0 0 20 0;
+#X connect 1 0 43 0;
+#X connect 3 0 36 0;
+#X connect 6 0 45 0;
+#X connect 6 1 27 0;
+#X connect 7 0 54 0;
+#X connect 8 0 51 1;
+#X connect 13 0 7 0;
+#X connect 15 0 6 0;
+#X connect 15 1 17 0;
+#X connect 16 0 15 1;
+#X connect 18 0 23 0;
+#X connect 20 0 43 0;
+#X connect 23 0 5 0;
+#X connect 23 1 25 0;
+#X connect 24 0 23 1;
+#X connect 25 0 5 0;
+#X connect 26 0 27 1;
+#X connect 26 0 28 1;
+#X connect 27 0 7 1;
+#X connect 28 0 53 0;
+#X connect 29 0 51 0;
+#X connect 30 0 32 0;
+#X connect 31 0 30 1;
+#X connect 31 0 33 1;
+#X connect 33 0 34 0;
+#X connect 35 0 13 0;
+#X connect 36 0 50 0;
+#X connect 36 1 28 0;
+#X connect 37 0 51 2;
+#X connect 38 0 51 3;
+#X connect 39 0 26 0;
+#X connect 40 0 39 0;
+#X connect 41 0 2 0;
+#X connect 42 0 38 0;
+#X connect 42 0 37 0;
+#X connect 43 0 15 0;
+#X connect 45 0 48 0;
+#X connect 46 0 48 1;
+#X connect 48 0 3 0;
+#X connect 49 1 33 0;
+#X connect 49 2 30 0;
+#X connect 49 3 31 0;
+#X connect 50 0 29 0;
+#X connect 50 1 49 0;
+#X connect 51 0 23 0;
+#X connect 53 0 35 0;
+#X connect 53 1 55 0;
+#X connect 54 0 8 0;
+#X connect 55 0 56 0;
+#X connect 56 0 54 1;
diff --git a/externals/gridflow/examples/nervous_video.pd b/externals/gridflow/examples/nervous_video.pd
new file mode 100644
index 00000000..acccbe7c
--- /dev/null
+++ b/externals/gridflow/examples/nervous_video.pd
@@ -0,0 +1,163 @@
+#N canvas 624 0 596 659 10;
+#N canvas 123 298 450 300 counter 0;
+#X obj 131 70 + 1;
+#X obj 131 23 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X floatatom 170 70 5 0 0 0 - - -;
+#X msg 131 47 1;
+#X floatatom 170 114 5 0 0 0 - - -;
+#X obj 132 157 select 1;
+#X msg 170 44 0;
+#X obj 132 178 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 70 25 inlet;
+#X obj 132 195 outlet;
+#X obj 220 65 inlet;
+#X obj 298 106 outlet;
+#X obj 170 95 >= 32;
+#X connect 0 0 2 0;
+#X connect 1 0 3 0;
+#X connect 2 0 0 1;
+#X connect 2 0 11 0;
+#X connect 2 0 12 0;
+#X connect 3 0 0 0;
+#X connect 4 0 5 0;
+#X connect 5 0 6 0;
+#X connect 5 0 7 0;
+#X connect 6 0 2 0;
+#X connect 7 0 9 0;
+#X connect 8 0 1 0;
+#X connect 10 0 12 1;
+#X connect 12 0 4 0;
+#X restore 341 140 pd counter;
+#X obj 14 262 / 10;
+#X floatatom 14 300 5 0 0 0 - - -;
+#X obj 14 50 tgl 15 0 empty empty empty 0 -6 0 8 -24198 -1 -1 0 1;
+#X floatatom 39 607 5 0 0 0 - - -;
+#X obj 14 607 fps;
+#X obj 14 67 metro 33.3667;
+#X msg 14 324 list \$1;
+#X msg 406 104 32;
+#X obj 14 243 random 320;
+#X obj 14 588 #out window;
+#X floatatom 406 124 5 0 0 0 - - -;
+#X obj 437 104 loadbang;
+#X text 448 123 maximum value is 32;
+#X text 449 136 (see below);
+#X obj 14 157 float;
+#X obj 14 199 shunt 4;
+#X obj 14 223 bang;
+#X obj 14 281 int;
+#X obj 125 163 vradio 15 1 0 4 empty empty empty 0 -6 0 8 -241291 -1
+-1 2;
+#X text 146 163 caffeine twitch;
+#X text 146 178 ethanol lag;
+#X obj 121 243 * 2;
+#X obj 150 243 * -1;
+#X text 146 209 back flash acid;
+#X text 145 193 acid flash back;
+#X obj 245 439 vradio 15 1 0 4 empty empty empty 0 -6 0 8 -241291 -1
+-1 2;
+#X text 263 436 plain;
+#X text 264 469 hilitemotion;
+#X text 263 485 embossmotion;
+#X text 193 37 This patch was created by Alexandre Castonguay \,;
+#X text 193 50 as a clone of Edo Tannenbaum's "nervous video" effect
+\, http://effectv.sourceforge.net;
+#X text 193 78 Later modified by Mathieu to add more effects;
+#X obj 71 491 # << 2;
+#X obj 92 243 + 1;
+#X obj 125 452 # -;
+#X obj 126 471 # + 128;
+#X obj 126 491 # max 0;
+#X obj 71 515 # min 255;
+#X obj 14 428 shunt 4;
+#X obj 109 423 shunt 4;
+#X text 263 454 mix 50%;
+#X obj 24 491 # >> 1;
+#X obj 24 458 # +;
+#X obj 14 86 t b b b;
+#X obj 4 626 cnv 15 700 30 empty empty empty 20 12 0 14 -200249 -66577
+0;
+#X text 13 633 GridFlow 0.8.0;
+#X text 13 633 GridFlow 0.8.0;
+#X obj 3 5 cnv 15 700 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X text 6 5 nervous_video.pd;
+#X text 146 114 <-- open this;
+#X msg 406 159 put_at ( \$1 0 0 0 );
+#X msg 215 386 reassign \, 32 240 320 3 b #;
+#X text 212 313 the buffer size decides the maximum loop length and
+dimension of each frame;
+#X msg 215 405 reassign \, 32 480 640 3 b #;
+#X obj 215 367 loadbang;
+#X obj 14 390 #store;
+#X obj 79 114 #camera 0;
+#X text 5 17 Copyright 2002 Alexandre Castonguay \, 2004 Mathieu Bouchard
+;
+#X obj 51 343 #cast b;
+#X obj 71 458 # abs-;
+#X obj 14 409 #cast i;
+#X obj 14 515 t a;
+#X obj 14 534 shunt;
+#X obj 44 553 #fade (1 4 16);
+#X obj 53 535 tgl 15 0 empty empty color_fade 18 8 0 12 -241291 -1
+-1 1 1;
+#X connect 0 1 51 0;
+#X connect 0 1 15 1;
+#X connect 1 0 18 0;
+#X connect 2 0 7 0;
+#X connect 3 0 6 0;
+#X connect 5 0 4 0;
+#X connect 6 0 44 0;
+#X connect 7 0 56 0;
+#X connect 8 0 11 0;
+#X connect 9 0 1 0;
+#X connect 10 0 5 0;
+#X connect 11 0 0 1;
+#X connect 12 0 8 0;
+#X connect 15 0 16 0;
+#X connect 16 0 17 0;
+#X connect 16 1 34 0;
+#X connect 16 2 22 0;
+#X connect 16 3 23 0;
+#X connect 17 0 9 0;
+#X connect 18 0 2 0;
+#X connect 19 0 16 1;
+#X connect 22 0 7 0;
+#X connect 23 0 7 0;
+#X connect 26 0 40 1;
+#X connect 26 0 39 1;
+#X connect 33 0 38 0;
+#X connect 34 0 7 0;
+#X connect 35 0 36 0;
+#X connect 36 0 37 0;
+#X connect 37 0 38 0;
+#X connect 38 0 62 0;
+#X connect 39 0 62 0;
+#X connect 39 1 43 0;
+#X connect 39 2 60 0;
+#X connect 39 3 35 0;
+#X connect 40 1 43 1;
+#X connect 40 2 60 1;
+#X connect 40 3 35 1;
+#X connect 42 0 62 0;
+#X connect 43 0 42 0;
+#X connect 44 0 15 0;
+#X connect 44 1 57 0;
+#X connect 44 2 0 0;
+#X connect 51 0 56 1;
+#X connect 52 0 56 1;
+#X connect 54 0 56 1;
+#X connect 55 0 52 0;
+#X connect 56 0 61 0;
+#X connect 57 0 40 0;
+#X connect 57 0 59 0;
+#X connect 59 0 56 1;
+#X connect 60 0 33 0;
+#X connect 61 0 39 0;
+#X connect 62 0 63 0;
+#X connect 63 0 10 0;
+#X connect 63 1 64 0;
+#X connect 64 0 10 0;
+#X connect 65 0 63 1;
diff --git a/externals/gridflow/examples/operator_spectrum.pd b/externals/gridflow/examples/operator_spectrum.pd
new file mode 100644
index 00000000..6c5f8e9f
--- /dev/null
+++ b/externals/gridflow/examples/operator_spectrum.pd
@@ -0,0 +1,102 @@
+#N canvas 693 0 542 648 10;
+#X obj 27 251 #cast f;
+#X obj 27 595 #clip;
+#X obj 26 386 #cast i;
+#X obj 27 67 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1
+;
+#X msg 197 103 4 2 # 0 0 0 1 1 1 1 0;
+#X obj 27 232 #outer * (1 0);
+#X obj 26 367 #remap_image;
+#X obj 26 348 # sqrt (f #);
+#X obj 27 329 #inner (2 f # 1 1) \, seed (f #);
+#X obj 27 310 # *;
+#X obj 27 289 t a a;
+#X obj 26 481 t a a;
+#X obj 27 103 #store (256 256 1 #);
+#X obj 27 122 #draw_polygon put (255);
+#X obj 79 484 # >> 8;
+#X obj 79 465 #inner (1 3 # 255 128 64);
+#X obj 27 576 # +;
+#X obj 127 586 #greyscale_to_rgb;
+#X obj 127 567 # * 255;
+#X obj 127 529 #convolve (3 3 # 0 -1 0 -1 4 -1);
+#X obj 27 84 metro 50;
+#X obj 197 84 loadbang;
+#X obj 26 405 # << 8;
+#X obj 26 462 # >> 8;
+#X obj 114 367 # + 128;
+#X obj 26 443 # + 128;
+#X obj 26 424 #fade 8;
+#X floatatom 442 65 5 0 0 0 - - -;
+#X floatatom 398 65 5 0 0 0 - - -;
+#X floatatom 354 65 5 0 0 0 - - -;
+#X msg 365 122 3 3 # \$1 \$2 \$1 \$2 \$3 \$2;
+#X obj 365 84 #pack 3;
+#X obj 365 103 #export_list;
+#X obj 292 354 # C.log (2 f #);
+#X obj 292 468 #greyscale_to_rgb;
+#X obj 292 430 #cast i;
+#X obj 292 373 #inner (2 f # 0 1) \, seed (f #);
+#X obj 292 411 # + (f # 128);
+#X obj 292 449 #clip;
+#X obj 292 392 # * (f # 40);
+#X obj 27 270 #fft;
+#X obj 197 122 # * 1;
+#X obj 127 548 # > 0;
+#X obj 128 510 # & 224;
+#X obj 57 183 #convolve (3 3 # -1 2 -1 2 -4 2);
+#X obj 27 149 #convolve (3 3 # 1 2 1 2 4 2 1 2 1);
+#X obj 27 213 # >> 4;
+#X text 28 8 Operator Spectrum patch.;
+#X text 28 25 Copyright 2007 by Mathieu Bouchard;
+#X text 28 42 as demonstrated at Pd Convention 2007;
+#X obj 27 614 #out window;
+#X connect 0 0 40 0;
+#X connect 1 0 50 0;
+#X connect 2 0 22 0;
+#X connect 3 0 20 0;
+#X connect 4 0 41 0;
+#X connect 5 0 0 0;
+#X connect 6 0 2 0;
+#X connect 6 1 24 0;
+#X connect 7 0 6 0;
+#X connect 8 0 7 0;
+#X connect 9 0 8 0;
+#X connect 10 0 9 0;
+#X connect 10 1 9 1;
+#X connect 11 0 43 0;
+#X connect 11 1 15 0;
+#X connect 12 0 13 0;
+#X connect 13 0 45 0;
+#X connect 14 0 16 1;
+#X connect 15 0 14 0;
+#X connect 16 0 1 0;
+#X connect 17 0 16 0;
+#X connect 18 0 17 0;
+#X connect 19 0 42 0;
+#X connect 20 0 12 0;
+#X connect 21 0 4 0;
+#X connect 22 0 26 0;
+#X connect 23 0 11 0;
+#X connect 24 0 6 1;
+#X connect 25 0 23 0;
+#X connect 26 0 25 0;
+#X connect 27 0 31 2;
+#X connect 28 0 31 1;
+#X connect 29 0 31 0;
+#X connect 30 0 45 1;
+#X connect 31 0 32 0;
+#X connect 32 0 30 0;
+#X connect 33 0 36 0;
+#X connect 35 0 38 0;
+#X connect 36 0 39 0;
+#X connect 37 0 35 0;
+#X connect 38 0 34 0;
+#X connect 39 0 37 0;
+#X connect 40 0 10 0;
+#X connect 41 0 13 2;
+#X connect 42 0 18 0;
+#X connect 43 0 19 0;
+#X connect 44 0 46 0;
+#X connect 45 0 46 0;
+#X connect 46 0 5 0;
diff --git a/externals/gridflow/examples/photo_pianoroll.pd b/externals/gridflow/examples/photo_pianoroll.pd
new file mode 100644
index 00000000..9ad80e38
--- /dev/null
+++ b/externals/gridflow/examples/photo_pianoroll.pd
@@ -0,0 +1,158 @@
+#N canvas 329 40 705 535 10;
+#X obj 146 62 #in lada.jpg;
+#X obj 38 290 #out window;
+#X obj 38 48 tgl 15 0 empty empty empty 0 -6 0 8 -24198 -1 -1 1 1;
+#X obj 38 114 #store;
+#X obj 164 41 loadbang;
+#X obj 146 42 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 255 466 dac~;
+#X obj 329 58 +;
+#X msg 329 39 1;
+#X obj 361 39 % 365;
+#N canvas 0 0 450 300 fft 0;
+#X obj 23 68 rifft~;
+#X obj 23 88 outlet~;
+#X obj 359 16 block~ 1024;
+#X obj 23 48 tabreceive~ array2;
+#X connect 0 0 1 0;
+#X connect 3 0 0 0;
+#X restore 255 423 pd fft;
+#X obj 17 85 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 38 84 t b b;
+#X msg 260 252 4 2 # 0 0 0 502 1 502 1 0;
+#X obj 260 271 # +;
+#X obj 38 233 t a b;
+#X msg 287 271 \$1 0;
+#X obj 38 252 #greyscale_to_rgb;
+#X obj 462 77 #store;
+#X obj 462 153 #export_list;
+#X obj 501 172 s array1;
+#X obj 171 177 # inv+ 255;
+#X obj 146 100 # min 255;
+#X obj 146 81 # * 3;
+#X msg 474 58 1 1 # \$1;
+#X obj 255 339 table array1 502;
+#X obj 462 172 t b a;
+#X obj 326 271 r row;
+#X obj 361 58 s row;
+#X obj 462 210 t f f;
+#X obj 462 305 tabwrite array2;
+#X obj 462 248 exp;
+#X obj 38 309 #mouse \, ...;
+#X obj 79 383 #draw_polygon put;
+#X obj 79 364 spigot;
+#X obj 29 413 t a a;
+#X obj 29 470 # +;
+#X obj 146 177 t a;
+#X msg 29 432 4 2 # 0 0 0 1 1 1 1 0;
+#X obj 29 451 # *;
+#X obj 105 459 nbx 5 14 -1e+37 1e+37 0 1 empty empty empty 0 -6 0 10
+-262131 -1 -1 20 256;
+#X msg 185 217 365 502 1 # 255;
+#X text 296 217 clear;
+#X obj 462 286 tabread4 array1;
+#X obj 462 191 for 0 64 1;
+#X obj 462 96 #fade 5;
+#X obj 255 358 table array2 1024;
+#X obj 255 442 lop~ 1000;
+#X obj 462 229 / 20;
+#X obj 462 267 * 22;
+#X obj 105 473 nbx 5 14 -1e+37 1e+37 0 1 empty empty empty 0 -6 0 10
+-262131 -1 -1 20 256;
+#X obj 54 470 #pack 2;
+#X obj 499 39 # >> 4;
+#X obj 146 138 # >> 2;
+#X obj 38 271 #draw_polygon put (3 # 255 0 0);
+#X obj 2 499 cnv 15 700 30 empty empty empty 20 12 0 14 -200249 -66577
+0;
+#X text 10 506 GridFlow 0.8.0;
+#X text 10 506 GridFlow 0.8.0;
+#X obj 2 0 cnv 15 700 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X text 17 -1 photo_pianoroll.pd;
+#X text 15 13 Copyright 2004 Mathieu Bouchard;
+#X obj 462 134 # / (f # 4000);
+#X obj 462 115 #cast f;
+#X obj 171 196 #convolve (1 7 # 1 1 2 8 2 1 1);
+#X obj 146 119 #convolve (2 2 # 1);
+#X msg 132 344 0;
+#X msg 136 364 1 # \$1;
+#X msg 162 344 255;
+#X obj 79 402 s feedback;
+#X obj 152 158 r feedback;
+#X obj 38 65 metro 46.44;
+#X text 575 7 How to play a car;
+#X connect 0 0 23 0;
+#X connect 1 0 32 0;
+#X connect 2 0 70 0;
+#X connect 3 0 15 0;
+#X connect 3 0 34 0;
+#X connect 4 0 0 0;
+#X connect 5 0 0 0;
+#X connect 7 0 9 0;
+#X connect 8 0 7 0;
+#X connect 9 0 7 1;
+#X connect 9 0 28 0;
+#X connect 9 0 24 0;
+#X connect 10 0 47 0;
+#X connect 11 0 12 0;
+#X connect 12 0 8 0;
+#X connect 12 1 3 0;
+#X connect 13 0 14 0;
+#X connect 14 0 54 2;
+#X connect 15 0 17 0;
+#X connect 15 1 13 0;
+#X connect 16 0 14 1;
+#X connect 17 0 54 0;
+#X connect 18 0 45 0;
+#X connect 19 0 26 0;
+#X connect 21 0 63 0;
+#X connect 22 0 64 0;
+#X connect 23 0 22 0;
+#X connect 24 0 18 0;
+#X connect 26 0 44 0;
+#X connect 26 1 20 0;
+#X connect 27 0 16 0;
+#X connect 29 0 48 0;
+#X connect 29 1 30 1;
+#X connect 31 0 49 0;
+#X connect 32 0 35 0;
+#X connect 32 1 35 0;
+#X connect 32 4 34 1;
+#X connect 32 4 65 0;
+#X connect 32 6 34 1;
+#X connect 32 6 67 0;
+#X connect 33 0 68 0;
+#X connect 34 0 33 0;
+#X connect 35 0 38 0;
+#X connect 35 1 36 1;
+#X connect 36 0 33 2;
+#X connect 37 0 3 1;
+#X connect 37 0 21 0;
+#X connect 38 0 39 0;
+#X connect 39 0 36 0;
+#X connect 40 0 51 0;
+#X connect 41 0 37 0;
+#X connect 43 0 30 0;
+#X connect 44 0 29 0;
+#X connect 45 0 62 0;
+#X connect 47 0 6 0;
+#X connect 47 0 6 1;
+#X connect 48 0 31 0;
+#X connect 49 0 43 0;
+#X connect 50 0 51 1;
+#X connect 51 0 39 1;
+#X connect 52 0 18 1;
+#X connect 53 0 37 0;
+#X connect 54 0 1 0;
+#X connect 61 0 19 0;
+#X connect 62 0 61 0;
+#X connect 63 0 52 0;
+#X connect 64 0 53 0;
+#X connect 65 0 66 0;
+#X connect 66 0 33 1;
+#X connect 67 0 33 1;
+#X connect 69 0 37 0;
+#X connect 70 0 12 0;
diff --git a/externals/gridflow/examples/pinwheel.pd b/externals/gridflow/examples/pinwheel.pd
new file mode 100644
index 00000000..b9d7c73f
--- /dev/null
+++ b/externals/gridflow/examples/pinwheel.pd
@@ -0,0 +1,108 @@
+#N canvas 582 117 634 630 10;
+#X obj 33 489 #outer * (255 255 255);
+#X obj 33 509 #out window;
+#X obj 33 50 tgl 15 0 empty empty empty 17 7 0 10 -4034 -1 -1 1 1;
+#X obj 65 195 f;
+#X obj 33 87 t b b;
+#X obj 95 195 + 250;
+#X obj 253 395 nbx 3 14 1 32 0 1 empty A empty 0 -8 0 10 -241291 -1
+-1 24 256;
+#X obj 253 358 nbx 3 14 0 512 0 1 empty B empty 0 -8 0 10 -241291 -1
+-1 175 256;
+#X obj 243 198 nbx 4 14 1 8192 0 1 empty C empty 0 -8 0 10 -241291
+-1 -1 3 256;
+#X obj 118 153 # c2p (128 128);
+#X obj 349 25 cnv 15 220 500 empty empty empty 20 12 0 14 -241291 -66577
+0;
+#X text 374 28 Presets:;
+#X text 24 26 Copyright 2009 by Federico Ferri;
+#X text 355 539 GridFlow 0.9.5;
+#X obj 118 133 #for (0 0) (256 256) (1 1);
+#X obj 33 528 fps;
+#X floatatom 33 547 5 0 0 0 - - -;
+#X obj 33 449 # % 36000;
+#X obj 33 469 # > 18000;
+#X obj 33 265 # + (0 0);
+#X msg 65 235 2 # 0 \$1;
+#X obj 65 215 + 18000;
+#X obj 33 429 #inner (1 1);
+#X obj 33 409 # * (1 1);
+#X obj 33 175 #t;
+#X obj 143 192 #inner (1 0);
+#X obj 143 212 # *;
+#X obj 143 352 #outer * (1 0);
+#X obj 143 392 # + (0 1);
+#X obj 143 372 # * 1;
+#X obj 233 258 # sin* 1;
+#X obj 143 232 shunt 2;
+#X obj 243 217 hradio 15 1 0 2 empty E empty 0 -8 0 10 -241291 -1 -1
+0;
+#X obj 143 291 # - 1;
+#X obj 279 226 nbx 3 14 0 512 0 1 empty D empty 0 -8 0 10 -241291 -1
+-1 0 256;
+#X obj 505 41 r P;
+#X msg 505 61 \; A \$1 \; B \$2 \; C \$3 \; D \$4 \; E \$5;
+#X msg 361 52 \; P 24 175 3 0 0;
+#X msg 361 92 \; P 1 512 1 0 0;
+#X msg 361 132 \; P 8 141 8 0 0;
+#X msg 361 172 \; P 31 74 8 0 0;
+#X msg 361 212 \; P 3 23 1 0 0;
+#X msg 361 252 \; P 2 15 8 0 0;
+#X msg 361 292 \; P 3 1 150 100 1;
+#X msg 361 332 \; P 3 1 1500 25 1;
+#X msg 361 372 \; P 16 1 1500 10 1;
+#X msg 361 412 \; P 5 5 275 11 1;
+#X msg 253 412 2 # \$1 \$1;
+#X obj 143 252 # >> 7;
+#X obj 143 272 # & 2;
+#X obj 33 156 #store;
+#X obj 118 112 loadbang;
+#X msg 200 53 256 256;
+#X msg 201 74 512 512;
+#X obj 189 96 t b a;
+#X obj 33 67 metro 10;
+#X connect 0 0 1 0;
+#X connect 1 0 15 0;
+#X connect 2 0 55 0;
+#X connect 3 0 5 0;
+#X connect 3 0 21 0;
+#X connect 4 0 50 0;
+#X connect 4 1 3 0;
+#X connect 5 0 3 1;
+#X connect 6 0 47 0;
+#X connect 7 0 29 1;
+#X connect 8 0 26 1;
+#X connect 9 0 50 1;
+#X connect 14 0 9 0;
+#X connect 15 0 16 0;
+#X connect 17 0 18 0;
+#X connect 18 0 0 0;
+#X connect 19 0 23 0;
+#X connect 20 0 19 1;
+#X connect 21 0 20 0;
+#X connect 22 0 17 0;
+#X connect 23 0 22 0;
+#X connect 24 0 19 0;
+#X connect 24 1 25 0;
+#X connect 25 0 26 0;
+#X connect 26 0 31 0;
+#X connect 27 0 29 0;
+#X connect 28 0 23 1;
+#X connect 29 0 28 0;
+#X connect 30 0 27 0;
+#X connect 31 0 48 0;
+#X connect 31 1 30 0;
+#X connect 32 0 31 1;
+#X connect 33 0 27 0;
+#X connect 34 0 30 1;
+#X connect 35 0 36 0;
+#X connect 47 0 22 1;
+#X connect 48 0 49 0;
+#X connect 49 0 33 0;
+#X connect 50 0 24 0;
+#X connect 51 0 14 0;
+#X connect 52 0 54 0;
+#X connect 53 0 54 0;
+#X connect 54 0 14 0;
+#X connect 54 1 14 1;
+#X connect 55 0 4 0;
diff --git a/externals/gridflow/examples/play_video.pd b/externals/gridflow/examples/play_video.pd
new file mode 100644
index 00000000..530c8e66
--- /dev/null
+++ b/externals/gridflow/examples/play_video.pd
@@ -0,0 +1,44 @@
+#N canvas 1036 382 502 475 10;
+#X obj 29 221 #in;
+#X obj 29 -37 tgl 15 0 empty empty empty 17 7 0 10 -24198 -1 -1 0 1
+;
+#X obj 30 323 display;
+#X obj -17 -85 cnv 15 500 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X obj -16 356 cnv 15 500 30 empty empty empty 20 12 0 14 -200249 -66577
+0;
+#X text -7 363 GridFlow 0.8.0;
+#X text -6 -83 play_video.pd;
+#X obj 29 -6 metro 33.333;
+#X obj 29 270 #out window \, title video;
+#X obj 29 296 fps;
+#X text -7 363 GridFlow 0.9.0;
+#X text 58 -38 <-- 2 start the metro;
+#X floatatom 69 167 5 0 0 0 - - -;
+#X msg 94 195 42;
+#X text 129 195 <-- select the frame number;
+#X text 116 84 libraries. Photo jpeg compression gives slightly;
+#X text 118 98 better results than mjpega. Rendering is cpu;
+#X text 117 112 intensive so if operations on the images is;
+#X text 117 70 Supported codecs will depend on your installed;
+#X text 114 166 <-- scrub the video (stop the metro first);
+#X text 117 138 such as 320 x 240;
+#X text 118 125 needed \, then start with a lower resolution;
+#X text 174 29 <-- 1 open a file \, make sure the correct;
+#X text 173 43 path is entered in pd's 'Path' preferences.;
+#X floatatom 53 246 5 0 0 0 - - -;
+#X obj 99 245 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
+-1;
+#X text 123 244 <-- outputs a bang when finished;
+#X text 139 -82 see also [#in]'s help file;
+#X msg 46 30 open violoncelle.mov;
+#X connect 0 0 8 0;
+#X connect 0 1 24 0;
+#X connect 0 1 25 0;
+#X connect 1 0 7 0;
+#X connect 7 0 0 0;
+#X connect 8 0 9 0;
+#X connect 9 0 2 0;
+#X connect 12 0 0 0;
+#X connect 13 0 0 0;
+#X connect 28 0 0 0;
diff --git a/externals/gridflow/examples/plot.pd b/externals/gridflow/examples/plot.pd
new file mode 100644
index 00000000..dad9db76
--- /dev/null
+++ b/externals/gridflow/examples/plot.pd
@@ -0,0 +1,73 @@
+#N canvas 211 415 621 272 10;
+#N canvas 803 450 420 235 plot-a-function 0;
+#X obj 8 61 # inv+ 640;
+#X obj 8 40 #for 0 640 1;
+#X obj 105 59 outlet;
+#X obj 33 175 #outer <;
+#X obj 105 80 inlet;
+#X text 209 199 to rgb;
+#X text 97 176 make graph \, twotone channelless;
+#X obj 35 232 outlet;
+#X obj 105 34 #for 0 640 1;
+#X obj 105 10 inlet;
+#X obj 92 132 #finished;
+#X obj 105 103 t a a;
+#X obj 33 200 #outer * (255 255 255);
+#X connect 0 0 3 0;
+#X connect 1 0 0 0;
+#X connect 3 0 12 0;
+#X connect 4 0 11 0;
+#X connect 8 0 2 0;
+#X connect 9 0 8 0;
+#X connect 10 0 1 0;
+#X connect 11 0 10 0;
+#X connect 11 1 3 1;
+#X connect 12 0 7 0;
+#X restore 57 47 pd plot-a-function ( tm );
+#X obj 257 81 # + 320;
+#X obj 57 72 #out window;
+#X obj 256 -3 # - 320;
+#X obj 256 53 # tanh* 343;
+#X obj 256 25 # * 30;
+#X obj 33 15 bng 15 250 50 0 empty empty empty 0 -6 0 8 -24198 -1 -1
+;
+#X obj -16 -85 cnv 15 620 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X obj -15 152 cnv 15 620 30 empty empty empty 20 12 0 14 -200249 -66577
+0;
+#X text -7 159 GridFlow 0.8.0;
+#X text -7 159 GridFlow 0.8.0;
+#X text -3 -86 plot.pd;
+#X obj 57 -10 tgl 15 0 empty empty empty 0 -6 0 8 -24198 -1 -1 1 1
+;
+#X obj 57 14 metro 100;
+#X obj 360 -3 hsl 128 15 0 500 0 0 empty empty empty -2 -6 0 8 -260818
+-1 -1 3600 1;
+#X floatatom 314 -2 5 0 0 0 - - -;
+#X obj 358 25 hsl 128 15 0 500 0 0 empty empty empty -2 -6 0 8 -260818
+-1 -1 1300 1;
+#X floatatom 311 26 5 0 0 0 - - -;
+#X obj 390 54 hsl 128 15 0 500 0 0 empty empty empty -2 -6 0 8 -260818
+-1 -1 6700 1;
+#X floatatom 343 54 5 0 0 0 - - -;
+#X obj 361 82 hsl 128 15 0 500 0 0 empty empty empty -2 -6 0 8 -260818
+-1 -1 5600 1;
+#X floatatom 314 82 5 0 0 0 - - -;
+#X text -3 -72 Copyright 2003 Mathieu Bouchard;
+#X connect 0 0 2 0;
+#X connect 0 1 3 0;
+#X connect 1 0 0 1;
+#X connect 3 0 5 0;
+#X connect 4 0 1 0;
+#X connect 5 0 4 0;
+#X connect 6 0 0 0;
+#X connect 12 0 13 0;
+#X connect 13 0 0 0;
+#X connect 14 0 15 0;
+#X connect 15 0 3 1;
+#X connect 16 0 17 0;
+#X connect 17 0 5 1;
+#X connect 18 0 19 0;
+#X connect 19 0 4 1;
+#X connect 20 0 21 0;
+#X connect 21 0 1 1;
diff --git a/externals/gridflow/examples/polar.pd b/externals/gridflow/examples/polar.pd
new file mode 100644
index 00000000..456976c7
--- /dev/null
+++ b/externals/gridflow/examples/polar.pd
@@ -0,0 +1,57 @@
+#N canvas 649 265 450 300 10;
+#X obj 29 71 tgl 15 0 empty empty empty 17 7 0 10 -204786 -1 -1 1 1
+;
+#X obj 29 129 #remap_image;
+#X obj 29 148 #out window;
+#X obj 190 124 # c2p (0 0);
+#X obj 190 143 # >>;
+#X obj 190 221 # <<;
+#X obj 190 162 #rotate;
+#X obj 379 145 * 100;
+#X obj 190 240 # p2c (0 0);
+#X obj 274 96 #pack;
+#X obj 190 184 # *>>8;
+#X obj 301 80 nbx 5 14 -1e+37 1e+37 0 1 empty empty empty 0 -8 0 10
+-262130 -1 -1 160 256;
+#X obj 301 64 nbx 5 14 -1e+37 1e+37 0 1 empty empty empty 0 -8 0 10
+-262130 -1 -1 120 256;
+#X obj 291 135 #pack;
+#X obj 318 119 nbx 5 14 -1e+37 1e+37 0 1 empty empty empty 0 -8 0 10
+-262130 -1 -1 1280 256;
+#X obj 318 103 nbx 5 14 -1e+37 1e+37 0 1 empty empty empty 0 -8 0 10
+-262130 -1 -1 256 256;
+#X obj 293 225 #pack;
+#X obj 320 209 nbx 5 14 -1e+37 1e+37 0 1 empty empty empty 0 -8 0 10
+-262130 -1 -1 5 256;
+#X obj 320 193 nbx 5 14 -1e+37 1e+37 0 1 empty empty empty 0 -8 0 10
+-262130 -1 -1 0 256;
+#X obj 379 129 nbx 5 14 -1e+37 1e+37 0 1 empty empty empty 0 -8 0 10
+-262130 -1 -1 0 256;
+#X obj 29 109 #camera 0 \, size 240 320;
+#X obj 29 90 metro 100;
+#X text 10 1 Copyright 2009 Mathieu Bouchard;
+#X text -3 274 GridFlow 0.9.5;
+#X connect 0 0 21 0;
+#X connect 1 0 2 0;
+#X connect 1 1 3 0;
+#X connect 3 0 4 0;
+#X connect 4 0 6 0;
+#X connect 5 0 8 0;
+#X connect 6 0 10 0;
+#X connect 7 0 6 1;
+#X connect 8 0 1 1;
+#X connect 9 0 3 1;
+#X connect 9 0 8 1;
+#X connect 10 0 5 0;
+#X connect 11 0 9 1;
+#X connect 12 0 9 0;
+#X connect 13 0 10 1;
+#X connect 14 0 13 1;
+#X connect 15 0 13 0;
+#X connect 16 0 5 1;
+#X connect 16 0 4 1;
+#X connect 17 0 16 1;
+#X connect 18 0 16 0;
+#X connect 19 0 7 0;
+#X connect 20 0 1 0;
+#X connect 21 0 20 0;
diff --git a/externals/gridflow/examples/polygon.pd b/externals/gridflow/examples/polygon.pd
new file mode 100644
index 00000000..a18980ea
--- /dev/null
+++ b/externals/gridflow/examples/polygon.pd
@@ -0,0 +1,123 @@
+#N canvas 130 96 584 565 10;
+#X obj 35 250 #draw_polygon +;
+#X obj 18 1 bng 15 250 50 0 empty empty empty 0 -6 0 8 -24198 -1 -1
+;
+#X obj 35 214 #store;
+#X obj 35 -36 tgl 15 0 empty empty empty 0 -6 0 8 -24198 -1 -1 1 1
+;
+#X obj 35 378 #out window;
+#X obj 306 7 vsl 15 137 0 36000 0 1 empty empty empty -2 -6 0 8 -260818
+-1 -1 3400 1;
+#N canvas 0 0 415 291 create 0;
+#X msg 82 66 0 \$1;
+#X obj 5 131 #outer + ( 0 9000 );
+#X obj 5 153 # +;
+#X obj 5 197 # + ( 120 160 );
+#X obj 5 175 # cos* 116;
+#X obj 5 109 # * 14400;
+#X obj 5 87 #for 0 5 1;
+#X obj 34 153 inlet rotation_angle;
+#X obj 5 10 inlet bang;
+#X obj 5 219 outlet polygon;
+#X obj 82 44 inlet tilt_factor;
+#X text 81 27 default: 9000 \, for flatness;
+#X connect 0 0 1 1;
+#X connect 1 0 2 0;
+#X connect 2 0 4 0;
+#X connect 3 0 9 0;
+#X connect 4 0 3 0;
+#X connect 5 0 1 0;
+#X connect 6 0 5 0;
+#X connect 7 0 2 1;
+#X connect 8 0 6 0;
+#X connect 10 0 0 0;
+#X restore 204 149 pd create star;
+#N canvas 0 0 450 300 color 0;
+#X obj 18 141 outlet 0;
+#X obj 18 95 # sin* 128;
+#X obj 18 117 # + 128;
+#X obj 18 37 # * 1146;
+#X obj 18 13 inlet;
+#X obj 18 60 #outer + ( 0 12000 24000 );
+#X text 139 52 each channel is a sine wave \; the three are offset
+from each other 120 degrees. it is almost like turning around in the
+color wheel except we don't support the HSV color model for now.;
+#X connect 1 0 2 0;
+#X connect 2 0 0 0;
+#X connect 3 0 5 0;
+#X connect 4 0 3 0;
+#X connect 5 0 1 0;
+#X restore 62 102 pd color generator;
+#X obj 35 -19 metro 33.3667;
+#X obj 35 0 t b b b;
+#X obj 35 71 t b;
+#X floatatom 307 151 6 0 0 0 - - -;
+#X obj 88 194 loadbang;
+#X obj 51 272 shunt 2;
+#X obj 104 274 tgl 15 1 empty empty empty 0 -6 0 8 -241291 -1 -1 1
+1;
+#X text 122 273 blur;
+#X msg 88 214 240 320 3 b # 0;
+#X obj 62 140 #cast b;
+#X obj 79 355 #solarize;
+#X obj 35 317 shunt 2;
+#X obj 88 319 tgl 15 1 empty empty empty 0 -6 0 8 -241291 -1 -1 1 1
+;
+#X obj 155 303 # >> (b # 2);
+#X obj 155 322 #convolve (1 3 b # 1 2 1) \, seed (b # 0);
+#X obj -15 442 cnv 15 580 30 empty empty empty 20 12 0 14 -200249 -66577
+0;
+#X text -7 450 GridFlow 0.8.0;
+#X text -7 450 GridFlow 0.8.0;
+#X obj -13 -85 cnv 15 580 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X text 0 -72 Copyright 2002 Mathieu Bouchard;
+#X text 0 -86 polygon.pd;
+#X obj 79 336 #cast i;
+#X obj 82 30 + 1;
+#X obj 57 30 i;
+#X msg 22 26 0;
+#X obj 182 75 expr ($f1*$f1/2);
+#X obj 155 341 # >> (b # 2);
+#X obj 155 360 #convolve (3 1 b # 1 2 1) \, seed (b # 0);
+#X obj 5 27 bng 15 250 50 0 empty empty empty 0 -6 0 8 -258699 -1 -1
+;
+#X obj 62 121 # >> 3;
+#X connect 0 0 13 0;
+#X connect 0 0 19 0;
+#X connect 1 0 9 0;
+#X connect 2 0 0 0;
+#X connect 3 0 8 0;
+#X connect 5 0 11 0;
+#X connect 6 0 0 2;
+#X connect 7 0 37 0;
+#X connect 8 0 9 0;
+#X connect 9 0 10 0;
+#X connect 9 1 31 0;
+#X connect 9 2 6 0;
+#X connect 10 0 2 0;
+#X connect 11 0 6 2;
+#X connect 12 0 16 0;
+#X connect 13 0 2 1;
+#X connect 13 1 21 0;
+#X connect 14 0 13 1;
+#X connect 16 0 2 1;
+#X connect 17 0 0 1;
+#X connect 18 0 4 0;
+#X connect 19 0 4 0;
+#X connect 19 1 29 0;
+#X connect 20 0 19 1;
+#X connect 21 0 22 0;
+#X connect 22 0 34 0;
+#X connect 29 0 18 0;
+#X connect 30 0 31 1;
+#X connect 31 0 30 0;
+#X connect 31 0 7 0;
+#X connect 31 0 33 0;
+#X connect 32 0 31 0;
+#X connect 33 0 6 1;
+#X connect 34 0 35 0;
+#X connect 35 0 2 1;
+#X connect 36 0 32 0;
+#X connect 36 0 16 0;
+#X connect 37 0 17 0;
diff --git a/externals/gridflow/examples/polygon_editor.pd b/externals/gridflow/examples/polygon_editor.pd
new file mode 100644
index 00000000..478a9d0e
--- /dev/null
+++ b/externals/gridflow/examples/polygon_editor.pd
@@ -0,0 +1,23 @@
+#N canvas 478 312 450 300 10;
+#X obj 41 33 metro 33.3667;
+#X obj 23 34 tgl 15 0 empty empty empty 0 -6 0 8 -24198 -1 -1 1 1;
+#X obj 41 52 #store (240 320 3 #);
+#X obj 41 219 #out window;
+#X obj 115 238 s events;
+#X obj 50 73 r events;
+#X obj 41 95 t a;
+#X obj 122 181 print unused_events;
+#X obj 41 181 route2 grid;
+#X obj 41 238 route bang;
+#X obj 41 147 #edit_polygon put (3 # 255) (3 2 # 0 0 100 200 200 100)
+;
+#X connect 0 0 2 0;
+#X connect 1 0 0 0;
+#X connect 2 0 6 0;
+#X connect 3 0 9 0;
+#X connect 5 0 6 0;
+#X connect 6 0 10 0;
+#X connect 8 0 3 0;
+#X connect 8 1 7 0;
+#X connect 9 1 4 0;
+#X connect 10 0 8 0;
diff --git a/externals/gridflow/examples/postdigital.pd b/externals/gridflow/examples/postdigital.pd
new file mode 100644
index 00000000..53e5c517
--- /dev/null
+++ b/externals/gridflow/examples/postdigital.pd
@@ -0,0 +1,67 @@
+#N canvas 681 68 541 475 10;
+#X obj 23 2 tgl 15 0 empty empty empty 0 -6 0 8 -24198 -1 -1 1 1;
+#X obj 65 89 #camera;
+#X obj 40 149 t a a a;
+#X obj 9 188 t a a;
+#X msg 39 207 close;
+#X msg 27 253 open /tmp/foo.mov \, bang \, cast uint8 \, close;
+#X obj 40 1 metro 100;
+#X obj 151 194 f;
+#X obj 111 194 bang;
+#X obj 65 109 #convolve (3 3 # 1 2 1 2 4 2);
+#X obj 65 128 # >> 4;
+#X obj 40 168 #finished;
+#X obj 41 230 #out;
+#X obj 27 272 #in;
+#X obj 29 302 # -;
+#X obj 30 414 #clip;
+#X obj 30 452 #out window;
+#X obj 14 38 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 34 63 #in babbage.jpg;
+#X msg 116 219 open quicktime /tmp/foo.mov \, codec jpeg \, parameter
+jpeg_quality \$1;
+#X obj 40 20 shunt;
+#X obj 79 21 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1
+;
+#X obj 30 355 # +;
+#X obj 30 336 # << 3;
+#X obj 176 194 nbx 3 14 0 100 0 0 empty empty empty 0 -8 0 10 -241291
+-1 -1 75 256;
+#X msg 176 175 75;
+#X obj 176 156 loadbang;
+#X text 64 301 compute difference between original image and jpeg decoding
+;
+#X text 80 336 boost the residue;
+#X text 64 355 add boosted residue to the original image;
+#X connect 0 0 6 0;
+#X connect 1 0 9 0;
+#X connect 2 0 11 0;
+#X connect 2 1 12 0;
+#X connect 2 2 8 0;
+#X connect 2 2 14 1;
+#X connect 2 2 22 1;
+#X connect 3 0 5 0;
+#X connect 3 1 4 0;
+#X connect 4 0 12 0;
+#X connect 5 0 13 0;
+#X connect 6 0 20 0;
+#X connect 7 0 19 0;
+#X connect 8 0 7 0;
+#X connect 9 0 10 0;
+#X connect 10 0 2 0;
+#X connect 11 0 3 0;
+#X connect 13 0 14 0;
+#X connect 14 0 23 0;
+#X connect 15 0 16 0;
+#X connect 17 0 18 0;
+#X connect 18 0 2 0;
+#X connect 19 0 12 0;
+#X connect 20 0 18 0;
+#X connect 20 1 1 0;
+#X connect 21 0 20 1;
+#X connect 22 0 15 0;
+#X connect 23 0 22 0;
+#X connect 24 0 7 1;
+#X connect 25 0 24 0;
+#X connect 26 0 25 0;
diff --git a/externals/gridflow/examples/radial_blur.pd b/externals/gridflow/examples/radial_blur.pd
new file mode 100644
index 00000000..acb7e039
--- /dev/null
+++ b/externals/gridflow/examples/radial_blur.pd
@@ -0,0 +1,102 @@
+#N canvas 1212 325 461 616 10;
+#X obj 47 166 #in;
+#X msg 134 149 open \$1;
+#X obj 134 89 openpanel;
+#X obj 134 71 bng 15 250 50 0 empty empty empty 17 7 0 10 -4034 -1
+-1;
+#X obj 47 516 #out window;
+#X obj 47 312 #remap_image;
+#X obj 47 496 #remap_image;
+#X obj 234 485 # + (0 9000);
+#X msg 317 439 1 \$1 # 1;
+#X obj 47 456 #convolve (1 1 # 1);
+#X obj 47 476 # / 1;
+#X obj 82 404 hsl 128 15 1 127 0 0 empty \$0.bluramount empty -2 -8
+0 10 -260097 -1 -1 0 1;
+#N canvas 3 94 450 300 blurtype 0;
+#X obj 51 49 inlet;
+#X obj 81 221 outlet;
+#X msg 78 165 set \, adddollar 1 \, add2 1 # 1;
+#X obj 82 113 sel 0;
+#X msg 147 138 set \, add2 1 \, adddollar 1 \, add2 # 1;
+#X obj 63 82 t b a;
+#X obj 47 256 s \$0.bluramount;
+#X connect 0 0 5 0;
+#X connect 2 0 1 0;
+#X connect 3 0 2 0;
+#X connect 3 1 4 0;
+#X connect 4 0 1 0;
+#X connect 5 0 6 0;
+#X connect 5 1 3 0;
+#X restore 317 419 pd blurtype;
+#X obj 79 422 i;
+#X obj 234 343 # - (0 9000);
+#X obj 47 186 #t;
+#X obj 294 203 #dim;
+#X obj 294 223 #redim (2);
+#X obj 308 243 # / 2;
+#X obj 294 263 # * (1 0);
+#X obj 294 283 # + (0 36000);
+#X obj 234 303 # * (0 0);
+#X obj 234 323 # / (1 1);
+#X obj 234 363 # p2c (0 0);
+#X obj 234 465 # c2p (0 0);
+#X obj 234 505 # * (0 0);
+#X obj 234 525 # / (1 1);
+#X obj 47 71 tgl 15 0 empty empty empty 17 7 0 10 -4034 -1 -1 0 1;
+#X obj 47 89 metro 100;
+#X text 78 385 amount:;
+#X text 24 556 GridFlow 0.9.5;
+#X text 197 62 1) OPEN AN IMAGE;
+#X msg 134 129 symbol teapot.png;
+#X msg 134 109 symbol babbage.jpg;
+#X obj 317 386 vradio 15 1 0 2 empty empty empty 0 -8 0 10 -4034 -1
+-1 0;
+#X text 335 400 angular blur;
+#X text 336 384 radial blur;
+#X obj 57 141 bng 15 250 50 0 empty empty empty 17 7 0 10 -4034 -1
+-1;
+#X text 24 26 Copyright 2009 by Federico Ferri;
+#X text 85 178 2) BANG #in (MANUALLY OR WITH METRO);
+#X text 58 367 3) PLAY WITH CONTROLS;
+#X connect 0 0 15 0;
+#X connect 1 0 0 0;
+#X connect 2 0 1 0;
+#X connect 3 0 2 0;
+#X connect 5 0 9 0;
+#X connect 5 1 21 0;
+#X connect 6 0 4 0;
+#X connect 6 1 24 0;
+#X connect 7 0 25 0;
+#X connect 8 0 9 1;
+#X connect 9 0 10 0;
+#X connect 10 0 6 0;
+#X connect 11 0 13 0;
+#X connect 12 0 8 0;
+#X connect 13 0 8 0;
+#X connect 13 0 10 1;
+#X connect 14 0 23 0;
+#X connect 15 0 5 0;
+#X connect 15 1 16 0;
+#X connect 16 0 17 0;
+#X connect 17 0 18 0;
+#X connect 17 0 22 1;
+#X connect 17 0 25 1;
+#X connect 18 0 19 0;
+#X connect 18 0 23 1;
+#X connect 18 0 24 1;
+#X connect 19 0 20 0;
+#X connect 20 0 21 1;
+#X connect 20 0 26 1;
+#X connect 21 0 22 0;
+#X connect 22 0 14 0;
+#X connect 23 0 5 1;
+#X connect 24 0 7 0;
+#X connect 25 0 26 0;
+#X connect 26 0 6 1;
+#X connect 27 0 28 0;
+#X connect 28 0 0 0;
+#X connect 32 0 1 0;
+#X connect 33 0 1 0;
+#X connect 34 0 12 0;
+#X connect 37 0 0 0;
diff --git a/externals/gridflow/examples/ripple.pd b/externals/gridflow/examples/ripple.pd
new file mode 100644
index 00000000..3756a874
--- /dev/null
+++ b/externals/gridflow/examples/ripple.pd
@@ -0,0 +1,184 @@
+#N canvas 276 26 683 618 10;
+#X obj 78 419 #out window;
+#X obj 78 105 +;
+#X obj 47 326 # +;
+#X obj 47 370 shunt 2;
+#X obj 283 189 # sin* 256;
+#N canvas 609 247 325 236 distance 0;
+#X text 16 15 bang;
+#X text 15 149 distances to middle;
+#X obj 18 36 inlet;
+#X obj 18 93 #fold +;
+#X text 89 95 pythagoras' theorem;
+#X obj 18 131 outlet;
+#X obj 18 55 #for (-128 -128) (128 128) (1 1);
+#X obj 18 112 # sqrt;
+#X obj 18 74 # sq-;
+#X connect 2 0 6 0;
+#X connect 3 0 7 0;
+#X connect 6 0 8 0;
+#X connect 7 0 5 0;
+#X connect 8 0 3 0;
+#X restore 164 41 pd distance map;
+#X obj 78 440 fps detailed;
+#X obj 283 130 loadbang;
+#X obj 47 42 t a a;
+#X obj 168 278 tgl 15 0 empty empty empty 0 -6 0 8 -241291 -1 -1 0
+1;
+#X msg 78 86 1;
+#X obj 47 105 # -;
+#X obj 47 62 #store;
+#N canvas 604 543 420 225 apply 0;
+#X obj 60 48 #fold +;
+#X obj 12 190 outlet 0;
+#X obj 60 16 inlet;
+#X obj 12 124 # +;
+#X obj 12 167 # max 0;
+#X obj 12 146 # min 255;
+#X obj 12 16 inlet;
+#X obj 58 101 #outer *>>8;
+#X obj 130 69 inlet;
+#X obj 60 73 # << 2;
+#X connect 0 0 9 0;
+#X connect 2 0 0 0;
+#X connect 3 0 5 0;
+#X connect 4 0 1 0;
+#X connect 5 0 4 0;
+#X connect 6 0 3 0;
+#X connect 7 0 3 1;
+#X connect 8 0 7 1;
+#X connect 9 0 7 0;
+#X restore 78 400 pd apply shading;
+#X obj 47 -27 tgl 15 0 empty empty empty 0 -6 0 8 -24198 -1 -1 1 1
+;
+#X obj 47 348 #store;
+#X obj 47 25 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 164 130 # + 10;
+#X text 187 278 shading on/off;
+#X obj 47 240 shunt 2;
+#X floatatom 106 108 5 0 0 0 - - -;
+#X obj 47 195 # *>>8;
+#X obj 164 310 loadbang;
+#X obj 164 21 loadbang;
+#X obj 78 462 print;
+#X obj 164 149 # inv* 10000;
+#N canvas 392 110 431 233 angle 0;
+#X obj 21 133 #outer atan;
+#X text 81 154 angles to centre;
+#X text 22 13 bang;
+#X obj 21 32 inlet;
+#X obj 21 56 #for -128 128 1;
+#X obj 21 153 outlet 0;
+#X obj 21 90 #t;
+#X connect 0 0 5 0;
+#X connect 3 0 4 0;
+#X connect 4 0 6 0;
+#X connect 6 0 0 0;
+#X connect 6 1 0 1;
+#X restore 283 151 pd angle map;
+#X obj 47 151 # *>>8;
+#X obj 46 218 # *>>8;
+#X obj 259 235 hsl 128 15 -256 256 0 1 empty empty empty -2 -6 0 8
+-260818 -1 -1 12600 1;
+#X obj 259 252 hsl 128 15 -256 256 0 1 empty empty empty -2 -6 0 8
+-260818 -1 -1 3200 1;
+#N canvas 637 537 387 220 compute 1;
+#X obj 8 113 #store;
+#X obj 55 113 # sin* 64;
+#X obj 55 71 #for 0 1024 1;
+#X obj 55 50 loadbang;
+#X obj 55 92 # * 900;
+#X obj 125 51 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 8 135 outlet;
+#X text 75 151 This is somewhat like [# sin];
+#X text 75 166 but much faster (lookup table);
+#X obj 8 11 inlet;
+#X obj 8 30 #outer ignore (0);
+#X connect 0 0 6 0;
+#X connect 1 0 0 1;
+#X connect 2 0 4 0;
+#X connect 3 0 2 0;
+#X connect 4 0 1 0;
+#X connect 5 0 2 0;
+#X connect 9 0 10 0;
+#X connect 10 0 0 0;
+#X restore 47 128 pd compute sine;
+#X text 232 358 background image;
+#X obj 165 375 #in teapot.png;
+#X obj 165 356 loadbang;
+#X text 215 219 intensity of wave;
+#X obj 47 4 metro 33.3667;
+#X text 246 5 waves.pd is more interesting;
+#X text 225 -9 this is a quite boring wave generator;
+#X text 95 61 table for distance map;
+#X floatatom 216 237 5 0 0 0 - - -;
+#X floatatom 216 253 5 0 0 0 - - -;
+#X obj 157 239 #pack 2;
+#X obj -13 -85 cnv 15 680 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X text 0 -72 Copyright 2002 Mathieu Bouchard;
+#X text 0 -85 ripple.pd;
+#X obj -15 501 cnv 15 680 30 empty empty empty 20 12 0 14 -200249 -66577
+0;
+#X text -7 508 GridFlow 0.8.0;
+#X text -7 508 GridFlow 0.8.0;
+#X obj 326 429 #color;
+#X text 411 410 color of ripple shading;
+#X obj 164 329 #for (0 0) (256 256) (1 1);
+#X obj 283 170 #outer + (0 9000);
+#X obj 47 173 #outer ignore (0 0);
+#X obj 40 274 #t;
+#X obj 326 391 loadbang;
+#X msg 326 410 255 255 100;
+#X connect 0 0 6 0;
+#X connect 1 0 20 0;
+#X connect 1 0 11 1;
+#X connect 2 0 15 0;
+#X connect 3 0 13 0;
+#X connect 3 1 0 0;
+#X connect 4 0 21 1;
+#X connect 5 0 17 0;
+#X connect 5 0 12 1;
+#X connect 6 0 24 0;
+#X connect 7 0 26 0;
+#X connect 8 0 12 0;
+#X connect 8 1 10 0;
+#X connect 9 0 19 1;
+#X connect 9 0 3 1;
+#X connect 10 0 1 0;
+#X connect 11 0 31 0;
+#X connect 12 0 11 0;
+#X connect 13 0 0 0;
+#X connect 14 0 36 0;
+#X connect 15 0 3 0;
+#X connect 16 0 8 0;
+#X connect 17 0 25 0;
+#X connect 19 0 54 0;
+#X connect 19 1 2 0;
+#X connect 20 0 1 1;
+#X connect 21 0 28 0;
+#X connect 22 0 51 0;
+#X connect 23 0 5 0;
+#X connect 25 0 27 1;
+#X connect 26 0 52 0;
+#X connect 27 0 53 0;
+#X connect 28 0 19 0;
+#X connect 29 0 40 0;
+#X connect 30 0 41 0;
+#X connect 31 0 27 0;
+#X connect 33 0 15 1;
+#X connect 34 0 33 0;
+#X connect 36 0 16 0;
+#X connect 40 0 42 0;
+#X connect 41 0 42 1;
+#X connect 42 0 28 1;
+#X connect 49 0 13 2;
+#X connect 51 0 2 1;
+#X connect 52 0 4 0;
+#X connect 53 0 21 0;
+#X connect 54 0 2 0;
+#X connect 54 1 13 1;
+#X connect 55 0 56 0;
+#X connect 56 0 49 0;
diff --git a/externals/gridflow/examples/sand.pd b/externals/gridflow/examples/sand.pd
new file mode 100644
index 00000000..9e7f2d3d
--- /dev/null
+++ b/externals/gridflow/examples/sand.pd
@@ -0,0 +1,392 @@
+#N canvas 344 26 680 557 10;
+#X text 287 159 disable falling;
+#X obj 2 96 t a a;
+#X obj 323 314 # != 0;
+#X obj 384 352 #fold +;
+#X obj 8 442 s position;
+#X obj 192 29 tgl 15 0 empty empty empty 0 -6 0 8 -24198 -1 -1 0 1
+;
+#X obj 323 371 #export;
+#X obj 192 82 #store;
+#X obj 217 113 shunt 2;
+#N canvas 25 226 369 359 mouse 0;
+#X text 143 214 is there a click?;
+#X obj 44 114 != 0;
+#X text 112 256 coordinates;
+#X obj 19 8 inlet;
+#X text 56 9 #out's outlet 0;
+#X obj 44 93 >> 8;
+#X obj 65 237 listsublist 0 2;
+#X obj 16 31 route position;
+#X obj 94 214 outlet;
+#X obj 65 257 outlet;
+#X obj 16 214 shunt 2;
+#X obj 44 72 listelement 2;
+#X obj 16 51 t a a;
+#X connect 1 0 8 0;
+#X connect 1 0 10 1;
+#X connect 3 0 7 0;
+#X connect 5 0 1 0;
+#X connect 6 0 9 0;
+#X connect 7 0 12 0;
+#X connect 10 1 6 0;
+#X connect 11 0 5 0;
+#X connect 12 0 10 0;
+#X connect 12 1 11 0;
+#X restore 366 132 pd mouse click/drag;
+#X obj 327 132 # / 2;
+#X obj 323 333 #ravel;
+#X obj 217 158 shunt 2;
+#X obj 34 96 s size;
+#X obj 323 352 #fold +;
+#X obj 420 95 tgl 15 0 empty empty empty 0 -6 0 8 -241291 -1 -1 0 1
+;
+#X obj 452 358 #export;
+#X obj 452 320 #ravel;
+#X obj 306 220 shunt 2;
+#X obj 271 159 tgl 15 0 empty empty empty 0 -6 0 8 -241291 -1 -1 0
+1;
+#X obj 384 371 #export;
+#X obj 367 94 shunt 2;
+#X obj 2 230 #greyscale_to_rgb;
+#X obj 367 113 r position;
+#N canvas 364 105 496 344 falling 0;
+#X obj 42 147 # +;
+#X text 227 189 vertical falling;
+#X obj 42 40 inlet;
+#X text 83 40 Dim[rows \, columns \, {height}];
+#X obj 42 168 # +;
+#X obj 42 209 # +;
+#X text 95 250 Dim[rows \, columns \, {height}];
+#X text 216 129 horizontal falling;
+#X obj 42 230 # +;
+#X obj 42 103 #store;
+#X obj 42 249 outlet;
+#X obj 42 84 #finished;
+#X obj 110 209 #convolve (2 1 # 1 1) \, fold inv+;
+#X obj 110 230 #convolve (3 1 # 1 1 0) \, fold inv+;
+#X obj 69 209 # / 4;
+#X obj 69 230 # / 4;
+#X obj 69 147 # / 4;
+#X obj 69 168 # / 4;
+#X obj 108 147 #convolve (1 2 # 1 1) \, fold inv+;
+#X obj 109 168 #convolve (1 3 # 1 1 0) \, fold inv+;
+#X obj 159 78 # rand;
+#X obj 123 116 # +;
+#X obj 42 59 t a a a;
+#X obj 159 59 # put 128;
+#X obj 159 97 # - 32;
+#X obj 159 116 # div 50;
+#X connect 0 0 4 0;
+#X connect 2 0 22 0;
+#X connect 4 0 5 0;
+#X connect 5 0 8 0;
+#X connect 8 0 10 0;
+#X connect 9 0 0 0;
+#X connect 11 0 9 0;
+#X connect 12 0 14 0;
+#X connect 13 0 15 0;
+#X connect 14 0 5 1;
+#X connect 15 0 8 1;
+#X connect 16 0 0 1;
+#X connect 17 0 4 1;
+#X connect 18 0 16 0;
+#X connect 19 0 17 0;
+#X connect 20 0 24 0;
+#X connect 21 0 18 0;
+#X connect 21 0 19 0;
+#X connect 21 0 12 0;
+#X connect 21 0 13 0;
+#X connect 22 0 11 0;
+#X connect 22 1 9 1;
+#X connect 22 1 21 0;
+#X connect 22 2 23 0;
+#X connect 23 0 20 0;
+#X connect 24 0 25 0;
+#X connect 25 0 21 1;
+#X restore 217 178 pd falling sand;
+#X obj 2 170 shunt 3;
+#X obj 2 480 print;
+#X obj 197 65 bng 15 250 50 0 empty empty empty 0 -6 0 8 -24198 -1
+-1;
+#X text 210 27 auto;
+#N canvas 301 45 536 447 finger 0;
+#X obj 192 7 inlet;
+#X obj 36 78 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 112 244 # / 20;
+#X obj 112 297 # *;
+#X obj 13 244 #store;
+#X obj 14 18 inlet;
+#X obj 279 51 loadbang;
+#X obj 13 38 t a a;
+#X obj 112 225 #fold +;
+#X text 22 159 "dig" the sphere into the sand;
+#X text 240 104 compute a halfsphere;
+#X obj 192 29 # - 32;
+#X obj 112 206 #ravel;
+#N canvas 1 58 415 284 make 0;
+#X obj 28 129 #fold +;
+#X obj 28 66 # -;
+#X obj 28 108 @! sq;
+#X obj 28 45 #for ( -32 -32 ) ( 32 32 ) ( 1 1 );
+#X obj 28 171 outlet;
+#X obj 28 87 # << 2;
+#X obj 28 150 @! sqrt;
+#X text 63 21 bang;
+#X obj 27 20 inlet;
+#X text 98 92 make distance map;
+#X connect 0 0 6 0;
+#X connect 1 0 5 0;
+#X connect 2 0 0 0;
+#X connect 3 0 1 0;
+#X connect 5 0 2 0;
+#X connect 6 0 4 0;
+#X connect 8 0 3 0;
+#X restore 259 74 pd make distance map with center 32;
+#X obj 13 420 outlet;
+#X obj 260 53 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X text 122 262 find out how high the compensation torus should be
+;
+#X obj 112 316 # div 256;
+#X obj 36 58 route grid;
+#X obj 13 225 #finished;
+#X obj 13 206 t a a;
+#N canvas 669 471 315 202 halfsphere 0;
+#X obj 45 19 inlet distancemap;
+#X obj 45 143 outlet image;
+#X obj 46 102 @! sqrt;
+#X obj 46 122 #outer ignore ( 0 );
+#X obj 46 62 # inv+ 200;
+#X text 121 63 16 * radius^2;
+#X obj 46 41 @! sq;
+#X obj 46 82 # max 0;
+#X connect 0 0 6 0;
+#X connect 2 0 3 0;
+#X connect 3 0 1 0;
+#X connect 4 0 7 0;
+#X connect 6 0 4 0;
+#X connect 7 0 2 0;
+#X restore 126 120 pd halfsphere;
+#N canvas 0 0 323 279 torus 0;
+#X obj 59 26 inlet;
+#X obj 56 185 outlet;
+#X obj 57 97 # inv+ 200;
+#X obj 57 76 @! sq;
+#X text 102 54 toroidal radius;
+#X obj 57 162 #outer ignore ( 0 );
+#X obj 56 120 # max 0;
+#X text 138 99 16*radius^2;
+#X obj 57 141 @! sqrt;
+#X obj 57 56 # - 20;
+#X connect 0 0 9 0;
+#X connect 2 0 6 0;
+#X connect 3 0 2 0;
+#X connect 5 0 1 0;
+#X connect 6 0 8 0;
+#X connect 8 0 5 0;
+#X connect 9 0 3 0;
+#X restore 259 326 pd torus;
+#X text 66 415 put extra sand as a ring around the hole;
+#X obj 112 278 #redim (64 64 1);
+#X obj 13 397 #draw_image - (1 1 1 #) (0 0);
+#X obj 13 141 #draw_image - (1 1 1 #) (0 0);
+#X obj 13 343 shunt 2;
+#X obj 64 343 tgl 15 0 empty empty empty 0 -6 0 8 -241291 -1 -1 0 1
+;
+#X connect 0 0 11 0;
+#X connect 1 0 15 0;
+#X connect 2 0 24 0;
+#X connect 3 0 17 0;
+#X connect 4 0 27 0;
+#X connect 5 0 7 0;
+#X connect 6 0 13 0;
+#X connect 7 0 26 0;
+#X connect 7 1 18 0;
+#X connect 8 0 2 0;
+#X connect 11 0 25 2;
+#X connect 11 0 26 2;
+#X connect 12 0 8 0;
+#X connect 13 0 21 0;
+#X connect 13 0 22 0;
+#X connect 15 0 13 0;
+#X connect 17 0 25 1;
+#X connect 18 0 1 0;
+#X connect 19 0 4 0;
+#X connect 20 0 19 0;
+#X connect 20 1 12 0;
+#X connect 20 1 4 1;
+#X connect 21 0 26 1;
+#X connect 22 0 3 1;
+#X connect 24 0 3 0;
+#X connect 25 0 14 0;
+#X connect 26 0 20 0;
+#X connect 27 0 25 0;
+#X connect 27 1 14 0;
+#X connect 28 0 27 1;
+#X restore 260 132 pd finger;
+#X obj 360 286 # -;
+#X obj 384 333 #ravel;
+#X msg 2 56 240 320;
+#X obj 452 339 #fold +;
+#X obj 2 211 # + 128;
+#X text 375 220 enable stats;
+#X text 289 411 checking for conservation of amounts of sand;
+#X msg 2 115 \$1 \$2 1 # 0;
+#N canvas 499 117 441 278 lighting 0;
+#X obj 28 234 outlet;
+#X obj 27 18 inlet;
+#X text 184 103 colourize the horizontal differences;
+#X text 184 149 colourize the vertical differences;
+#X obj 60 149 #outer & (0 -1 0);
+#X obj 60 129 #convolve (4 1 # 1 -8 8 -1);
+#X obj 60 84 #convolve (1 4 # 1 -8 8 -1);
+#X obj 28 177 # << 2;
+#X obj 28 215 #clip;
+#X obj 28 196 # + (220 200 180);
+#X obj 27 37 #t;
+#X obj 28 56 #greyscale_to_rgb;
+#X obj 28 104 # +;
+#X obj 28 149 # +;
+#X obj 60 104 #outer & (-1 0 0);
+#X connect 1 0 10 0;
+#X connect 4 0 13 1;
+#X connect 5 0 4 0;
+#X connect 6 0 14 0;
+#X connect 7 0 9 0;
+#X connect 8 0 0 0;
+#X connect 9 0 8 0;
+#X connect 10 0 11 0;
+#X connect 10 1 6 0;
+#X connect 10 1 5 0;
+#X connect 11 0 12 0;
+#X connect 12 0 13 0;
+#X connect 13 0 7 0;
+#X connect 14 0 12 1;
+#X restore 24 298 pd lighting;
+#X obj 2 461 fps detailed;
+#X obj 359 221 tgl 15 0 empty empty empty 0 -6 0 8 -241291 -1 -1 0
+1;
+#X text 213 65 step;
+#X obj 67 183 vradio 15 1 0 3 empty empty empty 0 -6 0 8 -241291 -1
+-1 1;
+#X obj 2 422 #out window;
+#X obj 323 392 nbx 5 14 -1e+37 1e+37 0 0 empty empty empty 0 -6 0 10
+-262144 -1 -1 0 256;
+#X obj 384 392 nbx 5 14 -1e+37 1e+37 0 0 empty empty empty 0 -6 0 10
+-262144 -1 -1 0 256;
+#X obj 452 377 nbx 8 14 -1e+37 1e+37 0 0 empty empty empty 0 -6 0 10
+-262144 -1 -1 0 256;
+#X text 87 196 differential;
+#X text 86 181 heightmap;
+#X text 86 212 topographic;
+#X obj 152 82 t a a;
+#X obj 217 220 t a a;
+#X obj 2 37 loadbang;
+#X text 436 95 disable finger;
+#X obj 350 264 t a a;
+#X obj 2 192 # << 2;
+#X obj -15 499 cnv 15 680 30 empty empty empty 20 12 0 14 -200249 -66577
+0;
+#X text -7 506 GridFlow 0.8.0;
+#X text -7 506 GridFlow 0.8.0;
+#X obj -13 -25 cnv 15 680 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X text 0 -25 sand.pd;
+#X text -1 21 set size & reset;
+#X obj 2 249 #clip;
+#X obj 24 279 # << 0;
+#X obj 68 144 loadbang;
+#X msg 68 163 1;
+#X obj 270 115 tgl 15 0 empty empty empty 0 -6 0 8 -241291 -1 -1 0
+1;
+#X msg 8 76 120 160;
+#X obj 192 46 metro 33.3667;
+#X obj 2 400 #scale_by 2;
+#N canvas 0 0 450 300 topographic 0;
+#X obj 35 18 inlet;
+#X obj 35 170 #greyscale_to_rgb;
+#X obj 35 37 #convolve (3 3 # 1 2 1 2 4 2);
+#X obj 35 151 #clip;
+#X obj 35 56 # & 127;
+#X obj 35 189 outlet;
+#X obj 35 75 # abs- 108;
+#X obj 35 94 # min 20;
+#X obj 35 113 # inv+ 20;
+#X obj 35 132 # << 5;
+#X connect 0 0 2 0;
+#X connect 1 0 5 0;
+#X connect 2 0 4 0;
+#X connect 3 0 1 0;
+#X connect 4 0 6 0;
+#X connect 6 0 7 0;
+#X connect 7 0 8 0;
+#X connect 8 0 9 0;
+#X connect 9 0 3 0;
+#X restore 46 317 pd topographic;
+#X text 0 -12 Copyright 2002 \, 2006 Mathieu Bouchard;
+#X obj 384 314 # abs-;
+#X connect 1 0 37 0;
+#X connect 1 1 13 0;
+#X connect 2 0 11 0;
+#X connect 3 0 20 0;
+#X connect 5 0 68 0;
+#X connect 6 0 44 0;
+#X connect 7 0 8 0;
+#X connect 8 0 12 0;
+#X connect 8 1 29 0;
+#X connect 9 0 10 0;
+#X connect 9 1 21 0;
+#X connect 10 0 29 1;
+#X connect 11 0 14 0;
+#X connect 12 0 24 0;
+#X connect 12 1 51 0;
+#X connect 14 0 6 0;
+#X connect 15 0 21 1;
+#X connect 16 0 46 0;
+#X connect 17 0 33 0;
+#X connect 18 1 17 0;
+#X connect 18 1 54 0;
+#X connect 19 0 12 1;
+#X connect 20 0 45 0;
+#X connect 21 0 8 1;
+#X connect 22 0 62 0;
+#X connect 23 0 9 0;
+#X connect 24 0 51 0;
+#X connect 25 0 55 0;
+#X connect 25 1 63 0;
+#X connect 25 2 70 0;
+#X connect 27 0 7 0;
+#X connect 29 0 12 0;
+#X connect 30 0 2 0;
+#X connect 30 0 72 0;
+#X connect 31 0 3 0;
+#X connect 32 0 1 0;
+#X connect 33 0 16 0;
+#X connect 34 0 22 0;
+#X connect 37 0 50 0;
+#X connect 38 0 69 0;
+#X connect 39 0 26 0;
+#X connect 40 0 18 1;
+#X connect 42 0 25 1;
+#X connect 43 0 39 0;
+#X connect 43 0 4 0;
+#X connect 50 0 25 0;
+#X connect 50 1 7 1;
+#X connect 51 0 50 0;
+#X connect 51 1 18 0;
+#X connect 52 0 32 0;
+#X connect 54 0 30 1;
+#X connect 54 1 30 0;
+#X connect 55 0 34 0;
+#X connect 62 0 69 0;
+#X connect 63 0 38 0;
+#X connect 64 0 65 0;
+#X connect 65 0 42 0;
+#X connect 66 0 8 1;
+#X connect 67 0 1 0;
+#X connect 68 0 7 0;
+#X connect 69 0 43 0;
+#X connect 70 0 69 0;
+#X connect 72 0 31 0;
diff --git a/externals/gridflow/examples/scratch_video.pd b/externals/gridflow/examples/scratch_video.pd
new file mode 100644
index 00000000..b97c0712
--- /dev/null
+++ b/externals/gridflow/examples/scratch_video.pd
@@ -0,0 +1,43 @@
+#N canvas 694 45 580 451 10;
+#X obj 119 273 listelement 1;
+#X floatatom 119 292 5 0 0 0 - - -;
+#X floatatom 246 217 5 0 0 0 - - -;
+#X obj 119 254 route position;
+#X obj 119 177 #in;
+#X obj -13 0 cnv 15 580 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X obj -16 417 cnv 15 580 30 empty empty empty 20 12 0 14 -200249 -66577
+0;
+#X text 0 13 Copyright 2003 Alexandre Castonguay;
+#X text -4 38 Use the mouse position to scratch the video \, a touchscreen
+works well.;
+#X obj 119 235 #out window;
+#X text 290 215 <-- frame number;
+#X text 223 272 <-- get x values;
+#X obj 92 130 bng 15 250 50 0 empty empty empty 0 -6 0 8 -24198 -1
+-1;
+#X text 0 0 scratch_video.pd;
+#X text 16 424 GridFlow 0.9.0;
+#X obj 119 334 s frame_number;
+#X obj 119 86 r frame_number;
+#X floatatom 78 338 5 0 0 0 - - -;
+#X msg 197 141 open violoncelle.mov;
+#X msg 237 82 get;
+#X obj 169 194 route frames;
+#X floatatom 169 216 5 0 0 0 - - -;
+#X text 336 140 320 x 240 \, 128 frames;
+#X obj 119 311 / 2.8;
+#X connect 0 0 1 0;
+#X connect 1 0 23 0;
+#X connect 3 0 0 0;
+#X connect 4 0 9 0;
+#X connect 4 1 2 0;
+#X connect 4 1 20 0;
+#X connect 9 0 3 0;
+#X connect 12 0 4 0;
+#X connect 16 0 4 0;
+#X connect 18 0 4 0;
+#X connect 19 0 4 0;
+#X connect 20 0 21 0;
+#X connect 23 0 15 0;
+#X connect 23 0 17 0;
diff --git a/externals/gridflow/examples/slitscanning.pd b/externals/gridflow/examples/slitscanning.pd
new file mode 100644
index 00000000..fe2927f0
--- /dev/null
+++ b/externals/gridflow/examples/slitscanning.pd
@@ -0,0 +1,54 @@
+#N canvas 398 50 401 530 10;
+#X obj 18 460 #out window;
+#X obj 18 205 #store;
+#X obj 18 178 #store;
+#X obj 93 122 loadbang;
+#X obj 18 106 t b b;
+#X obj 34 353 @join 0;
+#X obj 18 55 tgl 15 0 empty empty empty 17 7 0 10 -24198 -1 -1 0 1
+;
+#X obj 18 432 #store;
+#X obj 34 284 #t;
+#X obj 18 228 #t;
+#X obj 78 301 b;
+#X obj 18 256 b;
+#X obj 18 411 #store;
+#X obj 106 349 loadbang;
+#X obj 18 83 metro 33.3333;
+#X obj 0 498 cnv 15 400 30 empty empty empty 20 12 0 14 -200249 -66577
+0;
+#X text 8 505 GridFlow 0.9.0;
+#X obj 1 0 cnv 15 400 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X text 14 0 slitscanning.pd;
+#X text 14 13 Copyright 2007 Roman Haefeli;
+#X text 38 55 <- start / stop;
+#X text 155 182 <- set dimensions to 240 320;
+#X obj 96 181 cnv 15 50 17 empty empty empty 20 12 0 14 -241291 -66577
+0;
+#X obj 96 182 #camera;
+#X obj 55 153 #for (119 0) (120 320) (1 1);
+#X obj 77 323 #store (600 320 3 #);
+#X obj 97 376 #for (0 0) (600 320) (1 1);
+#X connect 1 0 9 0;
+#X connect 2 0 1 0;
+#X connect 3 0 24 0;
+#X connect 4 0 2 0;
+#X connect 4 1 23 0;
+#X connect 5 0 7 1;
+#X connect 6 0 14 0;
+#X connect 7 0 0 0;
+#X connect 7 0 25 1;
+#X connect 8 0 5 0;
+#X connect 8 1 10 0;
+#X connect 9 0 11 0;
+#X connect 9 1 8 0;
+#X connect 10 0 25 0;
+#X connect 11 0 12 0;
+#X connect 12 0 7 0;
+#X connect 13 0 26 0;
+#X connect 14 0 4 0;
+#X connect 23 0 1 1;
+#X connect 24 0 2 1;
+#X connect 25 0 5 1;
+#X connect 26 0 12 1;
diff --git a/externals/gridflow/examples/spectrogram.pd b/externals/gridflow/examples/spectrogram.pd
new file mode 100644
index 00000000..fb6730d2
--- /dev/null
+++ b/externals/gridflow/examples/spectrogram.pd
@@ -0,0 +1,108 @@
+#N canvas 370 65 588 508 10;
+#X msg 147 208 reset;
+#X obj 21 50 tgl 15 0 empty empty empty 0 -6 0 8 -24198 -1 -1 0 1;
+#X obj 297 54 adc~;
+#X obj 38 170 tabread4 array1;
+#X obj 21 69 bng 15 250 50 0 empty empty empty 0 -6 0 8 -24198 -1 -1
+;
+#X obj 332 55 table array1 1024;
+#X obj 208 212 loadbang;
+#X obj 191 214 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#N canvas 0 0 306 167 analysis 0;
+#X obj 24 -205 inlet~;
+#X obj 26 -135 tabsend~ array1;
+#X obj 24 -184 rfft~;
+#X obj 25 -157 expr~ sqrt($v1*$v1+$v2*$v2)/64;
+#X obj 148 -198 block~ 1024;
+#X connect 0 0 2 0;
+#X connect 2 0 3 0;
+#X connect 2 1 3 1;
+#X connect 3 0 1 0;
+#X restore 298 77 pd analysis;
+#X obj 284 256 vradio 15 1 0 2 empty empty empty 0 -6 0 8 -241291 -1
+-1 0;
+#X obj 190 291 loadbang;
+#X obj 173 293 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 38 68 for 0 320 1;
+#X obj 38 189 * 2000;
+#X text 303 257 black stripes;
+#X text 302 270 graph;
+#X obj 38 117 / 2;
+#X text 83 189 <-- adding some extra gain;
+#X obj 81 138 exp;
+#X obj 194 136 vradio 15 1 0 2 empty empty empty 0 -6 0 8 -241291 -1
+-1 0;
+#X text 216 136 linear;
+#X text 214 150 logarithmic;
+#X obj 82 117 / 51;
+#X obj 38 395 #fade;
+#X obj 130 396 loadbang;
+#X msg 79 395 16 4 1;
+#X obj 38 49 metro 23.22;
+#X text 115 117 = 1000*1024/44100;
+#X obj 38 208 #import ( 320 );
+#X obj 38 227 # *>>8;
+#X obj 38 246 #fade 2;
+#X obj 38 309 # inv+ 255;
+#X obj 113 292 #outer <;
+#X obj 113 311 # * 255;
+#X obj 113 330 #transpose;
+#X obj 38 357 #redim (120 320 1);
+#X obj 38 376 #greyscale_to_rgb;
+#X obj 38 414 #clip;
+#X obj 38 433 #scale_by 2;
+#X obj 38 452 #out window;
+#X obj 6 476 cnv 15 580 30 empty empty empty 20 12 0 14 -200249 -66577
+0;
+#X text 14 483 GridFlow 0.8.0;
+#X text 14 483 GridFlow 0.8.0;
+#X obj 6 5 cnv 15 580 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X text 19 5 spectrogram.pd;
+#X obj 173 310 #for 120 0 -1;
+#X obj 191 231 #for 0 320 1;
+#X obj 191 250 # + 10;
+#X text 19 18 Copyright 2004 Mathieu Bouchard;
+#X obj 38 91 shunt 2;
+#X obj 38 265 shunt 2;
+#X connect 0 0 28 0;
+#X connect 1 0 26 0;
+#X connect 2 0 8 0;
+#X connect 2 1 8 0;
+#X connect 3 0 13 0;
+#X connect 4 0 12 0;
+#X connect 6 0 7 0;
+#X connect 7 0 46 0;
+#X connect 9 0 50 1;
+#X connect 10 0 11 0;
+#X connect 11 0 45 0;
+#X connect 12 0 49 0;
+#X connect 13 0 28 0;
+#X connect 16 0 3 0;
+#X connect 18 0 3 0;
+#X connect 19 0 49 1;
+#X connect 22 0 18 0;
+#X connect 23 0 37 0;
+#X connect 24 0 25 0;
+#X connect 25 0 23 1;
+#X connect 26 0 12 0;
+#X connect 28 0 29 0;
+#X connect 29 0 30 0;
+#X connect 30 0 50 0;
+#X connect 31 0 35 0;
+#X connect 32 0 33 0;
+#X connect 33 0 34 0;
+#X connect 34 0 35 0;
+#X connect 35 0 36 0;
+#X connect 36 0 23 0;
+#X connect 37 0 38 0;
+#X connect 38 0 39 0;
+#X connect 45 0 32 1;
+#X connect 46 0 47 0;
+#X connect 47 0 29 1;
+#X connect 49 0 16 0;
+#X connect 49 1 22 0;
+#X connect 50 0 31 0;
+#X connect 50 1 32 0;
diff --git a/externals/gridflow/examples/surface_tension.pd b/externals/gridflow/examples/surface_tension.pd
new file mode 100644
index 00000000..97611abb
--- /dev/null
+++ b/externals/gridflow/examples/surface_tension.pd
@@ -0,0 +1,138 @@
+#N canvas 481 120 730 701 10;
+#X obj 91 -43 tgl 15 0 empty empty empty 0 -6 0 8 -24198 -1 -1 0 1
+;
+#X obj 91 8 #camera;
+#X obj 38 113 t a a;
+#X msg 96 114 240 320 3 #;
+#X obj 95 92 loadbang;
+#N canvas 286 95 450 300 analysis 0;
+#X obj 46 17 inlet;
+#X obj 49 236 outlet;
+#X obj 64 67 spigot;
+#X obj 46 44 t a a;
+#X obj 114 68 tgl 15 0 empty empty empty 0 -6 0 8 -241291 -1 -1 0 1
+;
+#X obj 114 15 inlet;
+#X obj 49 86 # -;
+#X obj 49 129 # - 30;
+#X obj 49 154 # max 0;
+#X obj 49 182 # * 20;
+#X obj 49 211 # min 256;
+#X obj 49 108 @! abs;
+#X connect 0 0 3 0;
+#X connect 2 0 6 1;
+#X connect 3 0 2 0;
+#X connect 3 1 6 0;
+#X connect 4 0 2 1;
+#X connect 5 0 4 0;
+#X connect 6 0 11 0;
+#X connect 7 0 8 0;
+#X connect 8 0 9 0;
+#X connect 9 0 10 0;
+#X connect 10 0 1 0;
+#X connect 11 0 7 0;
+#X restore 192 94 pd analysis;
+#X obj 275 94 tgl 15 0 empty empty empty 0 -6 0 8 -241291 -1 -1 0 1
+;
+#X obj 123 433 r cam;
+#X obj 113 67 s cam;
+#X obj 91 33 t a a b;
+#X obj 340 65 loadbang;
+#X msg 307 66 1;
+#X obj 417 85 loadbang;
+#X msg 306 88 0;
+#X obj 150 484 loadbang;
+#X msg 150 504 set_geometry 0 0 480 640 \, hidecursor;
+#X obj 338 89 delay 5000;
+#X obj 91 -17 metro 33.3667;
+#X obj -15 -84 cnv 15 640 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X obj -17 582 cnv 15 640 30 empty empty empty 20 12 0 14 -200249 -66577
+0;
+#X text -6 592 GridFlow 0.8.0;
+#X text 157 9 <-- open this and set your camera up;
+#X obj 38 92 #store;
+#X obj 71 143 # put 63;
+#X obj 71 164 # rand;
+#X obj 38 184 # +;
+#X obj 161 144 # *>>8;
+#X obj 192 121 # inv+ 256;
+#X obj 38 211 #convolve (1 5 # 1);
+#X obj 39 233 #convolve (5 1 # 1);
+#X obj 39 306 # max -128;
+#X obj 39 325 # min 127;
+#X obj 39 344 # + 128;
+#X obj 39 365 #inner (3 3 # 3 0 1 1 3 0 0 1 3);
+#X obj 39 387 # >> 2;
+#X obj 113 383 # inv+ 255;
+#X obj 39 407 # *>>8;
+#X obj 39 431 # +;
+#X obj 70 431 # *>>8;
+#X obj 39 457 #clip;
+#X obj 337 209 #rgb_to_greyscale;
+#X obj 337 235 # +;
+#X obj 337 256 #convolve (1 3 # 1);
+#X obj 337 278 #convolve (3 1 # 1);
+#X obj 337 324 # min 255;
+#X obj 337 345 #greyscale_to_rgb;
+#X obj 116 547 #out window;
+#X text 1 -85 surface_tension.pd;
+#X obj 39 478 #scale_by 2;
+#X obj 71 185 # - 31;
+#X obj 337 301 # *>>8 27;
+#X obj 39 287 # *>>8 25;
+#X text 1 -71 Copyright 2004 Mathieu Bouchard;
+#X obj 39 261 # + 5;
+#X connect 0 0 17 0;
+#X connect 1 0 9 0;
+#X connect 2 0 25 0;
+#X connect 2 1 23 0;
+#X connect 3 0 22 1;
+#X connect 4 0 3 0;
+#X connect 5 0 27 0;
+#X connect 5 0 40 0;
+#X connect 6 0 5 1;
+#X connect 7 0 38 0;
+#X connect 9 0 5 0;
+#X connect 9 1 8 0;
+#X connect 9 2 22 0;
+#X connect 10 0 11 0;
+#X connect 11 0 6 0;
+#X connect 12 0 16 0;
+#X connect 13 0 6 0;
+#X connect 14 0 15 0;
+#X connect 15 0 46 0;
+#X connect 16 0 13 0;
+#X connect 17 0 1 0;
+#X connect 22 0 2 0;
+#X connect 23 0 24 0;
+#X connect 24 0 49 0;
+#X connect 25 0 28 0;
+#X connect 26 0 22 1;
+#X connect 27 0 26 1;
+#X connect 28 0 29 0;
+#X connect 29 0 53 0;
+#X connect 30 0 31 0;
+#X connect 31 0 26 0;
+#X connect 31 0 32 0;
+#X connect 32 0 33 0;
+#X connect 33 0 34 0;
+#X connect 34 0 36 0;
+#X connect 35 0 36 1;
+#X connect 36 0 37 0;
+#X connect 37 0 39 0;
+#X connect 38 0 37 1;
+#X connect 39 0 48 0;
+#X connect 40 0 41 0;
+#X connect 41 0 42 0;
+#X connect 42 0 43 0;
+#X connect 43 0 50 0;
+#X connect 44 0 41 1;
+#X connect 44 0 45 0;
+#X connect 45 0 35 0;
+#X connect 45 0 38 1;
+#X connect 48 0 46 0;
+#X connect 49 0 25 1;
+#X connect 50 0 44 0;
+#X connect 51 0 30 0;
+#X connect 53 0 51 0;
diff --git a/externals/gridflow/examples/threshold.pd b/externals/gridflow/examples/threshold.pd
new file mode 100644
index 00000000..0b90b07f
--- /dev/null
+++ b/externals/gridflow/examples/threshold.pd
@@ -0,0 +1,78 @@
+#N canvas 660 79 581 531 10;
+#X obj 72 208 inv+ 0;
+#X obj 40 8 tgl 15 0 empty empty empty 0 -6 0 8 -24198 -1 -1 0 1;
+#X obj 99 57 tgl 15 0 empty empty empty 0 -6 0 8 -241291 -1 -1 0 1
+;
+#X floatatom 124 224 5 0 0 0 - - -;
+#X obj 124 91 vsl 15 128 0 256 0 0 empty empty empty 0 -8 0 8 -260818
+-1 -1 0 1;
+#X obj 40 67 shunt 2;
+#X text 7 104 simple per-channel threshold;
+#X text 276 53 bluescreen luma threshold;
+#X text 340 195 here we have a mask;
+#X text 320 207 (alpha as separate image);
+#X obj 257 278 @join 2;
+#X text 346 226 make a RGBA image;
+#X obj 270 88 t b a a;
+#X text 210 379 = medium blue;
+#X obj 257 221 t a a;
+#X obj 121 416 fps;
+#X floatatom 146 418 5 0 0 0 - - -;
+#X obj 40 29 metro 100;
+#X msg 70 378 240 320 3 # 0 0 170;
+#X text 279 68 with alpha channel;
+#X text 13 349 you could also load a picture;
+#X text 13 361 instead of using uniform blue;
+#X text 58 10 1000/100 = 10 fps (max) (adjustable);
+#X obj 40 48 #camera;
+#X obj -13 -45 cnv 15 580 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X text 0 -32 Copyright 2002 Mathieu Bouchard;
+#X obj -15 450 cnv 15 580 30 empty empty empty 20 12 0 14 -200249 -66577
+0;
+#X text -7 457 GridFlow 0.8.0;
+#X text -7 457 GridFlow 0.8.0;
+#X text 0 -45 threshold.pd;
+#X obj 257 259 #store;
+#X obj 257 240 #finished;
+#X obj 314 145 # * 255;
+#X obj 314 126 # >=;
+#X obj 314 107 #rgb_to_greyscale;
+#X obj 70 397 #draw_image put \, alpha 1;
+#X obj 40 166 # -;
+#X obj 40 185 # max 0;
+#X obj 40 208 # ||;
+#X obj 40 227 # +;
+#X obj 40 416 #out window;
+#X text 387 -38 see also color_detect.pd;
+#X connect 0 0 38 1;
+#X connect 1 0 17 0;
+#X connect 2 0 5 1;
+#X connect 3 0 0 0;
+#X connect 3 0 33 1;
+#X connect 3 0 36 1;
+#X connect 3 0 39 1;
+#X connect 4 0 3 0;
+#X connect 5 0 36 0;
+#X connect 5 1 12 0;
+#X connect 10 0 35 1;
+#X connect 12 0 18 0;
+#X connect 12 1 14 0;
+#X connect 12 2 34 0;
+#X connect 14 0 31 0;
+#X connect 14 1 30 1;
+#X connect 15 0 16 0;
+#X connect 17 0 23 0;
+#X connect 18 0 35 0;
+#X connect 23 0 5 0;
+#X connect 30 0 10 0;
+#X connect 31 0 30 0;
+#X connect 32 0 10 1;
+#X connect 33 0 32 0;
+#X connect 34 0 33 0;
+#X connect 35 0 40 0;
+#X connect 36 0 37 0;
+#X connect 37 0 38 0;
+#X connect 38 0 39 0;
+#X connect 39 0 40 0;
+#X connect 40 0 15 0;
diff --git a/externals/gridflow/examples/transform.pd b/externals/gridflow/examples/transform.pd
new file mode 100644
index 00000000..d8785933
--- /dev/null
+++ b/externals/gridflow/examples/transform.pd
@@ -0,0 +1,61 @@
+#N canvas 726 225 674 481 10;
+#X obj 136 286 #remap_image;
+#X obj 136 324 #out window;
+#X obj 125 103 tgl 15 0 empty empty empty 0 -6 0 8 -24198 -1 -1 1 1
+;
+#X obj 294 376 # -;
+#X obj 294 202 t a a a;
+#X obj 356 261 # % 2;
+#X obj 356 280 # * -2;
+#X obj 356 299 # + 1;
+#X obj 316 300 # *;
+#X obj 403 230 # / 2;
+#X obj 377 167 hsl 128 15 0 127 0 0 empty empty empty -2 -6 0 8 -261681
+-1 -1 0 1;
+#X obj 316 281 # -;
+#X obj 374 190 t f;
+#X obj 316 262 # %;
+#X obj 356 242 # /;
+#X obj 186 214 #camera;
+#X obj 125 120 metro 10;
+#X obj 8 442 cnv 15 720 30 empty empty empty 20 12 0 14 -200249 -66577
+0;
+#X text 16 449 GridFlow 0.8.0;
+#X obj 374 449 #reverse;
+#X text 293 450 see also :;
+#X obj 1 -2 cnv 15 720 15 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X text 4 -2 Transform.pd;
+#X obj 95 215 #in r001.jpg;
+#X obj 125 139 shunt;
+#X obj 164 140 tgl 15 0 empty empty empty 0 -6 0 8 -241291 -1 -1 0
+1;
+#X text 68 32 By Mathieu Bouchard \, based on Clifford Smith's 'Transform'
+effect that is part of Fukuchi Kentaro's EffecTV : http://effectv.sourceforge.net
+;
+#X text 187 138 <-- choose from a still image or camera input;
+#X connect 0 0 1 0;
+#X connect 0 1 4 0;
+#X connect 2 0 16 0;
+#X connect 3 0 0 1;
+#X connect 4 0 3 0;
+#X connect 4 1 13 0;
+#X connect 4 2 14 0;
+#X connect 5 0 6 0;
+#X connect 6 0 7 0;
+#X connect 7 0 8 1;
+#X connect 8 0 3 1;
+#X connect 9 0 11 1;
+#X connect 10 0 12 0;
+#X connect 11 0 8 0;
+#X connect 12 0 9 0;
+#X connect 12 0 13 1;
+#X connect 12 0 14 1;
+#X connect 13 0 11 0;
+#X connect 14 0 5 0;
+#X connect 15 0 0 0;
+#X connect 16 0 24 0;
+#X connect 23 0 0 0;
+#X connect 24 0 23 0;
+#X connect 24 1 15 0;
+#X connect 25 0 24 1;
diff --git a/externals/gridflow/examples/translation_tracker.pd b/externals/gridflow/examples/translation_tracker.pd
new file mode 100644
index 00000000..a78b0068
--- /dev/null
+++ b/externals/gridflow/examples/translation_tracker.pd
@@ -0,0 +1,162 @@
+#N canvas 734 0 486 689 10;
+#X obj 28 15 tgl 15 0 empty empty empty 17 7 0 10 -24198 -1 -1 1 1
+;
+#X obj 172 7 bng 15 250 50 0 empty empty empty 17 7 0 10 -241291 -1
+-1;
+#X obj 189 12 loadbang;
+#X obj 28 120 #remap_image;
+#X floatatom 378 62 5 0 0 0 - - -;
+#X obj 345 83 #pack;
+#X obj 28 195 #cast f;
+#X obj 28 492 #cast i;
+#X obj 172 195 #cast f;
+#X obj 172 233 #fft;
+#X obj 172 214 #outer * (2 f # 1 0);
+#X obj 28 511 #rgb_to_greyscale;
+#X obj 29 648 display;
+#X obj 28 361 # C.*conj;
+#X obj 28 530 #t;
+#X obj 28 609 # >=;
+#X obj 28 628 #moment;
+#X floatatom 378 42 5 0 0 0 - - -;
+#X obj 193 610 #moment;
+#X obj 194 633 display;
+#X obj 191 567 #clip;
+#X text 241 459 this is the same as magnitude;
+#X text 244 472 because imaginary = 0 here;
+#X obj 28 101 #store;
+#X obj 28 51 shunt;
+#X obj 65 52 tgl 15 0 empty empty empty 17 7 0 10 -241291 -1 -1 0 1
+;
+#X obj 58 70 #camera;
+#X obj 228 121 gf.oneshot;
+#X obj 189 121 t a a;
+#X obj 301 122 bng 15 250 50 0 empty empty empty 17 7 0 10 -260818
+-1 -1;
+#X obj 141 645 fps;
+#X obj 142 665 display;
+#X obj 141 626 bang;
+#X obj 331 216 # inv* (f # 1);
+#X obj 172 252 # * (f #);
+#X obj 189 31 t b b;
+#X obj 233 164 #window A;
+#X obj 83 182 #window B;
+#X obj 148 183 tgl 15 0 empty empty empty 17 7 0 10 -241291 -1 -1 0
+1;
+#X obj 298 165 tgl 15 0 empty empty empty 17 7 0 10 -241291 -1 -1 0
+1;
+#X obj 320 587 tgl 15 0 empty empty empty 17 7 0 10 -241291 -1 -1 0
+1;
+#X obj 44 568 #fold max;
+#X obj 44 549 #ravel;
+#X text 83 431 this bufferises the data to avoid an alignment warning
+;
+#X obj 331 235 # sq- (f #);
+#X obj 116 120 # -;
+#X obj 11 36 bng 15 250 50 0 empty empty empty 17 7 0 10 -24198 -1
+-1;
+#X obj 28 240 #fft \, real;
+#X obj 350 280 tgl 15 0 empty empty empty 17 7 0 10 -241291 -1 -1 0
+1;
+#X obj 28 311 t a;
+#X obj 262 291 #cast i;
+#X obj 262 386 #clip;
+#X obj 172 63 #in pure-data.jpg;
+#X msg 331 197 list f # 76800;
+#X obj 262 310 # sq-;
+#X obj 262 272 spigot;
+#X obj 262 329 #fold +;
+#X obj 262 348 # sqrt;
+#X obj 262 405 #window D;
+#X obj 350 261 loadbang;
+#X obj 191 586 #window C;
+#X obj 191 510 spigot;
+#X obj 320 568 loadbang;
+#X obj 28 449 #fft \, sign 1 \, real;
+#X obj 262 367 # >> 4;
+#X obj 28 32 metro 33.3667;
+#X obj 191 548 # -;
+#X obj 192 529 # >> 6;
+#X obj 216 550 nbx 3 14 -1e+37 1e+37 0 1 empty empty empty 0 -8 0 10
+-262144 -1 -1 256 256;
+#X obj 67 408 tgl 15 0 empty empty empty 17 7 0 10 -241291 -1 -1 0
+1;
+#X obj 28 407 shunt;
+#X obj 58 430 #t;
+#X connect 0 0 65 0;
+#X connect 1 0 52 0;
+#X connect 2 0 35 0;
+#X connect 3 0 37 0;
+#X connect 3 0 6 0;
+#X connect 3 1 45 0;
+#X connect 4 0 5 1;
+#X connect 5 0 45 1;
+#X connect 6 0 47 0;
+#X connect 7 0 11 0;
+#X connect 7 0 61 0;
+#X connect 8 0 10 0;
+#X connect 9 0 34 0;
+#X connect 10 0 9 0;
+#X connect 11 0 14 0;
+#X connect 11 0 18 0;
+#X connect 13 0 70 0;
+#X connect 14 0 15 0;
+#X connect 14 1 42 0;
+#X connect 15 0 16 0;
+#X connect 16 0 12 0;
+#X connect 16 0 32 0;
+#X connect 17 0 5 0;
+#X connect 18 0 19 0;
+#X connect 20 0 60 0;
+#X connect 23 0 3 0;
+#X connect 24 0 23 0;
+#X connect 24 1 26 0;
+#X connect 25 0 24 1;
+#X connect 26 0 28 0;
+#X connect 27 0 36 0;
+#X connect 27 0 8 0;
+#X connect 28 0 6 0;
+#X connect 28 1 27 0;
+#X connect 29 0 27 1;
+#X connect 30 0 31 0;
+#X connect 32 0 30 0;
+#X connect 33 0 44 0;
+#X connect 34 0 13 1;
+#X connect 35 0 52 0;
+#X connect 35 1 53 0;
+#X connect 38 0 37 1;
+#X connect 39 0 36 1;
+#X connect 40 0 60 1;
+#X connect 40 0 61 1;
+#X connect 41 0 15 1;
+#X connect 42 0 41 0;
+#X connect 44 0 34 1;
+#X connect 45 0 3 1;
+#X connect 46 0 24 0;
+#X connect 47 0 49 0;
+#X connect 48 0 55 1;
+#X connect 48 0 58 1;
+#X connect 49 0 13 0;
+#X connect 49 0 55 0;
+#X connect 50 0 54 0;
+#X connect 51 0 58 0;
+#X connect 52 0 23 1;
+#X connect 52 0 8 0;
+#X connect 53 0 33 0;
+#X connect 54 0 56 0;
+#X connect 55 0 50 0;
+#X connect 56 0 57 0;
+#X connect 57 0 64 0;
+#X connect 59 0 48 0;
+#X connect 61 0 67 0;
+#X connect 62 0 40 0;
+#X connect 63 0 7 0;
+#X connect 64 0 51 0;
+#X connect 65 0 24 0;
+#X connect 66 0 20 0;
+#X connect 67 0 66 0;
+#X connect 68 0 66 1;
+#X connect 69 0 70 1;
+#X connect 70 0 63 0;
+#X connect 70 1 71 0;
+#X connect 71 0 63 0;
diff --git a/externals/gridflow/examples/translation_tracker2.pd b/externals/gridflow/examples/translation_tracker2.pd
new file mode 100644
index 00000000..56eeb2e9
--- /dev/null
+++ b/externals/gridflow/examples/translation_tracker2.pd
@@ -0,0 +1,126 @@
+#N canvas 770 0 450 674 10;
+#X obj 6 6 tgl 15 0 empty empty empty 17 7 0 10 -24198 -1 -1 0 1;
+#X obj 36 170 #cast f;
+#X obj 36 208 #fft;
+#X obj 36 327 #cast i;
+#X obj 36 189 #outer * (2 f # 1 0);
+#X obj 180 170 #cast f;
+#X obj 180 208 #fft;
+#X obj 180 189 #outer * (2 f # 1 0);
+#X obj 36 279 #fft \, sign -1;
+#X obj 36 151 # - 128;
+#X obj 180 151 # - 128;
+#X obj 36 346 #rgb_to_greyscale;
+#X obj 36 260 # C.*conj;
+#X obj 52 403 #fold max;
+#X obj 36 365 #t;
+#X obj 36 424 # >=;
+#X obj 36 443 #moment;
+#X obj 199 401 #out window;
+#X obj 199 382 #clip;
+#X obj 199 363 # + 128;
+#X obj 36 298 #inner (2 f # 1 0) \, seed (f #);
+#X text 249 294 this is the same as magnitude;
+#X text 252 307 because imaginary = 0 here;
+#X obj 36 61 #camera;
+#X obj 296 467 fps;
+#X obj 297 486 display;
+#X obj 296 448 bang;
+#X obj 331 232 # inv* (f # 1);
+#X obj 328 151 loadbang;
+#X msg 328 207 list f # 172800;
+#X obj 36 227 # * (f #);
+#X obj 180 228 # * (f #);
+#X obj 52 384 #ravel;
+#X msg 332 178 list f # 76800;
+#X obj 27 119 #out window;
+#X obj 35 483 # % (240 320);
+#X obj 35 502 # - (120 160);
+#X obj 35 464 # + (120 160);
+#X floatatom 252 365 5 0 0 0 - - -;
+#X obj 199 344 # >> 5;
+#X obj 35 521 # +;
+#X obj 60 521 t a;
+#X msg 166 514 240 320;
+#X obj 136 459 loadbang;
+#X obj 89 80 s \$0-meuh;
+#X obj 88 606 r \$0-meuh;
+#X obj 6 42 t b b;
+#X obj 6 647 #out window;
+#X obj 35 540 #export_list;
+#X obj 52 628 #store;
+#X obj 35 559 t b a;
+#X obj 272 558 display;
+#X msg 74 559 put_at ( \$1 \$2 0 );
+#X obj 136 495 t b b;
+#X obj 136 478 bng 15 250 50 0 empty empty empty 17 7 0 10 -260818
+-1 -1;
+#X obj 6 23 metro 100;
+#X msg 136 533 720 960 3 #;
+#X obj 6 628 #store;
+#X obj 36 80 t a a a;
+#X msg 12 585 op avg;
+#X connect 0 0 55 0;
+#X connect 1 0 4 0;
+#X connect 2 0 30 0;
+#X connect 3 0 11 0;
+#X connect 3 0 39 0;
+#X connect 4 0 2 0;
+#X connect 5 0 7 0;
+#X connect 6 0 31 0;
+#X connect 7 0 6 0;
+#X connect 8 0 20 0;
+#X connect 9 0 1 0;
+#X connect 10 0 5 0;
+#X connect 11 0 14 0;
+#X connect 12 0 8 0;
+#X connect 13 0 15 1;
+#X connect 14 0 15 0;
+#X connect 14 1 32 0;
+#X connect 15 0 16 0;
+#X connect 16 0 26 0;
+#X connect 16 0 37 0;
+#X connect 18 0 17 0;
+#X connect 19 0 18 0;
+#X connect 20 0 3 0;
+#X connect 23 0 58 0;
+#X connect 24 0 25 0;
+#X connect 26 0 24 0;
+#X connect 27 0 30 1;
+#X connect 27 0 31 1;
+#X connect 28 0 33 0;
+#X connect 29 0 27 0;
+#X connect 30 0 12 0;
+#X connect 31 0 12 1;
+#X connect 32 0 13 0;
+#X connect 33 0 27 0;
+#X connect 35 0 36 0;
+#X connect 36 0 40 0;
+#X connect 37 0 35 0;
+#X connect 38 0 19 1;
+#X connect 39 0 19 0;
+#X connect 40 0 41 0;
+#X connect 40 0 48 0;
+#X connect 41 0 40 1;
+#X connect 42 0 40 1;
+#X connect 43 0 54 0;
+#X connect 45 0 49 1;
+#X connect 46 0 57 0;
+#X connect 46 1 23 0;
+#X connect 48 0 50 0;
+#X connect 48 0 51 0;
+#X connect 49 0 57 1;
+#X connect 50 0 49 0;
+#X connect 50 1 52 0;
+#X connect 52 0 57 1;
+#X connect 53 0 56 0;
+#X connect 53 1 42 0;
+#X connect 54 0 53 0;
+#X connect 55 0 46 0;
+#X connect 56 0 57 1;
+#X connect 57 0 47 0;
+#X connect 58 0 34 0;
+#X connect 58 0 10 0;
+#X connect 58 1 9 0;
+#X connect 58 2 44 0;
+#X connect 59 0 57 0;
diff --git a/externals/gridflow/examples/videodev_effects.pd b/externals/gridflow/examples/videodev_effects.pd
new file mode 100644
index 00000000..22a9d443
--- /dev/null
+++ b/externals/gridflow/examples/videodev_effects.pd
@@ -0,0 +1,264 @@
+#N canvas 623 0 597 657 10;
+#X obj 80 486 tgl 15 0 empty empty crosshair_of_centroid 20 7 0 10
+-241291 -1 -1 1 1;
+#X obj 71 261 # max 0;
+#X obj 27 349 shunt 2;
+#X obj 71 131 #downscale_by 2 smoothly;
+#X obj 27 484 shunt 2;
+#X obj 81 351 tgl 15 0 empty empty gamma_correction 18 7 0 10 -241291
+-1 -1 0 1;
+#X obj 80 176 tgl 15 0 empty empty frame_difference 18 7 0 10 -241291
+-1 -1 0 1;
+#X obj 27 47 tgl 15 0 empty empty empty 0 -6 0 8 -24198 -1 -1 0 1;
+#X obj 27 112 shunt 2;
+#X obj 27 541 #out window;
+#X obj 80 113 tgl 15 0 empty empty smaller_picture 18 7 0 10 -241291
+-1 -1 0 1;
+#X obj 27 579 print;
+#X obj 240 382 #for 0 256 1;
+#X floatatom 240 347 5 0 0 0 - - -;
+#X obj 99 243 hsl 128 15 0 127 0 0 empty empty empty -2 -6 0 8 -260818
+-1 -1 0 1;
+#X obj 27 295 shunt 2;
+#X obj 173 441 tgl 15 0 empty empty empty 0 -6 0 8 -241291 -1 -1 0
+1;
+#X obj 27 421 shunt 2;
+#X obj 27 560 fps detailed;
+#X obj 240 309 loadbang;
+#X obj 80 421 tgl 15 0 empty empty empty 0 -6 0 8 -241291 -1 -1 0 1
+;
+#X obj 71 393 #store;
+#N canvas 81 205 480 500 sort 0;
+#X obj 180 257 # * 255;
+#X obj 10 345 # >> 0;
+#X obj 113 472 outlet;
+#X obj 226 42 inlet;
+#X obj 225 191 # / 2;
+#X obj 10 325 # +;
+#X obj 44 9 inlet;
+#X obj 242 150 # - 1;
+#X obj 131 422 # +;
+#X obj 180 238 # < 176;
+#X obj 10 369 #store;
+#X obj 91 28 #grade;
+#X obj 131 444 # >> 1;
+#X obj 283 266 # / 351;
+#X obj 91 47 shunt 2;
+#X obj 135 66 #grade;
+#X obj 144 119 inlet;
+#X text 271 128 extract width;
+#X obj 10 266 #finished;
+#X obj 283 247 # * 255;
+#X obj 91 9 #fold +;
+#X obj 91 119 shunt 4;
+#X obj 117 399 shunt 4;
+#X msg 235 126 \$2;
+#X obj 211 65 #dim;
+#X obj 44 37 t a a;
+#X msg 186 127 \$1 \$2;
+#X obj 211 85 #export_list;
+#X obj 76 146 t a a;
+#X obj 10 285 #for (0 0) (288 352) (1 1);
+#X obj 106 176 #outer & (0 -1);
+#X obj 292 300 #outer ignore (3 #);
+#X obj 10 305 # * (1 0);
+#X connect 0 0 31 0;
+#X connect 1 0 10 0;
+#X connect 3 0 14 1;
+#X connect 4 0 9 1;
+#X connect 5 0 1 0;
+#X connect 6 0 25 0;
+#X connect 7 0 13 1;
+#X connect 8 0 12 0;
+#X connect 9 0 0 0;
+#X connect 10 0 22 0;
+#X connect 11 0 14 0;
+#X connect 12 0 2 0;
+#X connect 13 0 31 0;
+#X connect 14 0 21 0;
+#X connect 14 1 15 0;
+#X connect 15 0 21 0;
+#X connect 16 0 21 1;
+#X connect 16 0 22 1;
+#X connect 18 0 29 0;
+#X connect 19 0 13 0;
+#X connect 20 0 11 0;
+#X connect 21 0 28 0;
+#X connect 21 1 28 0;
+#X connect 21 2 9 0;
+#X connect 21 3 19 0;
+#X connect 22 0 2 0;
+#X connect 22 1 8 0;
+#X connect 23 0 4 0;
+#X connect 23 0 7 0;
+#X connect 24 0 27 0;
+#X connect 25 0 20 0;
+#X connect 25 1 10 1;
+#X connect 25 1 24 0;
+#X connect 25 1 8 1;
+#X connect 26 0 29 1;
+#X connect 27 0 23 0;
+#X connect 27 0 26 0;
+#X connect 28 0 18 0;
+#X connect 28 1 30 0;
+#X connect 29 0 32 0;
+#X connect 30 0 5 1;
+#X connect 31 0 2 0;
+#X connect 32 0 5 0;
+#X restore 71 440 pd sort me out;
+#X obj 240 401 # gamma;
+#X obj 71 242 # -;
+#X obj 80 296 tgl 15 0 empty empty empty 0 -6 0 8 -241291 -1 -1 0 1
+;
+#N canvas 372 198 399 273 motion 0;
+#X obj 15 113 # << 2;
+#X obj 15 9 inlet;
+#X obj 18 80 # -;
+#X obj 70 174 # + 128;
+#X obj 15 245 outlet;
+#X obj 15 204 # min 255;
+#X obj 15 224 # max 0;
+#X obj 70 155 # << 2;
+#X obj 15 35 t a a;
+#X obj 15 134 shunt 2;
+#X obj 70 133 inlet render;
+#X obj 155 54 inlet type;
+#X obj 15 54 shunt 2;
+#X obj 15 162 # abs-;
+#X connect 0 0 9 0;
+#X connect 1 0 8 0;
+#X connect 2 0 0 0;
+#X connect 3 0 5 0;
+#X connect 5 0 6 0;
+#X connect 6 0 4 0;
+#X connect 7 0 3 0;
+#X connect 8 0 12 0;
+#X connect 8 1 2 0;
+#X connect 9 0 13 0;
+#X connect 9 1 7 0;
+#X connect 10 0 9 1;
+#X connect 11 0 12 1;
+#X connect 12 0 2 1;
+#X connect 13 0 5 0;
+#X restore 71 223 pd motion detection;
+#X obj 117 423 hradio 15 1 0 4 empty empty empty 0 -6 0 8 -241291 -1
+-1 0;
+#X text 125 261 noise reduction (on find-edges only);
+#X obj 27 64 metro 33.3667;
+#X obj 27 175 shunt 2;
+#X obj 135 191 vradio 15 1 0 2 empty empty empty 0 -6 0 8 -241291 -1
+-1 0;
+#X floatatom 184 577 5 0 0 0 - - -;
+#X floatatom 228 577 5 0 0 0 - - -;
+#N canvas 547 147 477 267 crosshair 0;
+#X obj 12 224 outlet;
+#X obj 12 9 inlet;
+#X msg 21 125 12 2 # \$1 \$2 \$1 \$3 \$2 \$3 \$2 \$4 \$3 \$4 \$3 \$3
+\$4 \$3 \$4 \$2 \$3 \$2 \$3 \$1 \$2 \$1 \$2 \$2;
+#X msg 54 95 -32 -1 1 32;
+#X obj 175 37 #fade 8;
+#X obj 175 18 inlet;
+#X obj 54 76 #finished;
+#X obj 95 169 # + (120 160);
+#X obj 12 205 #draw_polygon + (0 170 0);
+#X obj 175 56 t a a;
+#X connect 1 0 8 0;
+#X connect 2 0 7 0;
+#X connect 3 0 2 0;
+#X connect 4 0 9 0;
+#X connect 5 0 4 0;
+#X connect 6 0 3 0;
+#X connect 7 0 8 2;
+#X connect 8 0 0 0;
+#X connect 9 0 6 0;
+#X connect 9 1 7 1;
+#X restore 71 522 pd crosshair;
+#X obj 27 522 t a;
+#X text 151 205 emboss;
+#X text 152 191 hilite;
+#X obj 199 191 vradio 15 1 0 2 empty empty empty 0 -6 0 8 -241291 -1
+-1 1;
+#X text 218 191 motion;
+#X text 219 205 presence;
+#X obj -13 625 cnv 15 620 30 empty empty empty 20 12 0 14 -200249 -66577
+0;
+#X obj -13 2 cnv 15 620 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X text 0 15 Copyright 2002 Mathieu Bouchard;
+#X text 0 1 videodev_effects.pd;
+#X obj 71 371 #outer ignore (0);
+#X obj 184 539 #moment;
+#X obj 240 363 t b a;
+#X obj 184 520 #rgb_to_greyscale;
+#X obj 71 503 #t;
+#X obj 71 314 #fade (16 4 1);
+#X obj 27 83 #camera 0;
+#X obj 184 558 #unpack;
+#X text -5 633 GridFlow 0.9.4;
+#X text 236 290 make gamma table;
+#X obj 240 420 #to_list;
+#X msg 240 328 512;
+#N canvas 0 0 450 300 (subpatch) 0;
+#X array gamma 256 float 2;
+#X coords 0 255 255 0 128 128 1;
+#X restore 400 337 graph;
+#X text 97 499 (use with "hilite" mode above);
+#X obj 240 439 list prepend 0;
+#X obj 240 458 s gamma;
+#X text 406 467 only for viewing;
+#X text 408 482 (not necessary);
+#X connect 0 0 4 1;
+#X connect 1 0 15 0;
+#X connect 2 0 17 0;
+#X connect 2 1 45 0;
+#X connect 3 0 30 0;
+#X connect 4 0 35 0;
+#X connect 4 1 49 0;
+#X connect 5 0 2 1;
+#X connect 6 0 30 1;
+#X connect 7 0 29 0;
+#X connect 8 0 30 0;
+#X connect 8 1 3 0;
+#X connect 9 0 18 0;
+#X connect 10 0 8 1;
+#X connect 12 0 23 0;
+#X connect 13 0 47 0;
+#X connect 14 0 24 1;
+#X connect 15 0 2 0;
+#X connect 15 1 50 0;
+#X connect 16 0 22 2;
+#X connect 17 0 4 0;
+#X connect 17 1 22 0;
+#X connect 18 0 11 0;
+#X connect 19 0 56 0;
+#X connect 20 0 17 1;
+#X connect 21 0 17 0;
+#X connect 22 0 4 0;
+#X connect 23 0 21 1;
+#X connect 23 0 55 0;
+#X connect 24 0 1 0;
+#X connect 25 0 15 1;
+#X connect 26 0 24 0;
+#X connect 27 0 22 1;
+#X connect 29 0 51 0;
+#X connect 30 0 15 0;
+#X connect 30 1 26 0;
+#X connect 31 0 26 1;
+#X connect 34 0 35 0;
+#X connect 35 0 9 0;
+#X connect 38 0 26 2;
+#X connect 45 0 21 0;
+#X connect 46 0 34 1;
+#X connect 46 0 52 0;
+#X connect 47 0 12 0;
+#X connect 47 1 23 1;
+#X connect 48 0 46 0;
+#X connect 49 0 34 0;
+#X connect 49 1 48 0;
+#X connect 50 0 2 0;
+#X connect 51 0 8 0;
+#X connect 52 0 32 0;
+#X connect 52 1 33 0;
+#X connect 55 0 59 0;
+#X connect 56 0 13 0;
+#X connect 59 0 60 0;
diff --git a/externals/gridflow/examples/wave_1d.pd b/externals/gridflow/examples/wave_1d.pd
new file mode 100644
index 00000000..b9cafd74
--- /dev/null
+++ b/externals/gridflow/examples/wave_1d.pd
@@ -0,0 +1,173 @@
+#N canvas 560 15 621 659 10;
+#X obj 13 13 tgl 15 0 empty empty empty 0 -6 0 8 -241291 -1 -1 1 1
+;
+#X obj 181 29 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 30 128 t a a;
+#X obj 17 250 shunt 2;
+#X obj 64 251 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1
+;
+#X obj 45 620 fps;
+#X floatatom 71 621 5 0 0 0 - - -;
+#X obj 17 269 t a b;
+#X obj 7 368 fps;
+#X floatatom 7 387 5 0 0 0 - - -;
+#X obj 45 419 spigot;
+#X obj 76 381 f;
+#X obj 109 378 + 1;
+#X obj 76 400 == 0;
+#X obj 30 30 t b;
+#X obj 174 9 loadbang;
+#X obj 105 487 loadbang;
+#X obj 461 449 loadbang;
+#X obj 244 595 unpack 0 0;
+#X obj 244 614 inv+ 64;
+#X msg 308 595 0 \$1;
+#X obj 480 494 t b l;
+#X obj 244 633 << 12;
+#X obj 17 186 t a a;
+#N canvas 627 255 450 300 synth 0;
+#X obj 17 16 inlet;
+#X obj 17 102 s foo;
+#X obj 20 125 tabreceive~ foo;
+#X obj 20 259 outlet~;
+#X obj 67 238 env~;
+#X floatatom 67 257 5 0 0 0 - - -;
+#X obj 99 27 loadbang;
+#X obj 76 25 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 334 58 table foo 2048;
+#X obj 21 144 rifft~;
+#X obj 20 201 +~;
+#X obj 21 163 expr~ tanh($v1*0.0001);
+#X obj 20 182 lop~ 2000;
+#X obj 339 24 block~ 2048;
+#X obj 17 36 # * 2048;
+#X obj 18 58 # /;
+#X obj 86 49 #for 1 257 1;
+#X obj 17 80 #export_list;
+#X connect 0 0 14 0;
+#X connect 2 0 9 0;
+#X connect 4 0 5 0;
+#X connect 6 0 16 0;
+#X connect 7 0 16 0;
+#X connect 9 0 11 0;
+#X connect 10 0 4 0;
+#X connect 10 0 3 0;
+#X connect 11 0 12 0;
+#X connect 12 0 10 0;
+#X connect 14 0 15 0;
+#X connect 15 0 17 0;
+#X connect 16 0 15 1;
+#X connect 17 0 1 0;
+#X restore 136 437 pd synth;
+#X obj 129 459 dac~;
+#X text 498 6 1-D wave generator;
+#X obj 174 47 #for -128 128 1;
+#X obj 174 66 # abs-;
+#X obj 174 85 # < 127;
+#X obj 159 107 # * 1e+07;
+#X obj 159 127 # * -1e+07;
+#X obj 30 85 # min;
+#X obj 30 104 # max;
+#X obj 131 253 #redim (1);
+#X obj 461 518 # + (0 6);
+#X obj 65 272 #draw_polygon put (1 #);
+#X obj 45 448 # >> 12;
+#X obj 45 467 #redim (256);
+#X obj 45 506 #outer <;
+#X obj 105 506 #for 64 -64 -1;
+#X obj 45 525 #transpose;
+#X obj 45 544 #outer * (3 # 255);
+#X obj 45 601 #out window;
+#X obj 240 533 #mouse \, ...;
+#X obj 244 576 #export_list;
+#X obj 30 66 #store (1 256 1 # 0);
+#X obj 17 147 # -;
+#X obj 45 563 #fade (16 4 1);
+#X obj 17 226 # -;
+#X obj 109 397 % 2;
+#X obj 30 11 metro 20;
+#X msg 461 468 4 2 # 0 0 0 4 1 4 1 0;
+#X obj 42 205 # >> 8;
+#X text 54 186 damping;
+#X text 249 147 wave equation;
+#X text 88 419 framerate-divider;
+#X obj 45 582 #scale_by 2;
+#X obj 244 557 # / 2;
+#X obj 55 148 #convolve (1 3 # 1 0 1) \, seed 1;
+#X obj 37 321 #convolve (1 3 # 1 2 1);
+#X obj 37 340 # >> 2;
+#X text 180 321 smoothing;
+#X text 224 120 cap at plus or minus ten million;
+#X text 389 19 Copyright 2004 \, 2007 Mathieu Bouchard;
+#X connect 0 0 51 0;
+#X connect 1 0 27 0;
+#X connect 2 0 47 1;
+#X connect 2 1 59 0;
+#X connect 3 0 7 0;
+#X connect 3 1 36 0;
+#X connect 4 0 3 1;
+#X connect 5 0 6 0;
+#X connect 7 0 46 1;
+#X connect 7 0 60 0;
+#X connect 7 1 8 0;
+#X connect 7 1 11 0;
+#X connect 8 0 9 0;
+#X connect 10 0 37 0;
+#X connect 11 0 12 0;
+#X connect 11 0 13 0;
+#X connect 12 0 50 0;
+#X connect 13 0 10 1;
+#X connect 14 0 46 0;
+#X connect 15 0 27 0;
+#X connect 16 0 40 0;
+#X connect 17 0 52 0;
+#X connect 18 0 19 0;
+#X connect 18 1 20 0;
+#X connect 19 0 22 0;
+#X connect 20 0 21 0;
+#X connect 21 0 52 0;
+#X connect 21 1 35 1;
+#X connect 22 0 34 0;
+#X connect 23 0 49 0;
+#X connect 23 1 53 0;
+#X connect 24 0 25 0;
+#X connect 24 0 25 1;
+#X connect 27 0 28 0;
+#X connect 28 0 29 0;
+#X connect 29 0 30 0;
+#X connect 29 0 31 0;
+#X connect 30 0 32 1;
+#X connect 31 0 33 1;
+#X connect 32 0 33 0;
+#X connect 33 0 2 0;
+#X connect 34 0 36 1;
+#X connect 35 0 36 2;
+#X connect 36 0 7 0;
+#X connect 37 0 38 0;
+#X connect 38 0 24 0;
+#X connect 38 0 39 0;
+#X connect 39 0 41 0;
+#X connect 40 0 39 1;
+#X connect 41 0 42 0;
+#X connect 42 0 48 0;
+#X connect 43 0 5 0;
+#X connect 43 0 44 0;
+#X connect 44 0 58 0;
+#X connect 44 1 58 0;
+#X connect 44 4 4 0;
+#X connect 45 0 18 0;
+#X connect 46 0 32 0;
+#X connect 47 0 23 0;
+#X connect 48 0 57 0;
+#X connect 49 0 3 0;
+#X connect 50 0 11 1;
+#X connect 51 0 14 0;
+#X connect 52 0 35 0;
+#X connect 53 0 49 1;
+#X connect 57 0 43 0;
+#X connect 58 0 45 0;
+#X connect 59 0 47 0;
+#X connect 60 0 61 0;
+#X connect 61 0 10 0;
diff --git a/externals/gridflow/examples/waves.pd b/externals/gridflow/examples/waves.pd
new file mode 100644
index 00000000..75e108e5
--- /dev/null
+++ b/externals/gridflow/examples/waves.pd
@@ -0,0 +1,429 @@
+#N canvas 371 0 848 642 10;
+#X obj 107 47 loadbang;
+#X obj 107 85 t a a;
+#X obj 266 412 print;
+#X obj 10 49 tgl 15 0 empty empty empty 0 -6 0 8 -24198 -1 -1 0 1;
+#X obj 260 453 # / 2;
+#X msg 107 104 \$1 \$2 1 # 0;
+#N canvas 137 251 392 303 finger 0;
+#X obj 149 39 #redim ( 4 2 );
+#X obj 71 16 inlet;
+#X obj 149 20 inlet;
+#X obj 71 217 outlet;
+#X obj 149 158 # +;
+#X obj 177 157 # *;
+#X msg 177 137 0 0 0 1 1 1 1 0;
+#X obj 193 79 inlet size;
+#X text 291 137 square or rect;
+#X obj 177 112 #finished;
+#X obj 70 195 #draw_polygon put (4000);
+#X connect 0 0 4 0;
+#X connect 1 0 10 0;
+#X connect 2 0 0 0;
+#X connect 4 0 10 2;
+#X connect 5 0 4 1;
+#X connect 6 0 5 0;
+#X connect 7 0 9 0;
+#X connect 7 0 5 1;
+#X connect 9 0 6 0;
+#X connect 10 0 3 0;
+#X restore 234 570 pd finger;
+#X obj 141 85 s size;
+#X obj 260 353 #scale_by 2;
+#X obj 10 243 #store;
+#N canvas 243 147 463 307 wave 0;
+#X obj 26 20 inlet;
+#X obj 23 293 outlet;
+#X text 65 205 time differential;
+#X text 81 50 space differential: (d/dx)^2 + (d/dy)^2;
+#X text 71 8 Recurrence equation for propagation of oscillations;
+#X obj 26 39 t a a;
+#X obj 207 147 outlet blah;
+#X obj 207 125 inlet blah;
+#X obj 23 205 # -;
+#X obj 23 225 # *>>8 252;
+#X obj 20 250 # min 30000;
+#X obj 20 270 # max -30000;
+#X obj 56 82 #convolve (3 3 # 1 4 1 4 12 4) \, seed 8;
+#X obj 56 101 # >> 4;
+#X connect 0 0 5 0;
+#X connect 5 0 8 1;
+#X connect 5 1 12 0;
+#X connect 7 0 8 0;
+#X connect 8 0 9 0;
+#X connect 9 0 10 0;
+#X connect 10 0 11 0;
+#X connect 11 0 1 0;
+#X connect 12 0 13 0;
+#X connect 13 0 6 0;
+#X restore 10 281 pd wave equation;
+#X obj 189 570 t a;
+#X obj 107 123 t a;
+#X obj 36 85 s metro;
+#X text 491 65 (Best complemented with a touchscreen);
+#X obj 355 209 vradio 15 1 0 3 empty empty empty 0 -6 0 8 -241291 -258699
+-1 0;
+#X text 373 224 height greys;
+#X obj 313 98 vradio 15 1 0 3 empty empty empty 0 -6 0 8 -241291 -258699
+-1 0;
+#X text 331 97 plain;
+#X text 331 113 line-art;
+#X text 330 46 smooth;
+#X obj 313 46 vradio 15 1 0 2 empty empty empty 0 -6 0 8 -241291 -258699
+-1 0;
+#X text 331 60 raw;
+#X obj 442 418 hradio 18 1 1 4 empty empty _1__2__3__4_ 0 -4 0 10 -241291
+-258699 -1 0;
+#X text 440 397 scale by...;
+#X obj 442 438 + 1;
+#X obj 573 105 loadbang;
+#X obj 573 276 spigot;
+#X obj 620 277 tgl 15 0 empty empty empty 18 8 0 8 -241291 -1 -62784
+0 1;
+#X obj 573 256 r metro;
+#N canvas 433 107 365 432 line-art 0;
+#X obj 32 123 # << 8;
+#X obj 32 37 inlet;
+#X obj 34 256 outlet;
+#X text 146 31 double-thresholding;
+#X text 146 114 else becomes 0;
+#X obj 32 82 # min 1;
+#X obj 32 103 # max -1;
+#X obj 32 172 # >> 2;
+#X obj 31 154 #convolve (3 1 # 1 2 1);
+#X obj 33 193 #convolve (1 3 # 1 2 1);
+#X obj 35 215 # >> 2;
+#X obj 32 60 # / 5;
+#X text 146 85 < -5 becomes -256;
+#X text 146 100 > +5 becomes +256;
+#X connect 0 0 8 0;
+#X connect 1 0 11 0;
+#X connect 5 0 6 0;
+#X connect 6 0 0 0;
+#X connect 7 0 9 0;
+#X connect 8 0 7 0;
+#X connect 9 0 10 0;
+#X connect 10 0 2 0;
+#X connect 11 0 5 0;
+#X restore 282 187 pd line-art;
+#X text 628 129 Background colour;
+#X text 637 277 enable video;
+#X text 371 209 four-colour emboss;
+#X obj 345 492 tgl 15 1 empty empty empty 0 -6 0 8 -241291 -1 -1 0
+1;
+#X obj 298 472 r metro;
+#X text 362 491 rain;
+#X obj 260 99 # >> 2;
+#X text 388 36 Originally made for Alexandre Castonguay's "DIGITALE"
+;
+#X text 505 50 But suitable for a lot more uses :-);
+#X msg 573 124 3 # 128;
+#X obj 573 143 #color;
+#X obj 260 59 shunt 2;
+#X obj 303 559 nbx 5 14 -1e+37 1e+37 0 1 empty empty empty 0 -6 0 10
+-262131 -1 -1 1 256;
+#X obj 303 573 nbx 5 14 -1e+37 1e+37 0 1 empty empty empty 0 -6 0 10
+-262131 -1 -1 1 256;
+#X obj 477 291 vradio 15 1 0 2 empty empty empty 0 -6 0 8 -241291 -258699
+-1 0;
+#X text 495 290 plain;
+#X text 495 307 refraction;
+#X obj 260 296 t a;
+#N canvas 203 363 443 300 heightmap2indexmap 0;
+#X obj 48 239 outlet;
+#X obj 9 8 inlet;
+#X obj 48 143 # +;
+#X obj 100 9 #dim;
+#X obj 132 9 #export_list;
+#X obj 48 8 t a a;
+#X obj 48 48 t a a;
+#X msg 132 28 \$1 \$2;
+#X obj 48 220 # +;
+#X obj 90 200 loadbang;
+#X obj 73 200 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 78 67 #convolve (1 2 #) \, op ignore \, fold inv+;
+#X obj 78 86 #outer & (-1 0);
+#X obj 48 105 #convolve (2 1 #) \, op ignore \, fold inv+;
+#X obj 48 124 #outer & (0 -1);
+#X obj 73 220 #for (0 0) (240 320) (1 1);
+#X obj 48 28 #redim ();
+#X obj 48 181 # >> 3;
+#X obj 48 162 # + 4;
+#X connect 1 0 5 0;
+#X connect 2 0 18 0;
+#X connect 3 0 4 0;
+#X connect 4 0 7 0;
+#X connect 5 0 16 0;
+#X connect 5 1 3 0;
+#X connect 6 0 13 0;
+#X connect 6 1 11 0;
+#X connect 7 0 16 1;
+#X connect 8 0 0 0;
+#X connect 9 0 15 0;
+#X connect 10 0 15 0;
+#X connect 11 0 12 0;
+#X connect 12 0 2 1;
+#X connect 13 0 14 0;
+#X connect 14 0 2 0;
+#X connect 15 0 8 1;
+#X connect 16 0 6 0;
+#X connect 17 0 8 0;
+#X connect 18 0 17 0;
+#X restore 397 345 pd heightmap2indexmap;
+#X obj -8 82 bng 15 250 50 0 empty empty empty 0 -6 0 8 -24198 -1 -1
+;
+#X obj 397 326 spigot;
+#X text 373 239 no reflection;
+#X obj 260 187 t a;
+#X obj 189 551 shunt 2;
+#X obj 226 521 shunt 2;
+#X obj 10 262 shunt 2;
+#X text 80 263 freeze time;
+#X obj 63 263 tgl 15 0 empty empty empty 0 -6 0 8 -241291 -1 -1 0 1
+;
+#X obj 132 123 r feedback;
+#X obj 189 589 s feedback;
+#X obj 10 303 t a;
+#X obj -13 5 cnv 15 780 30 empty empty empty 20 12 0 14 -233017 -66577
+0;
+#X obj -15 611 cnv 15 780 30 empty empty empty 20 12 0 14 -200249 -66577
+0;
+#X text -7 619 GridFlow 0.8.0;
+#X text -7 619 GridFlow 0.8.0;
+#X text 0 4 waves.pd;
+#X obj 555 276 bng 15 250 50 0 empty empty empty 0 -6 0 8 -24198 -1
+-1;
+#X obj 573 315 spigot;
+#X obj 620 316 tgl 15 0 empty empty empty 18 8 0 8 -241291 -1 -62784
+0 1;
+#X text 637 315 test camera output;
+#X obj 10 85 t b;
+#X obj 298 491 spigot;
+#X obj 620 334 sel 0 1;
+#X msg 642 353 open window;
+#X obj 573 334 #out;
+#X msg 620 372 close;
+#X obj 266 393 fps detailed \, period 2;
+#X obj 574 226 #in;
+#X obj 344 510 r size;
+#X obj 298 510 #store;
+#X obj 298 529 # rand;
+#X obj 260 372 #out window;
+#X obj 260 334 #clip;
+#X obj 260 78 #convolve (2 2 #) \, op ignore;
+#X obj 303 592 #pack 2;
+#X obj 260 431 #mouse \, ...;
+#N canvas 123 224 450 366 doodle 0;
+#X obj 26 17 inlet wave;
+#X obj 23 258 outlet wave;
+#X obj 171 29 inlet tog;
+#X obj 306 36 inlet pos;
+#X obj 139 9 r metro;
+#X obj 138 57 spigot;
+#X obj 231 202 # +;
+#X obj 137 83 t b b;
+#X msg 219 123 4 2 # 0 0 0 1 1 1 1 0;
+#X obj 224 158 # * 8;
+#X obj 127 334 outlet rgb;
+#X obj 347 78 inlet mode;
+#X obj 347 221 #redim (1);
+#X obj 130 238 #draw_polygon put (0);
+#X obj 24 69 # *>>8;
+#X obj 129 290 #inner (1 3 # 0 1 1);
+#X obj 141 267 # inv+ 256;
+#X obj 364 191 # inv+ 256;
+#X obj 46 107 loadbang;
+#X obj 347 159 # * 256;
+#X obj 48 146 #store (240 320 1 # 256);
+#X connect 0 0 14 0;
+#X connect 2 0 5 1;
+#X connect 3 0 6 1;
+#X connect 4 0 5 0;
+#X connect 5 0 7 0;
+#X connect 6 0 13 2;
+#X connect 7 0 20 0;
+#X connect 7 1 8 0;
+#X connect 8 0 9 0;
+#X connect 9 0 6 0;
+#X connect 11 0 19 0;
+#X connect 12 0 13 1;
+#X connect 13 0 16 0;
+#X connect 13 0 20 1;
+#X connect 14 0 1 0;
+#X connect 15 0 10 0;
+#X connect 16 0 15 0;
+#X connect 17 0 12 0;
+#X connect 18 0 20 0;
+#X connect 19 0 12 0;
+#X connect 20 0 13 0;
+#X connect 20 0 14 1;
+#X restore 130 282 pd doodle;
+#X obj 199 282 # +;
+#X msg 574 207 load g001.jpg;
+#X obj 90 178 route position;
+#X msg 90 197 \$3;
+#X obj 90 216 & 1;
+#X msg 107 66 240 320;
+#X obj 573 296 #camera;
+#X obj 260 118 shunt 3;
+#X obj 304 147 # ** 3;
+#X text 331 127 cubit;
+#X obj 304 166 # >> 10;
+#X obj 578 438 #checkers;
+#X obj 578 418 #for (0 0) (240 320) (1 1);
+#X obj 421 296 t a;
+#X obj 576 398 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X text 0 18 Copyright 2003 \, 2004 \, 2005 \, 2008 Mathieu Bouchard
+;
+#X text 466 79 Also contains several effects not made for Digitale
+;
+#N canvas 0 0 450 379 light_mode 0;
+#X obj 16 20 inlet;
+#X obj 244 25 inlet;
+#X obj 38 104 #greyscale_to_rgb;
+#X obj 38 80 # >> 1;
+#X obj 16 50 shunt 3;
+#X obj 86 80 # put 0;
+#X text 51 205 produce red/cyan from horiz differences;
+#X obj 16 317 # +;
+#X obj 68 150 #dim;
+#X obj 100 150 #export_list;
+#X obj 16 149 t a a;
+#X obj 16 189 t a a;
+#X msg 101 170 \$1 \$2;
+#X obj 16 169 #redim ();
+#X obj 46 222 #convolve (1 2 #) \, op ignore \, fold inv+;
+#X obj 16 279 #convolve (2 1 #) \, op ignore \, fold inv+;
+#X obj 46 241 #outer & (-1 0 0);
+#X obj 16 298 #outer & (-1 -1 0);
+#X text 24 263 produce yellow/blue from vertical differences;
+#X obj 16 354 outlet;
+#X connect 0 0 4 0;
+#X connect 1 0 4 1;
+#X connect 2 0 19 0;
+#X connect 3 0 2 0;
+#X connect 4 0 10 0;
+#X connect 4 1 3 0;
+#X connect 4 2 5 0;
+#X connect 5 0 2 0;
+#X connect 7 0 19 0;
+#X connect 8 0 9 0;
+#X connect 9 0 12 0;
+#X connect 10 0 13 0;
+#X connect 10 1 8 0;
+#X connect 11 0 15 0;
+#X connect 11 1 14 0;
+#X connect 12 0 13 1;
+#X connect 13 0 11 0;
+#X connect 14 0 16 0;
+#X connect 15 0 17 0;
+#X connect 16 0 7 1;
+#X connect 17 0 7 0;
+#X restore 260 226 pd light_mode;
+#X obj 397 364 #store 0;
+#X obj 260 315 # +;
+#X obj 10 66 metro 33.3667;
+#X connect 0 0 93 0;
+#X connect 1 0 5 0;
+#X connect 1 1 7 0;
+#X connect 3 0 108 0;
+#X connect 4 0 87 2;
+#X connect 4 0 6 1;
+#X connect 5 0 12 0;
+#X connect 6 0 11 0;
+#X connect 8 0 82 0;
+#X connect 9 0 56 0;
+#X connect 10 0 61 0;
+#X connect 10 1 87 0;
+#X connect 11 0 60 0;
+#X connect 12 0 9 1;
+#X connect 12 0 42 0;
+#X connect 15 0 105 1;
+#X connect 17 0 95 1;
+#X connect 21 0 42 1;
+#X connect 23 0 25 0;
+#X connect 25 0 8 1;
+#X connect 25 0 4 1;
+#X connect 26 0 40 0;
+#X connect 27 0 94 0;
+#X connect 28 0 27 1;
+#X connect 29 0 27 0;
+#X connect 30 0 53 0;
+#X connect 34 0 54 1;
+#X connect 34 0 55 1;
+#X connect 34 0 72 1;
+#X connect 35 0 72 0;
+#X connect 37 0 95 0;
+#X connect 40 0 41 0;
+#X connect 41 0 101 0;
+#X connect 42 0 84 0;
+#X connect 42 1 95 0;
+#X connect 43 0 85 0;
+#X connect 44 0 85 1;
+#X connect 45 0 51 1;
+#X connect 48 0 107 0;
+#X connect 49 0 106 0;
+#X connect 50 0 71 0;
+#X connect 51 0 49 0;
+#X connect 53 0 51 0;
+#X connect 53 0 105 0;
+#X connect 54 0 11 0;
+#X connect 54 1 6 0;
+#X connect 55 0 54 1;
+#X connect 56 0 10 0;
+#X connect 56 1 61 0;
+#X connect 58 0 56 1;
+#X connect 59 0 12 0;
+#X connect 61 0 54 0;
+#X connect 67 0 94 0;
+#X connect 68 0 75 0;
+#X connect 69 0 68 1;
+#X connect 69 0 73 0;
+#X connect 71 0 13 0;
+#X connect 71 0 9 0;
+#X connect 72 0 80 0;
+#X connect 73 0 76 0;
+#X connect 73 1 74 0;
+#X connect 74 0 75 0;
+#X connect 76 0 75 0;
+#X connect 77 0 2 0;
+#X connect 78 0 101 0;
+#X connect 79 0 80 1;
+#X connect 80 0 81 0;
+#X connect 81 0 6 1;
+#X connect 82 0 77 0;
+#X connect 82 0 86 0;
+#X connect 82 0 90 0;
+#X connect 83 0 8 0;
+#X connect 84 0 37 0;
+#X connect 85 0 6 2;
+#X connect 86 0 4 0;
+#X connect 86 1 4 0;
+#X connect 86 4 55 0;
+#X connect 86 6 87 1;
+#X connect 87 0 10 1;
+#X connect 87 1 88 1;
+#X connect 88 0 83 0;
+#X connect 89 0 78 0;
+#X connect 90 0 91 0;
+#X connect 91 0 92 0;
+#X connect 92 0 87 3;
+#X connect 93 0 1 0;
+#X connect 94 0 68 0;
+#X connect 94 0 101 0;
+#X connect 95 0 53 0;
+#X connect 95 1 30 0;
+#X connect 95 2 96 0;
+#X connect 96 0 98 0;
+#X connect 98 0 53 0;
+#X connect 99 0 101 0;
+#X connect 100 0 99 0;
+#X connect 101 0 106 1;
+#X connect 101 0 107 1;
+#X connect 102 0 100 0;
+#X connect 105 0 48 0;
+#X connect 106 0 107 1;
+#X connect 107 0 88 0;
+#X connect 108 0 71 0;
diff --git a/externals/gridflow/examples/wobble.pd b/externals/gridflow/examples/wobble.pd
new file mode 100644
index 00000000..4d9e352d
--- /dev/null
+++ b/externals/gridflow/examples/wobble.pd
@@ -0,0 +1,56 @@
+#N canvas 735 285 450 338 10;
+#X obj 31 -32 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0
+1;
+#X obj 31 226 #out window;
+#X obj 212 97 #make_cross;
+#X obj 31 15 t b b;
+#X obj 212 -17 # << 8;
+#X obj 212 78 # >> 8;
+#X obj 236 59 t a;
+#X obj 212 59 # +;
+#X obj 212 40 # +;
+#X obj 212 2 # -;
+#X obj 212 21 # >> 3;
+#X obj 212 -36 #store;
+#X obj 31 270 s p0;
+#X obj 252 -36 r p0;
+#X obj 31 107 #store (240 320 3 #);
+#X obj 31 245 #mouse .....;
+#X obj 31 164 # >> 4;
+#X obj 31 145 #convolve (3 3 # 1 2 1 2 3 2);
+#X obj 31 -13 metro 40;
+#X obj 236 40 # *>>8 250;
+#X text 139 196 click and drag in the window to trigger animations
+;
+#X obj 31 188 #fade (16 4 1);
+#X obj 31 207 #clip;
+#X obj 31 126 #draw_polygon + (500 500 500);
+#X text 168 262 Copyright 2007 Mathieu Bouchard;
+#X connect 0 0 18 0;
+#X connect 1 0 15 0;
+#X connect 2 0 23 2;
+#X connect 3 0 14 0;
+#X connect 3 1 11 0;
+#X connect 4 0 9 0;
+#X connect 5 0 2 0;
+#X connect 6 0 7 1;
+#X connect 7 0 6 0;
+#X connect 7 0 5 0;
+#X connect 7 0 9 1;
+#X connect 8 0 7 0;
+#X connect 8 0 19 0;
+#X connect 9 0 10 0;
+#X connect 10 0 8 0;
+#X connect 11 0 4 0;
+#X connect 13 0 11 1;
+#X connect 14 0 23 0;
+#X connect 15 0 12 0;
+#X connect 15 1 12 0;
+#X connect 16 0 14 1;
+#X connect 16 0 21 0;
+#X connect 17 0 16 0;
+#X connect 18 0 3 0;
+#X connect 19 0 8 1;
+#X connect 21 0 22 0;
+#X connect 22 0 1 0;
+#X connect 23 0 17 0;
diff --git a/externals/gridflow/images/README b/externals/gridflow/images/README
new file mode 100644
index 00000000..20ba6aa3
--- /dev/null
+++ b/externals/gridflow/images/README
@@ -0,0 +1,81 @@
+$Id: README 2501 2006-07-24 16:25:29Z matju $
+
+Here's the file to list the authors of the pictures
+
+b001.jpg, r001.jpg:
+ Eyewire Catalogue, 1999 or before. It should be checked
+ whether there still exists a copyright on this, because
+ the original provider has disappeared (bankruptcy??)
+ several years ago.
+
+babbage.jpg :
+ (check provenance)
+Charles Babbage (1791-1871) is widely regarded as the first computer pioneer and
+the great ancestral figure in the history of computing. Babbage excelled in a variety of
+scientific and philosophical subjects though his present-day reputation rests largely
+on the invention and design of his vast mechanical calculating engines. His
+Analytical Engine conceived in 1834 is one of the startling intellectual feats of the
+nineteenth century. The design of this machine possesses all the essential logical
+features of the modern general purpose computer.
+from -> http://www.sciencemuseum.org.uk/on-line/babbage/index.asp
+
+etch_a_sketch.jpg :
+ by Stephanie Brodeur and Darsha Hewitt, 2006
+
+g001.jpg:
+ by Alexandre Castonguay, 1999 (?).
+
+bluemarble.jpg:
+ NASA (?)
+
+lada.jpg:
+ hungarian newspaper ad.
+
+lena.jpg:
+ Lena Sjööblom Soderberg, centerfold of Playboy 1972.11.
+ Researchers in infographics have extensively used that
+ picture without necessarily asking for copyright, and
+ apparently Playboy doesn't mind.
+
+lite_brite_code.jpg :
+ by Stephanie Brodeur and Darsha Hewitt, 2006
+
+lite_brite_1.jpg :
+ by Stephanie Brodeur and Darsha Hewitt, 2006
+
+litmus.jpg :
+ by Alexandre Castonguay, 2006.
+
+lucida-typewriter-12.grid.gz:
+ a grid(256,13,7) containing the Lucida Typewriter 12
+ medium font.
+
+opensource.png:
+ modification of a World War Two poster. Both authors
+ (original's and spoof's) are unknown to me. Should check.
+
+rose.jpg:
+ unknown origin.
+
+ruby0216.jpg:
+ photo from a conference about the Ruby programming language,
+ held somewhere in Japan in 2003 or so. (?)
+
+scissors.jpg, sewing.jpg, working.jpg :
+ original source (?)
+ by Stephanie Brodeur and Darsha Hewitt, 2006
+
+teapot.png:
+ Researchers in infographics have also extensively used
+ that picture (actually the wireframe model). This is
+ (afaik) the original model, produced in the 1970's (?)
+ by one such researcher, and then was rendered in the
+ 1990's using the Povray raytracer, and then bundled as
+ teapot.ppm in Tcl/Tk, and finally in 2001 I grabbed
+ that picture
+
+test.mpeg:
+ unknown origin. Too small to be copyrightable.
+
+tux.tga.gz:
+ unknown origin.
diff --git a/externals/gridflow/images/b001.jpg b/externals/gridflow/images/b001.jpg
new file mode 100644
index 00000000..444bf24e
--- /dev/null
+++ b/externals/gridflow/images/b001.jpg
Binary files differ
diff --git a/externals/gridflow/images/babbage.jpg b/externals/gridflow/images/babbage.jpg
new file mode 100644
index 00000000..1f8eef37
--- /dev/null
+++ b/externals/gridflow/images/babbage.jpg
Binary files differ
diff --git a/externals/gridflow/images/bluemarble.jpg b/externals/gridflow/images/bluemarble.jpg
new file mode 100644
index 00000000..ea182f5f
--- /dev/null
+++ b/externals/gridflow/images/bluemarble.jpg
Binary files differ
diff --git a/externals/gridflow/images/compose-8859-1.pdd b/externals/gridflow/images/compose-8859-1.pdd
new file mode 100644
index 00000000..c5eee9e6
--- /dev/null
+++ b/externals/gridflow/images/compose-8859-1.pdd
@@ -0,0 +1,28 @@
+192 65 96;
+193 65 180;
+194 65 94;
+195 65 126;
+196 65 168;
+197 65 176;
+199 67 184;
+200 69 96;
+201 69 180;
+202 69 94;
+203 69 168;
+204 73 96;
+205 73 180;
+206 73 94;
+207 73 168;
+208 70 45;
+209 78 126;
+210 79 96;
+211 79 180;
+212 79 94;
+213 79 126;
+214 79 168;
+216 79 47;
+217 85 96;
+218 85 180;
+219 85 94;
+220 85 168;
+221 89 180;
diff --git a/externals/gridflow/images/david.jpg b/externals/gridflow/images/david.jpg
new file mode 100644
index 00000000..453da2f2
--- /dev/null
+++ b/externals/gridflow/images/david.jpg
Binary files differ
diff --git a/externals/gridflow/images/etch_a_sketch.jpg b/externals/gridflow/images/etch_a_sketch.jpg
new file mode 100644
index 00000000..f8eed72a
--- /dev/null
+++ b/externals/gridflow/images/etch_a_sketch.jpg
Binary files differ
diff --git a/externals/gridflow/images/g001.jpg b/externals/gridflow/images/g001.jpg
new file mode 100644
index 00000000..ff2b5019
--- /dev/null
+++ b/externals/gridflow/images/g001.jpg
Binary files differ
diff --git a/externals/gridflow/images/hello.hpgl b/externals/gridflow/images/hello.hpgl
new file mode 100644
index 00000000..53bae073
--- /dev/null
+++ b/externals/gridflow/images/hello.hpgl
@@ -0,0 +1,3 @@
+PU0,300;LBallô l'monde
+(ça va chez vous?)
+PU0,0;LBéêè çÇ ÉÊÈ
diff --git a/externals/gridflow/images/hershey-latin-1/168.hpgl b/externals/gridflow/images/hershey-latin-1/168.hpgl
new file mode 100644
index 00000000..0e8a35cd
--- /dev/null
+++ b/externals/gridflow/images/hershey-latin-1/168.hpgl
@@ -0,0 +1,4 @@
+BP;IN;PS10668;IP0,0,8128,8128;SC0,10000,0,10000;WU1;SP1;TR0;LT;LA1,4,2,4;LA3,10;PW0.1217;
+PA85,345;PD;PA73,333,85,321,98,333,85,345;
+PU205,345;PD;PA193,333,205,321,218,333,205,345;
+PU;PM2;EP;SP0;
diff --git a/externals/gridflow/images/hershey-latin-1/180.hpgl b/externals/gridflow/images/hershey-latin-1/180.hpgl
new file mode 100644
index 00000000..ae220848
--- /dev/null
+++ b/externals/gridflow/images/hershey-latin-1/180.hpgl
@@ -0,0 +1,2 @@
+BP;IN;PS10668;IP0,0,8128,8128;SC0,10000,0,10000;WU1;SP1;TR0;LT;LA1,4,2,4;LA3,10;PW0.1217;
+PU85,284;PD206,345;PU;PM2;EP;SP0;
diff --git a/externals/gridflow/images/hershey-latin-1/94.hpgl b/externals/gridflow/images/hershey-latin-1/94.hpgl
new file mode 100644
index 00000000..1ff0607d
--- /dev/null
+++ b/externals/gridflow/images/hershey-latin-1/94.hpgl
@@ -0,0 +1,2 @@
+BP;IN;PS10668;IP0,0,8128,8128;SC0,10000,0,10000;WU1;SP1;TR0;LT;LA1,4,2,4;LA3,10;PW0.1217;
+PU85,284;PD145,345,206,284;PU;PM2;EP;SP0;
diff --git a/externals/gridflow/images/hershey-latin-1/96.hpgl b/externals/gridflow/images/hershey-latin-1/96.hpgl
new file mode 100644
index 00000000..6dbeb4b1
--- /dev/null
+++ b/externals/gridflow/images/hershey-latin-1/96.hpgl
@@ -0,0 +1,2 @@
+BP;IN;PS10668;IP0,0,8128,8128;SC0,10000,0,10000;WU1;SP1;TR0;LT;LA1,4,2,4;LA3,10;PW0.1217;
+PU85,345;PD206,284;PU;PM2;EP;SP0;
diff --git a/externals/gridflow/images/lada.jpg b/externals/gridflow/images/lada.jpg
new file mode 100644
index 00000000..d53a5ed2
--- /dev/null
+++ b/externals/gridflow/images/lada.jpg
Binary files differ
diff --git a/externals/gridflow/images/lena.jpg b/externals/gridflow/images/lena.jpg
new file mode 100644
index 00000000..11c051f1
--- /dev/null
+++ b/externals/gridflow/images/lena.jpg
Binary files differ
diff --git a/externals/gridflow/images/lite_brite_1.jpg b/externals/gridflow/images/lite_brite_1.jpg
new file mode 100644
index 00000000..a1539779
--- /dev/null
+++ b/externals/gridflow/images/lite_brite_1.jpg
Binary files differ
diff --git a/externals/gridflow/images/lite_brite_code.jpg b/externals/gridflow/images/lite_brite_code.jpg
new file mode 100644
index 00000000..56676033
--- /dev/null
+++ b/externals/gridflow/images/lite_brite_code.jpg
Binary files differ
diff --git a/externals/gridflow/images/litmus.jpg b/externals/gridflow/images/litmus.jpg
new file mode 100644
index 00000000..f360e76c
--- /dev/null
+++ b/externals/gridflow/images/litmus.jpg
Binary files differ
diff --git a/externals/gridflow/images/lots_of_text.hpgl b/externals/gridflow/images/lots_of_text.hpgl
new file mode 100644
index 00000000..a2e80bc1
--- /dev/null
+++ b/externals/gridflow/images/lots_of_text.hpgl
@@ -0,0 +1,2 @@
+PU0,675;LB«Je vais parler d'économie, de finance, je ne sais pas trop la différence. Je vais en parler comme un enfant, mais pas l'enfant de la fable du roi nu, vous savez: le roi se présenta nu devant ses courtisans, tous le félicitèrent de son bel habit, seul l'enfant s'écria le roi est nu. Ce n'est qu'une fable, l'innocence n'a jamais rendu personne lucide.» -- Pierre Foglia, 2008.10.18
+
diff --git a/externals/gridflow/images/lucida-typewriter-12.grid b/externals/gridflow/images/lucida-typewriter-12.grid
new file mode 100644
index 00000000..694ef409
--- /dev/null
+++ b/externals/gridflow/images/lucida-typewriter-12.grid
Binary files differ
diff --git a/externals/gridflow/images/opensource.png b/externals/gridflow/images/opensource.png
new file mode 100644
index 00000000..aca9d1cf
--- /dev/null
+++ b/externals/gridflow/images/opensource.png
Binary files differ
diff --git a/externals/gridflow/images/plotter_parser_old.pd.hpgl b/externals/gridflow/images/plotter_parser_old.pd.hpgl
new file mode 100644
index 00000000..25436c77
--- /dev/null
+++ b/externals/gridflow/images/plotter_parser_old.pd.hpgl
@@ -0,0 +1,341 @@
+IN;SC;PU;PU;SP1;LT;VS10
+IN;SC;PU;PU;SP1;LT;VS10
+PW1.001;PU-593,6242;PD-223,6242;PD-223,6072;PD-593,6072;PD-593,6242;
+PW1.001;PU-593,6082;PD-523,6082;PD-523,6072;PD-593,6072;PD-593,6082;
+DI100,0;SI0.12012,0.12012;PU-583,6149;LBinlet;
+PW1.001;PU-593,2298;PD-153,2298;PD-153,2128;PD-593,2128;PD-593,2298;
+PW1.001;PU-593,2298;PD-523,2298;PD-523,2288;PD-593,2288;PD-593,2298;
+DI100,0;SI0.12012,0.12012;PU-583,2206;LBoutlet;
+PW1.001;PU-593,6052;PD2859,6052;PD2859,5881;PD-593,5881;PD-593,6052;
+PW1.001;PU-593,5891;PD-523,5891;PD-523,5881;PD-593,5881;PD-593,5891;
+PW1.001;PU-173,5891;PD-103,5891;PD-103,5881;PD-173,5881;PD-173,5891;
+PW1.001;PU247,5891;PD317,5891;PD317,5881;PD247,5881;PD247,5891;
+PW1.001;PU667,5891;PD737,5891;PD737,5881;PD667,5881;PD667,5891;
+PW1.001;PU1098,5891;PD1168,5891;PD1168,5881;PD1098,5881;PD1098,5891;
+PW1.001;PU1518,5891;PD1588,5891;PD1588,5881;PD1518,5881;PD1518,5891;
+PW1.001;PU1938,5891;PD2008,5891;PD2008,5881;PD1938,5881;PD1938,5891;
+PW1.001;PU2359,5891;PD2429,5891;PD2429,5881;PD2359,5881;PD2359,5891;
+PW1.001;PU2789,5891;PD2859,5891;PD2859,5881;PD2789,5881;PD2789,5891;
+PW1.001;PU-593,6052;PD-523,6052;PD-523,6042;PD-593,6042;PD-593,6052;
+DI100,0;SI0.12012,0.12012;PU-583,5959;LBroute pu pd pa sp ip other print print_from_ascii;
+PW1.001;PU2879,5861;PD4861,5861;PD4861,5691;PD2879,5691;PD2879,5861;
+PW1.001;PU2879,5861;PD2949,5861;PD2949,5851;PD2879,5851;PD2879,5861;
+DI100,0;SI0.12012,0.12012;PU2889,5769;LBgf.error unknown method '%s';
+PW1.001;PU2879,6052;PD3180,6052;PD3180,5881;PD2879,5881;PD2879,6052;
+PW1.001;PU2879,5891;PD2949,5891;PD2949,5881;PD2879,5881;PD2879,5891;
+PW1.001;PU2879,6052;PD2949,6052;PD2949,6042;PD2879,6042;PD2879,6052;
+PW1.001;PU3110,6052;PD3180,6052;PD3180,6042;PD3110,6042;PD3110,6052;
+DI100,0;SI0.12012,0.12012;PU2889,5959;LBlist;
+PW1.001;PU-173,3469;PD727,3469;PD687,3429;PD687,3339;PD727,3299;PD-173,3299;PD-173,3469;
+PW1.001;PU-173,3309;PD-103,3309;PD-103,3299;PD-173,3299;PD-173,3309;
+PW1.001;PU-173,3469;PD-103,3469;PD-103,3459;PD-173,3459;PD-173,3469;
+DI100,0;SI0.12012,0.12012;PU-163,3377;LBlist PD, end;
+PW1.001;PU-593,3279;PD307,3279;PD267,3239;PD267,3149;PD307,3109;PD-593,3109;PD-593,3279;
+PW1.001;PU-593,3119;PD-523,3119;PD-523,3109;PD-593,3109;PD-593,3119;
+PW1.001;PU-593,3279;PD-523,3279;PD-523,3269;PD-593,3269;PD-593,3279;
+DI100,0;SI0.12012,0.12012;PU-583,3186;LBlist PU, end;
+PW1.001;PU-593,2698;PD-183,2698;PD-223,2658;PD-223,2568;PD-183,2528;PD-593,2528;PD-593,2698;
+PW1.001;PU-593,2538;PD-523,2538;PD-523,2528;PD-593,2528;PD-593,2538;
+PW1.001;PU-593,2698;PD-523,2698;PD-523,2688;PD-593,2688;PD-593,2698;
+DI100,0;SI0.12012,0.12012;PU-583,2606;LB59 10;
+DI100,0;SI0.12012,0.12012;PU-143,2606;LBcomma+newline;
+PW1.001;PU247,3659;PD2199,3659;PD2159,3619;PD2159,3529;PD2199,3489;PD247,3489;PD247,3659;
+PW1.001;PU247,3499;PD317,3499;PD317,3489;PD247,3489;PD247,3499;
+PW1.001;PU247,3659;PD317,3659;PD317,3649;PD247,3649;PD247,3659;
+DI100,0;SI0.12012,0.12012;PU257,3567;LBlist PA, $1, comma, $2, end;
+PW1.001;PU827,2338;PD1338,2338;PD1338,2168;PD827,2168;PD827,2338;
+PW1.001;PU827,2178;PD897,2178;PD897,2168;PD827,2168;PD827,2178;
+PW1.001;PU827,2338;PD897,2338;PD897,2328;PD827,2328;PD827,2338;
+PW1.001;PU1268,2338;PD1338,2338;PD1338,2328;PD1268,2328;PD1268,2338;
+DI100,0;SI0.12012,0.12012;PU837,2246;LB#import;
+PW1.001;PU827,2528;PD1658,2528;PD1618,2488;PD1618,2398;PD1658,2358;PD827,2358;PD827,2528;
+PW1.001;PU827,2368;PD897,2368;PD897,2358;PD827,2358;PD827,2368;
+PW1.001;PU827,2528;PD897,2528;PD897,2518;PD827,2518;PD827,2528;
+DI100,0;SI0.12012,0.12012;PU837,2436;LBto_ascii $1;
+PW1.001;PU827,2148;PD1478,2148;PD1478,1978;PD827,1978;PD827,2148;
+PW1.001;PU827,1988;PD897,1988;PD897,1978;PD827,1978;PD827,1988;
+PW1.001;PU827,2148;PD897,2148;PD897,2138;PD827,2138;PD827,2148;
+DI100,0;SI0.12012,0.12012;PU837,2055;LB#to_float;
+PW1.001;PU-93,2898;PD177,2898;PD137,2858;PD137,2768;PD177,2728;PD-93,2728;PD-93,2898;
+PW1.001;PU-93,2738;PD-23,2738;PD-23,2728;PD-93,2728;PD-93,2738;
+PW1.001;PU-93,2898;PD-23,2898;PD-23,2888;PD-93,2888;PD-93,2898;
+DI100,0;SI0.12012,0.12012;PU-83,2806;LB44 ;
+PW1.001;PU667,3859;PD1848,3859;PD1808,3819;PD1808,3729;PD1848,3689;PD667,3689;PD667,3859;
+PW1.001;PU667,3699;PD737,3699;PD737,3689;PD667,3689;PD667,3699;
+PW1.001;PU667,3859;PD737,3859;PD737,3849;PD667,3849;PD667,3859;
+DI100,0;SI0.12012,0.12012;PU677,3767;LBlist SP, $1, end;
+PW1.001;PU1037,4050;PD4741,4050;PD4701,4010;PD4701,3919;PD4741,3879;PD1037,3879;PD1037,4050;
+PW1.001;PU1037,3889;PD1108,3889;PD1108,3879;PD1037,3879;PD1037,3889;
+PW1.001;PU1037,4050;PD1108,4050;PD1108,4040;PD1037,4040;PD1037,4050;
+DI100,0;SI0.12012,0.12012;PU1048,3957;LBlist IP, $1, comma, $2, comma, $3... VARARGS... OOPS;
+PW1.001;PU1628,4800;PD2179,4800;PD2139,4760;PD2139,4670;PD2179,4630;PD1628,4630;PD1628,4800;
+PW1.001;PU1628,4640;PD1698,4640;PD1698,4630;PD1628,4630;PD1628,4640;
+PW1.001;PU1628,4800;PD1698,4800;PD1698,4790;PD1628,4790;PD1628,4800;
+DI100,0;SI0.12012,0.12012;PU1638,4708;LBlist IP;
+PW1.001;PU1098,4800;PD1608,4800;PD1608,4630;PD1098,4630;PD1098,4800;
+PW1.001;PU1098,4640;PD1168,4640;PD1168,4630;PD1098,4630;PD1098,4640;
+PW1.001;PU1318,4640;PD1388,4640;PD1388,4630;PD1318,4630;PD1318,4640;
+PW1.001;PU1538,4640;PD1608,4640;PD1608,4630;PD1538,4630;PD1538,4640;
+PW1.001;PU1098,4800;PD1168,4800;PD1168,4790;PD1098,4790;PD1098,4800;
+DI100,0;SI0.12012,0.12012;PU1108,4708;LBt b a b;
+PW1.001;PU2789,3409;PD3300,3409;PD3300,3239;PD2789,3239;PD2789,3409;
+PW1.001;PU2789,3249;PD2859,3249;PD2859,3239;PD2789,3239;PD2789,3249;
+PW1.001;PU2789,3409;PD2859,3409;PD2859,3399;PD2789,3399;PD2789,3409;
+DI100,0;SI0.12012,0.12012;PU2799,3317;LBforeach;
+PW1.001;PU2789,3649;PD3160,3649;PD3160,3479;PD2789,3479;PD2789,3649;
+PW1.001;PU2789,3489;PD2859,3489;PD2859,3479;PD2789,3479;PD2789,3489;
+PW1.001;PU3090,3489;PD3160,3489;PD3160,3479;PD3090,3479;PD3090,3489;
+PW1.001;PU2789,3649;PD2859,3649;PD2859,3639;PD2789,3639;PD2789,3649;
+DI100,0;SI0.12012,0.12012;PU2799,3557;LBt a b;
+PW1.001;PU3180,3649;PD3450,3649;PD3410,3609;PD3410,3519;PD3450,3479;PD3180,3479;PD3180,3649;
+PW1.001;PU3180,3489;PD3250,3489;PD3250,3479;PD3180,3479;PD3180,3489;
+PW1.001;PU3180,3649;PD3250,3649;PD3250,3639;PD3180,3639;PD3180,3649;
+DI100,0;SI0.12012,0.12012;PU3190,3557;LB0 ;
+PW1.001;PU1098,4610;PD1368,4610;PD1328,4570;PD1328,4480;PD1368,4440;PD1098,4440;PD1098,4610;
+PW1.001;PU1098,4450;PD1168,4450;PD1168,4440;PD1098,4440;PD1098,4450;
+PW1.001;PU1098,4610;PD1168,4610;PD1168,4600;PD1098,4600;PD1098,4610;
+DI100,0;SI0.12012,0.12012;PU1108,4518;LBend;
+PW1.001;PU3310,3219;PD3750,3219;PD3750,3049;PD3310,3049;PD3310,3219;
+PW1.001;PU3310,3059;PD3380,3059;PD3380,3049;PD3310,3049;PD3310,3059;
+PW1.001;PU3310,3219;PD3380,3219;PD3380,3209;PD3310,3209;PD3310,3219;
+PW1.001;PU3680,3219;PD3750,3219;PD3750,3209;PD3680,3209;PD3680,3219;
+DI100,0;SI0.12012,0.12012;PU3320,3126;LBspigot;
+PW1.001;PU3560,2969;PD3830,2969;PD3790,2928;PD3790,2838;PD3830,2798;PD3560,2798;PD3560,2969;
+PW1.001;PU3560,2808;PD3630,2808;PD3630,2798;PD3560,2798;PD3560,2808;
+PW1.001;PU3560,2969;PD3630,2969;PD3630,2959;PD3560,2959;PD3560,2969;
+DI100,0;SI0.12012,0.12012;PU3570,2876;LB1 ;
+PW1.001;PU2779,3219;PD3290,3219;PD3290,3049;PD2779,3049;PD2779,3219;
+PW1.001;PU2779,3059;PD2849,3059;PD2849,3049;PD2779,3049;PD2779,3059;
+PW1.001;PU2999,3059;PD3069,3059;PD3069,3049;PD2999,3049;PD2999,3059;
+PW1.001;PU3220,3059;PD3290,3059;PD3290,3049;PD3220,3049;PD3220,3059;
+PW1.001;PU2779,3219;PD2849,3219;PD2849,3209;PD2779,3209;PD2779,3219;
+DI100,0;SI0.12012,0.12012;PU2789,3126;LBt b a b;
+PW1.001;PU3310,2778;PD3720,2778;PD3680,2738;PD3680,2648;PD3720,2608;PD3310,2608;PD3310,2778;
+PW1.001;PU3310,2618;PD3380,2618;PD3380,2608;PD3310,2608;PD3310,2618;
+PW1.001;PU3310,2778;PD3380,2778;PD3380,2768;PD3310,2768;PD3310,2778;
+DI100,0;SI0.12012,0.12012;PU3320,2686;LBcomma;
+PW1.001;PU2999,2778;PD3230,2778;PD3230,2608;PD2999,2608;PD2999,2778;
+PW1.001;PU2999,2618;PD3069,2618;PD3069,2608;PD2999,2608;PD2999,2618;
+PW1.001;PU2999,2778;PD3069,2778;PD3069,2768;PD2999,2768;PD2999,2778;
+DI100,0;SI0.12012,0.12012;PU3009,2686;LBt a;
+PW1.001;PU1518,5811;PD2379,5811;PD2379,5641;PD1518,5641;PD1518,5811;
+PW1.001;PU1518,5651;PD1588,5651;PD1588,5641;PD1518,5641;PD1518,5651;
+PW1.001;PU1908,5651;PD1978,5651;PD1978,5641;PD1908,5641;PD1908,5651;
+PW1.001;PU2309,5651;PD2379,5651;PD2379,5641;PD2309,5641;PD2309,5651;
+PW1.001;PU1518,5811;PD1588,5811;PD1588,5801;PD1518,5801;PD1518,5811;
+PW1.001;PU2309,5811;PD2379,5811;PD2379,5801;PD2309,5801;PD2309,5811;
+DI100,0;SI0.12012,0.12012;PU1528,5719;LBlist split 1;
+PW1.001;PU1738,5431;PD2038,5431;PD2038,5261;PD1738,5261;PD1738,5431;
+PW1.001;PU1738,5271;PD1808,5271;PD1808,5261;PD1738,5261;PD1738,5271;
+PW1.001;PU1738,5431;PD1808,5431;PD1808,5421;PD1738,5421;PD1738,5431;
+PW1.001;PU1968,5431;PD2038,5431;PD2038,5421;PD1968,5421;PD1968,5431;
+DI100,0;SI0.12012,0.12012;PU1748,5339;LBlist;
+PW1.001;PU2559,5451;PD3070,5451;PD3070,5281;PD2559,5281;PD2559,5451;
+PW1.001;PU2559,5291;PD2629,5291;PD2629,5281;PD2559,5281;PD2559,5291;
+PW1.001;PU2559,5451;PD2629,5451;PD2629,5441;PD2559,5441;PD2559,5451;
+PW1.001;PU2999,5451;PD3069,5451;PD3069,5441;PD2999,5441;PD2999,5451;
+DI100,0;SI0.12012,0.12012;PU2569,5359;LB#import;
+PW1.001;PU2559,5261;PD3070,5261;PD3070,5091;PD2559,5091;PD2559,5261;
+PW1.001;PU2559,5101;PD2629,5101;PD2629,5091;PD2559,5091;PD2559,5101;
+PW1.001;PU2559,5261;PD2629,5261;PD2629,5251;PD2559,5251;PD2559,5261;
+PW1.001;PU2999,5261;PD3069,5261;PD3069,5251;PD2999,5251;PD2999,5261;
+DI100,0;SI0.12012,0.12012;PU2569,5168;LB# & -33;
+DI100,0;SI0.12012,0.12012;PU3120,5178;LBturns to uppercase if content is only letters;
+PW1.001;PU2559,5071;PD3560,5071;PD3560,4900;PD2559,4900;PD2559,5071;
+PW1.001;PU2559,4910;PD2629,4910;PD2629,4900;PD2559,4900;PD2559,4910;
+PW1.001;PU2559,5071;PD2629,5071;PD2629,5061;PD2559,5061;PD2559,5071;
+DI100,0;SI0.12012,0.12012;PU2569,4978;LB#export_symbol;
+PW1.001;PU3980,3409;PD4491,3409;PD4491,3239;PD3980,3239;PD3980,3409;
+PW1.001;PU3980,3249;PD4050,3249;PD4050,3239;PD3980,3239;PD3980,3249;
+PW1.001;PU3980,3409;PD4050,3409;PD4050,3399;PD3980,3399;PD3980,3409;
+DI100,0;SI0.12012,0.12012;PU3990,3317;LBforeach;
+PW1.001;PU3980,3649;PD4351,3649;PD4351,3479;PD3980,3479;PD3980,3649;
+PW1.001;PU3980,3489;PD4050,3489;PD4050,3479;PD3980,3479;PD3980,3489;
+PW1.001;PU4281,3489;PD4351,3489;PD4351,3479;PD4281,3479;PD4281,3489;
+PW1.001;PU3980,3649;PD4050,3649;PD4050,3639;PD3980,3639;PD3980,3649;
+DI100,0;SI0.12012,0.12012;PU3990,3557;LBt a b;
+PW1.001;PU4371,3649;PD4641,3649;PD4601,3609;PD4601,3519;PD4641,3479;PD4371,3479;PD4371,3649;
+PW1.001;PU4371,3489;PD4441,3489;PD4441,3479;PD4371,3479;PD4371,3489;
+PW1.001;PU4371,3649;PD4441,3649;PD4441,3639;PD4371,3639;PD4371,3649;
+DI100,0;SI0.12012,0.12012;PU4381,3557;LB0 ;
+PW1.001;PU4501,3219;PD4941,3219;PD4941,3049;PD4501,3049;PD4501,3219;
+PW1.001;PU4501,3059;PD4571,3059;PD4571,3049;PD4501,3049;PD4501,3059;
+PW1.001;PU4501,3219;PD4571,3219;PD4571,3209;PD4501,3209;PD4501,3219;
+PW1.001;PU4871,3219;PD4941,3219;PD4941,3209;PD4871,3209;PD4871,3219;
+DI100,0;SI0.12012,0.12012;PU4511,3126;LBspigot;
+PW1.001;PU4751,2969;PD5021,2969;PD4981,2928;PD4981,2838;PD5021,2798;PD4751,2798;PD4751,2969;
+PW1.001;PU4751,2808;PD4821,2808;PD4821,2798;PD4751,2798;PD4751,2808;
+PW1.001;PU4751,2969;PD4821,2969;PD4821,2959;PD4751,2959;PD4751,2969;
+DI100,0;SI0.12012,0.12012;PU4761,2876;LB1 ;
+PW1.001;PU3970,3219;PD4481,3219;PD4481,3049;PD3970,3049;PD3970,3219;
+PW1.001;PU3970,3059;PD4040,3059;PD4040,3049;PD3970,3049;PD3970,3059;
+PW1.001;PU4191,3059;PD4261,3059;PD4261,3049;PD4191,3049;PD4191,3059;
+PW1.001;PU4411,3059;PD4481,3059;PD4481,3049;PD4411,3049;PD4411,3059;
+PW1.001;PU3970,3219;PD4040,3219;PD4040,3209;PD3970,3209;PD3970,3219;
+DI100,0;SI0.12012,0.12012;PU3980,3126;LBt b a b;
+PW1.001;PU4191,2778;PD4421,2778;PD4421,2608;PD4191,2608;PD4191,2778;
+PW1.001;PU4191,2618;PD4261,2618;PD4261,2608;PD4191,2608;PD4191,2618;
+PW1.001;PU4191,2778;PD4261,2778;PD4261,2768;PD4191,2768;PD4191,2778;
+DI100,0;SI0.12012,0.12012;PU4201,2686;LBt a;
+PW1.001;PU4501,2778;PD4911,2778;PD4871,2738;PD4871,2648;PD4911,2608;PD4501,2608;PD4501,2778;
+PW1.001;PU4501,2618;PD4571,2618;PD4571,2608;PD4501,2608;PD4501,2618;
+PW1.001;PU4501,2778;PD4571,2778;PD4571,2768;PD4501,2768;PD4501,2778;
+DI100,0;SI0.12012,0.12012;PU4511,2686;LBspace;
+PW1.001;PU347,2898;PD617,2898;PD577,2858;PD577,2768;PD617,2728;PD347,2728;PD347,2898;
+PW1.001;PU347,2738;PD417,2738;PD417,2728;PD347,2728;PD347,2738;
+PW1.001;PU347,2898;PD417,2898;PD417,2888;PD347,2888;PD347,2898;
+DI100,0;SI0.12012,0.12012;PU357,2806;LB32 ;
+PW1.001;PU2499,4810;PD2799,4810;PD2799,4640;PD2499,4640;PD2499,4810;
+PW1.001;PU2499,4650;PD2569,4650;PD2569,4640;PD2499,4640;PD2499,4650;
+PW1.001;PU2499,4810;PD2569,4810;PD2569,4800;PD2499,4800;PD2499,4810;
+PW1.001;PU2729,4810;PD2799,4810;PD2799,4800;PD2729,4800;PD2729,4810;
+DI100,0;SI0.12012,0.12012;PU2509,4718;LBlist;
+PW1.001;PU3029,4620;PD3580,4620;PD3540,4580;PD3540,4490;PD3580,4450;PD3029,4450;PD3029,4620;
+PW1.001;PU3029,4460;PD3100,4460;PD3100,4450;PD3029,4450;PD3029,4460;
+PW1.001;PU3029,4620;PD3100,4620;PD3100,4610;PD3029,4610;PD3029,4620;
+DI100,0;SI0.12012,0.12012;PU3039,4528;LBlist LB;
+PW1.001;PU1518,5621;PD2028,5621;PD2028,5451;PD1518,5451;PD1518,5621;
+PW1.001;PU1518,5461;PD1588,5461;PD1588,5451;PD1518,5451;PD1518,5461;
+PW1.001;PU1738,5461;PD1808,5461;PD1808,5451;PD1738,5451;PD1738,5461;
+PW1.001;PU1958,5461;PD2028,5461;PD2028,5451;PD1958,5451;PD1958,5461;
+PW1.001;PU1518,5621;PD1588,5621;PD1588,5611;PD1518,5611;PD1518,5621;
+DI100,0;SI0.12012,0.12012;PU1528,5529;LBt b b s;
+PW1.001;PU1518,5211;PD1788,5211;PD1748,5171;PD1748,5081;PD1788,5041;PD1518,5041;PD1518,5211;
+PW1.001;PU1518,5051;PD1588,5051;PD1588,5041;PD1518,5041;PD1518,5051;
+PW1.001;PU1518,5211;PD1588,5211;PD1588,5201;PD1518,5201;PD1518,5211;
+DI100,0;SI0.12012,0.12012;PU1528,5118;LBend;
+PW1.001;PU2499,4620;PD3009,4620;PD3009,4450;PD2499,4450;PD2499,4620;
+PW1.001;PU2499,4460;PD2569,4460;PD2569,4450;PD2499,4450;PD2499,4460;
+PW1.001;PU2719,4460;PD2789,4460;PD2789,4450;PD2719,4450;PD2719,4460;
+PW1.001;PU2939,4460;PD3009,4460;PD3009,4450;PD2939,4450;PD2939,4460;
+PW1.001;PU2499,4620;PD2569,4620;PD2569,4610;PD2499,4610;PD2499,4620;
+DI100,0;SI0.12012,0.12012;PU2509,4528;LBt b l b;
+PW1.001;PU-593,3089;PD1318,3089;PD1318,2918;PD-593,2918;PD-593,3089;
+PW1.001;PU-593,2928;PD-523,2928;PD-523,2918;PD-593,2918;PD-593,2928;
+PW1.001;PU-133,2928;PD-63,2928;PD-63,2918;PD-133,2918;PD-133,2928;
+PW1.001;PU327,2928;PD397,2928;PD397,2918;PD327,2918;PD327,2928;
+PW1.001;PU787,2928;PD857,2928;PD857,2918;PD787,2918;PD787,2928;
+PW1.001;PU1248,2928;PD1318,2928;PD1318,2918;PD1248,2918;PD1248,2928;
+PW1.001;PU-593,3089;PD-523,3089;PD-523,3079;PD-593,3079;PD-593,3089;
+DI100,0;SI0.12012,0.12012;PU-583,2996;LBroute end comma space break;
+PW1.001;PU787,2878;PD1058,2878;PD1017,2838;PD1017,2748;PD1058,2708;PD787,2708;PD787,2878;
+PW1.001;PU787,2718;PD857,2718;PD857,2708;PD787,2708;PD787,2718;
+PW1.001;PU787,2878;PD857,2878;PD857,2868;PD787,2868;PD787,2878;
+DI100,0;SI0.12012,0.12012;PU797,2786;LB3 ;
+PW1.001;PU2499,4420;PD3260,4420;PD3220,4380;PD3220,4290;PD3260,4250;PD2499,4250;PD2499,4420;
+PW1.001;PU2499,4260;PD2569,4260;PD2569,4250;PD2499,4250;PD2499,4260;
+PW1.001;PU2499,4420;PD2569,4420;PD2569,4410;PD2499,4410;PD2499,4420;
+DI100,0;SI0.12012,0.12012;PU2509,4328;LBbreak, end;
+PW1.001;PU3920,5101;PD4431,5101;PD4431,4930;PD3920,4930;PD3920,5101;
+PW1.001;PU3920,4940;PD3990,4940;PD3990,4930;PD3920,4930;PD3920,4940;
+PW1.001;PU4141,4940;PD4211,4940;PD4211,4930;PD4141,4930;PD4141,4940;
+PW1.001;PU4361,4940;PD4431,4940;PD4431,4930;PD4361,4930;PD4361,4940;
+PW1.001;PU3920,5101;PD3990,5101;PD3990,5091;PD3920,5091;PD3920,5101;
+DI100,0;SI0.12012,0.12012;PU3930,5008;LBt b l b;
+PW1.001;PU4361,4910;PD4911,4910;PD4871,4870;PD4871,4780;PD4911,4740;PD4361,4740;PD4361,4910;
+PW1.001;PU4361,4750;PD4431,4750;PD4431,4740;PD4361,4740;PD4361,4750;
+PW1.001;PU4361,4910;PD4431,4910;PD4431,4900;PD4361,4900;PD4361,4910;
+DI100,0;SI0.12012,0.12012;PU4371,4818;LBlist LB;
+PW1.001;PU4141,4700;PD5142,4700;PD5142,4530;PD4141,4530;PD4141,4700;
+PW1.001;PU4141,4540;PD4211,4540;PD4211,4530;PD4141,4530;PD4141,4540;
+PW1.001;PU4141,4700;PD4211,4700;PD4211,4690;PD4141,4690;PD4141,4700;
+DI100,0;SI0.12012,0.12012;PU4151,4608;LB#export_symbol;
+PW1.001;PU3920,4280;PD4151,4280;PD4151,4110;PD3920,4110;PD3920,4280;
+PW1.001;PU3920,4120;PD3990,4120;PD3990,4110;PD3920,4110;PD3920,4120;
+PW1.001;PU3920,4280;PD3990,4280;PD3990,4270;PD3920,4270;PD3920,4280;
+DI100,0;SI0.12012,0.12012;PU3930,4188;LBt a;
+PW1.001;PU3920,4470;PD4681,4470;PD4641,4430;PD4641,4340;PD4681,4300;PD3920,4300;PD3920,4470;
+PW1.001;PU3920,4310;PD3990,4310;PD3990,4300;PD3920,4300;PD3920,4310;
+PW1.001;PU3920,4470;PD3990,4470;PD3990,4460;PD3920,4460;PD3920,4470;
+DI100,0;SI0.12012,0.12012;PU3930,4378;LBbreak, end;
+PU5061,4420;FT1;PM0;PW0;PU5061,4420;PD6153,4420;PD6153,4250;PD5061,4250;PD5061,4420;PM2;FP;EP;
+PW1.001;PU5061,4420;PD6153,4420;PD6153,4250;PD5061,4250;PD5061,4420;
+PU5061,4420;FT1;PM0;PW0;PU5061,4420;PD5132,4420;PD5132,4420;PD5061,4420;PM2;FP;EP;
+PW1.001;PU5061,4420;PD5132,4420;PD5132,4420;PD5061,4420;
+DI100,0;SI0.12012,0.12012;PU5092,4320;LBsymbol ;
+PU3640,5491;FT1;PM0;PW0;PU3640,5491;PD4801,5491;PD4801,5321;PD3640,5321;PD3640,5491;PM2;FP;EP;
+PW1.001;PU3640,5491;PD4801,5491;PD4801,5321;PD3640,5321;PD3640,5491;
+PU3640,5491;FT1;PM0;PW0;PU3640,5491;PD3710,5491;PD3710,5491;PD3640,5491;PM2;FP;EP;
+PW1.001;PU3640,5491;PD3710,5491;PD3710,5491;PD3640,5491;
+DI100,0;SI0.12012,0.12012;PU3670,5391;LBlist 29 29 13 10;
+PW1.001;PU-563,6072;PD-563,6052;
+PW1.001;PU-563,5881;PD-563,3279;
+PW1.001;PU-143,5881;PD-143,3469;
+PW1.001;PU277,5881;PD277,3659;
+PW1.001;PU697,5881;PD697,3859;
+PW1.001;PU1128,5881;PD1128,4800;
+PW1.001;PU1548,5881;PD1548,5811;
+PW1.001;PU1968,5881;PD2529,4810;
+PW1.001;PU2389,5881;PD3950,5101;
+PW1.001;PU2389,5881;PD3670,5491;
+PW1.001;PU2819,5881;PD2909,6052;
+PW1.001;PU2909,5881;PD2909,5861;
+PW1.001;PU-143,3299;PD-563,3089;
+PW1.001;PU-563,3109;PD-563,3089;
+PW1.001;PU-563,2528;PD-563,2298;
+PW1.001;PU277,3489;PD-563,3089;
+PW1.001;PU857,2168;PD857,2148;
+PW1.001;PU857,2358;PD857,2338;
+PW1.001;PU857,1978;PD-563,2298;
+PW1.001;PU-63,2728;PD-563,2298;
+PW1.001;PU697,3689;PD-563,3089;
+PW1.001;PU1658,4630;PD-563,3089;
+PW1.001;PU1128,4630;PD1128,4610;
+PW1.001;PU1348,4630;PD2819,3649;
+PW1.001;PU1568,4630;PD1658,4800;
+PW1.001;PU2819,3239;PD2809,3219;
+PW1.001;PU2819,3479;PD2819,3409;
+PW1.001;PU3120,3479;PD3210,3649;
+PW1.001;PU3210,3479;PD3710,3219;
+PW1.001;PU1128,4440;PD-563,3089;
+PW1.001;PU3340,3049;PD3340,2778;
+PW1.001;PU3590,2798;PD3710,3219;
+PW1.001;PU2809,3049;PD3590,2969;
+PW1.001;PU3029,3049;PD3029,2778;
+PW1.001;PU3250,3049;PD3340,3219;
+PW1.001;PU3340,2608;PD3029,2778;
+PW1.001;PU3029,2608;PD-563,3089;
+PW1.001;PU1548,5641;PD1548,5621;
+PW1.001;PU1938,5641;PD1998,5431;
+PW1.001;PU1768,5261;PD2819,3649;
+PW1.001;PU2589,5281;PD2589,5261;
+PW1.001;PU2589,5091;PD2589,5071;
+PW1.001;PU2589,4900;PD-563,3089;
+PW1.001;PU4010,3239;PD4000,3219;
+PW1.001;PU4010,3479;PD4010,3409;
+PW1.001;PU4311,3479;PD4401,3649;
+PW1.001;PU4401,3479;PD4901,3219;
+PW1.001;PU4531,3049;PD4531,2778;
+PW1.001;PU4781,2798;PD4901,3219;
+PW1.001;PU4000,3049;PD4781,2969;
+PW1.001;PU4221,3049;PD4221,2778;
+PW1.001;PU4441,3049;PD4531,3219;
+PW1.001;PU4221,2608;PD-563,3089;
+PW1.001;PU4531,2608;PD4221,2778;
+PW1.001;PU377,2728;PD-563,2298;
+PW1.001;PU2529,4640;PD2529,4620;
+PW1.001;PU3060,4450;PD-563,3089;
+PW1.001;PU1548,5451;PD1548,5211;
+PW1.001;PU1768,5451;PD1768,5431;
+PW1.001;PU1988,5451;PD2589,5451;
+PW1.001;PU1548,5041;PD-563,3089;
+PW1.001;PU2529,4450;PD2529,4420;
+PW1.001;PU2749,4450;PD4010,3649;
+PW1.001;PU2969,4450;PD3060,4620;
+PW1.001;PU-563,2918;PD-563,2698;
+PW1.001;PU-103,2918;PD-63,2898;
+PW1.001;PU357,2918;PD377,2898;
+PW1.001;PU817,2918;PD817,2878;
+PW1.001;PU1278,2918;PD857,2528;
+PW1.001;PU817,2708;PD-563,2298;
+PW1.001;PU2529,4250;PD-563,3089;
+PW1.001;PU3950,4930;PD3950,4470;
+PW1.001;PU4171,4930;PD4171,4700;
+PW1.001;PU4391,4930;PD4391,4910;
+PW1.001;PU4391,4740;PD3950,4280;
+PW1.001;PU4171,4530;PD3950,4280;
+PW1.001;PU4171,4530;PD5092,4420;
+PW1.001;PU3950,4110;PD-563,3089;
+PW1.001;PU3950,4300;PD3950,4280;
+PU;SP;EC;PG1;EC1;OE
+PU;PA0,0;SP;EC;PG1;EC1;OE
diff --git a/externals/gridflow/images/pmask.png b/externals/gridflow/images/pmask.png
new file mode 100644
index 00000000..007e79a3
--- /dev/null
+++ b/externals/gridflow/images/pmask.png
Binary files differ
diff --git a/externals/gridflow/images/pure-data.jpg b/externals/gridflow/images/pure-data.jpg
new file mode 100644
index 00000000..18804a32
--- /dev/null
+++ b/externals/gridflow/images/pure-data.jpg
Binary files differ
diff --git a/externals/gridflow/images/r001.jpg b/externals/gridflow/images/r001.jpg
new file mode 100644
index 00000000..c2374f9c
--- /dev/null
+++ b/externals/gridflow/images/r001.jpg
Binary files differ
diff --git a/externals/gridflow/images/rose.jpg b/externals/gridflow/images/rose.jpg
new file mode 100644
index 00000000..b34ca5d3
--- /dev/null
+++ b/externals/gridflow/images/rose.jpg
Binary files differ
diff --git a/externals/gridflow/images/scissors.jpg b/externals/gridflow/images/scissors.jpg
new file mode 100644
index 00000000..d4ddf344
--- /dev/null
+++ b/externals/gridflow/images/scissors.jpg
Binary files differ
diff --git a/externals/gridflow/images/sewing.jpg b/externals/gridflow/images/sewing.jpg
new file mode 100644
index 00000000..e5d3933a
--- /dev/null
+++ b/externals/gridflow/images/sewing.jpg
Binary files differ
diff --git a/externals/gridflow/images/teapot.png b/externals/gridflow/images/teapot.png
new file mode 100644
index 00000000..3632eb7c
--- /dev/null
+++ b/externals/gridflow/images/teapot.png
Binary files differ
diff --git a/externals/gridflow/images/test.mpeg b/externals/gridflow/images/test.mpeg
new file mode 100644
index 00000000..ddb18a4c
--- /dev/null
+++ b/externals/gridflow/images/test.mpeg
Binary files differ
diff --git a/externals/gridflow/images/tux.tga.gz b/externals/gridflow/images/tux.tga.gz
new file mode 100644
index 00000000..c6c4bc46
--- /dev/null
+++ b/externals/gridflow/images/tux.tga.gz
Binary files differ
diff --git a/externals/gridflow/images/violoncelle.mov b/externals/gridflow/images/violoncelle.mov
new file mode 100644
index 00000000..f2b65539
--- /dev/null
+++ b/externals/gridflow/images/violoncelle.mov
Binary files differ
diff --git a/externals/gridflow/images/working.jpg b/externals/gridflow/images/working.jpg
new file mode 100644
index 00000000..412dba53
--- /dev/null
+++ b/externals/gridflow/images/working.jpg
Binary files differ
diff --git a/externals/gridflow/src/aalib.cxx b/externals/gridflow/src/aalib.cxx
new file mode 100644
index 00000000..771c5eab
--- /dev/null
+++ b/externals/gridflow/src/aalib.cxx
@@ -0,0 +1,144 @@
+/*
+ $Id: aalib.c 4620 2009-11-01 21:16:58Z matju $
+
+ GridFlow
+ Copyright (c) 2001-2009 by Mathieu Bouchard
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ See file ../COPYING for further informations on licensing terms.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "gridflow.hxx.fcs"
+#define aa_hardwareparams aa_hardware_params
+#include <aalib.h>
+#include <map>
+
+/* MINNOR is a typo in aalib.h, sorry */
+typedef
+#if AA_LIB_MINNOR == 2
+ int
+#else
+ enum aa_attribute
+#endif
+AAAttr;
+
+static std::map<string,const aa_driver *> drivers;
+
+\class FormatAALib : Format {
+ aa_context *context;
+ aa_renderparams *rparams;
+ \attr bool autodraw;
+ bool raw_mode;
+ /* !@#$ varargs missing here */
+ \constructor (t_symbol *mode, string target) {
+ context=0; autodraw=1;
+ argc-=2; argv+=2;
+ char *argv2[argc];
+ for (int i=0; i<argc; i++) argv2[i] = strdup(string(argv[i]).data());
+ if (mode!=gensym("out")) RAISE("write-only, sorry");
+ aa_parseoptions(0,0,&argc,argv2);
+ for (int i=0; i<argc; i++) free(argv2[i]);
+ if (drivers.find(target)==drivers.end()) RAISE("unknown aalib driver '%s'",target.data());
+ const aa_driver *driver = drivers[target];
+ context = aa_init(driver,&aa_defparams,0);
+ rparams = aa_getrenderparams();
+ if (!context) RAISE("opening aalib didn't work");
+ int32 v[]={context->imgheight,context->imgwidth,1};
+ post("aalib image size: %s",(new Dim(3,v))->to_s());
+ }
+ ~FormatAALib () {if (context) aa_close(context);}
+ \decl 0 hidecursor ();
+ \decl 0 print (int y, int x, int a, string text);
+ \decl 0 draw ();
+ \decl 0 dump ();
+ \grin 0 int
+};
+
+GRID_INLET(0) {
+ if (!context) RAISE("boo");
+ if (in->dim->n != 3)
+ RAISE("expecting 3 dimensions: rows,columns,channels");
+ switch (in->dim->get(2)) {
+ case 1: raw_mode = false; break;
+ case 2: raw_mode = true; break;
+ default:
+ RAISE("expecting 1 greyscale channel (got %d)",in->dim->get(2));
+ }
+ in->set_chunk(1);
+} GRID_FLOW {
+ int f = in->dim->prod(1);
+ if (raw_mode) {
+ int sx = min(f,aa_scrwidth(context));
+ int y = dex/f;
+ while (n) {
+ if (y>=aa_scrheight(context)) return;
+ for (int x=0; x<sx; x++) {
+ context->textbuffer[y*aa_scrwidth(context)+x]=data[x*2+0];
+ context->attrbuffer[y*aa_scrwidth(context)+x]=data[x*2+1];
+ }
+ y++;
+ n-=f;
+ data+=f;
+ }
+ } else {
+ int sx = min(f,context->imgwidth);
+ int y = dex/f;
+ while (n) {
+ if (y>=context->imgheight) return;
+ for (int x=0; x<sx; x++) aa_putpixel(context,x,y,data[x]);
+ y++;
+ n-=f;
+ data+=f;
+ }
+ }
+} GRID_FINISH {
+ if (!raw_mode) {
+ aa_palette pal;
+ for (int i=0; i<256; i++) aa_setpalette(pal,i,i,i,i);
+ aa_renderpalette(context,pal,rparams,0,0,
+ aa_scrwidth(context),aa_scrheight(context));
+ }
+ if (autodraw==1) aa_flush(context);
+} GRID_END
+
+\def 0 hidecursor () { aa_hidemouse(context); }
+\def 0 draw () { aa_flush(context); }
+\def 0 print (int y, int x, int a, string text) {
+ aa_puts(context,x,y,(AAAttr)a,(char *)text.data());
+ if (autodraw==1) aa_flush(context);
+}
+
+\def 0 dump () {
+ int32 v[] = {aa_scrheight(context), aa_scrwidth(context), 2};
+ GridOutlet out(this,0,new Dim(3,v));
+ for (int y=0; y<aa_scrheight(context); y++) {
+ for (int x=0; x<aa_scrwidth(context); x++) {
+ int32 data[2];
+ data[0] = context->textbuffer[y*aa_scrwidth(context)+x];
+ data[1] = context->attrbuffer[y*aa_scrwidth(context)+x];
+ out.send(2,data);
+ }
+ }
+}
+
+\end class FormatAALib {
+ const aa_driver *const *p = aa_drivers;
+ for (; *p; p++) drivers[(*p)->shortname] = *p;
+ install_format("#io.aalib",2,"");
+}
+void startup_aalib () {
+ \startall
+}
diff --git a/externals/gridflow/src/classes1.cxx b/externals/gridflow/src/classes1.cxx
new file mode 100644
index 00000000..07031e30
--- /dev/null
+++ b/externals/gridflow/src/classes1.cxx
@@ -0,0 +1,2342 @@
+/*
+ $Id: flow_objects.c 4548 2009-10-31 20:26:25Z matju $
+
+ GridFlow
+ Copyright (c) 2001-2009 by Mathieu Bouchard
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ See file ../COPYING for further informations on licensing terms.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include <sys/time.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string>
+#include <sstream>
+#include <iomanip>
+#include <errno.h>
+#include "gridflow.hxx.fcs"
+#ifdef DESIRE
+#include "desire.h"
+#else
+extern "C" {
+#include "bundled/g_canvas.h"
+};
+extern "C" t_canvas *canvas_getrootfor(t_canvas *x);
+#endif
+
+//using namespace std; // can't
+
+//#undef GRID_INPUT
+//#define GRID_INPUT(I,V) GRID_INLET(I) {in->buf=V=new Grid(in->dim,NumberTypeE_type_of(data));} GRID_FINISH
+
+/* ---------------------------------------------------------------- */
+
+// BAD HACK: GCC complains: unimplemented (--debug mode only) (i don't remember which GCC this was)
+#ifdef HAVE_DEBUG
+#define SCOPY(a,b,n) COPY(a,b,n)
+#else
+#define SCOPY(a,b,n) SCopy<n>::f(a,b)
+#endif
+
+template <long n> class SCopy {
+public: template <class T> static inline void __attribute__((always_inline)) f(T *a, T *b) {
+ *a=*b; SCopy<n-1>::f(a+1,b+1);}};
+template <> class SCopy<0> {
+public: template <class T> static inline void __attribute__((always_inline)) f(T *a, T *b) {}};
+
+/*template <> class SCopy<4> {
+public: template <class T>
+ static inline void __attribute__((always_inline)) f(T *a, T *b) {
+ *a=*b; SCopy<3>::f(a+1,b+1);}
+ static inline void __attribute__((always_inline)) f(uint8 *a, uint8 *b)
+ { *(int32 *)a=*(int32 *)b; }
+};*/
+
+Numop *op_add, *op_sub, *op_mul, *op_div, *op_mod, *op_shl, *op_and, *op_put;
+
+static void expect_dim_dim_list (P<Dim> d) {
+ if (d->n!=1) RAISE("dimension list should be Dim[n], not %s",d->to_s());}
+//static void expect_min_one_dim (P<Dim> d) {
+// if (d->n<1) RAISE("minimum 1 dimension");}
+static void expect_max_one_dim (P<Dim> d) {
+ if (d->n>1) RAISE("expecting Dim[] or Dim[n], got %s",d->to_s());}
+//static void expect_exactly_one_dim (P<Dim> d) {
+// if (d->n!=1) RAISE("expecting Dim[n], got %s",d->to_s());}
+
+//****************************************************************
+\class GridCast : FObject {
+ \attr NumberTypeE nt;
+ \constructor (NumberTypeE nt) {this->nt = nt;}
+ \grin 0
+};
+GRID_INLET(0) {
+ out = new GridOutlet(this,0,in->dim,nt);
+} GRID_FLOW {
+ out->send(n,data);
+} GRID_END
+\end class {install("#cast",1,1); add_creator("@cast");}
+
+//****************************************************************
+
+GridHandler *stromgol; // remove this asap
+
+//{ ?,Dim[B] -> Dim[*Cs] }
+// out0 nt to be specified explicitly
+\class GridImport : FObject {
+ \attr NumberTypeE cast;
+ \attr P<Dim> dim; // size of grids to send
+ PtrGrid dim_grid;
+ \constructor (...) {
+ dim_grid.constrain(expect_dim_dim_list);
+ this->cast = argc>=2 ? NumberTypeE_find(argv[1]) : int32_e;
+ if (argc>2) RAISE("too many arguments");
+ if (argc>0 && argv[0]!=gensym("per_message")) {
+ dim_grid=new Grid(argv[0]);
+ dim = dim_grid->to_dim();
+ if (!dim->prod()) RAISE("target grid size must not be zero");
+ }
+ }
+ ~GridImport() {}
+ \decl 0 reset();
+ \decl 0 symbol(t_symbol *x);
+ \decl 0 to_ascii(...);
+ \decl 0 bang();
+ //\decl 0 list(...);
+ \decl 1 per_message();
+ \grin 0
+ \grin 1 int32
+ template <class T> void process (long n, T *data) {
+ if (in.size()<=0) in.resize(1);
+ if (!in[0]) in[0]=new GridInlet((FObject *)this,stromgol);
+ while (n) {
+ if (!out || !out->dim) out = new GridOutlet(this,0,dim?dim:in[0]->dim,cast);
+ long n2 = min((long)n,out->dim->prod()-out->dex);
+ out->send(n2,data);
+ n-=n2; data+=n2;
+ }
+ }
+};
+
+GRID_INLET(0) {} GRID_FLOW {process(n,data);} GRID_END
+GRID_INPUT(1,dim_grid) {
+ P<Dim> d = dim_grid->to_dim();
+ if (!d->prod()) RAISE("target grid size must not be zero");
+ dim = d;
+} GRID_END
+
+\def 0 symbol(t_symbol *x) {
+ const char *name = x->s_name;
+ long n = strlen(name);
+ if (!dim) out=new GridOutlet(this,0,new Dim(n));
+ process(n,(uint8 *)name);
+}
+\def 0 to_ascii(...) {
+ std::ostringstream os;
+ pd_oprint(os,argc,argv);
+ string s = os.str();
+ long n = s.length();
+ if (!dim) out=new GridOutlet(this,0,new Dim(n),cast);
+ process(n,(uint8 *)s.data());
+}
+
+\def 0 bang() {_0_list(0,0);}
+\def 0 list(...) {//first two lines are there until grins become strictly initialized.
+ if (in.size()<=0) in.resize(1);
+ if (!in[0]) in[0]=new GridInlet((FObject *)this,stromgol);
+ in[0]->from_list(argc,argv,cast);
+ if (!argc && !dim) out = new GridOutlet(this,0,new Dim(0),cast);
+}
+\def 1 per_message() {dim=0; dim_grid=0;}
+
+\def 0 reset() {int32 foo[1]={0}; if (out) while (out->dim) out->send(1,foo);}
+\end class {install("#import",2,1); add_creator("@import"); stromgol = &GridImport_grid_0_hand;}
+
+//****************************************************************
+/*{ Dim[*As] -> ? }*/
+/* in0: integer nt */
+\class GridToFloat : FObject {
+ \constructor () {}
+ \grin 0
+};
+GRID_INLET(0) {
+} GRID_FLOW {
+ for (int i=0; i<n; i++) outlet_float(bself->outlets[0],data[i]);
+} GRID_END
+\end class {install("#to_float",1,1); add_creator("#export"); add_creator("@export");}
+
+\class GridToSymbol : FObject {
+ \constructor () {}
+ \grin 0
+};
+GRID_INLET(0) {
+ in->set_chunk(0);
+} GRID_FLOW {
+ char c[n+1];
+ for (int i=0; i<n; i++) c[i]=(char)data[i];
+ c[n]=0;
+ outlet_symbol(bself->outlets[0],gensym(c));
+} GRID_END
+\end class {install("#to_symbol",1,1); add_creator("#export_symbol"); add_creator("@export_symbol");}
+
+/*{ Dim[*As] -> ? }*/
+/* in0: integer nt */
+\class GridExportList : FObject {
+ \constructor () {}
+ int n;
+ \grin 0
+};
+
+GRID_INLET(0) {
+ long n = in->dim->prod();
+ if (n>1000000) RAISE("list too big (%ld elements, max 1000000)", n);
+ this->n = n;
+ in->set_chunk(0);
+} GRID_FLOW {
+ send_out(0,n,data);
+} GRID_FINISH {
+ if (in->dim->prod()==0) send_out(0,0,data);
+} GRID_END
+
+\end class {install("#to_list",1,1); add_creator("#export_list"); add_creator("@export_list");}
+
+/* **************************************************************** */
+\class GridPrint : FObject {
+ \constructor (t_symbol *name=0) {
+ this->dest = 0;
+ this->name = name;
+ base=10; trunc=70; maxrows=50;
+ }
+ \attr t_symbol *name;
+ \grin 0
+ int base;
+ uint32 trunc;
+ int maxrows;
+ int columns;
+ t_pd *dest;
+ \decl 0 dest (void *p);
+ \decl void end_hook ();
+ \decl 0 base (int x);
+ \decl 0 trunc (int x);
+ \decl 0 maxrows (int y);
+ void puts (const char *s) {
+ if (!dest) post("%s",s);
+ else {
+ int n = strlen(s);
+ t_atom a[n];
+ for (int i=0; i<n; i++) SETFLOAT(a+i,s[i]);
+ //fprintf(stderr,"dest=%p\n",dest);
+ //fprintf(stderr,"*dest={%08x,%08x,%08x,%08x,...}\n",dest[0],dest[1],dest[2],dest[3]);
+ pd_typedmess(dest,gensym("very_long_name_that_nobody_uses"),n,a);
+ }
+ }
+ void puts (std::string s) {puts(s.data());}
+ void puts (std::ostringstream &s) {puts(s.str());}
+ template <class T> void make_columns (int n, T *data);
+ template <class T> void dump(std::ostream &s, int n, T *data, char sep=' ', int trunc=-1) {
+ if (trunc<0) trunc=this->trunc;
+ std::string f = format(NumberTypeE_type_of(data));
+ for (int i=0; i<n; i++) {
+ if (base!=2) oprintf(s,f.data(),data[i]);
+ else {
+ T x = gf_abs(data[i]);
+ int ndigits = 1+highest_bit(uint64(x));
+ for (int j=columns-ndigits-(data[i]!=x); j>=0; j--) s<<' ';
+ if (data[i]!=x) s<<'-';
+ for (int j=ndigits-1; j>=0; j--) {
+ s<<char('0'+(((long)x>>j)&1));
+ }
+ }
+ if (i<n-1) s << sep;
+ if (s.tellp()>trunc) return;
+ }
+ }
+ void dump_dims(std::ostream &s, GridInlet *in) {
+ if (name && name!=&s_) s << name->s_name << ": ";
+ s << "Dim[";
+ for (int i=0; i<in->dim->n; i++) {
+ s << in->dim->v[i];
+ if (i<in->dim->n-1) s << ',';
+ }
+ s << "]";
+ if (in->nt!=int32_e) s << "(" << number_type_table[in->nt].name << ")";
+ s << ": ";
+ }
+ std::string format (NumberTypeE nt) {
+ if (nt==float32_e) return "%6.6f";
+ if (nt==float64_e) return "%14.14f";
+ std::ostringstream r;
+ r << "%";
+ r << columns;
+ //if (nt==int64_e) r << "l";
+ if (base==2) r << "b"; else
+ if (base==8) r << "o"; else
+ if (base==10) r << "d"; else
+ if (base==16) r << "x";
+ return r.str();
+ }
+};
+\def 0 dest (void *p) {dest = (t_pd *)p;}
+\def void end_hook () {}
+\def 0 base (int x) { if (x==2 || x==8 || x==10 || x==16) base=x; else RAISE("base %d not supported",x); }
+\def 0 trunc (int x) {
+ if (x<0 || x>240) RAISE("out of range (not in 0..240 range)");
+ trunc = x;
+}
+\def 0 maxrows (int y) {maxrows = y;}
+template <class T> void GridPrint::make_columns (int n, T *data) {
+ long maxv=0;
+ long minv=0;
+ for (int i=0; i<n; i++) {
+ if (maxv<data[i]) maxv=long(data[i]);
+ if (minv>data[i]) minv=long(data[i]);
+ }
+ int maxd = 1 + (maxv<0) + int(log(max(1.,fabs(maxv)))/log(base));
+ int mind = 1 + (minv<0) + int(log(max(1.,fabs(minv)))/log(base));
+ //fprintf(stderr,"v=(%d,%d) d=(%d,%d)\n",minv,maxv,mind,maxd);
+ columns = max(maxd,mind);
+}
+GRID_INLET(0) {
+ in->set_chunk(0);
+} GRID_FLOW {
+ std::ostringstream head;
+ dump_dims(head,in);
+ int ndim = in->dim->n;
+ if (ndim > 3) {
+ head << " (not printed)";
+ puts(head);
+ } else if (ndim < 2) {
+ make_columns(n,data);
+ dump(head,n,data,' ',trunc);
+ puts(head);
+ } else if (ndim == 2) {
+ puts(head);
+ make_columns(n,data);
+ long sy = in->dim->v[0];
+ long sx = n/sy;
+ for (int row=0; row<sy; row++) {
+ std::ostringstream body;
+ dump(body,sx,&data[sx*row],' ',trunc);
+ if (body.tellp()>trunc) body << "...";
+ puts(body);
+ if (row>maxrows) {puts("..."); break;}
+ }
+ } else if (ndim == 3) {
+ puts(head);
+ make_columns(n,data);
+ int sy = in->dim->v[0];
+ int sx = in->dim->v[1];
+ int sz = n/sy;
+ int sz2 = sz/in->dim->v[1];
+ for (int row=0; row<sy; row++) {
+ std::ostringstream str;
+ for (int col=0; col<sx; col++) {
+ str << "(";
+ dump(str,sz2,&data[sz*row+sz2*col],' ',trunc);
+ if (str.tellp()>trunc) {str << "..."; break;} else str << ")";
+ }
+ puts(str);
+ if (row>maxrows) {puts("..."); break;}
+ }
+ }
+ end_hook(0,0);
+} GRID_FINISH {
+ std::ostringstream head;
+ dump_dims(head,in);
+ if (in->dim->prod()==0) puts(head);
+} GRID_END
+\end class {install("#print",1,1); add_creator("@print");}
+
+/* **************************************************************** */
+// [#store] is the class for storing a grid and restituting it on demand.
+// The right inlet receives the grid. The left inlet receives either a bang
+// (which forwards the whole image) or a grid describing what to send.
+//{ Dim[*As,B],Dim[*Cs,*Ds] -> Dim[*As,*Ds] }
+// in0: integer nt
+// in1: whatever nt
+// out0: same nt as in1
+\class GridStore : FObject {
+
+ PtrGrid r; // can't be \attr
+ PtrGrid put_at; // can't be //\attr
+ \attr Numop *op;
+ int32 *wdex ; // temporary buffer, copy of put_at
+ int32 *fromb;
+ int32 *to2 ;
+ int lsd; // lsd = Last Same Dimension (for put_at)
+ int d; // goes with wdex
+ long cs; // chunksize used in put_at
+ \constructor (Grid *r=0) {
+ put_at.constrain(expect_max_one_dim);
+ this->r = r?r:new Grid(new Dim(),int32_e,true);
+ op = op_put;
+ wdex = NEWBUF(int32,Dim::MAX_DIM); // temporary buffer, copy of put_at
+ fromb = NEWBUF(int32,Dim::MAX_DIM);
+ to2 = NEWBUF(int32,Dim::MAX_DIM);
+ }
+ ~GridStore () {
+ DELBUF(wdex);
+ DELBUF(fromb);
+ DELBUF(to2);
+ }
+ \decl 0 bang ();
+ \decl 1 reassign ();
+ \decl 1 put_at (...);
+ \grin 0 int
+ \grin 1
+ template <class T> void compute_indices(T *v, long nc, long nd);
+};
+
+// takes the backstore of a grid and puts it back into place. a backstore
+// is a grid that is filled while the grid it would replace has not
+// finished being used.
+static void snap_backstore (PtrGrid &r) {if (r.next) {r=r.next.p; r.next=0;}}
+
+template <class T> void GridStore::compute_indices(T *v, long nc, long nd) {
+ for (int i=0; i<nc; i++) {
+ uint32 wrap = r->dim->v[i];
+ bool fast = lowest_bit(wrap)==highest_bit(wrap); // is power of two?
+ if (i) {
+ if (fast) op_shl->map(nd,v,(T)highest_bit(wrap));
+ else op_mul->map(nd,v,(T)wrap);
+ }
+ if (fast) op_and->map(nd,v+nd*i,(T)(wrap-1));
+ else op_mod->map(nd,v+nd*i,(T)(wrap));
+ if (i) op_add->zip(nd,v,v+nd*i);
+ }
+}
+
+// !@#$ i should ensure that n is not exceedingly large
+// !@#$ worse: the size of the foo buffer may still be too large
+GRID_INLET(0) {
+ // snap_backstore must be done before *anything* else
+ snap_backstore(r);
+ int na = in->dim->n;
+ int nb = r->dim->n;
+ int32 v[Dim::MAX_DIM];
+ if (na<1) RAISE("must have at least 1 dimension.",na,1,1+nb);
+ long nc = in->dim->get(na-1);
+ if (nc>nb) RAISE("got %d elements in last dimension, expecting <= %d", nc, nb);
+ long nnc = r->dim->prod(nc);
+ int lastindexable = nnc ? r->dim->prod()/nnc-1 : 0; // SIGFPE happened when r was especially empty (nnc==0)
+ int ngreatest = nt_greatest((T *)0);
+ if (lastindexable > ngreatest) RAISE("lastindexable=%d > ngreatest=%d (ask matju)",lastindexable,ngreatest);
+ int nd = nb-nc+na-1;
+ COPY(v,in->dim->v,na-1);
+ COPY(v+na-1,r->dim->v+nc,nb-nc);
+ out=new GridOutlet(this,0,new Dim(nd,v),r->nt);
+ if (nc>0) in->set_chunk(na-1);
+} GRID_FLOW {
+ int na = in->dim->n;
+ int nc = in->dim->get(na-1);
+ long size = r->dim->prod(nc);
+ long nd = n/nc;
+ T w[n];
+ T *v=w;
+ if (sizeof(T)==1 && nc==1 && r->dim->v[0]<=256) {
+ // bug? shouldn't modulo be done here?
+ v=data;
+ } else {
+ COPY(v,data,n);
+ for (long k=0,i=0; i<nc; i++) for (long j=0; j<n; j+=nc) v[k++] = data[i+j];
+ compute_indices(v,nc,nd);
+ }
+#define FOO(type) { \
+ type *p = (type *)*r; \
+ if (size<=16) { \
+ type tada[nd*size]; \
+ type *foo = tada; \
+ long i=0; \
+ switch (size) { \
+ case 1: for (; i<(nd&-4); i+=4, foo+=4) { \
+ foo[0] = p[v[i+0]]; \
+ foo[1] = p[v[i+1]]; \
+ foo[2] = p[v[i+2]]; \
+ foo[3] = p[v[i+3]]; \
+ } break; \
+ case 2: for (; i<nd; i++, foo+=2) SCOPY(foo,p+2*v[i],2); break; \
+ case 3: for (; i<nd; i++, foo+=3) SCOPY(foo,p+3*v[i],3); break; \
+ case 4: for (; i<nd; i++, foo+=4) SCOPY(foo,p+4*v[i],4); break; \
+ default:; }; \
+ for (; i<nd; i++, foo+=size) COPY(foo,p+size*v[i],size); \
+ out->send(size*nd,tada); \
+ } else { \
+ for (int i=0; i<nd; i++) out->send(size,p+size*v[i]); \
+ } \
+}
+ TYPESWITCH(r->nt,FOO,)
+#undef FOO
+} GRID_FINISH {
+ if (in->dim->prod()==0) {
+ long n = in->dim->prod(0,-2);
+ long size = r->dim->prod();
+#define FOO(T) while (n--) out->send(size,(T *)*r);
+ TYPESWITCH(r->nt,FOO,)
+#undef FOO
+ }
+} GRID_END
+
+GRID_INLET(1) {
+ NumberTypeE nt = NumberTypeE_type_of(data);
+ if (!put_at) { // reassign
+ if (in[0].dim) r.next = new Grid(in->dim,nt);
+ else r = new Grid(in->dim,nt);
+ return;
+ }
+ // put_at ( ... )
+ snap_backstore(r);
+ SAME_TYPE(in,r);
+ //!@#$ should check types. if (r->nt!=in->nt) RAISE("shoo");
+ long nn=r->dim->n, na=put_at->dim->v[0], nb=in->dim->n;
+ int32 sizeb[nn];
+ for (int i=0; i<nn; i++) { fromb[i]=0; sizeb[i]=1; }
+ COPY(wdex ,(int32 *)*put_at ,put_at->dim->prod());
+ COPY(fromb+nn-na,(int32 *)*put_at ,na);
+ COPY(sizeb+nn-nb,(int32 *)in->dim->v,nb);
+ for (int i=0; i<nn; i++) to2[i] = fromb[i]+sizeb[i];
+ d=0;
+ // find out when we can skip computing indices
+ //!@#$ should actually also stop before blowing up packet size
+ lsd=nn;
+ while (lsd>=nn-in->dim->n) {
+ lsd--;
+ //int cs = in->dim->prod(lsd-nn+in->dim->n);
+ if (/*cs*(number_type_table[in->nt].size/8)>GridOutlet::MAX_PACKET_SIZE ||*/
+ fromb[lsd]!=0 || sizeb[lsd]!=r->dim->v[lsd]) break;
+ }
+ lsd++;
+ long chunk = lsd-nn+in->dim->n;
+ in->set_chunk( chunk);
+ cs = in->dim->prod(chunk);
+} GRID_FLOW {
+ //fprintf(stderr,"d=%d\n",d);
+ if (!put_at) { // reassign
+ COPY(((T *)*(r.next ? r.next.p : &*r.p))+dex, data, n);
+ return;
+ }
+ // put_at (...)
+ int32 v[lsd];
+ int32 *x = wdex;
+ while (n) {
+ // here d is the dim# to reset; d=n for none
+ for(;d<lsd;d++) x[d]=fromb[d];
+ COPY(v,x,lsd);
+ compute_indices(v,lsd,1);
+ op->zip(cs,(T *)*r+v[0]*cs,data);
+ data+=cs;
+ n-=cs;
+ // find next set of indices; here d is the dim# to increment
+ for(;;) {d--; if (d<0) return; x[d]++; if (x[d]<to2[d]) break;}
+ d++;
+ }
+} GRID_END
+\def 0 bang () {
+ t_atom a[2];
+ SETFLOAT(a+0,0);
+ SETSYMBOL(a+1,gensym("#"));
+ pd_list((t_pd *)bself,&s_list,2,a);
+}
+\def 1 reassign () {put_at=0;}
+\def 1 put_at (...) {
+ if (argv[0].a_type==A_LIST) put_at=convert(argv[0],(Grid **)0);
+ else {
+ put_at=new Grid(new Dim(argc),int32_e);
+ int32 *v = (int32 *)*put_at;
+ for (int i=0; i<argc; i++) v[i]=convert(argv[i],(int32 *)0);
+ }
+}
+\end class {install("#store",2,1); add_creator("@store");}
+
+//****************************************************************
+//{ Dim[*As]<T> -> Dim[*As]<T> } or
+//{ Dim[*As]<T>,Dim[*Bs]<T> -> Dim[*As]<T> }
+\class GridOp : FObject {
+ \attr Numop *op;
+ PtrGrid r;
+ \constructor (Numop *op, Grid *r=0) {
+ this->op=op;
+ this->r=r?r:new Grid(new Dim(),int32_e,true);
+ }
+ \grin 0
+ \grin 1
+};
+
+GRID_INLET(0) {
+ snap_backstore(r);
+ SAME_TYPE(in,r);
+ out=new GridOutlet(this,0,in->dim,in->nt);
+ if (op->size>1 && (in->dim->get(in->dim->n-1)!=op->size || r->dim->get(r->dim->n-1)!=op->size))
+ RAISE("using %s requires Dim(...,%d) in both inlets but got: left=%s right=%s",
+ op->name,op->size,in->dim->to_s(),r->dim->to_s());
+ //if (out->inlets.size()==1) post("[#]: 1 receiver with bugger size %s",out->inlets[0]->dim->to_s());
+} GRID_FLOW {
+ T *rdata = (T *)*r;
+ long loop = r->dim->prod();
+ T tada[n];
+ COPY(tada,data,n);
+ if (loop>1) {
+ if (dex+n <= loop) {
+ op->zip(n/op->size,tada,rdata+dex);
+ } else {
+ // !@#$ should prebuild and reuse this array when "loop" is small
+ T data2[n];
+ long ii = mod(dex,loop);
+ long m = min(loop-ii,n);
+ COPY(data2,rdata+ii,m);
+ long nn = m+((n-m)/loop)*loop;
+ for (long i=m; i<nn; i+=loop) COPY(data2+i,rdata,loop);
+ if (n>nn) COPY(data2+nn,rdata,n-nn);
+ op->zip(n/op->size,tada,data2);
+ }
+ } else op->map(n,tada,*rdata);
+ out->send(n,tada);
+} GRID_END
+
+GRID_INPUT2(1,r) {} GRID_END
+\end class {install("#",2,1); add_creator("@");}
+
+//****************************************************************
+\class GridFold : FObject {
+ \attr Numop *op;
+ \attr PtrGrid seed;
+ \constructor (Numop *op) {this->op=op;}
+ \grin 0
+};
+
+GRID_INLET(0) {
+ //{ Dim[*As,B,*Cs]<T>,Dim[*Cs]<T> -> Dim[*As,*Cs]<T> }
+ if (seed) SAME_TYPE(in,seed);
+ int an = in->dim->n;
+ int bn = seed?seed->dim->n:0;
+ if (an<=bn) RAISE("minimum 1 more dimension than the seed (%d vs %d)",an,bn);
+ int32 v[an-1];
+ int yi = an-bn-1;
+ COPY(v,in->dim->v,yi);
+ COPY(v+yi,in->dim->v+an-bn,bn);
+ if (seed) SAME_DIM(an-(yi+1),in->dim,(yi+1),seed->dim,0);
+ out=new GridOutlet(this,0,new Dim(an-1,v),in->nt);
+ in->set_chunk(yi);
+ if (in->dim->prod(yi)==0) {
+ long n = out->dim->prod();
+ T x=0; op->on(x)->neutral(&x,at_left);
+ for(long i=0; i<n; i++) out->send(1,&x);
+ }
+} GRID_FLOW {
+ int an = in->dim->n;
+ int bn = seed?seed->dim->n:0;
+ long yn = in->dim->v[an-bn-1];
+ long zn = in->dim->prod(an-bn);
+ T buf[n/yn];
+ long nn=n;
+ long yzn=yn*zn;
+ for (long i=0; n; i+=zn, data+=yzn, n-=yzn) {
+ if (seed) COPY(buf+i,((T *)*seed),zn);
+ else {T neu; op->on(*buf)->neutral(&neu,at_left); op_put->map(zn,buf+i,neu);}
+ op->fold(zn,yn,buf+i,data);
+ }
+ out->send(nn/yn,buf);
+} GRID_FINISH {
+} GRID_END
+
+\end class {install("#fold",1,1);}
+
+\class GridScan : FObject {
+ \attr Numop *op;
+ \attr PtrGrid seed;
+ \constructor (Numop *op) {this->op = op;}
+ \grin 0
+};
+
+GRID_INLET(0) {
+ //{ Dim[*As,B,*Cs]<T>,Dim[*Cs]<T> -> Dim[*As,B,*Cs]<T> }
+ if (seed) SAME_TYPE(in,seed);
+ int an = in->dim->n;
+ int bn = seed?seed->dim->n:0;
+ if (an<=bn) RAISE("minimum 1 more dimension than the right hand");
+ if (seed) SAME_DIM(bn,in->dim,an-bn,seed->dim,0);
+ out=new GridOutlet(this,0,in->dim,in->nt);
+ in->set_chunk(an-bn-1);
+} GRID_FLOW {
+ int an = in->dim->n;
+ int bn = seed?seed->dim->n:0;
+ long yn = in->dim->v[an-bn-1];
+ long zn = in->dim->prod(an-bn);
+ long factor = yn*zn;
+ T buf[n];
+ COPY(buf,data,n);
+ if (seed) {
+ for (long i=0; i<n; i+=factor) op->scan(zn,yn,(T *)*seed,buf+i);
+ } else {
+ T neu; op->on(*buf)->neutral(&neu,at_left);
+ T seed[zn]; op_put->map(zn,seed,neu);
+ for (long i=0; i<n; i+=factor) op->scan(zn,yn, seed,buf+i);
+ }
+ out->send(n,buf);
+} GRID_END
+
+\end class {install("#scan",1,1);}
+
+//****************************************************************
+// L is a Dim[*si,sj, *ss]<T>
+// R is a Dim[ sj,*sk,*ss]<T>
+// Seed is a Dim[ *ss]<T>
+// result is a Dim[*si, *sk,*ss]<T>
+// Currently *ss can only be = Dim[]
+\class GridInner : FObject {
+ \attr Numop *op;
+ \attr Numop *fold;
+ \attr PtrGrid seed;
+ PtrGrid r;
+ PtrGrid r2; // temporary
+ bool use_dot;
+ \constructor (Grid *r=0) {
+ this->op = op_mul;
+ this->fold = op_add;
+ this->seed = new Grid(new Dim(),int32_e,true);
+ this->r = r ? r : new Grid(new Dim(),int32_e,true);
+ }
+ \grin 0
+ \grin 1
+};
+
+// let's see this as a matrix product like L[i,j]*R[j,k] in Einstein notation
+// L: matrix of size si by sj
+// R: matrix of size sj by sk
+// LR: matrix of size si by sk
+template <class T> void inner_child_a (T *as, T *bs, int sj, int sk, int chunk) {
+ for (int j=0; j<chunk; j++, as+=sk, bs+=sj) op_put->map(sk,as,*bs);}
+template <class T, int sk> void inner_child_b (T *as, T *bs, int sj, int chunk) {
+ for (int j=0; j<chunk; j++, as+=sk, bs+=sj) op_put->map(sk,as,*bs);}
+
+// Inner product in a Module on the (+,*) Ring
+// | BBBBB
+// j BBBBB
+// | BBBBB
+// --j--*---k---
+// AAAAA CCCCC
+template <class T> void dot_add_mul (long sk, long sj, T *cs, T *as, T *bs) {
+ for (long k=0; k<sk; k++) {T c=0; for (long j=0; j<sj; j++) {c+=as[j]*bs[j*sk+k];} *cs++=c;}}
+template <class T, long sj> void dot_add_mul (long sk, T *cs, T *as, T *bs) {
+ for (long k=0; k<sk; k++) {T c=0; for (long j=0; j<sj; j++) {c+=as[j]*bs[j*sk+k];} *cs++=c;}}
+template <class T, long sj, long sk> void dot_add_mul (T *cs, T *as, T *bs) {
+ for (long k=0; k<sk; k++) {T c=0; for (long j=0; j<sj; j++) {c+=as[j]*bs[j*sk+k];} *cs++=c;}}
+
+GRID_INLET(0) {
+ SAME_TYPE(in,r);
+ SAME_TYPE(in,seed);
+ P<Dim> a=in->dim, b=r->dim;
+ if (a->n<1) RAISE("a: minimum 1 dimension");
+ if (b->n<1) RAISE("b: minimum 1 dimension");
+ if (seed->dim->n != 0) RAISE("seed must be a scalar");
+ int n = a->n+b->n-2;
+ SAME_DIM(1,a,a->n-1,b,0);
+ int32 v[n];
+ COPY(v,a->v,a->n-1);
+ COPY(v+a->n-1,b->v+1,b->n-1);
+ out=new GridOutlet(this,0,new Dim(n,v),in->nt);
+ in->set_chunk(a->n-1);
+ long sjk=r->dim->prod(), sj=in->dim->prod(a->n-1), sk=sjk/sj;
+ long chunk = max(1L,GridOutlet::MAX_PACKET_SIZE/sjk);
+ T *rdata = (T *)*r;
+ r2=new Grid(new Dim(chunk*sjk),r->nt);
+ T *buf3 = (T *)*r2;
+ for (long i=0; i<sj; i++)
+ for (long j=0; j<chunk; j++)
+ COPY(buf3+(j+i*chunk)*sk,rdata+i*sk,sk);
+ use_dot = op==op_mul && fold==op_add && seed->dim->n==0 && *(T *)*seed==0;
+} GRID_FLOW {
+ long sjk=r->dim->prod(), sj=in->dim->prod(in->dim->n-1), sk=sjk/sj;
+ long chunk = max(1L,GridOutlet::MAX_PACKET_SIZE/sjk), off=chunk;
+ T buf [chunk*sk];
+ T buf2[chunk*sk];
+ if (use_dot) {
+ while (n) {
+ if (chunk*sj>n) chunk=n/sj;
+ if (sj<=4 && sk<=4) switch ((sj-1)*4+(sk-1)) {
+#define DOT_ADD_MUL_3(sj,sk) for (int i=0; i<chunk; i++) dot_add_mul<T,sj,sk>( buf2+sk*i,data+sj*i,(T *)*r);
+ case 0: DOT_ADD_MUL_3(1,1); break;
+ case 1: DOT_ADD_MUL_3(1,2); break;
+ case 2: DOT_ADD_MUL_3(1,3); break;
+ case 3: DOT_ADD_MUL_3(1,4); break;
+ case 4: DOT_ADD_MUL_3(2,1); break;
+ case 5: DOT_ADD_MUL_3(2,2); break;
+ case 6: DOT_ADD_MUL_3(2,3); break;
+ case 7: DOT_ADD_MUL_3(2,4); break;
+ case 8: DOT_ADD_MUL_3(3,1); break;
+ case 9: DOT_ADD_MUL_3(3,2); break;
+ case 10: DOT_ADD_MUL_3(3,3); break;
+ case 11: DOT_ADD_MUL_3(3,4); break;
+ case 12: DOT_ADD_MUL_3(4,1); break;
+ case 13: DOT_ADD_MUL_3(4,2); break;
+ case 14: DOT_ADD_MUL_3(4,3); break;
+ case 15: DOT_ADD_MUL_3(4,4); break;
+ } else switch (sj) {
+#define DOT_ADD_MUL_2(sj) for (int i=0; i<chunk; i++) dot_add_mul<T,sj>(sk,buf2+sk*i,data+sj*i,(T *)*r);
+ case 1: DOT_ADD_MUL_2(1); break;
+ case 2: DOT_ADD_MUL_2(2); break;
+ case 3: DOT_ADD_MUL_2(3); break;
+ case 4: DOT_ADD_MUL_2(4); break;
+ default:for (int i=0; i<chunk; i++) dot_add_mul(sk,sj,buf2+sk*i,data+sj*i,(T *)*r);
+ }
+ out->send(chunk*sk,buf2);
+ n-=chunk*sj;
+ data+=chunk*sj;
+ }
+ } else {
+ while (n) {
+ if (chunk*sj>n) chunk=n/sj;
+ op_put->map(chunk*sk,buf2,*(T *)*seed);
+ for (long i=0; i<sj; i++) {
+ switch (sk) {
+ case 1: inner_child_b<T,1>(buf,data+i,sj,chunk); break;
+ case 2: inner_child_b<T,2>(buf,data+i,sj,chunk); break;
+ case 3: inner_child_b<T,3>(buf,data+i,sj,chunk); break;
+ case 4: inner_child_b<T,4>(buf,data+i,sj,chunk); break;
+ default: inner_child_a(buf,data+i,sj,sk,chunk);
+ }
+ op->zip(chunk*sk,buf,(T *)*r2+i*off*sk);
+ fold->zip(chunk*sk,buf2,buf);
+ }
+ out->send(chunk*sk,buf2);
+ n-=chunk*sj;
+ data+=chunk*sj;
+ }
+ }
+} GRID_FINISH {
+ r2=0;
+} GRID_END
+
+GRID_INPUT(1,r) {} GRID_END
+
+\end class {install("#inner",2,1);}
+
+/* **************************************************************** */
+/*{ Dim[*As]<T>,Dim[*Bs]<T> -> Dim[*As,*Bs]<T> }*/
+\class GridOuter : FObject {
+ \attr Numop *op;
+ PtrGrid r;
+ \constructor (Numop *op, Grid *r=0) {
+ this->op = op;
+ this->r = r ? r : new Grid(new Dim(),int32_e,true);
+ }
+ \grin 0
+ \grin 1
+};
+
+GRID_INLET(0) {
+ SAME_TYPE(in,r);
+ P<Dim> a = in->dim;
+ P<Dim> b = r->dim;
+ int n = a->n+b->n;
+ int32 v[n];
+ COPY(v,a->v,a->n);
+ COPY(v+a->n,b->v,b->n);
+ out=new GridOutlet(this,0,new Dim(n,v),in->nt);
+} GRID_FLOW {
+ long b_prod = r->dim->prod();
+ if (!b_prod) return; /* nothing to do... and avoid deadly divisions by zero */
+ if (b_prod > 4) {
+ T buf[b_prod];
+ while (n) {
+ for (long j=0; j<b_prod; j++) buf[j] = *data;
+ op->zip(b_prod,buf,(T *)*r);
+ out->send(b_prod,buf);
+ data++; n--;
+ }
+ return;
+ }
+ n*=b_prod;
+ T buf[n];
+ T buf2[b_prod*64];
+ for (int i=0; i<64; i++) COPY(buf2+i*b_prod,(T *)*r,b_prod);
+ switch (b_prod) {
+ #define Z buf[k++]=data[i]
+ case 1: for (long i=0,k=0; k<n; i++) {Z;} break;
+ case 2: for (long i=0,k=0; k<n; i++) {Z;Z;} break;
+ case 3: for (long i=0,k=0; k<n; i++) {Z;Z;Z;} break;
+ case 4: for (long i=0,k=0; k<n; i++) {Z;Z;Z;Z;} break;
+ default:for (long i=0,k=0; k<n; i++) for (int j=0; j<b_prod; j++, k++) Z;
+ }
+ #undef Z
+ int ch=64*b_prod;
+ int nn=(n/ch)*ch;
+ for (int j=0; j<nn; j+=ch) op->zip(ch,buf+j,buf2);
+ op->zip(n-nn,buf+nn,buf2);
+ out->send(n,buf);
+} GRID_END
+
+GRID_INPUT(1,r) {} GRID_END
+
+\end class {install("#outer",2,1); add_creator("@outer");}
+
+//****************************************************************
+//{ Dim[]<T>,Dim[]<T>,Dim[]<T> -> Dim[A]<T> } or
+//{ Dim[B]<T>,Dim[B]<T>,Dim[B]<T> -> Dim[*As,B]<T> }
+\class GridFor : FObject {
+ \attr PtrGrid from;
+ \attr PtrGrid to;
+ \attr PtrGrid step;
+ \constructor (Grid *from, Grid *to, Grid *step) {
+ this->from.constrain(expect_max_one_dim);
+ this->to .constrain(expect_max_one_dim);
+ this->step.constrain(expect_max_one_dim);
+ this->from=from;
+ this->to =to;
+ this->step=step;
+ }
+ \decl 0 set (Grid *r=0);
+ \decl 0 bang ();
+ \grin 0 int
+ \grin 1 int
+ \grin 2 int
+ template <class T> void trigger (T bogus);
+};
+
+template <class T>
+void GridFor::trigger (T bogus) {
+ int n = from->dim->prod();
+ int32 nn[n+1];
+ T x[64*n];
+ T *fromb = (T *)*from;
+ T * tob = (T *)*to ;
+ T *stepb = (T *)*step;
+ T to2[n];
+
+ for (int i=step->dim->prod()-1; i>=0; i--)
+ if (!stepb[i]) RAISE("step must not contain zeroes");
+ for (int i=0; i<n; i++) {
+ nn[i] = (tob[i] - fromb[i] + stepb[i] - cmp(stepb[i],(T)0)) / stepb[i];
+ if (nn[i]<0) nn[i]=0;
+ to2[i] = fromb[i]+stepb[i]*nn[i];
+ }
+ P<Dim> d;
+ if (from->dim->n==0) { d = new Dim(*nn); }
+ else { nn[n]=n; d = new Dim(n+1,nn); }
+ int total = d->prod();
+ out=new GridOutlet(this,0,d,from->nt);
+ if (total==0) return;
+ int k=0;
+ for(int d=0;;d++) {
+ // here d is the dim# to reset; d=n for none
+ for(;d<n;d++) x[k+d]=fromb[d];
+ k+=n;
+ if (k==64*n) {out->send(k,x); k=0; COPY(x,x+63*n,n);}
+ else { COPY(x+k,x+k-n,n);}
+ d--;
+ // here d is the dim# to increment
+ for(;;d--) {
+ if (d<0) goto end;
+ x[k+d]+=stepb[d];
+ if (x[k+d]!=to2[d]) break;
+ }
+ }
+ end: if (k) out->send(k,x);
+}
+
+\def 0 bang () {
+ SAME_TYPE(from,to);
+ SAME_TYPE(from,step);
+ if (!from->dim->equal(to->dim) || !to->dim->equal(step->dim))
+ RAISE("dimension mismatch: from:%s to:%s step:%s",
+ from->dim->to_s(),to->dim->to_s(),step->dim->to_s());
+#define FOO(T) trigger((T)0);
+ TYPESWITCH_JUSTINT(from->nt,FOO,);
+#undef FOO
+}
+
+\def 0 set (Grid *r) { from=new Grid(argv[0]); }
+GRID_INPUT(2,step) {} GRID_END
+GRID_INPUT(1,to) {} GRID_END
+GRID_INPUT(0,from) {_0_bang(0,0);} GRID_END
+\end class {install("#for",3,1); add_creator("@for");}
+
+//****************************************************************
+\class GridFinished : FObject {
+ \constructor () {}
+ \grin 0
+};
+GRID_INLET(0) {
+ //in->set_mode(0);
+} GRID_FINISH {
+ outlet_bang(bself->outlets[0]);
+} GRID_END
+\end class {install("#finished",1,1); add_creator("@finished");}
+\class GridDim : FObject {
+ \constructor () {}
+ \grin 0
+};
+GRID_INLET(0) {
+ GridOutlet out(this,0,new Dim(in->dim->n));
+ out.send(in->dim->n,in->dim->v);
+ //in->set_mode(0);
+} GRID_END
+\end class {install("#dim",1,1); add_creator("@dim");}
+\class GridType : FObject {
+ \constructor () {}
+ \grin 0
+};
+GRID_INLET(0) {
+ outlet_symbol(bself->outlets[0],gensym(const_cast<char *>(number_type_table[in->nt].name)));
+ /*in->set_mode(0);*/
+} GRID_END
+\end class {install("#type",1,1); add_creator("@type");}
+
+//****************************************************************
+//{ Dim[*As]<T>,Dim[B] -> Dim[*Cs]<T> }
+\class GridRedim : FObject {
+ \attr P<Dim> dim;
+ PtrGrid dim_grid;
+ PtrGrid temp; // temp->dim is not of the same shape as dim
+ ~GridRedim() {}
+ \constructor (Grid *d) {
+ dim_grid.constrain(expect_dim_dim_list);
+ dim_grid=d;
+ dim = dim_grid->to_dim();
+ // if (!dim->prod()) RAISE("target grid size must not be zero");
+ }
+ \grin 0
+ \grin 1 int32
+};
+
+GRID_INLET(0) {
+ long a=in->dim->prod(), b=dim->prod();
+ if (a<b) temp=new Grid(new Dim(a),in->nt);
+ out=new GridOutlet(this,0,dim,in->nt);
+} GRID_FLOW {
+ long i = dex;
+ if (!temp) {
+ long n2 = min(n,dim->prod()-i);
+ if (n2>0) out->send(n2,data);
+ // discard other values if any
+ } else {
+ long n2 = min(n,in->dim->prod()-i);
+ COPY((T *)*temp+i,data,n2);
+ if (n2>0) out->send(n2,data);
+ }
+} GRID_FINISH {
+ if (!!temp) {
+ long a = in->dim->prod(), b = dim->prod();
+ if (a) {
+ for (long i=a; i<b; i+=a) out->send(min(a,b-i),(T *)*temp);
+ } else {
+ T foo[1]={0}; for (long i=0; i<b; i++) out->send(1,foo);
+ }
+ }
+ temp=0;
+} GRID_END
+
+GRID_INPUT(1,dim_grid) {
+ P<Dim> d = dim_grid->to_dim();
+// if (!d->prod()) RAISE("target grid size must not be zero"); else post("d->prod=%d",d->prod());
+ dim = d;
+} GRID_END
+
+\end class {install("#redim",2,1); add_creator("@redim");}
+
+//****************************************************************
+\class GridJoin : FObject {
+ \attr int which_dim;
+ PtrGrid r;
+ \grin 0
+ \grin 1
+ \constructor (int which_dim=-1, Grid *r=0) {
+ this->which_dim = which_dim;
+ this->r=r;
+ }
+};
+
+GRID_INLET(0) {
+ NOTEMPTY(r);
+ SAME_TYPE(in,r);
+ P<Dim> d = in->dim;
+ if (d->n != r->dim->n) RAISE("wrong number of dimensions");
+ int w = which_dim;
+ if (w<0) w+=d->n;
+ if (w<0 || w>=d->n)
+ RAISE("can't join on dim number %d on %d-dimensional grids",
+ which_dim,d->n);
+ int32 v[d->n];
+ for (int i=0; i<d->n; i++) {
+ v[i] = d->get(i);
+ if (i==w) {
+ v[i]+=r->dim->v[i];
+ } else {
+ if (v[i]!=r->dim->v[i]) RAISE("dimensions mismatch: dim #%i, left is %d, right is %d",i,v[i],r->dim->v[i]);
+ }
+ }
+ out=new GridOutlet(this,0,new Dim(d->n,v),in->nt);
+ in->set_chunk(w);
+} GRID_FLOW {
+ int w = which_dim;
+ if (w<0) w+=in->dim->n;
+ long a = in->dim->prod(w);
+ long b = r->dim->prod(w);
+ T *data2 = (T *)*r + dex*b/a;
+ if (a==3 && b==1) {
+ int m = n+n*b/a;
+ T data3[m];
+ T *data4 = data3;
+ while (n) {
+ SCOPY(data4,data,3); SCOPY(data4+3,data2,1);
+ n-=3; data+=3; data2+=1; data4+=4;
+ }
+ out->send(m,data3);
+ } else if (a+b<=16) {
+ int m = n+n*b/a;
+ T data3[m];
+ int i=0;
+ while (n) {
+ COPY(data3+i,data,a); data+=a; i+=a; n-=a;
+ COPY(data3+i,data2,b); data2+=b; i+=b;
+ }
+ out->send(m,data3);
+ } else {
+ while (n) {
+ out->send(a,data);
+ out->send(b,data2);
+ data+=a; data2+=b; n-=a;
+ }
+ }
+} GRID_FINISH {
+ if (in->dim->prod()==0) out->send(r->dim->prod(),(T *)*r);
+} GRID_END
+
+GRID_INPUT(1,r) {} GRID_END
+
+\end class {install("#join",2,1); add_creator("@join");}
+
+//****************************************************************
+\class GridGrade : FObject {
+ \constructor () {}
+ \grin 0
+};
+
+typedef int (*comparator_t)(const void *, const void *);
+
+template <class T> struct GradeFunction {
+ static int comparator (T **a, T **b) {return **a-**b;}};
+#define FOO(T) \
+template <> struct GradeFunction<T> { \
+ static int comparator (T **a, T **b) {T x = **a-**b; return x<0 ? -1 : x>0;}};
+FOO(int64)
+FOO(float32)
+FOO(float64)
+#undef FOO
+
+GRID_INLET(0) {
+ out=new GridOutlet(this,0,in->dim);
+ in->set_chunk(in->dim->n-1);
+} GRID_FLOW {
+ long m = in->dim->prod(in->dim->n-1);
+ T *foo[m];
+ T bar[m];
+ for (; n; n-=m,data+=m) {
+ for (int i=0; i<m; i++) foo[i] = &data[i];
+ qsort(foo,m,sizeof(T *),(comparator_t)GradeFunction<T>::comparator);
+ for (int i=0; i<m; i++) bar[i] = foo[i]-(T *)data;
+ out->send(m,bar);
+ }
+} GRID_END
+
+\end class {install("#grade",1,1); add_creator("@grade");}
+
+//****************************************************************
+//\class GridMedian : FObject
+//****************************************************************
+
+\class GridTranspose : FObject {
+ \attr int dim1;
+ \attr int dim2;
+ int d1,d2,na,nb,nc,nd; // temporaries
+ \constructor (int dim1=0, int dim2=1) {
+ this->dim1 = dim1;
+ this->dim2 = dim2;
+ }
+ \decl 1 float (int dim1);
+ \decl 2 float (int dim2);
+ \grin 0
+};
+
+\def 1 float (int dim1) { this->dim1=dim1; }
+\def 2 float (int dim2) { this->dim2=dim2; }
+
+GRID_INLET(0) {
+ int32 v[in->dim->n];
+ COPY(v,in->dim->v,in->dim->n);
+ d1=dim1; d2=dim2;
+ if (d1<0) d1+=in->dim->n;
+ if (d2<0) d2+=in->dim->n;
+ if (d1>=in->dim->n || d2>=in->dim->n || d1<0 || d2<0)
+ RAISE("would swap dimensions %d and %d but this grid has only %d dimensions", dim1,dim2,in->dim->n);
+ memswap(v+d1,v+d2,1);
+ if (d1==d2) {
+ out=new GridOutlet(this,0,new Dim(in->dim->n,v), in->nt);
+ } else {
+ nd = in->dim->prod(1+max(d1,d2));
+ nc = in->dim->v[max(d1,d2)];
+ nb = nc&&nd ? in->dim->prod(1+min(d1,d2))/nc/nd : 0;
+ na = in->dim->v[min(d1,d2)];
+ out=new GridOutlet(this,0,new Dim(in->dim->n,v), in->nt);
+ in->set_chunk(min(d1,d2));
+ }
+ // Turns a Grid[*,na,*nb,nc,*nd] into a Grid[*,nc,*nb,na,*nd].
+} GRID_FLOW {
+ //T res[na*nb*nc*nd];
+ T *res = NEWBUF(T,na*nb*nc*nd);
+ if (dim1==dim2) { out->send(n,data); return; }
+ int prod = na*nb*nc*nd;
+ for (; n; n-=prod, data+=prod) {
+ for (long a=0; a<na; a++)
+ for (long b=0; b<nb; b++)
+ for (long c=0; c<nc; c++)
+ COPY(res +((c*nb+b)*na+a)*nd,
+ data+((a*nb+b)*nc+c)*nd,nd);
+ out->send(na*nb*nc*nd,res);
+ }
+ DELBUF(res); //!@#$ if an exception was thrown by out->send, this never gets done
+} GRID_END
+
+\end class {install("#transpose",3,1); add_creator("@transpose");}
+
+//****************************************************************
+\class GridReverse : FObject {
+ \attr int dim1; // dimension to act upon
+ int d; // temporaries
+ \constructor (int dim1=0) {this->dim1 = dim1;}
+ \decl 1 float (int dim1);
+ \grin 0
+};
+
+\def 1 float (int dim1) { this->dim1=dim1; }
+
+GRID_INLET(0) {
+ d=dim1;
+ if (d<0) d+=in->dim->n;
+ if (d>=in->dim->n || d<0)
+ RAISE("would reverse dimension %d but this grid has only %d dimensions",
+ dim1,in->dim->n);
+ out=new GridOutlet(this,0,new Dim(in->dim->n,in->dim->v), in->nt);
+ in->set_chunk(d);
+} GRID_FLOW {
+ long f1=in->dim->prod(d), f2=in->dim->prod(d+1);
+ while (n) {
+ long hf1=f1/2;
+ T *data2 = data+f1-f2;
+ for (long i=0; i<hf1; i+=f2) memswap(data+i,data2-i,f2);
+ out->send(f1,data);
+ data+=f1; n-=f1;
+ }
+} GRID_END
+
+\end class {install("#reverse",2,1);}
+
+//****************************************************************
+\class GridCentroid : FObject {
+ \constructor () {}
+ \grin 0 int
+ int sumx,sumy,sum,y; // temporaries
+};
+
+GRID_INLET(0) {
+ if (in->dim->n != 3) RAISE("expecting 3 dims");
+ if (in->dim->v[2] != 1) RAISE("expecting 1 channel");
+ in->set_chunk(1);
+ out=new GridOutlet(this,0,new Dim(2), in->nt);
+ sumx=0; sumy=0; sum=0; y=0;
+} GRID_FLOW {
+ int sx = in->dim->v[1];
+ while (n) {
+ for (int x=0; x<sx; x++) {
+ sumx+=x*data[x];
+ sumy+=y*data[x];
+ sum += data[x];
+ }
+ n-=sx;
+ data+=sx;
+ y++;
+ }
+} GRID_FINISH {
+ int32 blah[2];
+ blah[0] = sum ? sumy/sum : 0;
+ blah[1] = sum ? sumx/sum : 0;
+ out->send(2,blah);
+ outlet_float(bself->outlets[1],blah[0]);
+ outlet_float(bself->outlets[2],blah[1]);
+} GRID_END
+
+\end class {install("#centroid",1,3);}
+
+//****************************************************************
+static void expect_pair (P<Dim> dim) {if (dim->prod()!=2) RAISE("expecting only two numbers. Dim(2)");}
+
+\class GridMoment : FObject {
+ \constructor (int order=1) {
+ offset.constrain(expect_pair);
+ //t_atom2 a[2] = {t_atom2(0),t_atom2(0)};
+ t_atom a[2]; SETFLOAT(a,0); SETFLOAT(a+1,0);
+ offset=new Grid(2,a,int32_e);
+ if (order!=1 && order!=2) RAISE("supports only orders 1 and 2 for now");
+ this->order=order;
+ }
+ \grin 0 int
+ \grin 1 int
+ \attr int order; // order
+ \attr PtrGrid offset;
+ int64 sumy,sumxy,sumx,sum,y; // temporaries
+};
+
+GRID_INLET(0) {
+ if (in->dim->n != 3) RAISE("expecting 3 dims");
+ if (in->dim->v[2] != 1) RAISE("expecting 1 channel");
+ in->set_chunk(1);
+ switch (order) {
+ case 1: out=new GridOutlet(this,0,new Dim(2 ), in->nt); break;
+ case 2: out=new GridOutlet(this,0,new Dim(2,2), in->nt); break;
+ default: RAISE("supports only orders 1 and 2 for now");
+ }
+ sumx=0; sumy=0; sumxy=0; sum=0; y=0;
+} GRID_FLOW {
+ int sx = in->dim->v[1];
+ int oy = ((int*)*offset)[0];
+ int ox = ((int*)*offset)[1];
+ while (n) {
+ switch (order) {
+ case 1:
+ for (int x=0; x<sx; x++) {
+ sumy+=y*data[x];
+ sumx+=x*data[x];
+ sum += data[x];
+ }
+ break;
+ case 2:
+ for (int x=0; x<sx; x++) {
+ int ty=y-oy;
+ int tx=x-ox;
+ sumy +=ty*ty*data[x];
+ sumxy+=tx*ty*data[x];
+ sumx +=tx*tx*data[x];
+ sum += data[x];
+ }
+ }
+ n-=sx;
+ data+=sx;
+ y++;
+ }
+} GRID_FINISH {
+ int32 blah[4];
+ switch (order) {
+ case 1: /* centroid vector */
+ blah[0] = sum ? sumy/sum : 0;
+ blah[1] = sum ? sumx/sum : 0;
+ out->send(2,blah);
+ break;
+ case 2: /* covariance matrix */
+ blah[0] = sum ? sumy/sum : 0;
+ blah[1] = sum ? sumxy/sum : 0;
+ blah[2] = sum ? sumxy/sum : 0;
+ blah[3] = sum ? sumx/sum : 0;
+ out->send(4,blah);
+ break;
+ }
+} GRID_END
+
+GRID_INPUT(1,offset) {} GRID_END
+
+\end class {install("#moment",2,1);}
+
+//****************************************************************
+\class GridLabelling : FObject {
+ \grin 0
+ \attr int form();
+ \attr int form_val;
+ \constructor (int form=0) {form_val=form; initialize3();}
+ void initialize3() {bself->noutlets_set(form_val ? 2 : 4);}
+};
+struct Stats {
+ int64 yy,yx,xx,y,x,area;
+ int64 x1,x2;
+ Stats() {yy=yx=xx=y=x=area=0;}
+};
+#define AT(y,x) dat[(y)*sx+(x)]
+template <class T> void flood_fill(T *dat, int sy, int sx, int y, int x, Stats *stat, int label, int form) {
+ /* find x1,x2 such that all the x of that horizontal segment are x1<=x<x2 */
+ int x2; for (x2=x; x2<sx; x2++) if (AT(y,x2)!=1) break;
+ int x1; for (x1=x; x1>=0; x1--) if (AT(y,x1)!=1) break;
+ x1++;
+ if (form==0) {
+ for (x=x1; x<x2; x++) {
+ AT(y,x)=label;
+ stat->yy += y*y; stat->y += y;
+ stat->yx += y*x; stat->area++;
+ stat->xx += x*x; stat->x += x;
+ }
+ for (x=x1; x<x2; x++) {
+ if (y>0 && AT(y-1,x)==1) flood_fill(dat,sy,sx,y-1,x,stat,label,form);
+ if (y<sy-1 && AT(y+1,x)==1) flood_fill(dat,sy,sx,y+1,x,stat,label,form);
+ }
+ } else {
+ for (x=x1; x<x2; x++) {
+ AT(y,x)=label;
+ }
+ stat->y=y;
+ stat->x1=x1;
+ stat->x2=x2;
+ }
+}
+
+GRID_INLET(0) {
+ if (in->dim->n<2 || in->dim->prod(2)!=1) RAISE("requires dim (y,x) or (y,x,1)");
+ in->set_chunk(0);
+} GRID_FLOW {
+ int sy=in->dim->v[0], sx=in->dim->v[1];
+ T *dat = NEWBUF(T,n);
+ for (int i=0; i<n; i++) dat[i]=data[i];
+ int y,x=0,label=2;
+ for (y=0; y<sy; y++) for (x=0; x<sx; x++) {
+ if (dat[y*sx+x]!=1) continue;
+ Stats s;
+ flood_fill(dat,sy,sx,y,x,&s,label,form_val);
+ if (form_val==0) {
+ float32 cooked[6] = {
+ (s.yy-s.y*s.y/s.area)/s.area,
+ (s.yx-s.y*s.x/s.area)/s.area,
+ (s.yx-s.y*s.x/s.area)/s.area,
+ (s.xx-s.x*s.x/s.area)/s.area,
+ s.y/s.area,
+ s.x/s.area};
+ float a[] = {s.area};
+ send_out(3,1,a);
+ GridOutlet o2(this,2,new Dim(2)); o2.send(2,cooked+4);
+ GridOutlet o1(this,1,new Dim(2,2)); o1.send(4,cooked);
+ } else {
+ float32 cooked[4] = {s.y,s.x1,s.y,s.x2};
+ GridOutlet o1(this,1,new Dim(2,2)); o1.send(4,cooked);
+ }
+ label++;
+ }
+ out = new GridOutlet(this,0,new Dim(sy,sx,1),in->nt);
+ out->send(n,dat);
+ DELBUF(dat);
+} GRID_END
+
+\def int form() {return form_val;}
+\def 0 form(int form) {
+ if (form<0 || form>1) RAISE("form must be 0 or 1, not %d",form);
+ form_val=form;
+ initialize3();
+}
+\end class {install("#labelling",1,0); add_creator("#labeling");}
+
+//****************************************************************
+\class GridPerspective : FObject {
+ \attr int32 z;
+ \grin 0
+ \constructor (int32 z=256) {this->z=z;}
+};
+GRID_INLET(0) {
+ int n = in->dim->n;
+ int32 v[n];
+ COPY(v,in->dim->v,n);
+ v[n-1]--;
+ in->set_chunk(in->dim->n-1);
+ out=new GridOutlet(this,0,new Dim(n,v),in->nt);
+} GRID_FLOW {
+ int m = in->dim->prod(in->dim->n-1);
+ for (; n; n-=m,data+=m) {
+ op_mul->map(m-1,data,(T)z);
+ op_div->map(m-1,data,data[m-1]);
+ out->send(m-1,data);
+ }
+} GRID_END
+\end class {install("#perspective",1,1); add_creator("@perspective");}
+
+//****************************************************************
+\class GridBorder : FObject {
+ \attr P<Dim> diml;
+ \attr P<Dim> dimr;
+ PtrGrid diml_grid;
+ PtrGrid dimr_grid;
+ \grin 0
+ \grin 1 int
+ \grin 2 int
+ \constructor (Grid *dl=0, Grid *dr=0) {
+ t_atom a[2]; SETFLOAT(a+0,1); SETFLOAT(a+1,1); SETFLOAT(a+2,0);
+ diml_grid=dl?dl:new Grid(3,a,int32_e);
+ dimr_grid=dr?dr:new Grid(3,a,int32_e);
+ diml = diml_grid->to_dim();
+ dimr = dimr_grid->to_dim();
+ }
+};
+
+GRID_INLET(0) {
+ int n = in->dim->n;
+ if (n!=3) RAISE("only 3 dims supported for now");
+ if (diml->n != n) RAISE("diml mismatch");
+ if (dimr->n != n) RAISE("dimr mismatch");
+ if (diml->v[2] || dimr->v[2]) RAISE("can't augment channels (todo)");
+ int32 v[n];
+ for (int i=0; i<n; i++) v[i]=in->dim->v[i]+diml->v[i]+dimr->v[i];
+ in->set_chunk(0);
+ out=new GridOutlet(this,0,new Dim(n,v),in->nt);
+} GRID_FLOW {
+ int sy = in->dim->v[0];
+ int sx = in->dim->v[1]; int zx = sx+diml->v[1]+dimr->v[1];
+ int sc = in->dim->v[2]; int zc = sc+diml->v[2]+dimr->v[2];
+ int sxc = sx*sc; int zxc = zx*zc;
+ int32 duh[zxc];
+ for (int x=0; x<zxc; x++) duh[x]=0;
+ for (int y=0; y<diml->v[0]; y++) out->send(zxc,duh);
+ for (int y=0; y<sy; y++) {
+ out->send(diml->v[1]*sc,duh);
+ out->send(sxc,data+y*sxc);
+ out->send(dimr->v[1]*sc,duh);
+ }
+ for (int i=0; i<dimr->v[0]; i++) out->send(zxc,duh);
+} GRID_END
+
+GRID_INPUT(1,diml_grid) {diml = diml_grid->to_dim();} GRID_END
+GRID_INPUT(2,dimr_grid) {dimr = dimr_grid->to_dim();} GRID_END
+
+\end class {install("#border",3,1);}
+
+static void expect_picture (P<Dim> d) {
+ if (d->n!=3) RAISE("(height,width,chans) dimensions please");}
+static void expect_rgb_picture (P<Dim> d) {
+ expect_picture(d);
+ if (d->get(2)!=3) RAISE("(red,green,blue) channels please");}
+static void expect_rgba_picture (P<Dim> d) {
+ expect_picture(d);
+ if (d->get(2)!=4) RAISE("(red,green,blue,alpha) channels please");}
+
+//****************************************************************
+//{ Dim[A,B,*Cs]<T>,Dim[D,E]<T> -> Dim[A,B,*Cs]<T> }
+
+static void expect_convolution_matrix (P<Dim> d) {
+ if (d->n != 2) RAISE("only exactly two dimensions allowed for now (got %d)",
+ d->n);
+}
+
+// entry in a compiled convolution kernel
+struct PlanEntry {long y,x; bool neutral;};
+
+\class GridConvolve : FObject {
+ \attr Numop *op;
+ \attr Numop *fold;
+ \attr PtrGrid seed;
+ \attr PtrGrid b;
+ \attr bool wrap;
+ \attr bool anti;
+ PtrGrid a;
+ int plann;
+ PlanEntry *plan;
+ int margx,margy; // margins
+ \constructor (Grid *r=0) {
+ plan=0;
+ b.constrain(expect_convolution_matrix); plan=0;
+ this->op = op_mul;
+ this->fold = op_add;
+ this->seed = new Grid(new Dim(),int32_e,true);
+ this->b= r ? r : new Grid(new Dim(1,1),int32_e,true);
+ this->wrap = true;
+ this->anti = true;
+ }
+ \grin 0
+ \grin 1
+ template <class T> void copy_row (T *buf, long sx, long y, long x);
+ template <class T> void make_plan (T bogus);
+ ~GridConvolve () {if (plan) delete[] plan;}
+};
+
+template <class T> void GridConvolve::copy_row (T *buf, long sx, long y, long x) {
+ long day = a->dim->get(0), dax = a->dim->get(1), dac = a->dim->prod(2);
+ y=mod(y,day); x=mod(x,dax);
+ T *ap = (T *)*a + y*dax*dac;
+ while (sx) {
+ long sx1 = min(sx,dax-x);
+ COPY(buf,ap+x*dac,sx1*dac);
+ x=0;
+ buf += sx1*dac;
+ sx -= sx1;
+ }
+}
+
+template <class T> void GridConvolve::make_plan (T bogus) {
+ P<Dim> da = a->dim, db = b->dim;
+ long dby = db->get(0);
+ long dbx = db->get(1);
+ if (plan) delete[] plan;
+ plan = new PlanEntry[dbx*dby];
+ long i=0;
+ for (long y=0; y<dby; y++) {
+ for (long x=0; x<dbx; x++) {
+ long k = anti ? y*dbx+x : (dby-1-y)*dbx+(dbx-1-x);
+ T rh = ((T *)*b)[k];
+ bool neutral = op->on(rh)->is_neutral( rh,at_right);
+ bool absorbent = op->on(rh)->is_absorbent(rh,at_right);
+ T foo[1]={0};
+ if (absorbent) {
+ op->map(1,foo,rh);
+ absorbent = fold->on(rh)->is_neutral(foo[0],at_right);
+ }
+ if (absorbent) continue;
+ plan[i].y = y;
+ plan[i].x = x;
+ plan[i].neutral = neutral;
+ i++;
+ }
+ }
+ plann = i;
+}
+
+GRID_INLET(0) {
+ SAME_TYPE(in,b);
+ SAME_TYPE(in,seed);
+ P<Dim> da=in->dim, db=b->dim;
+ if (!db) RAISE("right inlet has no grid");
+ if (!seed) RAISE("seed missing");
+ if (db->n != 2) RAISE("right grid must have two dimensions");
+ if (da->n < 2) RAISE("left grid has less than two dimensions");
+ if (seed->dim->n != 0) RAISE("seed must be scalar");
+ if (da->get(0) < db->get(0)) RAISE("grid too small (y): %d < %d", da->get(0), db->get(0));
+ if (da->get(1) < db->get(1)) RAISE("grid too small (x): %d < %d", da->get(1), db->get(1));
+ margy = (db->get(0)-1)/2;
+ margx = (db->get(1)-1)/2;
+ //if (a) post("for %p, a->dim=%s da=%s",this,a->dim->to_s(),da->to_s());
+ if (!a || !a->dim->equal(da)) a=new Grid(da,in->nt); // with this condition it's 2% faster on Linux but takes more RAM.
+ //a=new Grid(da,in->nt); // with this condition it's 2% faster but takes more RAM.
+ int v[da->n]; COPY(v,da->v,da->n);
+ if (!wrap) {v[0]-=db->v[0]-1; v[1]-=db->v[1]-1;}
+ out=new GridOutlet(this,0,new Dim(da->n,v),in->nt);
+} GRID_FLOW {
+ COPY((T *)*a+dex, data, n);
+} GRID_FINISH {
+ make_plan((T)0);
+ long dbx = b->dim->get(1);
+ long dby = b->dim->get(0);
+ long day = out->dim->get(0);
+ long n = out->dim->prod(1);
+ long sx = out->dim->get(1)+dbx-1;
+ long sxc = out->dim->prod(2)*sx;
+ T buf[n];
+ T buf2[sxc];
+ T orh=0;
+ for (long ay=0; ay<day; ay++) {
+ op_put->map(n,buf,*(T *)*seed);
+ for (long i=0; i<plann; i++) {
+ long by = plan[i].y;
+ long bx = plan[i].x;
+ long k = anti ? by*dbx+bx : (dby-1-by)*dbx+(dbx-1-bx);
+ T rh = ((T *)*b)[k];
+ if (i==0 || by!=plan[i-1].y || orh!=rh) {
+ if (wrap) copy_row(buf2,sx,ay+by-margy,-margx);
+ else copy_row(buf2,sx,ay+by,0);
+ if (!plan[i].neutral) op->map(sxc,buf2,rh);
+ }
+ fold->zip(n,buf,buf2+bx*out->dim->prod(2));
+ orh=rh;
+ }
+ out->send(n,buf);
+ }
+ //a=0; // comment this out when trying to recycle a (use the dim->equal above)
+} GRID_END
+
+GRID_INPUT(1,b) {} GRID_END
+
+\end class {install("#convolve",2,1);}
+
+/* ---------------------------------------------------------------- */
+/* "#scale_by" does quick scaling of pictures by integer factors */
+/*{ Dim[A,B,3]<T> -> Dim[C,D,3]<T> }*/
+
+static void expect_scale_factor (P<Dim> dim) {
+ if (dim->prod()!=1 && dim->prod()!=2)
+ RAISE("expecting only one or two numbers");
+}
+
+\class GridScaleBy : FObject {
+ \attr PtrGrid scale; // integer scale factor
+ int scaley;
+ int scalex;
+ \constructor (Grid *factor=0) {
+ scale.constrain(expect_scale_factor);
+ t_atom a[1]; SETFLOAT(a,2);
+ scale = factor?factor:new Grid(1,a,int32_e);
+ prepare_scale_factor();
+ }
+ \grin 0
+ \grin 1
+ void prepare_scale_factor () {
+ scaley = ((int32 *)*scale)[0];
+ scalex = ((int32 *)*scale)[scale->dim->prod()==1 ? 0 : 1];
+ if (scaley<1) scaley=2;
+ if (scalex<1) scalex=2;
+ }
+};
+
+GRID_INLET(0) {
+ P<Dim> a = in->dim;
+ expect_picture(a);
+ out=new GridOutlet(this,0,new Dim(a->get(0)*scaley,a->get(1)*scalex,a->get(2)),in->nt);
+ in->set_chunk(1);
+} GRID_FLOW {
+ int rowsize = in->dim->prod(1);
+ T buf[rowsize*scalex];
+ int chans = in->dim->get(2);
+ #define Z(z) buf[p+z]=data[i+z]
+ for (; n>0; data+=rowsize, n-=rowsize) {
+ int p=0;
+ #define LOOP(z) \
+ for (int i=0; i<rowsize; i+=z) \
+ for (int k=0; k<scalex; k++, p+=z)
+ switch (chans) {
+ case 3: LOOP(3) {Z(0);Z(1);Z(2);} break;
+ case 4: LOOP(4) {Z(0);Z(1);Z(2);Z(3);} break;
+ default: LOOP(chans) {for (int c=0; c<chans; c++) Z(c);}
+ }
+ #undef LOOP
+ for (int j=0; j<scaley; j++) out->send(rowsize*scalex,buf);
+ }
+ #undef Z
+} GRID_END
+
+GRID_INPUT(1,scale) {prepare_scale_factor();} GRID_END
+
+\end class {install("#scale_by",2,1); add_creator("@scale_by");}
+
+// ----------------------------------------------------------------
+//{ Dim[A,B,3]<T> -> Dim[C,D,3]<T> }
+\class GridDownscaleBy : FObject {
+ \attr PtrGrid scale;
+ \attr bool smoothly;
+ int scaley;
+ int scalex;
+ PtrGrid temp;
+ \constructor (Grid *factor=0, t_symbol *option=0) {
+ scale.constrain(expect_scale_factor);
+ t_atom a[1]; SETFLOAT(a,2);
+ scale = factor?factor:new Grid(1,a,int32_e);
+ prepare_scale_factor();
+ smoothly = option==gensym("smoothly");
+ }
+ \grin 0
+ \grin 1
+ void prepare_scale_factor () {
+ scaley = ((int32 *)*scale)[0];
+ scalex = ((int32 *)*scale)[scale->dim->prod()==1 ? 0 : 1];
+ if (scaley<1) scaley=2;
+ if (scalex<1) scalex=2;
+ }
+};
+
+GRID_INLET(0) {
+ P<Dim> a = in->dim;
+ if (a->n!=3) RAISE("(height,width,chans) please");
+ out=new GridOutlet(this,0,new Dim(a->get(0)/scaley,a->get(1)/scalex,a->get(2)),in->nt);
+ in->set_chunk(1);
+ // i don't remember why two rows instead of just one.
+ temp=new Grid(new Dim(2,in->dim->get(1)/scalex,in->dim->get(2)),in->nt);
+} GRID_FLOW {
+ int rowsize = in->dim->prod(1);
+ int rowsize2 = temp->dim->prod(1);
+ T *buf = (T *)*temp; //!@#$ maybe should be something else than T ?
+ int xinc = in->dim->get(2)*scalex;
+ int y = dex / rowsize;
+ int chans=in->dim->get(2);
+ #define Z(z) buf[p+z]+=data[i+z]
+ if (smoothly) {
+ while (n>0) {
+ if (y%scaley==0) CLEAR(buf,rowsize2);
+ #define LOOP(z) \
+ for (int i=0,p=0; p<rowsize2; p+=z) \
+ for (int j=0; j<scalex; j++,i+=z)
+ switch (chans) {
+ case 1: LOOP(1) {Z(0);} break;
+ case 2: LOOP(2) {Z(0);Z(1);} break;
+ case 3: LOOP(3) {Z(0);Z(1);Z(2);} break;
+ case 4: LOOP(4) {Z(0);Z(1);Z(2);Z(3);} break;
+ default:LOOP(chans) {for (int k=0; k<chans; k++) Z(k);} break;
+ }
+ #undef LOOP
+ y++;
+ if (y%scaley==0 && out->dim) {
+ op_div->map(rowsize2,buf,(T)(scalex*scaley));
+ out->send(rowsize2,buf);
+ CLEAR(buf,rowsize2);
+ }
+ data+=rowsize;
+ n-=rowsize;
+ }
+ #undef Z
+ } else {
+ #define Z(z) buf[p+z]=data[i+z]
+ for (; n>0 && out->dim; data+=rowsize, n-=rowsize,y++) {
+ if (y%scaley!=0) continue;
+ #define LOOP(z) for (int i=0,p=0; p<rowsize2; i+=xinc, p+=z)
+ switch(in->dim->get(2)) {
+ case 1: LOOP(1) {Z(0);} break;
+ case 2: LOOP(2) {Z(0);Z(1);} break;
+ case 3: LOOP(3) {Z(0);Z(1);Z(2);} break;
+ case 4: LOOP(4) {Z(0);Z(1);Z(2);Z(3);} break;
+ default:LOOP(chans) {for (int k=0; k<chans; k++) Z(k);}break;
+ }
+ #undef LOOP
+ out->send(rowsize2,buf);
+ }
+ }
+ #undef Z
+} GRID_END
+
+GRID_INPUT(1,scale) {prepare_scale_factor();} GRID_END
+
+\end class {install("#downscale_by",2,1); add_creator("@downscale_by");}
+
+//****************************************************************
+\class GridLayer : FObject {
+ PtrGrid r;
+ \constructor () {r.constrain(expect_rgb_picture);}
+ \grin 0 int
+ \grin 1 int
+};
+
+GRID_INLET(0) {
+ NOTEMPTY(r);
+ SAME_TYPE(in,r);
+ P<Dim> a = in->dim;
+ expect_rgba_picture(a);
+ if (a->get(1)!=r->dim->get(1)) RAISE("same width please");
+ if (a->get(0)!=r->dim->get(0)) RAISE("same height please");
+ in->set_chunk(2);
+ out=new GridOutlet(this,0,r->dim);
+} GRID_FLOW {
+ T *rr = ((T *)*r) + dex*3/4;
+ T foo[n*3/4];
+#define COMPUTE_ALPHA(c,a) \
+ foo[j+c] = (data[i+c]*data[i+a] + rr[j+c]*(256-data[i+a])) >> 8
+ for (int i=0,j=0; i<n; i+=4,j+=3) {
+ COMPUTE_ALPHA(0,3);
+ COMPUTE_ALPHA(1,3);
+ COMPUTE_ALPHA(2,3);
+ }
+#undef COMPUTE_ALPHA
+ out->send(n*3/4,foo);
+} GRID_END
+
+GRID_INPUT(1,r) {} GRID_END
+
+\end class {install("#layer",2,1); add_creator("@layer");}
+
+// ****************************************************************
+// pad1,pad2 only are there for 32-byte alignment
+struct Line {int32 y1,x1,y2,x2,x,m,ox,pad2;};
+
+static void expect_polygon (P<Dim> d) {
+ if (d->n!=2 || d->get(1)!=2) RAISE("expecting Dim[n,2] polygon");
+}
+
+enum DrawMode {DRAW_FILL,DRAW_LINE,DRAW_POINT};
+enum OmitMode {OMIT_NONE,OMIT_LAST,OMIT_ODD};
+DrawMode convert(const t_atom &x, DrawMode *foo) {
+ t_symbol *s = convert(x,(t_symbol **)0);
+ if (s==gensym("fill")) return DRAW_FILL;
+ if (s==gensym("line")) return DRAW_LINE;
+ if (s==gensym("point")) return DRAW_POINT;
+ RAISE("unknown DrawMode '%s' (want fill or line)",s->s_name);
+}
+OmitMode convert(const t_atom &x, OmitMode *foo) {
+ t_symbol *s = convert(x,(t_symbol **)0);
+ if (s==gensym("none")) return OMIT_NONE;
+ if (s==gensym("last")) return OMIT_LAST;
+ if (s==gensym("odd")) return OMIT_ODD;
+ RAISE("unknown OmitMode '%s' (want none or last or odd)",s->s_name);
+}
+\class DrawPolygon : FObject {
+ \attr Numop *op;
+ \attr PtrGrid color;
+ \attr PtrGrid polygon;
+ \attr DrawMode draw;
+ \attr OmitMode omit;
+ PtrGrid color2;
+ PtrGrid lines;
+ int lines_start;
+ int lines_stop;
+ \constructor (Numop *op=op_put, Grid *color=0, Grid *polygon=0) {
+ draw=DRAW_FILL;
+ omit=OMIT_NONE;
+ this->color.constrain(expect_max_one_dim);
+ this->polygon.constrain(expect_polygon);
+ this->op = op;
+ if (color) this->color=color;
+ if (polygon) {this->polygon=polygon; init_lines();}
+ }
+ \grin 0
+ \grin 1
+ \grin 2 int32
+ void init_lines();
+ void changed(t_symbol *s) {init_lines();}
+};
+void DrawPolygon::init_lines () {
+ if (!polygon) return;
+ int tnl = polygon->dim->get(0);
+ int nl = omit==OMIT_LAST ? tnl-1 : omit==OMIT_ODD ? (tnl+1)/2 : tnl;
+ lines=new Grid(new Dim(nl,8), int32_e);
+ Line *ld = (Line *)(int32 *)*lines;
+ int32 *pd = *polygon;
+ for (int i=0,j=0; i<nl; i++) {
+ ld[i].y1 = pd[j+0];
+ ld[i].x1 = pd[j+1];
+ j=(j+2)%(2*tnl);
+ ld[i].y2 = pd[j+0];
+ ld[i].x2 = pd[j+1];
+ if (omit==OMIT_ODD) j=(j+2)%(2*tnl);
+ if (draw!=DRAW_POINT) if (ld[i].y1>ld[i].y2) memswap((int32 *)(ld+i)+0,(int32 *)(ld+i)+2,2);
+ long dy = ld[i].y2-ld[i].y1;
+ long dx = ld[i].x2-ld[i].x1;
+ ld[i].m = dy ? (dx<<16)/dy : 0;
+ }
+}
+
+static int order_by_starting_scanline (const void *a, const void *b) {
+ return ((Line *)a)->y1 - ((Line *)b)->y1;
+}
+
+static int order_by_column (const void *a, const void *b) {
+ return ((Line *)a)->x - ((Line *)b)->x;
+}
+
+GRID_INLET(0) {
+ NOTEMPTY(color);
+ NOTEMPTY(polygon);
+ NOTEMPTY(lines);
+ SAME_TYPE(in,color);
+ if (in->dim->n!=3) RAISE("expecting 3 dimensions");
+ if (in->dim->get(2)!=color->dim->get(0)) RAISE("image does not have same number of channels as stored color");
+ out=new GridOutlet(this,0,in->dim,in->nt);
+ lines_start = lines_stop = 0;
+ in->set_chunk(1);
+ int nl = lines->dim->get(0);
+ qsort((int32 *)*lines,nl,sizeof(Line),order_by_starting_scanline);
+ int cn = color->dim->prod();
+ color2=new Grid(new Dim(cn*16), color->nt);
+ for (int i=0; i<16; i++) COPY((T *)*color2+cn*i,(T *)*color,cn);
+} GRID_FLOW {
+ int nl = lines->dim->get(0);
+ Line *ld = (Line *)(int32 *)*lines;
+ int f = in->dim->prod(1);
+ int y = dex/f;
+ int cn = color->dim->prod();
+ T *cd = (T *)*color2;
+ while (n) {
+ while (lines_stop != nl && ld[lines_stop].y1<=y) {
+ Line &l = ld[lines_stop];
+ l.x = l.x1 + (((y-l.y1)*l.m)>>16);
+ lines_stop++;
+ }
+ if (draw!=DRAW_POINT) {
+ int fudge = draw==DRAW_FILL?0:1;
+ for (int i=lines_start; i<lines_stop; i++) {
+ if (ld[i].y2<=y-fudge) {memswap(ld+i,ld+lines_start,1); lines_start++;}
+ }
+ }
+ if (lines_start == lines_stop) {
+ out->send(f,data);
+ } else {
+ int32 xl = in->dim->get(1);
+ T data2[f];
+ COPY(data2,data,f);
+ for (int i=lines_start; i<lines_stop; i++) {
+ Line &l = ld[i];
+ l.ox = l.x;
+ l.x = l.x1 + (((y-l.y1)*l.m)>>16);
+ }
+ if (draw!=DRAW_POINT) qsort(ld+lines_start,lines_stop-lines_start,sizeof(Line),order_by_column);
+ if (draw==DRAW_FILL) {
+ for (int i=lines_start; i<lines_stop-1; i+=2) {
+ int xs = max(ld[i].x,(int32)0);
+ int xe = min(ld[i+1].x,xl);
+ if (xs>=xe) continue; /* !@#$ WHAT? */
+ while (xe-xs>=16) {op->zip(16*cn,data2+cn*xs,cd); xs+=16;}
+ op->zip((xe-xs)*cn,data2+cn*xs,cd);
+ }
+ } else if (draw==DRAW_LINE) {
+ for (int i=lines_start; i<lines_stop; i++) {
+ if (ld[i].y1==ld[i].y2) ld[i].ox=ld[i].x2;
+ int xs = min(ld[i].x,ld[i].ox);
+ int xe = max(ld[i].x,ld[i].ox);
+ if (xs==xe) xe++;
+ if ((xs<0 && xe<0) || (xs>=xl && xe>=xl)) continue;
+ xs = max(0,xs);
+ xe = min(xl,xe);
+ while (xe-xs>=16) {op->zip(16*cn,data2+cn*xs,cd); xs+=16;}
+ op->zip((xe-xs)*cn,data2+cn*xs,cd);
+ }
+ } else {
+ for (int i=lines_start; i<lines_stop; i++) {
+ if (y!=ld[i].y1) continue;
+ int xs=ld[i].x1;
+ int xe=xs+1;
+ if (xs<0 || xs>=xl) continue;
+ op->zip((xe-xs)*cn,data2+cn*xs,cd);
+ }
+ lines_start=lines_stop;
+ }
+ out->send(f,data2);
+ }
+ n-=f;
+ data+=f;
+ y++;
+ }
+} GRID_END
+
+
+GRID_INPUT(1,color) {} GRID_END
+GRID_INPUT(2,polygon) {init_lines();} GRID_END
+
+\end class {install("#draw_polygon",3,1); add_creator("@draw_polygon");}
+
+//****************************************************************
+static void expect_position(P<Dim> d) {
+ if (d->n!=1) RAISE("position should have 1 dimension, not %d", d->n);
+ if (d->v[0]!=2) RAISE("position dim 0 should have 2 elements, not %d", d->v[0]);
+}
+
+\class DrawImage : FObject {
+ \attr Numop *op;
+ \attr PtrGrid image;
+ \attr PtrGrid position;
+ \attr bool alpha;
+ \attr bool tile;
+ \constructor (Numop *op=op_put, Grid *image=0, Grid *position=0) {
+ alpha=false; tile=false;
+ this->op = op;
+ this->position.constrain(expect_position);
+ this->image.constrain(expect_picture);
+ if (image) this->image=image;
+ if (position) this->position=position;
+ else this->position=new Grid(new Dim(2),int32_e,true);
+ }
+ \grin 0
+ \grin 1
+ \grin 2 int32
+ // draw row # ry of right image in row buffer buf, starting at xs
+ // overflow on both sides has to be handled automatically by this method
+ template <class T> void draw_segment(T *obuf, T *ibuf, int ry, int x0);
+};
+
+#define COMPUTE_ALPHA(c,a) obuf[j+(c)] = ibuf[j+(c)] + (rbuf[a])*(obuf[j+(c)]-ibuf[j+(c)])/256;
+#define COMPUTE_ALPHA4(b) \
+ COMPUTE_ALPHA(b+0,b+3); \
+ COMPUTE_ALPHA(b+1,b+3); \
+ COMPUTE_ALPHA(b+2,b+3); \
+ obuf[b+3] = rbuf[b+3] + (255-rbuf[b+3])*(ibuf[j+b+3])/256;
+
+template <class T> void DrawImage::draw_segment(T *obuf, T *ibuf, int ry, int x0) {
+ if (ry<0 || ry>=image->dim->get(0)) return; // outside of image
+ int sx = in[0]->dim->get(1), rsx = image->dim->get(1);
+ int sc = in[0]->dim->get(2), rsc = image->dim->get(2);
+ T *rbuf = (T *)*image + ry*rsx*rsc;
+ if (x0>sx || x0<=-rsx) return; // outside of buffer
+ int n=rsx;
+ if (x0+n>sx) n=sx-x0;
+ if (x0<0) { rbuf-=rsc*x0; n+=x0; x0=0; }
+ if (alpha && rsc==4 && sc==3) { // RGB by RGBA //!@#$ optimise
+ int j=sc*x0;
+ for (; n; n--, rbuf+=4, j+=3) {
+ op->zip(sc,obuf+j,rbuf); COMPUTE_ALPHA(0,3); COMPUTE_ALPHA(1,3); COMPUTE_ALPHA(2,3);
+ }
+ } else if (alpha && rsc==4 && sc==4) { // RGBA by RGBA
+ op->zip(n*rsc,obuf+x0*rsc,rbuf);
+ int j=sc*x0;
+ for (; n>=4; n-=4, rbuf+=16, j+=16) {
+ COMPUTE_ALPHA4(0);COMPUTE_ALPHA4(4);
+ COMPUTE_ALPHA4(8);COMPUTE_ALPHA4(12);
+ }
+ for (; n; n--, rbuf+=4, j+=4) {
+ COMPUTE_ALPHA4(0);
+ }
+ } else { // RGB by RGB, etc
+ op->zip(n*rsc,obuf+sc*x0,rbuf);
+ }
+}
+
+GRID_INLET(0) {
+ NOTEMPTY(image);
+ NOTEMPTY(position);
+ SAME_TYPE(in,image);
+ if (in->dim->n!=3) RAISE("expecting 3 dimensions");
+ if (image->dim->n!=3) RAISE("expecting 3 dimensions in right_hand");
+ int lchan = in->dim->get(2);
+ int rchan = image->dim->get(2);
+ if (alpha && rchan!=4) {
+ RAISE("alpha mode works only with 4 channels in right_hand");
+ }
+ if (lchan != rchan-(alpha?1:0) && lchan != rchan) {
+ RAISE("right_hand has %d channels, alpha=%d, left_hand has %d, expecting %d or %d",
+ rchan, alpha?1:0, lchan, rchan-(alpha?1:0), rchan);
+ }
+ out=new GridOutlet(this,0,in->dim,in->nt);
+ in->set_chunk(1);
+} GRID_FLOW {
+ int f = in->dim->prod(1);
+ int y = dex/f;
+ if (position->nt != int32_e) RAISE("position has to be int32");
+ int py = ((int32*)*position)[0], rsy = image->dim->v[0];
+ int px = ((int32*)*position)[1], rsx = image->dim->v[1], sx=in->dim->get(1);
+ for (; n; y++, n-=f, data+=f) {
+ int ty = div2(y-py,rsy);
+ if (tile || ty==0) {
+ T data2[f];
+ COPY(data2,data,f);
+ if (tile) {
+ for (int x=px-div2(px+rsx-1,rsx)*rsx; x<sx; x+=rsx) {
+ draw_segment(data2,data,mod(y-py,rsy),x);
+ }
+ } else {
+ draw_segment(data2,data,y-py,px);
+ }
+ out->send(f,data2);
+ } else {
+ out->send(f,data);
+ }
+ }
+} GRID_END
+
+GRID_INPUT(1,image) {} GRID_END
+GRID_INPUT(2,position) {} GRID_END
+
+\end class {install("#draw_image",3,1); add_creator("@draw_image");}
+
+//****************************************************************
+// Dim[*A],Dim[*B],Dim[C,size(A)-size(B)] -> Dim[*A]
+
+/* NOT FINISHED */
+\class GridDrawPoints : FObject {
+ \attr Numop *op;
+ \attr PtrGrid color;
+ \attr PtrGrid points;
+ \grin 0
+ \grin 1 int32
+ \grin 2 int32
+ \constructor (Numop *op=op_put, Grid *color=0, Grid *points=0) {
+ this->op = op;
+ if (color) this->color=color;
+ if (points) this->points=points;
+ }
+};
+
+GRID_INPUT(1,color) {} GRID_END
+GRID_INPUT(2,points) {} GRID_END
+
+GRID_INLET(0) {
+ NOTEMPTY(color);
+ NOTEMPTY(points);
+ SAME_TYPE(in,color);
+ out=new GridOutlet(this,0,in->dim,in->nt);
+ if (points->dim->n!=2) RAISE("points should be a 2-D grid");
+ if (points->dim->v[1] != in->dim->n - color->dim->n)
+ RAISE("wrong number of dimensions");
+ in->set_chunk(0);
+} GRID_FLOW {
+ long m = points->dim->v[1];
+ long cn = in->dim->prod(-color->dim->n); /* size of color (RGB=3, greyscale=1, ...) */
+ int32 *pdata = (int32 *)points->data;
+ T *cdata = (T *)color->data;
+ for (long i=0; i<n; i++) {
+ long off = 0;
+ for (long k=0; k>m; k++) off = off*in->dim->v[k] + pdata[i*points->dim->v[1]+k];
+ off *= cn;
+ for (long j=0; j<cn; j++) data[off+j] = cdata[j];
+ }
+// out->send(data);
+} GRID_END
+\end class {install("#draw_points",3,1);}
+
+//****************************************************************
+\class GridNoiseGateYuvs : FObject {
+ \grin 0
+ int thresh;
+ \decl 1 float(int v);
+ \constructor (int v=0) {thresh=v;}
+};
+
+GRID_INLET(0) {
+ if (in->dim->n!=3) RAISE("requires 3 dimensions: dim(y,x,3)");
+ if (in->dim->v[2]!=3) RAISE("requires 3 channels");
+ out=new GridOutlet(this,0,in->dim,in->nt);
+ in->set_chunk(2);
+} GRID_FLOW {
+ T tada[n];
+ for (long i=0; i<n; i+=3) {
+ if (data[i+0]<=thresh) {
+ tada[i+0]=0; tada[i+1]=0; tada[i+2]=0;
+ } else {
+ tada[i+0]=data[i+0]; tada[i+1]=data[i+1]; tada[i+2]=data[i+2];
+ }
+ }
+ out->send(n,tada);
+} GRID_END
+
+\def 1 float(int v) {thresh=v;}
+\end class {install("#noise_gate_yuvs",2,1);}
+
+//****************************************************************
+
+\class GridPack : FObject {
+ int n;
+ PtrGrid a;
+ \constructor (int n=2, NumberTypeE nt=int32_e) {
+ if (n<1) RAISE("n=%d must be at least 1",n);
+ if (n>32) RAISE("n=%d is too many?",n);
+ a = new Grid(new Dim(n),nt,true);
+ this->n=n;
+ bself->ninlets_set(this->n);
+ }
+ \decl void _n_float (int inlet, float f);
+ \decl void _n_list (int inlet, float f);
+ \decl 0 bang ();
+ //\grin 0
+};
+\def void _n_float (int inlet, float f) {
+#define FOO(T) ((T *)*a)[inlet] = (T)f;
+TYPESWITCH(a->nt,FOO,);
+#undef FOO
+ _0_bang(argc,argv);
+}
+\def void _n_list (int inlet, float f) {_n_float(argc,argv,inlet,f);}
+\def 0 bang () {
+ out=new GridOutlet(this,0,a->dim,a->nt);
+#define FOO(T) out->send(n,(T *)*a);
+TYPESWITCH(a->nt,FOO,);
+#undef FOO
+}
+\end class {install("#pack",1,1); add_creator("@pack");}
+
+\class GridUnpack : FObject {
+ int n;
+ \constructor (int n=2) {
+ if (n<1) RAISE("n=%d must be at least 1",n);
+ if (n>32) RAISE("n=%d is too many?",n);
+ this->n=n;
+ bself->noutlets_set(this->n);
+ }
+ \grin 0
+};
+GRID_INLET(0) {
+ if (in->dim->n!=1) RAISE("expect one dimension");
+ if (in->dim->v[0]!=this->n) RAISE("expecting dim(%ld), got dim(%ld)",this->n,in->dim->v[0]);
+ in->set_chunk(0);
+} GRID_FLOW {
+ for (int i=n-1; i>=0; i--) outlet_float(bself->outlets[i],(t_float)data[i]);
+} GRID_END
+\end class {install("#unpack",1,0);}
+
+//****************************************************************
+
+\class GridRotatificator : FObject {
+ int angle;
+ int from, to, n;
+ \decl 0 float (int scale);
+ \decl 0 axis (int from, int to, int n);
+ \constructor (int from=0, int to=1, int n=2) {
+ angle=0;
+ _0_axis(0,0,from,to,n);
+ }
+ \decl 1 float(int angle);
+};
+\def 0 float (int scale) {
+ int32 rotator[n*n];
+ for (int i=0; i<n; i++) for (int j=0; j<n; j++) rotator[i*n+j] = scale * (i==j);
+ float th = angle * M_PI / 18000;
+ for (int i=0; i<2; i++) for (int j=0; j<2; j++)
+ rotator[(i?to:from)*n+(j?to:from)] = (int32)round(scale*cos(th+(j-i)*M_PI/2));
+ GridOutlet out(this,0,new Dim(n,n),int32_e);
+ out.send(n*n,rotator);
+}
+\def 0 axis(int from, int to, int n) {
+ if (n<0) RAISE("n-axis number incorrect");
+ if (from<0 || from>=n) RAISE("from-axis number incorrect");
+ if (to <0 || to >=n) RAISE( "to-axis number incorrect");
+ this->from = from;
+ this-> to = to;
+ this-> n = n;
+}
+\def 1 float(int angle) {this->angle = angle;}
+\end class {install("#rotatificator",2,1);}
+
+static void expect_min_one_dim (P<Dim> d) {
+ if (d->n<1) RAISE("expecting at least one dimension, got %s",d->to_s());}
+
+#define OP(x) op_dict[string(#x)]
+\class GridClusterAvg : FObject {
+ \attr int numClusters;
+ \attr PtrGrid r;
+ \attr PtrGrid sums;
+ \attr PtrGrid counts;
+ \constructor (int v) {_1_float(0,0,v); r.constrain(expect_min_one_dim);}
+ \decl 1 float (int v);
+ \grin 0 int32
+ \grin 2
+ template <class T> void make_stats (long n, int32 *ldata, T *rdata) {
+ int32 chans = r->dim->v[r->dim->n-1];
+ T *sdata = (T *)*sums;
+ int32 *cdata = (int32 *)*counts;
+ for (int i=0; i<n; i++, ldata++, rdata+=chans) {
+ if (*ldata<0 || *ldata>=numClusters) RAISE("value out of range in left grid");
+ OP(+)->zip(chans,sdata+(*ldata)*chans,rdata);
+ cdata[*ldata]++;
+ }
+ for (int i=0; i<numClusters; i++) OP(/)->map(chans,sdata+i*chans,(T)cdata[i]);
+ out = new GridOutlet(this,1,counts->dim,counts->nt);
+ out->send(counts->dim->prod(),(int32 *)*counts);
+ out = new GridOutlet(this,0,sums->dim,sums->nt);
+ out->send(sums->dim->prod(),(T *)*sums);
+ }
+};
+
+GRID_INLET(0) {
+ NOTEMPTY(r);
+ int32 v[r->dim->n];
+ COPY(v,r->dim->v,r->dim->n-1);
+ v[r->dim->n-1]=1;
+ P<Dim> t = new Dim(r->dim->n,v);
+ if (!t->equal(in->dim)) RAISE("left %s must be equal to right %s except last dimension should be 1",in->dim->to_s(),r->dim->to_s());
+ in->set_chunk(0);
+ int32 w[2] = {numClusters,r->dim->v[r->dim->n-1]};
+ sums = new Grid(new Dim(2,w),r->nt, true);
+ counts = new Grid(new Dim(1,w),int32_e,true);
+} GRID_FLOW {
+ #define FOO(U) make_stats(n,data,(U *)*r);
+ TYPESWITCH(r->nt,FOO,)
+ #undef FOO
+} GRID_END
+\def 1 float (int v) {numClusters = v;}
+GRID_INPUT(2,r) {
+} GRID_END
+
+\end class {install("#cluster_avg",3,2);}
+
+//****************************************************************
+
+void startup_flow_objects () {
+ op_add = OP(+);
+ op_sub = OP(-);
+ op_mul = OP(*);
+ op_shl = OP(<<);
+ op_mod = OP(%);
+ op_and = OP(&);
+ op_div = OP(/);
+ op_put = OP(put);
+ \startall
+}
diff --git a/externals/gridflow/src/classes2.cxx b/externals/gridflow/src/classes2.cxx
new file mode 100644
index 00000000..6ca9a62a
--- /dev/null
+++ b/externals/gridflow/src/classes2.cxx
@@ -0,0 +1,1183 @@
+/*
+ $Id: flow_objects.c 4097 2008-10-03 19:49:03Z matju $
+
+ GridFlow
+ Copyright (c) 2001-2009 by Mathieu Bouchard
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ See file ../COPYING for further informations on licensing terms.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "gridflow.hxx.fcs"
+#ifdef DESIRE
+#include "desire.h"
+#else
+extern "C" {
+#include "bundled/g_canvas.h"
+#include "bundled/m_imp.h"
+extern t_class *text_class;
+};
+#endif
+#include <algorithm>
+#include <errno.h>
+#include <sys/time.h>
+#include <string>
+
+typedef int (*comparator_t)(const void *, const void *);
+
+#ifndef DESIREDATA
+struct _outconnect {
+ struct _outconnect *next;
+ t_pd *to;
+};
+struct _outlet {
+ t_object *owner;
+ struct _outlet *next;
+ t_outconnect *connections;
+ t_symbol *sym;
+};
+#endif
+
+//****************************************************************
+
+struct ArgSpec {
+ t_symbol *name;
+ t_symbol *type;
+ t_atom defaultv;
+};
+
+\class Args : FObject {
+ ArgSpec *sargv;
+ int sargc;
+ \constructor (...) {
+ sargc = argc;
+ sargv = new ArgSpec[argc];
+ for (int i=0; i<argc; i++) {
+ if (argv[i].a_type==A_LIST) {
+ t_binbuf *b = (t_binbuf *)argv[i].a_gpointer;
+ int bac = binbuf_getnatom(b);
+ t_atom *bat = binbuf_getvec(b);
+ sargv[i].name = atom_getsymbolarg(0,bac,bat);
+ sargv[i].type = atom_getsymbolarg(1,bac,bat);
+ if (bac<3) SETNULL(&sargv[i].defaultv); else sargv[i].defaultv = bat[2];
+ } else if (argv[i].a_type==A_SYMBOL) {
+ sargv[i].name = argv[i].a_symbol;
+ sargv[i].type = gensym("a");
+ SETNULL(&sargv[i].defaultv);
+ } else RAISE("expected symbol or nested list");
+ }
+ bself->noutlets_set(sargc);
+ }
+ ~Args () {delete[] sargv;}
+ \decl 0 bang ();
+ \decl 0 loadbang ();
+ void process_args (int argc, t_atom *argv);
+};
+/* get the owner of the result of canvas_getenv */
+static t_canvas *canvas_getabstop(t_canvas *x) {
+ while (!x->gl_env) if (!(x = x->gl_owner)) bug("t_canvasenvironment", x);
+ return x;
+}
+\def 0 bang () {post("%s shouldn't bang [args] anymore.",canvas_getabstop(bself->mom)->gl_name->s_name);}
+void outlet_anything2 (t_outlet *o, int argc, t_atom *argv) {
+ if (!argc) outlet_bang(o);
+ else if (argv[0].a_type==A_SYMBOL) outlet_anything(o,argv[0].a_symbol,argc-1,argv+1);
+ else if (argv[0].a_type==A_FLOAT && argc==1) outlet_float(o,argv[0].a_float);
+ else outlet_anything(o,&s_list,argc,argv);
+}
+void pd_anything2 (t_pd *o, int argc, t_atom *argv) {
+ if (!argc) pd_bang(o);
+ else if (argv[0].a_type==A_SYMBOL) pd_typedmess(o,argv[0].a_symbol,argc-1,argv+1);
+ else if (argv[0].a_type==A_FLOAT && argc==1) pd_float(o,argv[0].a_float);
+ else pd_typedmess(o,&s_list,argc,argv);
+}
+\def 0 loadbang () {
+ t_canvasenvironment *env = canvas_getenv(bself->mom);
+ int ac = env->ce_argc;
+ t_atom av[ac];
+ for (int i=0; i<ac; i++) av[i] = env->ce_argv[i];
+ //ac = handle_braces(ac,av);
+ t_symbol *comma = gensym(",");
+ int j;
+ for (j=0; j<ac; j++) if (av[j].a_type==A_SYMBOL && av[j].a_symbol==comma) break;
+ int jj = handle_braces(j,av);
+ process_args(jj,av);
+ while (j<ac) {
+ j++;
+ int k=j;
+ for (; j<ac; j++) if (av[j].a_type==A_SYMBOL && av[j].a_symbol==comma) break;
+ //outlet_anything2(bself->outlets[sargc],j-k,av+k);
+ t_text *t = (t_text *)canvas_getabstop(bself->mom);
+ if (!t->te_inlet) RAISE("can't send init-messages, because object has no [inlet]");
+ pd_anything2((t_pd *)t->te_inlet,j-k,av+k);
+ }
+}
+void Args::process_args (int argc, t_atom *argv) {
+ t_canvas *canvas = canvas_getrootfor(bself->mom);
+ t_symbol *wildcard = gensym("*");
+ for (int i=sargc-1; i>=0; i--) {
+ t_atom *v;
+ if (i>=argc) {
+ if (sargv[i].defaultv.a_type != A_NULL) {
+ v = &sargv[i].defaultv;
+ } else if (sargv[i].name!=wildcard) {
+ pd_error(canvas,"missing argument $%d named \"%s\"", i+1,sargv[i].name->s_name);
+ continue;
+ }
+ } else v = &argv[i];
+ if (sargv[i].name==wildcard) {
+ if (argc-i>0) outlet_list(bself->outlets[i],&s_list,argc-i,argv+i);
+ else outlet_bang(bself->outlets[i]);
+ } else {
+ if (v->a_type==A_LIST) {
+ t_binbuf *b = (t_binbuf *)v->a_gpointer;
+ outlet_list(bself->outlets[i],&s_list,binbuf_getnatom(b),binbuf_getvec(b));
+ } else if (v->a_type==A_SYMBOL) outlet_symbol(bself->outlets[i],v->a_symbol);
+ else outlet_anything2(bself->outlets[i],1,v);
+ }
+ }
+ if (argc>sargc && sargv[sargc-1].name!=wildcard) pd_error(canvas,"warning: too many args (got %d, want %d)", argc, sargc);
+}
+\end class {install("args",1,1);}
+
+//****************************************************************
+
+namespace {
+template <class T> void swap (T &a, T &b) {T c; c=a; a=b; b=c;}
+};
+
+\class ListReverse : FObject {
+ \constructor () {}
+ \decl 0 list(...);
+};
+\def 0 list (...) {
+ for (int i=(argc-1)/2; i>=0; i--) swap(argv[i],argv[argc-i-1]);
+ outlet_list(bself->te_outlet,&s_list,argc,argv);
+}
+\end class {install("listreverse",1,1);}
+
+\class ListFlatten : FObject {
+ std::vector<t_atom2> contents;
+ \constructor () {}
+ \decl 0 list(...);
+ void traverse (int argc, t_atom2 *argv) {
+ for (int i=0; i<argc; i++) {
+ if (argv[i].a_type==A_LIST) traverse(binbuf_getnatom(argv[i]),(t_atom2 *)binbuf_getvec(argv[i]));
+ else contents.push_back(argv[i]);
+ }
+ }
+};
+\def 0 list (...) {
+ traverse(argc,argv);
+ outlet_list(bself->te_outlet,&s_list,contents.size(),&contents[0]);
+ contents.clear();
+
+}
+\end class {install("listflatten",1,1);}
+
+// does not do recursive comparison of lists.
+static bool atom_eq (t_atom &a, t_atom &b) {
+ if (a.a_type!=b.a_type) return false;
+ if (a.a_type==A_FLOAT) return a.a_float ==b.a_float;
+ if (a.a_type==A_SYMBOL) return a.a_symbol ==b.a_symbol;
+ if (a.a_type==A_POINTER) return a.a_gpointer==b.a_gpointer;
+ if (a.a_type==A_LIST) return a.a_gpointer==b.a_gpointer;
+ RAISE("don't know how to compare elements of type %d",a.a_type);
+}
+
+\class ListFind : FObject {
+ int ac;
+ t_atom *at;
+ ~ListFind() {if (at) delete[] at;}
+ \constructor (...) {ac=0; at=0; _1_list(argc,argv);}
+ \decl 0 list(...);
+ \decl 1 list(...);
+ \decl 0 float(float f);
+ \decl 0 symbol(t_symbol *s);
+};
+\def 1 list (...) {
+ if (at) delete[] at;
+ ac = argc;
+ at = new t_atom[argc];
+ for (int i=0; i<argc; i++) at[i] = argv[i];
+}
+\def 0 list (...) {
+ if (argc<1) RAISE("empty input");
+ int i=0; for (; i<ac; i++) if (atom_eq(at[i],argv[0])) break;
+ outlet_float(bself->outlets[0],i==ac?-1:i);
+}
+\def 0 float (float f) {
+ int i=0; for (; i<ac; i++) if (atom_eq(at[i],argv[0])) break;
+ outlet_float(bself->outlets[0],i==ac?-1:i);
+}
+\def 0 symbol (t_symbol *s) {
+ int i=0; for (; i<ac; i++) if (atom_eq(at[i],argv[0])) break;
+ outlet_float(bself->outlets[0],i==ac?-1:i);
+}
+//doc:_1_list,"list to search into"
+//doc:_0_float,"float to find in that list"
+//doc_out:_0_float,"position of the incoming float in the stored list"
+\end class {install("listfind",2,1);}
+
+void outlet_atom (t_outlet *self, t_atom *av) {
+ if (av->a_type==A_FLOAT) outlet_float( self,av->a_float); else
+ if (av->a_type==A_SYMBOL) outlet_symbol( self,av->a_symbol); else
+ if (av->a_type==A_POINTER) outlet_pointer(self,av->a_gpointer); else
+ outlet_list(self,gensym("list"),1,av);
+}
+
+\class ListRead : FObject { /* sounds like tabread */
+ int ac;
+ t_atom *at;
+ ~ListRead() {if (at) delete[] at;}
+ \constructor (...) {ac=0; at=0; _1_list(argc,argv);}
+ \decl 0 float(float f);
+ \decl 1 list(...);
+};
+\def 0 float(float f) {
+ int i = int(f);
+ if (i<0) i+=ac;
+ if (i<0 || i>=ac) {outlet_bang(bself->outlets[0]); return;} /* out-of-range */
+ outlet_atom(bself->outlets[0],&at[i]);
+}
+\def 1 list (...) {
+ if (at) delete[] at;
+ ac = argc;
+ at = new t_atom[argc];
+ for (int i=0; i<argc; i++) at[i] = argv[i];
+}
+\end class {install("listread",2,1);}
+
+\class Range : FObject {
+ t_float *mosusses;
+ int nmosusses;
+ \constructor (...) {
+ nmosusses = argc;
+ for (int i=0; i<argc; i++) if (argv[i].a_type!=A_FLOAT) RAISE("$%d: expected float",i+1);
+ mosusses = new t_float[argc];
+ for (int i=0; i<argc; i++) mosusses[i]=argv[i].a_float;
+ bself-> ninlets_set(1+nmosusses);
+ bself->noutlets_set(1+nmosusses);
+ }
+ ~Range () {delete[] mosusses;}
+ \decl 0 float(float f);
+ \decl 0 list(float f);
+ \decl void _n_float(int i, float f);
+};
+\def 0 list(float f) {_0_float(argc,argv,f);}
+\def 0 float(float f) {
+ int i; for (i=0; i<nmosusses; i++) if (f<mosusses[i]) break;
+ outlet_float(bself->outlets[i],f);
+}
+ // precedence problem in dispatcher... does this problem still exist?
+\def void _n_float(int i, float f) {if (!i) _0_float(argc,argv,f); else mosusses[i-1] = f;}
+\end class {install("range",1,1);}
+
+//****************************************************************
+
+string ssprintf(const char *fmt, ...) {
+ std::ostringstream os;
+ va_list va;
+ va_start(va,fmt);
+ voprintf(os,fmt,va);
+ va_end(va);
+ return os.str();
+}
+
+\class GFPrint : FObject {
+ t_symbol *prefix;
+ t_pd *gp;
+ //t_symbol *rsym;
+ \constructor (t_symbol *s=0) {
+ //rsym = gensym(const_cast<char *>(ssprintf("gf.print:%08x",this).data())); // not in use atm.
+ prefix=s?s:gensym("print");
+ t_atom a[1];
+ SETSYMBOL(a,prefix);
+ pd_typedmess(&pd_objectmaker,gensym("#print"),1,a);
+ gp = pd_newest();
+ SETPOINTER(a,(t_gpointer *)bself);
+ //pd_typedmess(gp,gensym("dest"),1,a);
+ }
+ ~GFPrint () {
+ //pd_unbind((t_pd *)bself,rsym);
+ pd_free(gp);
+ }
+ \decl 0 grid(...);
+ \decl void anything (...);
+};
+std::ostream &operator << (std::ostream &self, const t_atom &a) {
+ switch (a.a_type) {
+ case A_FLOAT: self << a.a_float; break;
+ case A_SYMBOL: self << a.a_symbol->s_name; break; // i would rather show backslashes here...
+ case A_DOLLSYM: self << a.a_symbol->s_name; break; // for real, it's the same thing as A_SYMBOL in pd >= 0.40
+ case A_POINTER: self << "\\p(0x" << std::hex << a.a_gpointer << std::dec << ")"; break;
+ case A_COMMA: self << ","; break;
+ case A_SEMI: self << ";"; break;
+ case A_DOLLAR: self << "$" << a.a_w.w_index; break;
+ case A_LIST: {
+ t_list *b = (t_list *)a.a_gpointer;
+ int argc = binbuf_getnatom(b);
+ t_atom *argv = binbuf_getvec(b);
+ self << "(";
+ for (int i=0; i<argc; i++) self << argv[i] << " )"[i==argc-1];
+ break;
+ }
+ default: self << "\\a(" << a.a_type << " " << std::hex << a.a_gpointer << std::dec << ")"; break;
+ }
+ return self;
+}
+\def 0 grid(...) {pd_typedmess(gp,gensym("grid"),argc,argv);}
+\def void anything(...) {
+ std::ostringstream text;
+ text << prefix->s_name << ":";
+ if (argv[0]==gensym("_0_list") && argc>=2 && argv[1].a_type==A_FLOAT) {
+ // don't show the selector.
+ } else if (argv[0]==gensym("_0_list") && argc==2 && argv[1].a_type==A_SYMBOL) {
+ text << " symbol";
+ } else if (argv[0]==gensym("_0_list") && argc==2 && argv[1].a_type==A_POINTER) {
+ text << " pointer";
+ } else if (argv[0]==gensym("_0_list") && argc==1) {
+ text << " bang";
+ } else {
+ text << " " << argv[0].a_symbol->s_name+3; // as is
+ }
+ for (int i=1; i<argc; i++) {text << " " << argv[i];}
+ post("%s",text.str().data());
+}
+\end class {install("gf.print",1,0); add_creator3(fclass,"print");}
+
+#ifdef HAVE_DESIREDATA
+t_glist *glist_getcanvas(t_glist *foo) {return foo;}//dummy
+void canvas_fixlinesfor(t_glist *foo,t_text *) {}//dummy
+#endif
+
+//#ifdef HAVE_DESIREDATA
+static void display_update(void *x);
+\class Display : FObject {
+ bool selected;
+ t_glist *canvas;
+ t_symbol *rsym;
+ int y,x,sy,sx;
+ bool vis;
+ std::ostringstream text;
+ t_clock *clock;
+ t_pd *gp;
+ \constructor () {
+ selected=false; canvas=0; y=0; x=0; sy=16; sx=80; vis=false; clock=0;
+ std::ostringstream os;
+ rsym = gensym(const_cast<char *>(ssprintf("display:%08x",this).data()));
+ pd_typedmess(&pd_objectmaker,gensym("#print"),0,0);
+ gp = pd_newest();
+ t_atom a[1];
+ SETFLOAT(a,20);
+ pd_typedmess(gp,gensym("maxrows"),1,a);
+ text << "...";
+ pd_bind((t_pd *)bself,rsym);
+ SETPOINTER(a,(t_gpointer *)bself);
+ pd_typedmess(gp,gensym("dest"),1,a);
+ clock = clock_new((void *)this,(void(*)())display_update);
+ }
+ ~Display () {
+ pd_unbind((t_pd *)bself,rsym);
+ pd_free(gp);
+ if (clock) clock_free(clock);
+ }
+ \decl void anything (...);
+ \decl 0 set_size(int sy, int sx);
+ \decl 0 grid(...);
+ \decl 0 very_long_name_that_nobody_uses(...);
+ void show() {
+ std::ostringstream quoted;
+ // def quote(text) "\"" + text.gsub(/["\[\]\n\$]/m) {|x| if x=="\n" then "\\n" else "\\"+x end } + "\"" end
+ std::string ss = text.str();
+ const char *s = ss.data();
+ int n = ss.length();
+ for (int i=0;i<n;i++) {
+ if (s[i]=='\n') quoted << "\\n";
+ else if (strchr("\"[]$",s[i])) quoted << "\\" << (char)s[i];
+ else quoted << (char)s[i];
+ }
+ //return if not canvas or not @vis # can't show for now...
+ /* we're not using quoting for now because there's a bug in it. */
+ /* btw, this quoting is using "", but we're gonna use {} instead for now, because of newlines */
+ sys_vgui("display_update %s %d %d #000000 #cccccc %s {Courier -12} .x%x.c {%s}\n",
+ rsym->s_name,bself->te_xpix,bself->te_ypix,selected?"#0000ff":"#000000",canvas,ss.data());
+ }
+};
+static void display_getrectfn(t_gobj *x, t_glist *glist, int *x1, int *y1, int *x2, int *y2) {
+ BFObject *bself = (BFObject*)x; Display *self = (Display *)bself->self; self->canvas = glist;
+ *x1 = bself->te_xpix-1;
+ *y1 = bself->te_ypix-1;
+ *x2 = bself->te_xpix+1+self->sx;
+ *y2 = bself->te_ypix+1+self->sy;
+}
+static void display_displacefn(t_gobj *x, t_glist *glist, int dx, int dy) {
+ BFObject *bself = (BFObject*)x; Display *self = (Display *)bself->self; self->canvas = glist;
+ bself->te_xpix+=dx;
+ bself->te_ypix+=dy;
+ self->canvas = glist_getcanvas(glist);
+ self->show();
+ canvas_fixlinesfor(glist, (t_text *)x);
+}
+static void display_selectfn(t_gobj *x, t_glist *glist, int state) {
+ BFObject *bself = (BFObject*)x; Display *self = (Display *)bself->self; self->canvas = glist;
+ self->selected=!!state;
+ sys_vgui(".x%x.c itemconfigure %s -outline %s\n",glist_getcanvas(glist),self->rsym->s_name,self->selected?"#0000ff":"#000000");
+}
+static void display_deletefn(t_gobj *x, t_glist *glist) {
+ BFObject *bself = (BFObject*)x; Display *self = (Display *)bself->self; self->canvas = glist;
+ if (self->vis) sys_vgui(".x%x.c delete %s %sTEXT\n",glist_getcanvas(glist),self->rsym->s_name,self->rsym->s_name);
+ canvas_deletelinesfor(glist, (t_text *)x);
+}
+static void display_visfn(t_gobj *x, t_glist *glist, int flag) {
+ BFObject *bself = (BFObject*)x; Display *self = (Display *)bself->self; self->canvas = glist;
+ self->vis = !!flag;
+ display_update(self);
+}
+static void display_update(void *x) {
+ Display *self = (Display *)x;
+ if (self->vis) self->show();
+}
+\def 0 set_size(int sy, int sx) {this->sy=sy; this->sx=sx;}
+\def void anything (...) {
+ string sel = string(argv[0]).data()+3;
+ text.str("");
+ if (sel != "float") {text << sel; if (argc>1) text << " ";}
+ long col = text.str().length();
+ char buf[MAXPDSTRING];
+ for (int i=1; i<argc; i++) {
+ atom_string(&argv[i],buf,MAXPDSTRING);
+ text << buf;
+ col += strlen(buf);
+ if (i!=argc-1) {
+ text << " ";
+ col++;
+ if (col>56) {text << "\\\\\n"; col=0;}
+ }
+ }
+ clock_delay(clock,0);
+}
+\def 0 grid(...) {
+ text.str("");
+ pd_typedmess(gp,gensym("grid"),argc,argv);
+ clock_delay(clock,0);
+}
+\def 0 very_long_name_that_nobody_uses(...) {
+ if (text.str().length()) text << "\n";
+ for (int i=0; i<argc; i++) text << (char)INT(argv[i]);
+}
+\end class {
+#ifndef DESIRE
+ install("display",1,0);
+ t_class *qlass = fclass->bfclass;
+ t_widgetbehavior *wb = new t_widgetbehavior;
+ wb->w_getrectfn = display_getrectfn;
+ wb->w_displacefn = display_displacefn;
+ wb->w_selectfn = display_selectfn;
+ wb->w_activatefn = 0;
+ wb->w_deletefn = display_deletefn;
+ wb->w_visfn = display_visfn;
+ wb->w_clickfn = 0;
+ class_setwidget(qlass,wb);
+ sys_gui("proc display_update {self x y fg bg outline font canvas text} { \n\
+ $canvas delete ${self}TEXT \n\
+ $canvas create text [expr $x+2] [expr $y+2] -fill $fg -font $font -text $text -anchor nw -tag ${self}TEXT \n\
+ foreach {x1 y1 x2 y2} [$canvas bbox ${self}TEXT] {} \n\
+ incr x -1 \n\
+ incr y -1 \n\
+ set sx [expr $x2-$x1+2] \n\
+ set sy [expr $y2-$y1+4] \n\
+ $canvas delete ${self} \n\
+ $canvas create rectangle $x $y [expr $x+$sx] [expr $y+$sy] -fill $bg -tags $self -outline $outline \n\
+ $canvas create rectangle $x $y [expr $x+7] $y -fill red -tags $self -outline $outline \n\
+ $canvas lower $self ${self}TEXT \n\
+ pd \"$self set_size $sy $sx;\" \n\
+ }\n");
+#endif
+}
+//#endif // ndef HAVE_DESIREDATA
+
+//****************************************************************
+
+\class UnixTime : FObject {
+ \constructor () {}
+ \decl 0 bang ();
+};
+\def 0 bang () {
+ timeval tv;
+ gettimeofday(&tv,0);
+ time_t t = time(0);
+ struct tm *tmp = localtime(&t);
+ if (!tmp) RAISE("localtime: %s",strerror(errno));
+ char tt[MAXPDSTRING];
+ strftime(tt,MAXPDSTRING,"%a %b %d %H:%M:%S %Z %Y",tmp);
+ t_atom a[6];
+ SETFLOAT(a+0,tmp->tm_year+1900);
+ SETFLOAT(a+1,tmp->tm_mon-1);
+ SETFLOAT(a+2,tmp->tm_mday);
+ SETFLOAT(a+3,tmp->tm_hour);
+ SETFLOAT(a+4,tmp->tm_min);
+ SETFLOAT(a+5,tmp->tm_sec);
+ t_atom b[3];
+ SETFLOAT(b+0,tv.tv_sec/86400);
+ SETFLOAT(b+1,mod(tv.tv_sec,86400));
+ SETFLOAT(b+2,tv.tv_usec);
+ outlet_anything(bself->outlets[2],&s_list,6,a);
+ outlet_anything(bself->outlets[1],&s_list,3,b);
+ send_out(0,strlen(tt),tt);
+}
+
+\end class UnixTime {install("unix_time",1,3);}
+
+
+//****************************************************************
+
+/* if using a DB-25 female connector as found on a PC, then the pin numbering is like:
+ 13 _____ 1
+ 25 \___/ 14
+ 1 = STROBE = the clock line is a square wave, often at 9600 Hz,
+ which determines the data rate in usual circumstances.
+ 2..9 = D0..D7 = the eight ordinary data bits
+ 10 = -ACK (status bit 6 ?)
+ 11 = BUSY (status bit 7)
+ 12 = PAPER_END (status bit 5)
+ 13 = SELECT (status bit 4 ?)
+ 14 = -AUTOFD
+ 15 = -ERROR (status bit 3 ?)
+ 16 = -INIT
+ 17 = -SELECT_IN
+ 18..25 = GROUND
+*/
+
+//#include <linux/parport.h>
+#define LPCHAR 0x0601
+#define LPCAREFUL 0x0609 /* obsoleted??? wtf? */
+#define LPGETSTATUS 0x060b /* return LP_S(minor) */
+#define LPGETFLAGS 0x060e /* get status flags */
+
+#include <sys/ioctl.h>
+
+struct ParallelPort;
+void ParallelPort_call(ParallelPort *self);
+\class ParallelPort : FObject {
+ FILE *f;
+ int fd;
+ int status;
+ int flags;
+ bool manually;
+ t_clock *clock;
+ ~ParallelPort () {if (clock) clock_free(clock); if (f) fclose(f);}
+ \constructor (string port, bool manually=0) {
+ f = fopen(port.data(),"r+");
+ if (!f) RAISE("open %s: %s",port.data(),strerror(errno));
+ fd = fileno(f);
+ status = 0xdeadbeef;
+ flags = 0xdeadbeef;
+ this->manually = manually;
+ clock = manually ? 0 : clock_new(this,(void(*)())ParallelPort_call);
+ clock_delay(clock,0);
+ }
+ void call ();
+ \decl 0 float (float x);
+ \decl 0 bang ();
+};
+\def 0 float (float x) {
+ uint8 foo = (uint8) x;
+ fwrite(&foo,1,1,f);
+ fflush(f);
+}
+void ParallelPort_call(ParallelPort *self) {self->call();}
+void ParallelPort::call() {
+ int flags;
+ if (ioctl(fd,LPGETFLAGS,&flags)<0) post("ioctl: %s",strerror(errno));
+ if (this->flags!=flags) outlet_float(bself->outlets[2],flags);
+ this->flags = flags;
+ int status;
+ if (ioctl(fd,LPGETSTATUS,&status)<0) post("ioctl: %s",strerror(errno));
+ if (this->status!=status) outlet_float(bself->outlets[1],status);
+ this->status = status;
+ if (clock) clock_delay(clock,2000);
+}
+\def 0 bang () {status = flags = 0xdeadbeef; call();}
+//outlet 0 reserved (future use)
+\end class {install("parallel_port",1,3);}
+
+//****************************************************************
+
+\class Route2 : FObject {
+ int nsels;
+ t_symbol **sels;
+ ~Route2() {if (sels) delete[] sels;}
+ \constructor (...) {nsels=0; sels=0; _1_list(argc,argv); bself->noutlets_set(1+nsels);}
+ \decl void anything(...);
+ \decl 1 list(...);
+};
+\def void anything(...) {
+ t_symbol *sel = gensym(argv[0].a_symbol->s_name+3);
+ int i=0;
+ for (i=0; i<nsels; i++) if (sel==sels[i]) break;
+ outlet_anything(bself->outlets[i],sel,argc-1,argv+1);
+}
+\def 1 list(...) {
+ for (int i=0; i<argc; i++) if (argv[i].a_type!=A_SYMBOL) {delete[] sels; RAISE("$%d: expected symbol",i+1);}
+ if (sels) delete[] sels;
+ nsels = argc;
+ sels = new t_symbol*[argc];
+ for (int i=0; i<argc; i++) sels[i] = argv[i].a_symbol;
+}
+\end class {install("route2",1,1);}
+
+template <class T> int sgn(T a, T b=0) {return a<b?-1:a>b;}
+
+\class Shunt : FObject {
+ int n;
+ \attr int index;
+ \attr int mode;
+ \attr int hi;
+ \attr int lo;
+ \constructor (int n=2, int i=0) {
+ this->n=n;
+ this->hi=n-1;
+ this->lo=0;
+ this->mode=0;
+ this->index=i;
+ bself->noutlets_set(n);
+ }
+ \decl void anything(...);
+ \decl 1 float(int i);
+};
+\def void anything(...) {
+ t_symbol *sel = gensym(argv[0].a_symbol->s_name+3);
+ outlet_anything(bself->outlets[index],sel,argc-1,argv+1);
+ if (mode) {
+ index += sgn(mode);
+ if (index<lo || index>hi) {
+ int k = max(hi-lo+1,0);
+ int m = gf_abs(mode);
+ if (m==1) index = mod(index-lo,k)+lo; else {mode=-mode; index+=mode;}
+ }
+ }
+}
+\def 1 float(int i) {index = mod(i,n);}
+\end class {install("shunt",2,0);}
+
+struct Receives;
+struct ReceivesProxy {
+ t_pd x_pd;
+ Receives *parent;
+ t_symbol *suffix;
+};
+t_class *ReceivesProxy_class;
+
+\class Receives : FObject {
+ int ac;
+ ReceivesProxy **av;
+ t_symbol *prefix;
+ t_symbol *local (t_symbol *suffix) {return gensym((string(prefix->s_name) + string(suffix->s_name)).data());}
+ \constructor (t_symbol *prefix=&s_, ...) {
+ this->prefix = prefix==gensym("empty") ? &s_ : prefix;
+ int n = min(1,argc);
+ do_bind(argc-n,argv+n);
+ }
+ \decl 0 bang ();
+ \decl 0 symbol (t_symbol *s);
+ \decl 0 list (...);
+ void do_bind (int argc, t_atom2 *argv) {
+ ac = argc;
+ av = new ReceivesProxy *[argc];
+ for (int i=0; i<ac; i++) {
+ av[i] = (ReceivesProxy *)pd_new(ReceivesProxy_class);
+ av[i]->parent = this;
+ av[i]->suffix = argv[i];
+ pd_bind( (t_pd *)av[i],local(av[i]->suffix));
+ }
+ }
+ void do_unbind () {
+ for (int i=0; i<ac; i++) {
+ pd_unbind((t_pd *)av[i],local(av[i]->suffix));
+ pd_free((t_pd *)av[i]);
+ }
+ delete[] av;
+ }
+ ~Receives () {do_unbind();}
+};
+\def 0 bang () {_0_list(0,0);}
+\def 0 symbol (t_symbol *s) {t_atom2 a[1]; SETSYMBOL(a,s); _0_list(1,a);}
+\def 0 list (...) {
+ do_unbind();
+ do_bind(argc,argv);
+}
+void ReceivesProxy_anything (ReceivesProxy *self, t_symbol *s, int argc, t_atom *argv) {
+ outlet_symbol( self->parent->bself->outlets[1],self->suffix);
+ outlet_anything(self->parent->bself->outlets[0],s,argc,argv);
+}
+\end class {
+ install("receives",1,2);
+ ReceivesProxy_class = class_new(gensym("receives.proxy"),0,0,sizeof(ReceivesProxy),CLASS_PD|CLASS_NOINLET, A_NULL);
+ class_addanything(ReceivesProxy_class,(t_method)ReceivesProxy_anything);
+}
+
+/* this can't report on bang,float,symbol,pointer,list because zgetfn can't either */
+\class ClassExists : FObject {
+ \constructor () {}
+ \decl void _0_symbol(t_symbol *s);
+};
+\def void _0_symbol(t_symbol *s) {
+ outlet_float(bself->outlets[0],!!zgetfn(&pd_objectmaker,s));
+}
+\end class {install("class_exists",1,1);}
+
+\class ListEqual : FObject {
+ t_list *list;
+ \constructor (...) {list=0; _1_list(argc,argv);}
+ \decl 0 list (...);
+ \decl 1 list (...);
+};
+\def 1 list (...) {
+ if (list) list_free(list);
+ list = list_new(argc,argv);
+}
+\def 0 list (...) {
+ if (binbuf_getnatom(list) != argc) {outlet_float(bself->outlets[0],0); return;}
+ t_atom2 *at = (t_atom2 *)binbuf_getvec(list);
+ for (int i=0; i<argc; i++) if (!atom_eq(at[i],argv[i])) {outlet_float(bself->outlets[0],0); return;}
+ outlet_float(bself->outlets[0],1);
+}
+\end class {install("list.==",2,1);}
+
+//****************************************************************
+//#ifdef UNISTD
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/times.h>
+#include <sys/param.h>
+#include <unistd.h>
+//#endif
+#if defined (__APPLE__) || defined (__FreeBSD__)
+#define HZ CLK_TCK
+#endif
+
+uint64 cpu_hertz;
+int uint64_compare(uint64 &a, uint64 &b) {return a<b?-1:a>b;}
+
+\class UserTime : FObject {
+ clock_t time;
+ \constructor () {_0_bang(argc,argv);}
+ \decl 0 bang ();
+ \decl 1 bang ();
+};
+\def 0 bang () {struct tms t; times(&t); time = t.tms_utime;}
+\def 1 bang () {struct tms t; times(&t); outlet_float(bself->outlets[0],(t.tms_utime-time)*1000/HZ);}
+\end class {install("usertime",2,1);}
+\class SystemTime : FObject {
+ clock_t time;
+ \constructor () {_0_bang(argc,argv);}
+ \decl 0 bang ();
+ \decl 1 bang ();
+};
+\def 0 bang () {struct tms t; times(&t); time = t.tms_stime;}
+\def 1 bang () {struct tms t; times(&t); outlet_float(bself->outlets[0],(t.tms_stime-time)*1000/HZ);}
+\end class {install("systemtime",2,1);}
+\class TSCTime : FObject {
+ uint64 time;
+ \constructor () {_0_bang(argc,argv);}
+ \decl 0 bang ();
+ \decl 1 bang ();
+};
+\def 0 bang () {time=rdtsc();}
+\def 1 bang () {outlet_float(bself->outlets[0],(rdtsc()-time)*1000.0/cpu_hertz);}
+\end class {install("tsctime",2,1);
+ struct timeval t0,t1;
+ uint64 u0,u1;
+ uint64 estimates[3];
+ for (int i=0; i<3; i++) {
+ u0=rdtsc(); gettimeofday(&t0,0); usleep(10000);
+ u1=rdtsc(); gettimeofday(&t1,0);
+ uint64 t = (t1.tv_sec-t0.tv_sec)*1000000+(t1.tv_usec-t0.tv_usec);
+ estimates[i] = (u1-u0)*1000000/t;
+ }
+ qsort(estimates,3,sizeof(uint64),(comparator_t)uint64_compare);
+ cpu_hertz = estimates[1];
+}
+
+\class GFError : FObject {
+ string format;
+ \constructor (...) {
+ std::ostringstream o;
+ char buf[MAXPDSTRING];
+ for (int i=0; i<argc; i++) {
+ atom_string(&argv[i],buf,MAXPDSTRING);
+ o << buf;
+ if (i!=argc-1) o << ' ';
+ }
+ format = o.str();
+ }
+ \decl 0 bang ();
+ \decl 0 float (float f);
+ \decl 0 symbol (t_symbol *s);
+ \decl 0 list (...);
+};
+\def 0 bang () {_0_list(0,0);}
+\def 0 float (float f) {_0_list(argc,argv);}
+\def 0 symbol (t_symbol *s) {_0_list(argc,argv);}
+
+\def 0 list (...) {
+ std::ostringstream o;
+ pd_oprintf(o,format.data(),argc,argv);
+ t_canvas *canvas = canvas_getrootfor(bself->mom);
+ string s = o.str();
+ pd_error(canvas,"%s",s.data());
+}
+\end class {install("gf.error",1,0);}
+
+//****************************************************************
+\class ForEach : FObject {
+ \constructor () {}
+ \decl 0 list (...);
+};
+\def 0 list (...) {
+ t_outlet *o = bself->outlets[0];
+ for (int i=0; i<argc; i++) {
+ if (argv[i].a_type==A_FLOAT) outlet_float( o,argv[i]);
+ else if (argv[i].a_type==A_SYMBOL) outlet_symbol(o,argv[i]);
+ else RAISE("oops. unsupported.");
+ }
+}
+\end class {install("foreach",1,1);}
+
+//****************************************************************
+
+#define MOM \
+ t_canvas *mom = bself->mom; \
+ for (int i=0; i<n; i++) {mom = mom->gl_owner; if (!mom) RAISE("no such canvas");}
+
+\class GFCanvasFileName : FObject {
+ int n;
+ \constructor (int n) {this->n=n;}
+ \decl 0 bang ();
+};
+\def 0 bang () {MOM; outlet_symbol(bself->outlets[0],mom->gl_name ? mom->gl_name : gensym("empty"));}
+\end class {install("gf/canvas_filename",1,1);}
+\class GFCanvasDollarZero : FObject {
+ int n;
+ \constructor (int n) {this->n=n;}
+ \decl 0 bang ();
+};
+\def 0 bang () {MOM; outlet_float(bself->outlets[0],canvas_getenv(mom)->ce_dollarzero);}
+\end class {install("gf/canvas_dollarzero",1,1);}
+\class GFCanvasGetPos : FObject {
+ int n;
+ \constructor (int n) {this->n=n;}
+ \decl 0 bang ();
+};
+\def 0 bang () {MOM;
+ t_atom a[2];
+ SETFLOAT(a+0,mom->gl_obj.te_xpix);
+ SETFLOAT(a+1,mom->gl_obj.te_ypix);
+ outlet_list(bself->outlets[0],&s_list,2,a);
+}
+\end class {install("gf/canvas_getpos",1,1);}
+\class GFCanvasSetPos : FObject {
+ int n;
+ \constructor (int n) {this->n=n;}
+ \decl 0 list (...);
+};
+\def 0 list (...) {
+ MOM;
+ if (argc!=2) RAISE("wrong number of args");
+ mom->gl_obj.te_xpix = atom_getfloatarg(0,argc,argv);
+ mom->gl_obj.te_ypix = atom_getfloatarg(1,argc,argv);
+ t_canvas *granny = mom->gl_owner;
+ if (!granny) RAISE("no such canvas");
+#ifdef DESIREDATA
+ gobj_changed(mom);
+#else
+ gobj_vis((t_gobj *)mom,granny,0);
+ gobj_vis((t_gobj *)mom,granny,1);
+ canvas_fixlinesfor(glist_getcanvas(granny), (t_text *)mom);
+#endif
+}
+\end class {install("gf/canvas_setpos",1,0);}
+\class GFCanvasEditMode : FObject {
+ int n;
+ \constructor (int n) {this->n=n;}
+ \decl 0 bang ();
+};
+\def 0 bang () {MOM;
+ t_atom a[1]; SETFLOAT(a+0,0);
+ outlet_float(bself->outlets[0],mom->gl_edit);
+}
+\end class {install("gf/canvas_edit_mode",1,1);}
+extern "C" void canvas_setgraph(t_glist *x, int flag, int nogoprect);
+\class GFCanvasSetGOP : FObject {
+ int n;
+ \constructor (int n) {this->n=n;}
+ \decl 0 float (float gop);
+};
+\def 0 float (float gop) {MOM; t_atom a[1]; SETFLOAT(a+0,0); canvas_setgraph(mom,gop,0);}
+\end class {install("gf/canvas_setgop",1,0);}
+\class GFCanvasXID : FObject {
+ int n;
+ t_symbol *name;
+ \constructor (int n_) {
+ n=n_;
+ name=symprintf("gf/canvas_xid:%lx",bself);
+ pd_bind((t_pd *)bself,name);
+ }
+ ~GFCanvasXID () {pd_unbind((t_pd *)bself,name);}
+ \decl 0 bang ();
+ \decl 0 xid (t_symbol *t, t_symbol *u);
+};
+\def 0 bang () {
+ t_canvas *mom = bself->mom;
+ for (int i=0; i<n; i++) {mom = mom->gl_owner; if (!mom) RAISE("no such canvas");}
+ sys_vgui("pd %s xid [winfo id .x%lx.c] [winfo id .x%lx]\\;\n",name->s_name,long(mom));
+}
+\def 0 xid (t_symbol *t, t_symbol *u) {
+ outlet_symbol(bself->outlets[0],t);
+ outlet_symbol(bself->outlets[1],u);
+}
+\end class {install("gf/canvas_xid",1,2);}
+
+\class GFCanvasHeHeHe : FObject {
+ int n;
+ \constructor (int n) {this->n=n;}
+ \decl 0 float (float y);
+};
+\def 0 float (float y) {MOM;
+ // was 568
+ mom->gl_screenx2 = mom->gl_screenx1 + 600;
+ if (mom->gl_screeny2-mom->gl_screeny1 < y) mom->gl_screeny2 = mom->gl_screeny1+y;
+ sys_vgui("wm geometry .x%lx %dx%d\n",long(mom),
+ int(mom->gl_screenx2-mom->gl_screenx1),
+ int(mom->gl_screeny2-mom->gl_screeny1));
+}
+\end class {install("gf/canvas_hehehe",1,1);}
+
+#define DASHRECT "-outline #80d4b2 -dash {2 6 2 6}"
+
+\class GFCanvasHoHoHo : FObject {
+ int n;
+ t_canvas *last;
+ \constructor (int n) {this->n=n; last=0;}
+ void hide () {if (last) sys_vgui(".x%lx.c delete %lxRECT\n",long(last),bself);}
+ ~GFCanvasHoHoHo () {hide();}
+ \decl 0 list (int x1, int y1, int x2, int y2);
+};
+\def 0 list (int x1, int y1, int x2, int y2) {
+ hide();
+ MOM;
+ last = mom;
+ sys_vgui(".x%lx.c create rectangle %d %d %d %d "DASHRECT" -tags %lxRECT\n",long(last),x1,y1,x2,y2,bself);
+}
+\end class {install("gf/canvas_hohoho",1,0);}
+
+#define canvas_each(y,x) for (t_gobj *y=x->gl_list; y; y=y->g_next)
+\class GFCanvasCount : FObject {
+ int n;
+ \constructor (int n) {this->n=n;}
+ \decl 0 bang ();
+};
+\def 0 bang () {MOM; int k=0; canvas_each(y,mom) k++; outlet_float(bself->outlets[0],k);}
+\end class {install("gf/canvas_count",1,1);}
+
+\class GFCanvasLoadbang : FObject {
+ int n;
+ \constructor (int n) {this->n=n;}
+ \decl 0 float (float m);
+};
+\def 0 float (float m) {MOM;
+ int k=0;
+ canvas_each(y,mom) {
+ k++;
+ if (k>=m && pd_class((t_pd *)y)==canvas_class) canvas_loadbang((t_canvas *)y);
+ }
+
+}
+\end class {
+ install("gf/canvas_loadbang",1,0);
+};
+
+\class GFLOL : FObject {
+ int n;
+ \constructor (int n) {this->n=n;}
+ \decl 0 wire_dotted (int r, int g, int b);
+ \decl 0 wire_hide ();
+ \decl 0 box_dotted (int r, int g, int b);
+ \decl 0 box_align (t_symbol *s, int x_start, int y_start, int incr);
+};
+#define BEGIN \
+ t_outlet *ouch = ((t_object *)bself->mom)->te_outlet; \
+ t_canvas *can = bself->mom->gl_owner; \
+ if (!can) RAISE("no such canvas"); \
+ for (int i=0; i<n; i++) {ouch = ouch->next; if (!ouch) {RAISE("no such outlet");}}
+#define wire_each(wire,ouchlet) for (t_outconnect *wire = ouchlet->connections; wire; wire=wire->next)
+\def 0 wire_dotted (int r, int g, int b) {
+#ifndef DESIREDATA
+ BEGIN
+ wire_each(wire,ouch) {
+ sys_vgui(".x%lx.c itemconfigure l%lx -fill #%02x%02x%02x -dash {3 3 3 3}\n",long(can),long(wire),r,g,b);
+ }
+#else
+ post("doesn't work with DesireData");
+#endif
+}
+\def 0 wire_hide () {
+#ifndef DESIREDATA
+ BEGIN
+ wire_each(wire,ouch) sys_vgui(".x%lx.c delete l%lx\n",long(can),long(wire));
+#else
+ post("doesn't work with DesireData");
+#endif
+}
+\def 0 box_dotted (int r, int g, int b) {
+#ifndef DESIREDATA
+ BEGIN
+ wire_each(wire,ouch) {
+ t_object *t = (t_object *)wire->to;
+ int x1,y1,x2,y2;
+ gobj_getrect((t_gobj *)wire->to,can,&x1,&y1,&x2,&y2);
+ // was #00aa66 {3 5 3 5}
+ sys_vgui(".x%lx.c delete %lxRECT; .x%lx.c create rectangle %d %d %d %d "DASHRECT" -tags %lxRECT\n",
+ long(can),long(t),long(can),x1,y1,x2,y2,long(t));
+ }
+#else
+ post("doesn't work with DesireData");
+#endif
+}
+bool comment_sort_y_lt(t_object * const &a, t_object * const &b) /* is a StrictWeakOrdering */ {
+ return a->te_ypix < b->te_ypix;
+}
+#define foreach(ITER,COLL) for(typeof(COLL.begin()) ITER = COLL.begin(); ITER != (COLL).end(); ITER++)
+static t_class *inlet_class, *floatinlet_class, *symbolinlet_class, *pointerinlet_class;
+static bool ISINLET(t_pd *o) {
+ t_class *c=pd_class(o);
+ return c==inlet_class || c==floatinlet_class || c==symbolinlet_class || c==pointerinlet_class;
+}
+struct _inlet {
+ t_pd pd;
+ struct _inlet *next;
+ t_object *owner;
+ t_pd *dest;
+ t_symbol *symfrom;
+ //union inletunion un;
+};
+\def 0 box_align (t_symbol *dir, int x_start, int y_start, int incr) {
+ int x=x_start, y=y_start;
+ bool horiz;
+ if (dir==&s_x) horiz=false; else
+ if (dir==&s_y) horiz=true; else RAISE("$1 must be x or y");
+#ifndef DESIREDATA
+ std::vector<t_object *> v;
+ BEGIN
+ wire_each(wire,ouch) {
+ //post("wire to object of class %s ISINLET=%d",pd_class(wire->to)->c_name->s_name,ISINLET(wire->to));
+ t_object *to = ISINLET(wire->to) ? ((t_inlet *)wire->to)->owner : (t_object *)wire->to;
+ v.push_back(to);
+ }
+ sort(v.begin(),v.end(),comment_sort_y_lt);
+ foreach(tt,v) {
+ t_object *t = *tt;
+ if (t->te_xpix!=x || t->te_ypix!=y) {
+ gobj_vis((t_gobj *)t,can,0);
+ t->te_xpix=x;
+ t->te_ypix=y;
+ gobj_vis((t_gobj *)t,can,1);
+ canvas_fixlinesfor(can,t);
+ }
+ int x1,y1,x2,y2;
+ gobj_getrect((t_gobj *)t,can,&x1,&y1,&x2,&y2);
+ if (horiz) x += x2-x1+incr;
+ else y += y2-y1+incr;
+ }
+ if (horiz) outlet_float(bself->outlets[0],x-x_start);
+ else outlet_float(bself->outlets[0],y-y_start);
+#else
+ post("doesn't work with DesireData");
+#endif
+}
+
+extern t_widgetbehavior text_widgetbehavior;
+t_widgetbehavior text_widgetbehavi0r;
+
+/* i was gonna use gobj_shouldvis but it's only for >= 0.42 */
+
+static int text_chou_de_vis(t_text *x, t_glist *glist) {
+ return (glist->gl_havewindow ||
+ (x->te_pd != canvas_class && x->te_pd->c_wb != &text_widgetbehavior) ||
+ (x->te_pd == canvas_class && (((t_glist *)x)->gl_isgraph)) ||
+ (glist->gl_goprect && (x->te_type == T_TEXT)));
+}
+
+static void text_visfn_hax0r (t_gobj *o, t_canvas *can, int vis) {
+ text_widgetbehavior.w_visfn(o,can,vis);
+ //if (vis) return; // if you want to see #X text inlets uncomment this line
+ t_rtext *y = glist_findrtext(can,(t_text *)o);
+ if (text_chou_de_vis((t_text *)o,can)) glist_eraseiofor(can,(t_object *)o,rtext_gettag(y));
+}
+\end class {
+ install("gf/lol",1,1);
+#ifndef DESIREDATA
+ class_setpropertiesfn(text_class,(t_propertiesfn)0xDECAFFED);
+ unsigned long *lol = (unsigned long *)text_class;
+ int i=0;
+ while (lol[i]!=0xDECAFFED) i++;
+ *((char *)(lol+i+1) + 6) = 1;
+ class_setpropertiesfn(text_class,0);
+ t_object *bogus = (t_object *)pd_new(text_class);
+ inlet_class = pd_class((t_pd *) inlet_new(bogus,0,0,0));
+ floatinlet_class = pd_class((t_pd *) floatinlet_new(bogus,0));
+ symbolinlet_class = pd_class((t_pd *) symbolinlet_new(bogus,0));
+ pointerinlet_class = pd_class((t_pd *)pointerinlet_new(bogus,0));
+ memcpy(&text_widgetbehavi0r,&text_widgetbehavior,sizeof(t_widgetbehavior));
+ text_widgetbehavi0r.w_visfn = text_visfn_hax0r;
+ class_setwidget(text_class,&text_widgetbehavi0r);
+#endif
+}
+
+\class GFStringReplace : FObject {
+ t_symbol *from;
+ t_symbol *to;
+ \constructor (t_symbol *from, t_symbol *to=&s_) {this->from=from; this->to=to;}
+ \decl 0 symbol (t_symbol *victim);
+};
+\def 0 symbol (t_symbol *victim) {
+ string a = string(victim->s_name);
+ string b = string(from->s_name);
+ string c = string(to->s_name);
+ for (size_t i=0;;) {
+ i = a.find(b,i);
+ if (i==string::npos) break;
+ a = a.replace(i,b.length(),c);
+ i += c.length();
+ }
+ outlet_symbol(bself->outlets[0],gensym(a.c_str()));
+}
+\end class {install("gf/string_replace",1,1);}
+
+\class GFStringLessThan : FObject {
+ t_symbol *than;
+ \constructor (t_symbol *than=&s_) {this->than=than;}
+ \decl 0 symbol (t_symbol *it);
+ \decl 1 symbol (t_symbol *than);
+};
+\def 0 symbol (t_symbol *it) {outlet_float(bself->outlets[0],strcmp(it->s_name,than->s_name)<0);}
+\def 1 symbol (t_symbol *than) {this->than=than;}
+\end class {install("gf/string_<",2,1);}
+
+void startup_flow_objects2 () {
+ \startall
+}
diff --git a/externals/gridflow/src/dc1394.cxx b/externals/gridflow/src/dc1394.cxx
new file mode 100644
index 00000000..e2361a8e
--- /dev/null
+++ b/externals/gridflow/src/dc1394.cxx
@@ -0,0 +1,287 @@
+/*
+ $Id: dc1394.c 4620 2009-11-01 21:16:58Z matju $
+
+ GridFlow
+ Copyright (c) 2001-2009 by Mathieu Bouchard
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ See file ../COPYING for further informations on licensing terms.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#define DC1394_INCLUDE_HERE
+#include <libraw1394/raw1394.h>
+#include "gridflow.hxx.fcs"
+
+/* speeds are numbered 0 to 5, worth 100<<speednum */
+/* framerates are numbers 32 to 39, worth 1.875<<(frameratenum-32) */
+
+#define MODE(x,y,palette) /* nothing for now */
+
+static std::map<int,string> feature_names;
+
+static void setup_modes () {
+ int i=64; // format 0
+ MODE(160,120,YUV444);
+ MODE(320,240,YUV422);
+ MODE(640,480,YUV411);
+ MODE(640,480,YUV422);
+ MODE(640,480,RGB);
+ MODE(640,480,MONO);
+ MODE(640,480,MONO16);
+ i=96; // format 1
+ MODE(800,600,YUV422);
+ MODE(800,600,RGB);
+ MODE(800,600,MONO);
+ MODE(1024,768,YUV422);
+ MODE(1024,768,RGB);
+ MODE(1024,768,MONO);
+ MODE(800,600,MONO16);
+ MODE(1024,768,MONO16);
+ i=128; // format 2
+ MODE(1280,960,YUV422);
+ MODE(1280,960,RGB);
+ MODE(1280,960,MONO);
+ MODE(1600,1200,YUV422);
+ MODE(1600,1200,RGB);
+ MODE(1600,1200,MONO);
+ MODE(1280,960,MONO16);
+ MODE(1600,1200,MONO16);
+ i=256; // format 6
+ // MODE_EXIF= 256
+ i=288; // format 7
+ //MODE_FORMAT7_0,
+ //MODE_FORMAT7_1,
+ //MODE_FORMAT7_2,
+ //MODE_FORMAT7_3,
+ //MODE_FORMAT7_4,
+ //MODE_FORMAT7_5,
+ //MODE_FORMAT7_6,
+ //MODE_FORMAT7_7
+
+// format7 color modes start at #320 and are MONO8 YUV411 YUV422 YUV444 RGB8 MONO16 RGB16 MONO16S RGB16S RAW8 RAW16
+// trigger modes start at #352 and are 0 1 2 3
+// image formats start at #384 and are VGA_NONCOMPRESSED SVGA_NONCOMPRESSED_1 SVGA_NONCOMPRESSED_2
+// and continue at #390 and are STILL_IMAGE FORMAT_SCALABLE_IMAGE_SIZE
+
+#define FEATURE(foo) feature_names[i++] = #foo;
+
+ i=416;
+ FEATURE(BRIGHTNESS);
+ FEATURE(EXPOSURE);
+ FEATURE(SHARPNESS);
+ FEATURE(WHITE_BALANCE);
+ FEATURE(HUE);
+ FEATURE(SATURATION);
+ FEATURE(GAMMA);
+ FEATURE(SHUTTER);
+ FEATURE(GAIN);
+ FEATURE(IRIS);
+ FEATURE(FOCUS);
+ FEATURE(TEMPERATURE);
+ FEATURE(TRIGGER);
+ FEATURE(TRIGGER_DELAY);
+ FEATURE(WHITE_SHADING);
+ FEATURE(FRAME_RATE);
+ i+=16;/* 16 reserved features */
+ FEATURE(ZOOM);
+ FEATURE(PAN);
+ FEATURE(TILT);
+ FEATURE(OPTICAL_FILTER);
+ i+=12;/* 12 reserved features */
+ FEATURE(CAPTURE_SIZE);
+ FEATURE(CAPTURE_QUALITY);
+ i+=14;/* 14 reserved features */
+
+ i=480; // operation modes
+ //OPERATION_MODE_LEGACY
+ //OPERATION_MODE_1394B
+
+ i=512; // sensor layouts
+ //RGGB
+ //GBRG,
+ //GRBG,
+ //BGGR
+
+ i=544; // IIDC_VERSION
+#if 0
+ IIDC_VERSION(1_04);
+ IIDC_VERSION(1_20);
+ IIDC_VERSION(PTGREY);
+ IIDC_VERSION(1_30);
+ IIDC_VERSION(1_31);
+ IIDC_VERSION(1_32);
+ IIDC_VERSION(1_33);
+ IIDC_VERSION(1_34);
+ IIDC_VERSION(1_35);
+ IIDC_VERSION(1_36);
+ IIDC_VERSION(1_37);
+ IIDC_VERSION(1_38);
+ IIDC_VERSION(1_39);
+#endif
+
+// Return values are SUCCESS FAILURE NO_FRAME NO_CAMERA
+
+// Parameter flags for dc1394_setup_format7_capture()
+//#define QUERY_FROM_CAMERA -1
+//#define USE_MAX_AVAIL -2
+//#define USE_RECOMMENDED -3
+
+// The video1394 policy: blocking (wait for a frame forever) or polling (returns if no frames in buffer
+// WAIT=0 POLL=1
+};
+
+typedef raw1394handle_t RH;
+typedef nodeid_t NID;
+
+#define IO(func,args...) if (func(rh,usenode,args)!=DC1394_SUCCESS) RAISE(#func " failed");
+
+\class FormatDC1394 : Format {
+ RH rh;
+ int useport;
+ int usenode;
+ int framerate_e;
+ int height;
+ int width;
+ dc1394_cameracapture camera;
+ dc1394_feature_set features;
+ std::map<int,int> feature_index;
+ \constructor (t_symbol *mode) {
+ bool gotone=false;
+ post("DC1394: hello world");
+ rh = raw1394_new_handle();
+ if (!rh) RAISE("could not get a handle for /dev/raw1394 and /dev/video1394");
+ int numPorts = raw1394_get_port_info(rh,0,0);
+ raw1394_destroy_handle(rh);
+ post("there are %d Feuerweuer ports",numPorts);
+ if (mode!=gensym("in")) RAISE("sorry, read-only");
+ for(int port=0; port<numPorts; port++) {
+ post("trying port #%d...",port);
+ RH rh = dc1394_create_handle(port);
+ int numCameras=0xDEADBEEF;
+ NID *nodes = dc1394_get_camera_nodes(rh,&numCameras,0);
+ post("port #%d has %d cameras",port,numCameras);
+ for (int i=0; i<numCameras; i++) {
+ post("camera at node #%d",nodes[i]);
+ if (!gotone) {gotone=true; useport=port; usenode=nodes[i];}
+ }
+ dc1394_destroy_handle(rh);
+ }
+ if (!gotone) RAISE("no cameras available");
+ this->rh = dc1394_create_handle(useport);
+ IO(dc1394_get_camera_feature_set,&features);
+ dc1394_print_feature_set(&features);
+ post("NUM_FEATURES=%d",NUM_FEATURES);
+ for (int i=0; i<NUM_FEATURES; i++) {
+ dc1394_feature_info &f = features.feature[i];
+ int id = f.feature_id;
+ string name = feature_names.find(id)==feature_names.end() ? "(unknown)" : feature_names[id];
+ bool is_there = f.available;
+ post(" feature %d '%s' is %s",id,name.data(),is_there?"present":"absent");
+ if (!is_there) continue;
+ post(" min=%u max=%u abs_min=%u abs_max=%u",f.min,f.max,f.abs_min,f.abs_max);
+ }
+ framerate_e = FRAMERATE_30;
+ height = 480;
+ width = 640;
+ setup();
+ }
+ \decl 0 bang ();
+ \attr float framerate();
+ \attr unsigned brightness();
+ \attr unsigned hue();
+ \attr unsigned colour();
+ //\attr uint16 contrast();
+ //\attr uint16 whiteness();
+ void setup ();
+ \decl 0 get (t_symbol *s=0);
+ \decl 0 size (int height, int width);
+};
+
+\def 0 get (t_symbol *s=0) {
+ FObject::_0_get(argc,argv,s);
+ t_atom a[2];
+ if (!s) {
+ SETFLOAT(a+0,camera.frame_height);
+ SETFLOAT(a+1,camera.frame_width);
+ outlet_anything(bself->outlets[0],gensym("size"),2,a); // abnormal (does not use nested list)
+ unsigned int width,height;
+ IO(dc1394_query_format7_max_image_size,MODE_FORMAT7_0,&width,&height);
+ SETFLOAT(a+0,height);
+ SETFLOAT(a+1,width);
+ outlet_anything(bself->outlets[0],gensym("maxsize"),2,a); // abnormal (does not use nested list)
+ }
+}
+\def 0 size (int height, int width) {
+ IO(dc1394_set_format7_image_size,MODE_FORMAT7_0,width,height);
+ this->height = height;
+ this->width = width;
+ setup();
+}
+
+\def unsigned brightness () {unsigned value; dc1394_get_brightness(rh,usenode,&value); return value;}
+\def 0 brightness (unsigned value) {dc1394_set_brightness(rh,usenode, value);}
+\def unsigned hue () {unsigned value; dc1394_get_hue( rh,usenode,&value); return value;}
+\def 0 hue (unsigned value) {dc1394_set_hue( rh,usenode, value);}
+\def unsigned colour () {unsigned value; dc1394_get_saturation(rh,usenode,&value); return value;}
+\def 0 colour (unsigned value) {dc1394_set_saturation(rh,usenode, value);}
+
+void FormatDC1394::setup () {
+ //dc1394_set_format7_image_size(rh,usenode,0,width,height);
+ IO(dc1394_setup_capture,0,FORMAT_VGA_NONCOMPRESSED,MODE_640x480_MONO,SPEED_400,framerate_e,&camera);
+ //IO(dc1394_setup_format7_capture,0,MODE_FORMAT7_0,SPEED_400,QUERY_FROM_CAMERA,0,0,width,height,&camera);
+ if (dc1394_set_trigger_mode(rh,usenode,TRIGGER_MODE_0) != DC1394_SUCCESS) RAISE("dc1394_set_trigger_mode error");
+ if (dc1394_start_iso_transmission(rh,usenode)!=DC1394_SUCCESS) RAISE("dc1394_start_iso_transmission error");
+}
+
+\def float framerate() {
+ return 1.875 * (1<<(framerate_e-FRAMERATE_1_875));
+}
+
+\def 0 framerate(float framerate) {
+ framerate_e = FRAMERATE_1_875;
+ while (framerate>=1.875 && framerate_e <= FRAMERATE_240) {framerate/=2; framerate_e++;}
+ setup();
+}
+
+static volatile int timeout=0;
+static void rien (int) {timeout=1; post("timeout2");}
+
+\def 0 bang () {
+ //struct itimerval tval;
+ //tval.it_interval.tv_sec = 1;
+ //tval.it_interval.tv_usec = 0;
+ //tval.it_value = tval.it_interval;
+ //setitimer(ITIMER_REAL,&tval,0);
+ //signal(SIGALRM,rien);
+ if (dc1394_single_capture(rh,&camera)!=DC1394_SUCCESS) RAISE("dc1394_single_capture error");
+ //setitimer(ITIMER_REAL,0,0);
+ out=new GridOutlet(this,0,new Dim(height,width,1));
+ //out->send(out->dim->prod(),(uint8 *)camera.capture_buffer);
+ for (int i=0; i<height; i++) out->send(out->dim->prod(1),(uint8 *)camera.capture_buffer+640*i);
+ //if (dc1394_stop_iso_transmission(rh,usenode)!=DC1394_SUCCESS) RAISE("dc1394_stop_iso_transmission error");
+ //post("frame_height=%d",camera.frame_height);
+ //post("frame_width=%d" ,camera.frame_width);
+ //post("quadlets_per_frame=%d" ,camera.quadlets_per_frame);
+ //post("quadlets_per_packet=%d" ,camera.quadlets_per_packet);
+}
+
+\end class FormatDC1394 {
+ install_format("#io.dc1394",4,"");
+ setup_modes();
+}
+void startup_dc1394 () {
+ \startall
+}
diff --git a/externals/gridflow/src/fftw.cxx b/externals/gridflow/src/fftw.cxx
new file mode 100644
index 00000000..7aa3f44c
--- /dev/null
+++ b/externals/gridflow/src/fftw.cxx
@@ -0,0 +1,114 @@
+/*
+ GridFlow
+ Copyright (c) 2001-2009 by Mathieu Bouchard
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ See file ../COPYING for further informations on licensing terms.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "gridflow.hxx.fcs"
+#include <fftw3.h>
+
+#define C(x) ((fftwf_complex *)x)
+
+\class GridFFT : FObject {
+ fftwf_plan plan;
+ P<Dim> lastdim; /* of last input (for plan cache) */
+ long lastchans; /* of last input (for plan cache) */
+ \attr int sign; /* -1 or +1 */
+ \attr int skip; /* 0 (y and x) or 1 (x only) */
+ \attr bool real;
+ bool lastreal;
+ \constructor () {sign=-1; plan=0; lastdim=0; lastchans=0; skip=0; real=false;}
+ \grin 0 float32
+};
+\def 0 sign (int sign) {
+ if (sign!=-1 && sign!=1) RAISE("sign should be -1 or +1");
+ this->sign=sign;
+ fftwf_destroy_plan(plan);
+}
+\def 0 skip (int skip) {
+ if (skip<0 || skip>1) RAISE("skip should be 0 or 1");
+ this->skip=skip;
+ if (plan) {fftwf_destroy_plan(plan); plan=0;}
+}
+GRID_INLET(0) {
+ if (in->nt != float32_e) RAISE("expecting float32");
+ if (real && sign==-1) {
+ if (in->dim->n != 2 && in->dim->n != 3) RAISE("expecting 2 or 3 dimensions: rows,columns,channels?");
+ } else {
+ if (in->dim->n != 3 && in->dim->n != 4) RAISE("expecting 3 or 4 dimensions: rows,columns,channels?,complex");
+ if (in->dim->get(in->dim->n-1)!=2) RAISE("expecting Dim(...,2): real,imaginary (got %d)",in->dim->get(2));
+ }
+ in->set_chunk(0);
+} GRID_FLOW {
+ if (skip==1 && !real) RAISE("can't do 1-D FFT in real mode, sorry");
+ Dim *dim;
+ if (!real) dim = in->dim;
+ else if (sign==-1) {
+ int v[Dim::MAX_DIM];
+ for (int i=0; i<in->dim->n; i++) v[i]=in->dim->v[i];
+ v[in->dim->n] = 2;
+ dim = new Dim(in->dim->n+1,v);
+ } else dim = new Dim(in->dim->n-1,in->dim->v);
+ GridOutlet out(this,0,dim,in->nt);
+ float32 *tada = (float32 *)memalign(16,dim->prod()*sizeof(float32));
+ long chans = in->dim->n>=3 ? in->dim->get(2) : 1;
+ CHECK_ALIGN16(data,in->nt)
+ CHECK_ALIGN16(tada,in->nt)
+ if (plan && lastdim && lastdim!=in->dim && chans!=lastchans && real==lastreal) {fftwf_destroy_plan(plan); plan=0;}
+ int v[] = {in->dim->v[0],in->dim->v[1],in->dim->n>2?in->dim->v[2]:1};
+// if (chans==1) {
+// if (skip==0) plan = fftwf_plan_dft_2d(v[0],v[1],data,tada,sign,0);
+// if (skip==1) plan = fftwf_plan_many_dft(1,&v[1],v[0],data,0,1,v[1],tada,0,1,v[1],sign,0);
+// }
+ if (skip==0) {
+ //plan = fftwf_plan_dft_2d(v[0],v[1],data,tada,sign,0);
+ if (!plan) {
+ int embed[] = {dim->v[0],dim->v[1]};
+ if (!real) {plan=fftwf_plan_many_dft( 2,&v[0],chans,C(data),0 ,chans,1,C(tada),0 ,chans,1,sign,0);}
+ else if (sign==-1) {plan=fftwf_plan_many_dft_r2c(2,&v[0],chans, data ,embed,chans,1,C(tada),embed,chans,1,0);}
+ else {plan=fftwf_plan_many_dft_c2r(2,&v[0],chans,C(data),embed,chans,1, tada ,embed,chans,1,0);}
+ }
+ if (!real) fftwf_execute_dft( plan,C(data),C(tada));
+ else if (sign==-1) fftwf_execute_dft_r2c(plan, data ,C(tada));
+ else fftwf_execute_dft_c2r(plan,C(data), tada );
+ }
+ if (skip==1) {
+ if (!plan) plan=fftwf_plan_many_dft(1,&v[1],chans,C(data),0,chans,1,C(tada),0,chans,1,sign,0);
+ //plan = fftwf_plan_many_dft(1,&v[1],v[0],C(data),0,1,v[1],C(tada),0,1,v[1],sign,0);
+ long incr = v[1]*chans;
+ for (int i=0; i<v[0]; i++) fftwf_execute_dft(plan,C(data)+i*incr,C(tada)+i*incr);
+ }
+ if (real && sign==-1) {
+ for (int i=0; i<v[0]; i++) {
+ int h = mod(-i,v[0]);
+ T *tada2 = tada + (h*v[1]+v[1]/2)*v[2]*2;
+ T *tada3 = tada + (i*v[1]+v[1]/2)*v[2]*2;
+ for (int j=1+v[1]/2; j<v[1]; j++) {
+ tada2-=v[2]*2; tada3+=v[2]*2;
+ for (int k=0; k<v[2]; k++) {tada3[k+k]=tada2[k+k]; tada3[k+k+1]=-tada2[k+k+1];}
+ }
+ }
+ }
+ out.send(out.dim->prod(),tada);
+ free(tada);
+ lastdim=in->dim; lastchans=chans; lastreal=real;
+} GRID_END
+\end class {install("#fft",1,1);}
+void startup_fftw () {
+ \startall
+}
diff --git a/externals/gridflow/src/formats.cxx b/externals/gridflow/src/formats.cxx
new file mode 100644
index 00000000..50574285
--- /dev/null
+++ b/externals/gridflow/src/formats.cxx
@@ -0,0 +1,266 @@
+/*
+ $Id$
+
+ GridFlow
+ Copyright (c) 2001-2009 by Mathieu Bouchard
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ See file ../COPYING for further informations on licensing terms.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "gridflow.hxx.fcs"
+#include <string>
+#include <map>
+#include <errno.h>
+#define L _L_
+
+/* API (version 0.9.3)
+ mode is :in or :out
+ def initialize(mode,*args) :
+ open a file handler (do it via .new of class)
+ attr_reader :description :
+ a _literal_ (constant) string describing the format handler
+ def self.info() optional :
+ return a string describing the format handler differently
+ than self.description(). in particular, it can list
+ compile-time options and similar things. for example,
+ quicktime returns a list of codecs.
+ def 0 bang() :
+ read one frame, send through outlet 0
+ return values :
+ Integer >= 0 : frame number of frame read.
+ false : no frame was read : end of sequence.
+ nil : a frame was read, but can't say its number.
+ note that trying to read a nonexistent frame should no longer
+ rewind automatically (@in handles that part), nor re-read the
+ last frame (mpeg/quicktime used to do this)
+ def 0 seek(Integer i) : select one frame to be read next (by number)
+ def 0 grid() : frame to write
+ def 0 get (optional Symbol s) : get one attribute value or all of them
+ def 0 ...() : options
+ outlet 0 grid() frame just read
+ outlet 0 ...() everything else
+ destructor : close a handler
+*/
+
+std::map<std::string,std::string> suffix_table;
+void suffixes_are (const char *name, const char *suffixes) {
+ std::string name2 = name;
+ char *suff2 = strdup(suffixes);
+ char *suff3 = suff2+strlen(suff2);
+ for (char *s=suff2; s<suff3; s++) if (*s==' ' || *s==',') *s=0;
+ for (char *s=suff2; s<suff3; s+=strlen(s)+1) {
+ std::string ss = s;
+ suffix_table[ss]=name2;
+ }
+}
+
+\class SuffixLookup : FObject {
+ \constructor () {}
+ \decl 0 symbol (t_symbol *str);
+};
+\def 0 symbol (t_symbol *str) {
+ char *s = strdup(str->s_name);
+ char *t = strrchr(s,'.');
+ if (!t) outlet_symbol(bself->outlets[2],gensym(s));
+ else {
+ *t = 0;
+ outlet_symbol(bself->outlets[1],gensym(t+1));
+ std::map<std::string,std::string>::iterator u = suffix_table.find(std::string(t+1));
+ if (u==suffix_table.end()) outlet_bang(bself->outlets[0]);
+ else outlet_symbol(bself->outlets[0],gensym((char *)u->second.data()));
+ }
+ free(s);
+}
+\end class SuffixLookup {install("gf.suffix_lookup",1,3);}
+
+\class Format : FObject
+Format::Format (BFObject *bself, MESSAGE) : FObject(bself,MESSAGE2) {
+ mode=0; fd=-1; f=0; cast=int32_e; frame=0;
+ if (argv[0]==gensym("out")) this->mode=2; else
+ if (argv[0]==gensym("in")) this->mode=4; else RAISE("unknown mode");
+// case mode
+// when :in; flags[2]==1
+// when :out; flags[1]==1
+// else raise "Format opening mode is incorrect"
+ //end or raise "Format '#{self.class.instance_eval{@symbol_name}}' does not support mode '#{mode}'"
+}
+
+\def 0 open(t_symbol *mode, string filename) {
+ const char *fmode;
+ if (mode==gensym("in")) fmode="r"; else
+ if (mode==gensym("out")) fmode="w"; else
+ RAISE("bad mode");
+ if (f) _0_close(0,0);
+ if (mode==gensym("in")) {filename = gf_find_file(filename);}
+ f = fopen(filename.data(),fmode);
+ if (!f) RAISE("can't open file '%s': %s",filename.data(),strerror(errno));
+ fd = fileno(f);
+// case gzfile:
+// if (mode==SYM(in)) {filename = GridFlow.find_file(filename);}
+// if (mode==:in) {raw_open_gzip_in filename; else raw_open_gzip_out filename;}
+// def self.rewind() raw_open(*@raw_open_args); @frame = 0 end unless @rewind_redefined
+// @rewind_redefined = true
+}
+\def 0 close() {if (f) {fclose(f); f=0; fd=-1;}}
+\def 0 cast(NumberTypeE nt) {cast = nt;}
+
+\def 0 seek(int frame) {
+ if (!frame) {_0_rewind(0,0); return;}
+ RAISE("don't know how to seek for frame other than # 0");
+}
+
+// this is what you should use to rewind
+// different file-sources may redefine this as something else
+// (eg: gzip)
+\def 0 rewind () {
+ if (!f) RAISE("Nothing to rewind about...");
+ fseek(f,0,SEEK_SET);
+ frame = 0;
+}
+
+Format::~Format () {if (f) fclose(f); /*if (fd>=0) close(fd);*/}
+\end class Format {}
+
+/* This is the Grid format I defined: */
+struct GridHeader {
+ char magic[5]; // = "\x7fgrid" on little endian, "\x7fGRID" on big endian
+ uint8 type; // supported: 8=int8 9=uint8 16=int16 32=int32
+ // unsupported: 34=float32 64=int64 66=float64
+ // (number of bits is multiple of 8; add 1 for unsigned; add 2 for float)
+ uint8 reserved; // set this to 0 all of the time.
+ uint8 dimn; // number of dimensions supported: at least 0..4)
+ // int32 dimv[dimn]; // number of elements in each dimension. (in the file's endianness!)
+ // raw data goes after that
+};
+
+\class FormatGrid : Format {
+ GridHeader head;
+ int endian;
+ NumberTypeE nt;
+ P<Dim> headerless_dim; // if null: headerful; if Dim: it is the assumed dimensions of received grids
+ \grin 0
+ \constructor (t_symbol *mode, string filename) {
+ nt = int32_e;
+ endian = is_le();
+ _0_open(0,0,mode,filename);
+ }
+ \decl 0 bang ();
+ \decl 0 headerless (...);
+ \decl 0 headerful ();
+ \decl 0 type (NumberTypeE nt);
+ ~FormatGrid() {
+ //@stream.close if @stream
+ //GridFlow.hunt_zombies
+ }
+// \decl void raw_open_gzip_in(string filename);
+// \decl void raw_open_gzip_out(string filename);
+};
+\def 0 bang () {
+ P<Dim> dim;
+ if (feof(f)) {outlet_bang(bself->te_outlet); return;}
+ if (headerless_dim) {
+ dim = headerless_dim;
+ } else {
+ if (fread(&head,1,8,f)<8) RAISE("can't read header");
+ uint8 *m = (uint8 *)head.magic;
+ if (strncmp((char *)m,"\x7fgrid",5)==0) endian=1; else
+ if (strncmp((char *)m,"\x7fGRID",5)==0) endian=0; else
+ RAISE("unknown header, can't read grid from file: "
+ "%02x %02x %02x %02x %02x %02x %02x %02x",
+ m[0],m[1],m[2],m[3],m[4],m[5],m[6],m[7]);
+ switch (head.type) {
+ case 8: nt=uint8_e; break; // sorry, was supposed to be signed.
+ case 9: nt=uint8_e; break;
+ case 16: nt=int16_e; break;
+ case 32: nt=int32_e; break;
+ default: RAISE("unsupported grid type %d in file",head.type);
+ }
+ // apparently, head.type 8 and 16 worked too.
+ if (head.reserved!=0) RAISE("unsupported grid reserved field %d in file",head.reserved);
+ if (head.dimn>16) RAISE("unsupported grid number of dimensions %d in file",head.dimn);
+ int32 dimv[head.dimn];
+ ;
+ if (fread(dimv,1,head.dimn*4,f)<size_t(head.dimn*4)) RAISE("can't read dimension list");
+ if (endian != is_le()) swap32(head.dimn,(uint32 *)dimv);
+ dim = new Dim(head.dimn,dimv);
+ }
+ GridOutlet out(this,0,dim,nt);
+ long nn = dim->prod();
+#define FOO(T) {T data[nn]; if (fread(data,1,nn*sizeof(T),f)<nn*sizeof(T)) RAISE("can't read grid data (body)"); out.send(nn,(T *)data);}
+TYPESWITCH(nt,FOO,)
+#undef FOO
+ SUPER;
+}
+
+GRID_INLET(0) {
+ if (!headerless_dim) {
+ strncpy(head.magic,is_le()?"\x7fgrid":"\x7fGRID",5);
+ switch (in->nt) {
+ case uint8_e: head.type = 9; break;
+ case int16_e: head.type = 16; break;
+ case int32_e: head.type = 32; break;
+ default: RAISE("can't write that type of number to a file");
+ }
+ head.reserved = 0;
+ head.dimn = in->dim->n;
+ fwrite(&head,1,8,f);
+ fwrite(in->dim->v,in->dim->n,4,f);
+ }
+} GRID_FLOW {
+#define FOO(T) {T data2[n]; for(int i=0; i<n; i++) data2[i]=(T)data[i]; \
+ if (endian!=is_le()) swap_endian(n,data2); \
+ fwrite(data2,n,sizeof(T),f);}
+TYPESWITCH(in->nt,FOO,)
+#undef FOO
+} GRID_FINISH {
+ fflush(f);
+} GRID_END
+
+\def 0 headerless (...) {
+ if (argc>=0 && argv[0].a_type==A_LIST) {
+ t_binbuf *b = (t_binbuf *)argv[0]; argc = binbuf_getnatom(b); argv = (t_atom2 *)binbuf_getvec(b);}
+ int v[argc];
+ for (int i=0; i<argc; i++) v[i] = argv[i];
+ headerless_dim = new Dim(argc,v);
+}
+\def 0 headerful () { headerless_dim = 0; }
+//#!@#$ method name conflict ?
+\def 0 type (NumberTypeE nt) {
+ //!@#$ bug: should not be able to modify this _during_ a transfer
+ switch (nt) {
+ case uint8_e: head.type= 8; break;
+ case int16_e: head.type=16; break;
+ case int32_e: head.type=32; break;
+ default: RAISE("unsupported type");
+ }
+ this->nt = nt;
+}
+
+//\def void raw_open_gzip_in(string filename) {
+ //r,w = IO.pipe
+ //if (pid=fork) {GridFlow.subprocesses[pid]=true; w.close; @stream = r;}
+ //else {r.close; STDOUT.reopen w; STDIN.reopen filename, "r"; exec "gzip", "-dc";}
+//\def void raw_open_gzip_out(string filename) {
+ //r,w = IO.pipe
+ //if (pid=fork) {GridFlow.subprocesses[pid]=true; r.close; @stream = w;}
+ //else {w.close; STDIN.reopen r; STDOUT.reopen filename, "w"; exec "gzip", "-c";}
+
+\end class FormatGrid {install_format("#io.grid",6,"grid");}
+
+void startup_format () {
+ \startall
+}
diff --git a/externals/gridflow/src/gem.cxx b/externals/gridflow/src/gem.cxx
new file mode 100644
index 00000000..4d1d00c3
--- /dev/null
+++ b/externals/gridflow/src/gem.cxx
@@ -0,0 +1,202 @@
+/*
+ $Id: gem.c 4621 2009-11-01 21:18:17Z matju $
+
+ GridFlow
+ Copyright (c) 2001-2009 by Mathieu Bouchard
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ See file ../COPYING for further informations on licensing terms.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "gridflow.hxx.fcs"
+#include <GL/gl.h>
+/* summarising GEM's headers: GemState.h and GemPixUtil.h */
+struct imageStruct {
+ imageStruct(); ~imageStruct();
+ unsigned char* allocate(size_t size); unsigned char* allocate();
+ unsigned char* reallocate(size_t size); unsigned char* reallocate();
+ void clear();
+ GLint xsize, ysize, csize;
+ GLenum type, format;
+ int notowned;
+ void copy2Image(imageStruct *to) const;
+ void copy2ImageStruct(imageStruct *to) const; // copy the imageStruct (but not the actual data)
+ void refreshImage(imageStruct *to);
+ void swapRedBlue ();
+ void convertTo (imageStruct*to, GLenum dest_format=0);
+ void convertFrom(imageStruct*from, GLenum dest_format=0);
+ unsigned char *data;
+ private:
+ unsigned char *pdata;
+ size_t datasize;
+ public:
+ GLboolean upsidedown;
+};
+struct pixBlock {
+ pixBlock();
+ imageStruct image;
+ int newimage, newfilm;
+};
+class TexCoord {
+ public:
+ TexCoord() : s(0.f), t(0.f) {}
+ TexCoord(float s_, float t_) : s(s_), t(t_) {}
+ float s,t;
+};
+class GemState {
+ public:
+ int dirty, inDisplayList, lighting, smooth, texture;
+ pixBlock *image;
+ TexCoord *texCoords;
+ int numTexCoords, multiTexUnits;
+ float tickTime;
+ GLenum drawType;
+ int stackDepth[4];
+ int VertexDirty;
+ GLfloat *VertexArray; int VertexArraySize; int VertexArrayStride;
+ GLfloat *ColorArray; int HaveColorArray;
+ GLfloat *NormalArray; int HaveNormalArray;
+ GLfloat *TexCoordArray; int HaveTexCoordArray;
+ GemState();
+ ~GemState();
+ float texCoordX(int num) const {if (texture && numTexCoords > num) return texCoords[num].s; else return 0.;}
+ float texCoordY(int num) const {if (texture && numTexCoords > num) return texCoords[num].t; else return 0.;}
+ void reset();
+};
+/* end of summary */
+
+// in 0: gem
+// in 1: grid
+// out 0: gem
+\class GridToPix : FObject {
+ P<BitPacking> bit_packing3;
+ P<BitPacking> bit_packing4;
+ pixBlock m_pixBlock;
+ \attr bool yflip;
+ \decl 0 gem_state (...);
+ void render(GemState *state) {state->image = &m_pixBlock;}
+ void startRendering () {m_pixBlock.newimage = 1;}
+ GridToPix (BFObject *bself, MESSAGE) : FObject(bself,MESSAGE2) {
+ yflip = false;
+ imageStruct &im = m_pixBlock.image = imageStruct();
+ im.ysize = 1;
+ im.xsize = 1;
+ im.csize = 4;
+ im.format = GL_RGBA;
+ im.type = GL_UNSIGNED_BYTE;
+ im.allocate();
+ *(int*)im.data = 0x0000ff;
+ uint32 mask[4] = {0x0000ff,0x00ff00,0xff0000,0x000000};
+ bit_packing3 = new BitPacking(is_le(),4,3,mask);
+ bit_packing4 = new BitPacking(is_le(),4,4,mask);
+ }
+ ~GridToPix () {}
+ \grin 1 int
+};
+\def 0 gem_state (...) {
+ if (argc==2) render((GemState *)(void *)argv[1]); else startRendering();
+ outlet_anything(bself->te_outlet,gensym("gem_state"),argc,argv);
+}
+GRID_INLET(1) {
+ if (in->dim->n != 3) RAISE("expecting 3 dimensions: rows,columns,channels");
+ int c = in->dim->get(2);
+ if (c!=3 && c!=4) RAISE("expecting 3 or 4 channels (got %d)",in->dim->get(2));
+ in->set_chunk(1);
+ imageStruct &im = m_pixBlock.image;
+ im.clear();
+ im.ysize = in->dim->get(0);
+ im.xsize = in->dim->get(1);
+ im.type = GL_UNSIGNED_BYTE;
+ switch (in->dim->get(2)) {
+ case 1: im.csize = 1; im.format = GL_LUMINANCE; break;
+ case 3: im.csize = 4; im.format = GL_RGBA; break;
+ case 4: im.csize = 4; im.format = GL_RGBA; break;
+ default: RAISE("you shouldn't see this error message.");
+ }
+ im.allocate();
+} GRID_FLOW {
+ uint8 *buf = (uint8 *)m_pixBlock.image.data;
+ /*!@#$ it would be nice to skip the bitpacking when we can */
+ long sxc = in->dim->prod(1);
+ long sx = in->dim->v[1];
+ long sy = in->dim->v[0];
+ BitPacking *bp = in->dim->get(2)==3 ? bit_packing3 : bit_packing4;
+ imageStruct &im = m_pixBlock.image;
+ if (yflip) {for (long y= dex/sxc; n; data+=sxc, n-=sxc, y++) bp->pack(sx,data,buf+y*sx*im.csize);}
+ else {for (long y=sy-1-dex/sxc; n; data+=sxc, n-=sxc, y--) bp->pack(sx,data,buf+y*sx*im.csize);}
+} GRID_END
+\end class {install("#to_pix",2,1); add_creator("#export_pix");}
+
+//------------------------------------------------------------------------
+
+\class GridFromPix : FObject {
+ P<BitPacking> bit_packing;
+ \attr bool yflip;
+ \attr NumberTypeE cast;
+ int channels;
+ GridFromPix () : FObject(0,0,0,0) {RAISE("don't call this. this exists only to make GEM happy.");}
+ GridFromPix (BFObject *bself, MESSAGE) : FObject(bself,MESSAGE2) {
+ uint32 mask[4] = {0x0000ff,0x00ff00,0xff0000,0x000000};
+ bit_packing = new BitPacking(is_le(),4,3,mask);
+ yflip = false;
+ cast = int32_e;
+ channels = 3;
+ }
+ virtual ~GridFromPix () {}
+ \decl 0 gem_state (...);
+ \decl 0 colorspace (t_symbol *s);
+ void render(GemState *state) {
+ if (!state->image) {::post("gemstate has no pix"); return;}
+ imageStruct &im = state->image->image;
+ if (im.format != GL_RGBA ) {::post("can't produce grid from pix format %d",im.format); return;}
+ if (im.type != GL_UNSIGNED_BYTE) {::post("can't produce grid from pix type %d", im.type ); return;}
+ int32 v[] = { im.ysize, im.xsize, channels };
+ GridOutlet out(this,0,new Dim(3,v),cast);
+ long sxc = im.xsize*channels;
+ long sy = v[0];
+ if (channels==3) {
+ #define FOO(T) {T buf[sxc]; \
+ for (int y=0; y<v[0]; y++) { \
+ uint8 *data = (uint8 *)im.data+im.xsize*im.csize*(yflip?y:sy-1-y); \
+ bit_packing->unpack(im.xsize,data,buf); out.send(sxc,buf);}}
+ TYPESWITCH(cast,FOO,)
+ #undef FOO
+ } else {
+ for (int y=0; y<v[0]; y++) out.send(sxc,(uint8 *)im.data+sxc*(yflip?y:sy-1-y));
+ }
+ }
+};
+\def 0 colorspace (t_symbol *s) {
+ if (s==gensym("rgb" )) channels=3; else
+ if (s==gensym("rgba")) channels=4; else
+ RAISE("unknown colorspace '%s'",s->s_name);
+}
+\def 0 gem_state (...) {if (argc==2) render((GemState *)(void *)argv[1]);}
+\end class {install("#from_pix",2,1); add_creator("#import_pix");}
+
+//------------------------------------------------------------------------
+
+void startup_gem () {
+ \startall
+}
+
+/*
+virtual void processRGBAImage(imageStruct &image) {}
+virtual void processRGBImage (imageStruct &image) {}
+virtual void processGrayImage(imageStruct &image) {}
+virtual void processYUVImage (imageStruct &image) {}
+*/
+
diff --git a/externals/gridflow/src/grid.cxx b/externals/gridflow/src/grid.cxx
new file mode 100644
index 00000000..3d721329
--- /dev/null
+++ b/externals/gridflow/src/grid.cxx
@@ -0,0 +1,295 @@
+/*
+ $Id: grid.c 4391 2009-10-25 16:56:27Z matju $
+
+ GridFlow
+ Copyright (c) 2001-2009 by Mathieu Bouchard
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ See file ../COPYING for further informations on licensing terms.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include <stdlib.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include "gridflow.hxx.fcs"
+#include <ctype.h>
+
+//#define TRACEBUFS
+
+#define CHECK_TYPE(d,NT) if (NumberTypeE_type_of(&d)!=NT) RAISE("(%s): " \
+ "type mismatch during transmission (got %s expecting %s)", __PRETTY_FUNCTION__, \
+ number_type_table[NumberTypeE_type_of(&d)].name, number_type_table[NT].name);
+#define CHECK_BUSY1(s) if (!dim) RAISE(#s " not busy");
+#define CHECK_BUSY(s) if (!dim) RAISE(#s " not busy (wanting to write %ld values)",(long)n);
+#define CHECK_ALIGN(d,nt) {int bytes = number_type_table[nt].size/8; int align = ((long)(void*)d)%bytes; \
+ if (align) {post("(%s): Alignment Warning: %p is not %d-aligned: %d", __PRETTY_FUNCTION__, (void*)d,bytes,align);}}
+
+// **************** Grid ******************************************
+
+void Grid::init_from_list(int n, t_atom *aa, NumberTypeE nt) {
+ t_atom2 *a = (t_atom2 *)aa;
+ t_symbol *delim = gensym("#");
+ for (int i=0; i<n; i++) {
+ if (a[i] == delim) {
+ int32 v[i];
+ if (i!=0 && a[i-1].a_type==A_SYMBOL) nt=NumberTypeE_find(a[--i]);
+ for (int j=0; j<i; j++) v[j] = convert(a[j],(int32*)0);
+ init(new Dim(i,v),nt);
+ CHECK_ALIGN(this->data,nt);
+ if (a[i] != delim) i++;
+ i++; a+=i; n-=i;
+ goto fill;
+ }
+ }
+ if (n!=0 && a[0].a_type==A_SYMBOL) {nt = NumberTypeE_find(a[0]); a++; n--;}
+ init(new Dim(n),nt);
+ CHECK_ALIGN(this->data,nt);
+ fill:
+ int nn = dim->prod();
+ n = min(n,nn);
+#define FOO(T) { \
+ T *p = (T *)*this; \
+ if (n==0) CLEAR(p,nn); else { \
+ for (int i=0; i<n; i++) p[i] = a[i]; \
+ for (int i=n; i<nn; i+=n) COPY(p+i,p,min(n,nn-i)); }}
+ TYPESWITCH(nt,FOO,)
+#undef FOO
+}
+
+void Grid::init_from_atom(const t_atom &x) {
+ const t_atom2 &a = *(t_atom2 *)&x;
+ if (a.a_type==A_LIST) {
+ t_binbuf *b = a;
+ init_from_list(binbuf_getnatom(b),binbuf_getvec(b));
+ } else if (x.a_type==A_FLOAT) {
+ init(new Dim(),int32_e);
+ CHECK_ALIGN(this->data,nt);
+ ((int32 *)*this)[0] = (int32)a.a_float;
+ } else {
+ std::ostringstream s; s << x;
+ RAISE("can't convert to grid: %s",s.str().data());
+ }
+}
+
+// **************** GridInlet *************************************
+
+// must be set before the end of GRID_BEGIN phase, and so cannot be changed
+// afterwards. This is to allow some optimisations. Anyway there is no good reason
+// why this would be changed afterwards.
+void GridInlet::set_chunk(long whichdim) {
+ chunk = whichdim;
+ long n = dim->prod(whichdim);
+ if (!n) n=1;
+ if(!dim) RAISE("huh?");
+ if (n>1) {
+ buf=new Grid(new Dim(n), sender->nt);
+ bufi=0;
+ } else buf=0;
+}
+
+bool GridInlet::supports_type(NumberTypeE nt) {
+#define FOO(T) return !! gh->flow_##T;
+ TYPESWITCH(nt,FOO,return false)
+#undef FOO
+}
+
+void GridInlet::begin(GridOutlet *sender) {
+ if (dim) RAISE("grid inlet aborting from %s at %ld/%ld because of %s",
+ ARGS(this->sender->parent),long(dex),long(dim->prod()),ARGS(sender->parent));
+ this->sender = sender;
+ if (!supports_type(sender->nt)) RAISE("number type %s not supported here", number_type_table[sender->nt].name);
+ this->nt = sender->nt;
+ this->dim = sender->dim;
+ dex=0;
+ buf=0;
+ try {
+#define FOO(T) gh->flow(this,dex,-1,(T *)0); break;
+ TYPESWITCH(sender->nt,FOO,)
+#undef FOO
+ } catch (Barf &barf) {this->dim=0; throw;}
+ this->dim = dim;
+ sender->callback(this);
+#ifdef TRACEBUFS
+ post("GridInlet: %20s buf for recving from %p",dim->to_s(),sender);
+#endif
+}
+
+#define CATCH_IT catch (Barf &slimy) {slimy.error(parent->bself);}
+
+template <class T> void GridInlet::flow(long n, T *data) {
+ CHECK_BUSY(inlet); CHECK_TYPE(*data,sender->nt); CHECK_ALIGN(data,sender->nt);
+ if (!n) return; // no data
+ long d = dex + bufi;
+ if (d+n > dim->prod()) {
+ post("grid input overflow: %ld of %ld from [%s] to [%s]", d+n, long(dim->prod()), ARGS(sender->parent), ARGS(parent));
+ n = dim->prod() - d;
+ if (n<=0) return;
+ }
+ int bufn = factor();
+ if (buf && bufi) {
+ T *bufd = *buf;
+ long k = min((long)n,bufn-bufi);
+ COPY(bufd+bufi,data,k);
+ bufi+=k; data+=k; n-=k;
+ if (bufi==bufn) {
+ long newdex = dex+bufn;
+ CHECK_ALIGN(bufd,sender->nt);
+ try {gh->flow(this,dex,bufn,bufd);} CATCH_IT;
+ dex = newdex;
+ bufi = 0;
+ }
+ }
+ int m = (n/bufn)*bufn;
+ if (m) {
+ int newdex = dex + m;
+ try {gh->flow(this,dex,m,data);} CATCH_IT;
+ dex = newdex;
+ }
+ data += m;
+ n -= m;
+ if (buf && n>0) COPY((T *)*buf+bufi,data,n), bufi+=n;
+}
+
+void GridInlet::finish() {
+ if (!dim) RAISE("inlet not busy");
+ if (dim->prod() != dex) post("%s: incomplete grid: %ld of %ld from [%s] to [%s]",
+ ARGS(parent),dex,long(dim->prod()),ARGS(sender->parent),ARGS(parent));
+#define FOO(T) try {gh->flow(this,dex,-2,(T *)0);} CATCH_IT;
+ TYPESWITCH(sender->nt,FOO,)
+#undef FOO
+ dim=0; buf=0; dex=0;
+}
+
+template <class T> void GridInlet::from_grid2(Grid *g, T foo) {
+ GridOutlet out(0,-1,g->dim,g->nt);
+ begin(&out);
+ size_t n = g->dim->prod();
+ if (n) out.send(n,(T *)*g); else finish();
+}
+
+void GridInlet::from_grid(Grid *g) {
+ if (!supports_type(g->nt)) RAISE("number type %s not supported here",number_type_table[g->nt].name);
+#define FOO(T) from_grid2(g,(T)0);
+ TYPESWITCH(g->nt,FOO,)
+#undef FOO
+}
+
+/* **************** GridOutlet ************************************ */
+
+GridOutlet::GridOutlet(FObject *parent_, int woutlet, P<Dim> dim_, NumberTypeE nt_) {
+ parent=parent_; dim=dim_; nt=nt_; dex=0; bufi=0; buf=0;
+ t_atom a[1];
+ SETGRIDOUT(a,this);
+ if (parent) {
+ outlet_anything(parent->bself->outlets[woutlet],bsym._grid,1,a);
+ if (!dim->prod()) finish();
+ }
+}
+
+void GridOutlet::create_buf () {
+ int32 lcm_factor = 1;
+ for (uint32 i=0; i<inlets.size(); i++) lcm_factor = lcm(lcm_factor,inlets[i]->factor());
+ //size_t ntsz = number_type_table[nt].size;
+ // biggest packet size divisible by lcm_factor
+ int32 v = (MAX_PACKET_SIZE/lcm_factor)*lcm_factor;
+ if (v==0) v=MAX_PACKET_SIZE; // factor too big. don't have a choice.
+ buf=new Grid(new Dim(v),nt);
+#ifdef TRACEBUFS
+ std::ostringstream text;
+ oprintf(text,"GridOutlet: %20s buf for sending to ",buf->dim->to_s());
+ for (uint i=0; i<inlets.size(); i++) text << " " << (void *)inlets[i]->parent;
+ post("%s",text.str().data());
+#endif
+}
+
+// send modifies dex; send_direct doesn't
+template <class T>
+void GridOutlet::send_direct(long n, T *data) {
+ CHECK_BUSY(outlet); CHECK_TYPE(*data,nt); CHECK_ALIGN(data,nt);
+ while (n>0) {
+ long pn = n;//min((long)n,MAX_PACKET_SIZE);
+ for (uint32 i=0; i<inlets.size(); i++) try {inlets[i]->flow(pn,data);} CATCH_IT;
+ data+=pn, n-=pn;
+ }
+}
+
+void GridOutlet::flush() {
+ if (!buf) return;
+ if (!bufi) return;
+#define FOO(T) send_direct(bufi,(T *)*buf);
+ TYPESWITCH(buf->nt,FOO,)
+#undef FOO
+ bufi = 0;
+}
+
+template <class T, class S>
+static void convert_number_type(int n, T *out, S *in) {for (int i=0; i<n; i++) out[i]=(T)in[i];}
+
+//!@#$ buffering in outlet still is 8x faster...?
+//!@#$ should use BitPacking for conversion...?
+// send modifies dex; send_direct doesn't
+template <class T>
+void GridOutlet::send_2(long n, T *data) {
+ //if (inlets.size()==1 && inlets[0]->buf) post("GridOutlet::send(%ld), bufsize %ld",long(n),long(inlets[0]->buf->dim->prod()));
+ if (!n) return;
+ CHECK_BUSY(outlet); CHECK_ALIGN(data,nt);
+ if (NumberTypeE_type_of(data)!=nt) {
+ int bs = MAX_PACKET_SIZE;
+#define FOO(T) {T data2[bs]; \
+ for (;n>=bs;n-=bs,data+=bs) {convert_number_type(bs,data2,data); send(bs,data2);} \
+ convert_number_type(n,data2,data); send(n,data2);}
+ TYPESWITCH(nt,FOO,)
+#undef FOO
+ } else {
+ dex += n;
+ if (n > MIN_PACKET_SIZE || bufi + n > MAX_PACKET_SIZE) flush();
+ if (n > MIN_PACKET_SIZE) {
+ //post("send_direct %d",n);
+ send_direct(n,data);
+ } else {
+ //post("send_indirect %d",n);
+ if (!buf) create_buf();
+ COPY((T *)*buf+bufi,data,n);
+ bufi += n;
+ }
+ if (dex==dim->prod()) finish();
+ }
+}
+
+void GridOutlet::callback(GridInlet *in) {
+ CHECK_BUSY1(outlet);
+ inlets.push_back(in);
+}
+
+void GridOutlet::finish () {
+ flush();
+ for (uint32 i=0; i<inlets.size(); i++) inlets[i]->finish();
+ dim=0;
+}
+
+// never call this. this is a hack to make some things work.
+// i'm trying to circumvent either a bug in the compiler or i don't have a clue. :-(
+void make_gimmick () {
+ GridOutlet foo(0,0,0);
+#define FOO(S) foo.send(0,(S *)0);
+EACH_NUMBER_TYPE(FOO)
+#undef FOO
+ //foo.send(0,(float64 *)0); // this doesn't work, when trying to fix the new link problem in --lite mode.
+}
diff --git a/externals/gridflow/src/gridflow.cxx b/externals/gridflow/src/gridflow.cxx
new file mode 100644
index 00000000..d30c8f4a
--- /dev/null
+++ b/externals/gridflow/src/gridflow.cxx
@@ -0,0 +1,961 @@
+/*
+ $Id: rubyext.c 3621 2008-04-19 01:47:38Z matju $
+
+ GridFlow
+ Copyright (c) 2001-2009 by Mathieu Bouchard
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ See file ../COPYING for further informations on licensing terms.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "gridflow.hxx.fcs"
+#include <ctype.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <errno.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <stdlib.h>
+//#include <cstdlib>
+#include <sys/stat.h>
+#include <time.h>
+#include <string.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <limits.h>
+
+#ifndef HAVE_DESIREDATA
+#include "bundled/g_canvas.h"
+#endif
+
+/* for exception-handling in 0.9.0... Linux-only */
+#ifndef MACOSX
+#include <exception>
+#include <execinfo.h>
+#endif
+#undef check
+
+std::map<string,FClass *> fclasses;
+std::map<t_class *,FClass *> fclasses_pd;
+
+//using namespace std;
+
+BuiltinSymbols bsym;
+
+Barf::Barf(const char *s, ...) {
+ std::ostringstream os;
+ va_list ap;
+ va_start(ap,s);
+ voprintf(os,s,ap);
+ va_end(ap);
+ text = os.str();
+}
+Barf::Barf(const char *file, int line, const char *func, const char *fmt, ...) {
+ std::ostringstream os;
+ va_list ap;
+ va_start(ap,fmt);
+ voprintf(os,fmt,ap);
+ //oprintf(os,"\n%s:%d:in `%s'",file,line,func);
+ va_end(ap);
+ text = os.str();
+}
+
+void Barf::error(BFObject *bself) {
+ if (bself) pd_error(bself,"%s: %s",bself->binbuf_string().data(),text.data());
+ else ::error( "%s: %s",bself->binbuf_string().data(),text.data());
+}
+
+void pd_oprint (std::ostream &o, int argc, t_atom *argv) {
+ for (int i=0; i<argc; i++) {
+ t_atomtype t = argv[i].a_type;
+ if (t==A_FLOAT) o << argv[i].a_float;
+ else if (t==A_SYMBOL) o << argv[i].a_symbol->s_name;
+ else if (t==A_POINTER) o << "(pointer)";
+ else if (t==A_COMMA) o << ",";
+ else if (t==A_SEMI) o << ";";
+ else if (t==A_LIST) {
+ t_binbuf *b = (t_binbuf *)argv[i].a_gpointer;
+ o << "[";
+ pd_oprint(o,binbuf_getnatom(b),binbuf_getvec(b));
+ o << "]";
+ } else o << "(atom of type " << t << ")";
+ if (i!=argc-1) o << " ";
+ }
+}
+
+void pd_post (const char *s, int argc, t_atom *argv) {
+ std::ostringstream os;
+ if (s) os << s << ": ";
+ pd_oprint(os,argc,argv);
+ post("%s",os.str().data());
+}
+
+void pd_oprintf (std::ostream &o, const char *s, int argc, t_atom *argv) {
+ int i=0;
+ for (; *s; s++) {
+ if (*s!='%') {o << (char)*s; continue;}
+ s++; // skip the %
+ switch (*s) {
+ case 'f':
+ if (!argc) RAISE("not enough args");
+ if (argv[i].a_type != A_FLOAT) RAISE("expected float");
+ o << argv[i++].a_float;
+ break;
+ case 's':
+ if (!argc) RAISE("not enough args");
+ if (argv[i].a_type != A_SYMBOL) RAISE("expected symbol");
+ o << argv[i++].a_symbol->s_name;
+ break;
+ case '_':
+ if (!argc) RAISE("not enough args");
+ char buf[MAXPDSTRING];
+ atom_string(&argv[i++],buf,MAXPDSTRING);
+ o << buf;
+ break;
+ case '%':
+ o << "%";
+ break;
+ default:
+ RAISE("sorry, the format character '%c' is not supported yet",*s);
+ }
+ }
+}
+
+//----------------------------------------------------------------
+// Dim
+
+void Dim::check() {
+ if (n>MAX_DIM) RAISE("too many dimensions");
+ for (int i=0; i<n; i++) if (v[i]<0) RAISE("Dim: negative dimension");
+}
+
+// !@#$ big leak machine?
+// returns a string like "Dim[240,320,3]"
+char *Dim::to_s() {
+ // if you blow 256 chars it's your own fault
+ char buf[256];
+ char *s = buf;
+ s += sprintf(s,"Dim[");
+ for(int i=0; i<n; i++) s += sprintf(s,"%s%d", ","+!i, v[i]);
+ s += sprintf(s,"]");
+ return strdup(buf);
+}
+
+NumberTypeE NumberTypeE_find (string s) {
+ if (number_type_dict.find(s)==number_type_dict.end()) RAISE("unknown number type \"%s\"", s.data());
+ return number_type_dict[s]->index;
+}
+
+NumberTypeE NumberTypeE_find (const t_atom &x) {
+ if (x.a_type!=A_SYMBOL) RAISE("expected number-type (as symbol)");
+ return NumberTypeE_find(string(x.a_symbol->s_name));
+}
+
+// don't touch.
+static void gfmemcopy32(int32 *as, int32 *bs, long n) {
+ ptrdiff_t ba = bs-as;
+#define FOO(I) as[I] = (as+ba)[I];
+ UNROLL_8(FOO,n,as)
+#undef FOO
+}
+
+void gfmemcopy(uint8 *out, const uint8 *in, long n) {
+ for (; n>16; in+=16, out+=16, n-=16) {
+ ((int32*)out)[0] = ((int32*)in)[0];
+ ((int32*)out)[1] = ((int32*)in)[1];
+ ((int32*)out)[2] = ((int32*)in)[2];
+ ((int32*)out)[3] = ((int32*)in)[3];
+ }
+ for (; n>4; in+=4, out+=4, n-=4) *(int32*)out = *(int32*)in;
+ for (; n; in++, out++, n--) *out=*in;
+}
+
+//----------------------------------------------------------------
+
+uint64 gf_timeofday () {
+ timeval t;
+ gettimeofday(&t,0);
+ return t.tv_sec*1000000+t.tv_usec;
+}
+
+#define CONVERT0(z) ((in[z] >> chop[z]) << slide[z])
+#define CONVERT1 t = CONVERT0(0) | CONVERT0(1) | CONVERT0(2)
+#define CONVERT2 for (t=0,i=0; i<self->size; i++) t |= CONVERT0(i);
+
+#define WRITE_LE \
+ for (int bytes = self->bytes; bytes; bytes--, t>>=8) *out++ = t;
+
+#define WRITE_BE {int bytes; \
+ bytes = self->bytes; \
+ while (bytes--) {out[bytes] = t; t>>=8;}\
+ out += self->bytes;}
+
+/* this macro would be faster if the _increment_
+ was done only once every loop. or maybe gcc does it, i dunno */
+#define NTIMES(_x_) \
+ for (; n>=4; n-=4) {_x_ _x_ _x_ _x_} \
+ for (; n; n--) {_x_}
+
+/* this could be faster (use asm) */
+void swap64 (long n, uint64 *data) {
+ NTIMES({
+ uint64 x = *data;
+ x = (x<<32) | (x>>32);
+ x = ((x&0x0000ffff0000ffffLL)<<16) | ((x>>16)&0x0000ffff0000ffffLL);
+ x = ((x&0x00ff00ff00ff00ffLL)<< 8) | ((x>> 8)&0x00ff00ff00ff00ffLL);
+ *data++ = x;
+ })
+}
+
+/* this could be faster (use asm) */
+void swap32 (long n, uint32 *data) {
+ NTIMES({
+ uint32 x = *data;
+ x = (x<<16) | (x>>16);
+ x = ((x&0xff00ff)<<8) | ((x>>8)&0xff00ff);
+ *data++ = x;
+ })
+}
+
+/* this could be faster (use asm or do it in int32 chunks) */
+void swap16 (long n, uint16 *data) {NTIMES({ uint16 x = *data; *data++ = (x<<8) | (x>>8); })}
+
+/* **************************************************************** */
+
+//#define DEBUG 1
+#ifdef DEBUG
+#define TRACE static int use=0; use++; if ((use%10000)==0) post("%s",__PRETTY_FUNCTION__);
+#else
+#define TRACE
+#endif
+
+template <class T>
+static void default_pack(BitPacking *self, long n, T *in, uint8 *out) {TRACE
+ uint32 t;
+ int i;
+ int sameorder = self->endian==2 || self->endian==::is_le();
+ int size = self->size;
+ uint32 mask[4]; memcpy(mask,self->mask,size*sizeof(uint32));
+ uint32 hb[4]; for (i=0; i<size; i++) hb[i] = highest_bit(mask[i]);
+ uint32 span[4]; for (i=0; i<size; i++) span[i] = hb[i] - lowest_bit(mask[i]);
+ uint32 chop[4]; for (i=0; i<size; i++) chop[i] = 7-span[i];
+ uint32 slide[4]; for (i=0; i<size; i++) slide[i] = hb[i]-span[i];
+
+ if (sameorder && size==3) {
+ switch(self->bytes) {
+ case 2: NTIMES(CONVERT1; *((int16 *)out)=t; out+=2; in+=3;) return;
+ case 4: NTIMES(CONVERT1; *((int32 *)out)=t; out+=4; in+=3;) return;
+ }
+ }
+ if (self->is_le()) {
+ switch (size) {
+ case 3: for (; n--; in+=3) {CONVERT1; WRITE_LE;} break;
+ case 4: for (; n--; in+=4) {CONVERT1; WRITE_LE;} break;
+ default:for (; n--; in+=size) {CONVERT2; WRITE_LE;}}
+ } else {
+ switch (size) {
+ case 3: for (; n--; in+=3) {CONVERT1; WRITE_BE;} break;
+ case 4: for (; n--; in+=4) {CONVERT1; WRITE_BE;} break;
+ default:for (; n--; in+=size) {CONVERT2; WRITE_BE;}}
+ }
+}
+
+#define LOOP_UNPACK(_reader_) \
+ for (; n; n--) { \
+ int bytes=0; uint32 temp=0; _reader_; \
+ for (int i=0; i<self->size; i++, out++) { \
+ uint32 t=temp&self->mask[i]; \
+ *out = (t<<(7-hb[i]))|(t>>(hb[i]-7));}}
+
+template <class T>
+static void default_unpack(BitPacking *self, long n, uint8 *in, T *out) {TRACE
+ int hb[4];
+ for (int i=0; i<self->size; i++) hb[i] = highest_bit(self->mask[i]);
+ if (is_le()) { // smallest byte first
+ LOOP_UNPACK(
+ for(; self->bytes>bytes; bytes++, in++) temp |= *in<<(8*bytes);
+ )
+ } else { // biggest byte first
+ LOOP_UNPACK(
+ bytes=self->bytes; for (; bytes; bytes--, in++) temp=(temp<<8)|*in;
+ )
+ }
+}
+
+/* **************************************************************** */
+
+template <class T>
+static void pack2_565(BitPacking *self, long n, T *in, uint8 *out) {TRACE
+ uint32 chop[3] = {3,2,3};
+ uint32 slide[3] = {11,5,0};
+ uint32 t;
+ NTIMES(CONVERT1; *((short *)out)=t; out+=2; in+=3;)
+}
+
+template <class T>
+static void pack3_888(BitPacking *self, long n, T *in, uint8 *out) {TRACE
+ int32 *o32 = (int32 *)out;
+ while (n>=4) {
+ o32[0] = (in[5]<<24) | (in[ 0]<<16) | (in[ 1]<<8) | in[2];
+ o32[1] = (in[7]<<24) | (in[ 8]<<16) | (in[ 3]<<8) | in[4];
+ o32[2] = (in[9]<<24) | (in[10]<<16) | (in[11]<<8) | in[6];
+ o32+=3; in+=12;
+ n-=4;
+ }
+ out = (uint8 *)o32;
+ NTIMES( out[2]=in[0]; out[1]=in[1]; out[0]=in[2]; out+=3; in+=3; )
+}
+/*
+template <>
+static void pack3_888(BitPacking *self, long n, uint8 *in, uint8 *out) {TRACE
+ uint32 *o32 = uint32 *((uint32 *)out.p,n*3/4);
+ uint32 *i32 = uint32 *((uint32 *)in.p,n*3/4);
+ while (n>=4) {
+#define Z(w,i) ((word##w>>(i*8))&255)
+ uint32 word0 = i32[0];
+ uint32 word1 = i32[1];
+ uint32 word2 = i32[2];
+ o32[0] = (Z(1,1)<<24) | (Z(0,0)<<16) | (Z(0,1)<<8) | Z(0,2);
+ o32[1] = (Z(1,3)<<24) | (Z(2,0)<<16) | (Z(0,3)<<8) | Z(1,0);
+ o32[2] = (Z(2,1)<<24) | (Z(2,2)<<16) | (Z(2,3)<<8) | Z(1,2);
+ o32+=3; i32+=3;
+ n-=4;
+ }
+#undef Z
+ out = (uint8 *)o32;
+ in = (uint8 *)i32;
+ NTIMES( out[2]=in[0]; out[1]=in[1]; out[0]=in[2]; out+=3; in+=3; )
+}
+*/
+
+template <class T> static void unpack3_888 (BitPacking *self, long n, uint8 *in, T *out) {TRACE
+ NTIMES( out[2]=in[0]; out[1]=in[1]; out[0]=in[2]; out+=3; in+=3; )
+}
+template <class T> static void pack3_888c(BitPacking *self, long n, T *in, uint8 *out) {TRACE
+ NTIMES( out[2]=in[0]; out[1]=in[1]; out[0]=in[2]; out[3]=0; out+=4; in+=3; )
+}
+template <class T> static void pack3_888d(BitPacking *self, long n, T *in, uint8 *out) {TRACE
+ NTIMES( out[0]=in[0]; out[1]=in[1]; out[2]=in[2]; out[3]=0; out+=4; in+=3; )
+}
+template <class T> static void unpack3_888d(BitPacking *self, long n, uint8 *in, T *out) {TRACE
+ NTIMES( out[0]=in[0]; out[1]=in[1]; out[2]=in[2]; out+=3; in+=4; )
+}
+template <class T> static void pack3_bgrn8888b(BitPacking *self, long n, T *in, uint8 *out) {TRACE
+ NTIMES( out[2]=in[0]; out[1]=in[1]; out[0]=in[2]; out[3]=0; out+=4; in+=4; )
+}
+
+template <class T>
+static void pack3_888b(BitPacking *self, long n, T *in, uint8 *out) {TRACE
+ int32 *o32 = (int32 *)out;
+ while (n>=4) {
+ o32[0] = (in[0]<<16) | (in [1]<<8) | in [2];
+ o32[1] = (in[3]<<16) | (in [4]<<8) | in [5];
+ o32[2] = (in[6]<<16) | (in [7]<<8) | in [8];
+ o32[3] = (in[9]<<16) | (in[10]<<8) | in[11];
+ o32+=4; in+=12;
+ n-=4;
+ }
+ NTIMES( o32[0] = (in[0]<<16) | (in[1]<<8) | in[2]; o32++; in+=3; )
+}
+
+// (R,G,B,?) -> B:8,G:8,R:8,0:8
+static void pack3_bgrn8888(BitPacking *self, long n, uint8 *in, uint8 *out) {TRACE
+/* NTIMES( out[2]=in[0]; out[1]=in[1]; out[0]=in[2]; out+=4; in+=4; ) */
+ int32 *i32 = (int32 *)in;
+ int32 *o32 = (int32 *)out;
+ while (n>=4) {
+ o32[0] = ((i32[0]&0xff)<<16) | (i32[0]&0xff00) | ((i32[0]>>16)&0xff);
+ o32[1] = ((i32[1]&0xff)<<16) | (i32[1]&0xff00) | ((i32[1]>>16)&0xff);
+ o32[2] = ((i32[2]&0xff)<<16) | (i32[2]&0xff00) | ((i32[2]>>16)&0xff);
+ o32[3] = ((i32[3]&0xff)<<16) | (i32[3]&0xff00) | ((i32[3]>>16)&0xff);
+ o32+=4; i32+=4; n-=4;
+ }
+ NTIMES( o32[0] = ((i32[0]&0xff)<<16) | (i32[0]&0xff00) | ((i32[0]>>16)&0xff); o32++; i32++; )
+}
+
+static uint32 bp_masks[][4] = {
+ {0x0000f800,0x000007e0,0x0000001f,0},
+ {0x00ff0000,0x0000ff00,0x000000ff,0},
+ {0x000000ff,0x0000ff00,0x00ff0000,0},
+};
+
+#define ANYCASE(a) {a,a,a}
+static Packer bp_packers[] = {
+ ANYCASE(default_pack),
+ ANYCASE(pack2_565),
+ ANYCASE(pack3_888),
+ {pack3_888b, default_pack, default_pack}, /* {pack3_888c, pack3_888c, pack3_888c}, not tested */
+ {pack3_bgrn8888, pack3_bgrn8888b, pack3_bgrn8888b},
+ ANYCASE(pack3_888d),
+};
+
+static Unpacker bp_unpackers[] = {
+ ANYCASE(default_unpack),
+ ANYCASE(unpack3_888),
+ {pack3_bgrn8888, default_unpack, default_unpack},
+ ANYCASE(unpack3_888d),
+};
+
+static BitPacking builtin_bitpackers[] = {
+ BitPacking(2, 2, 3, bp_masks[0], &bp_packers[1], &bp_unpackers[0]),
+ BitPacking(1, 3, 3, bp_masks[1], &bp_packers[2], &bp_unpackers[1]),
+ BitPacking(1, 4, 3, bp_masks[1], &bp_packers[3], &bp_unpackers[0]),
+ BitPacking(1, 4, 4, bp_masks[1], &bp_packers[4], &bp_unpackers[2]),
+ BitPacking(1, 4, 3, bp_masks[2], &bp_packers[5], &bp_unpackers[3]),
+};
+
+/* **************************************************************** */
+
+bool BitPacking::eq(BitPacking *o) {
+ if (!(bytes == o->bytes)) return false;
+ if (!(size == o->size)) return false;
+ for (int i=0; i<size; i++) {
+ if (!(mask[i] == o->mask[i])) return false;
+ }
+ if (endian==o->endian) return true;
+ /* same==little on a little-endian; same==big on a big-endian */
+ return (endian ^ o->endian ^ ::is_le()) == 2;
+}
+
+void post_BitPacking(BitPacking *b) {
+ ::post("Bitpacking: endian=%d bytes=%d size=%d packer=%d unpacker=%d",
+ b->endian,b->bytes,b->size,b->packer-bp_packers,b->unpacker-bp_unpackers);
+ ::post(" mask=[0x%08x,0x%08x,0x%08x,0x%08x]",b->mask[0],b->mask[1],b->mask[2],b->mask[3]);
+}
+
+BitPacking::BitPacking(int endian, int bytes, int size, uint32 *mask, Packer *packer, Unpacker *unpacker) {
+ this->endian = endian;
+ this->bytes = bytes;
+ this->size = size;
+ for (int i=0; i<size; i++) this->mask[i] = mask[i];
+ if (packer) {
+ this->packer = packer;
+ this->unpacker = unpacker;
+ return;
+ }
+ int packeri=-1;
+ this->packer = &bp_packers[0];
+ this->unpacker = &bp_unpackers[0];
+ for (int i=0; i<(int)(sizeof(builtin_bitpackers)/sizeof(BitPacking)); i++) {
+ BitPacking *bp = &builtin_bitpackers[i];
+ if (this->eq(bp)) {
+ this-> packer = bp-> packer;
+ this->unpacker = bp->unpacker;
+ packeri=i;
+ goto end;
+ }
+ }
+end:;
+}
+
+bool BitPacking::is_le() {return endian==1 || (endian ^ ::is_le())==3;}
+
+#undef TRACE
+#ifdef DEBUG
+#define TRACE static int use=0; use++; if ((use%10000)==0) post_BitPacking(this);
+#else
+#define TRACE
+#endif
+template <class T> void BitPacking:: pack(long n, T *in, uint8 *out) {TRACE
+ switch (NumberTypeE_type_of(in)) {
+ case uint8_e: packer->as_uint8(this,n,(uint8 *)in,out); break;
+ case int16_e: packer->as_int16(this,n,(int16 *)in,out); break;
+ case int32_e: packer->as_int32(this,n,(int32 *)in,out); break;
+ default: RAISE("argh");}}
+template <class T> void BitPacking::unpack(long n, uint8 *in, T *out) {TRACE
+ switch (NumberTypeE_type_of(out)) {
+ case uint8_e: unpacker->as_uint8(this,n,in,(uint8 *)out); break;
+ case int16_e: unpacker->as_int16(this,n,in,(int16 *)out); break;
+ case int32_e: unpacker->as_int32(this,n,in,(int32 *)out); break;
+ default: RAISE("argh");}}
+
+// i'm sorry... see the end of grid.c for an explanation...
+//static
+void make_hocus_pocus () {
+// exit(1);
+#define FOO(S) \
+ ((BitPacking*)0)-> pack(0,(S *)0,(uint8 *)0); \
+ ((BitPacking*)0)->unpack(0,(uint8 *)0,(S *)0);
+EACH_NUMBER_TYPE(FOO)
+#undef FOO
+}
+
+std::vector<string> gf_data_path;
+string gf_find_file (string x) {
+ if (strchr(x.data(),'/')) return x;
+ int n = gf_data_path.size();
+ struct stat dummy;
+ for (int i=0; i<n; i++) {
+ string s = gf_data_path[i]+"/"+x;
+ if (lstat(s.data(),&dummy)==0) return s;
+ }
+ return x;
+}
+
+/* **************************************************************** */
+
+#undef pd_class
+#define pd_class(x) (*(t_pd *)x)
+#define pd_classname(x) (fclasses_pd[pd_class(x)]->name.data())
+
+static FMethod funcall_lookup (FClass *fclass, const char *sel) {
+ int n = fclass->methodsn;
+ for (int i=0; i<n; i++) if (strcmp(fclass->methods[i].selector,sel)==0) return fclass->methods[i].method;
+ if (fclass->super) return funcall_lookup(fclass->super,sel);
+ return 0;
+}
+static FMethod funcall_lookup (BFObject *bself, const char *sel) {
+ return funcall_lookup(fclasses_pd[pd_class(bself)],sel);
+}
+
+void call_super(int argc, t_atom *argv) {/* unimplemented */}
+
+//****************************************************************
+// BFObject
+
+struct BFProxy : t_object {
+ BFObject *parent;
+ t_inlet *inlet;
+ int id;
+};
+
+static t_class *BFProxy_class;
+
+static void BFObject_loadbang (BFObject *bself) {
+ FMethod m = funcall_lookup(bself,"_0_loadbang");
+ m(bself->self,0,0);
+}
+
+static void BFObject_anything (BFObject *bself, int winlet, t_symbol *selector, int ac, t_atom2 *at) {
+ try {
+ t_atom2 argv[ac+1];
+ for (int i=0; i<ac; i++) argv[i+1] = at[i];
+ int argc = handle_braces(ac,argv+1);
+ SETFLOAT(argv+0,winlet);
+ char buf[256];
+ sprintf(buf,"_n_%s",selector->s_name);
+ FMethod m;
+ m = funcall_lookup(bself,buf);
+ if (m) {m(bself->self,argc+1,argv); return;}
+ sprintf(buf,"_%d_%s",winlet,selector->s_name);
+ m = funcall_lookup(bself,buf);
+ if (m) {m(bself->self,argc,argv+1); return;}
+ m = funcall_lookup(bself,"anything");
+ if (m) {SETSYMBOL(argv+0,gensym(buf)); m(bself->self,argc+1,argv); return;}
+ pd_error((t_pd *)bself, "method '%s' not found for inlet %d in class '%s'",selector->s_name,winlet,pd_classname(bself));
+ } catch (Barf &oozy) {oozy.error(bself);}
+}
+static void BFObject_anything0 (BFObject *self, t_symbol *s, int argc, t_atom2 *argv) {
+ BFObject_anything(self,0,s,argc,argv);
+}
+static void BFProxy_anything (BFProxy *self, t_symbol *s, int argc, t_atom2 *argv) {
+ BFObject_anything(self->parent,self->id,s,argc,argv);
+}
+
+static void *BFObject_new (t_symbol *classsym, int ac, t_atom *at) {
+ string name = string(classsym->s_name);
+ if (fclasses.find(name)==fclasses.end()) {post("GF: class not found: '%s'",classsym->s_name); return 0;}
+ t_class *qlass = fclasses[name]->bfclass;
+ BFObject *bself = (BFObject *)pd_new(qlass);
+ try {
+ int argc = ac;
+ t_atom argv[argc];
+ for (int i=0; i<argc; i++) argv[i] = at[i];
+ argc = handle_braces(argc,argv);
+ //pd_post(classsym->s_name,argc,argv);
+ int j;
+ for (j=0; j<argc; j++) if (argv[j].a_type==A_COMMA) break;
+
+ bself->self = 0;
+ bself->mom = (t_canvas *)canvas_getcurrent();
+ bself->ninlets = 1;
+ bself->noutlets = 0;
+ bself->inlets = new BFProxy*[1];
+ bself->outlets = new t_outlet*[1];
+ bself->inlets[0] = 0; // inlet 0 of this table is not in use
+ bself->ninlets_set( fclasses[classsym->s_name]->ninlets ,false);
+ bself->noutlets_set(fclasses[classsym->s_name]->noutlets,false);
+ t_allocator alloc = fclasses[string(classsym->s_name)]->allocator;
+ bself->self = alloc(bself,0,j,(t_atom2 *)argv);
+ while (j<argc) {
+ j++;
+ int k=j;
+ for (; j<argc; j++) if (argv[j].a_type==A_COMMA) break;
+ if (argv[k].a_type==A_SYMBOL) pd_typedmess((t_pd *)bself,argv[k].a_symbol,j-k-1,argv+k+1);
+ }
+ return bself;
+ } catch (Barf &oozy) {oozy.error(bself); return 0;}
+}
+
+static void BFObject_delete (BFObject *bself) {
+ try {delete bself->self;} catch (Barf &oozy) {oozy.error(bself);}
+ bself->ninlets_set(1,false);
+ delete[] bself->inlets;
+ delete[] bself->outlets;
+}
+
+//****************************************************************
+
+static void BFObject_undrawio (BFObject *bself) {
+#ifndef HAVE_DESIREDATA
+ if (!bself->mom || !glist_isvisible(bself->mom)) return;
+ t_rtext *rt = glist_findrtext(bself->mom,bself);
+ if (!rt) return;
+ glist_eraseiofor(bself->mom,bself,rtext_gettag(rt));
+#endif
+}
+
+static void BFObject_redraw (BFObject *bself) {
+#ifndef HAVE_DESIREDATA
+ if (!bself->mom || !glist_isvisible(bself->mom)) return;
+ t_rtext *rt = glist_findrtext(bself->mom,bself);
+ if (!rt) return;
+ gobj_vis((t_gobj *)bself,bself->mom,0);
+ gobj_vis((t_gobj *)bself,bself->mom,1);
+ canvas_fixlinesfor(bself->mom,(t_text *)bself);
+#endif
+}
+
+/* warning: deleting inlets that are connected will cause pd to crash */
+void BFObject::ninlets_set (int n, bool draw) {
+ if (!te_binbuf) draw=false;
+ if (n<1) RAISE("ninlets_set: n=%d must be at least 1",n);
+ if (draw) BFObject_undrawio(this);
+ if (ninlets<n) {
+ BFProxy **noo = new BFProxy*[n];
+ memcpy(noo,inlets,ninlets*sizeof(BFProxy*));
+ delete[] inlets;
+ inlets = noo;
+ while (ninlets<n) {
+ BFProxy *p = inlets[ninlets] = (BFProxy *)pd_new(BFProxy_class);
+ p->parent = this;
+ p->id = ninlets;
+ p->inlet = inlet_new(this, &p->ob_pd, 0,0);
+ ninlets++;
+ }
+ } else {
+ while (ninlets>n) {
+ ninlets--;
+ inlet_free(inlets[ninlets]->inlet);
+ pd_free((t_pd *)inlets[ninlets]);
+ }
+ }
+ if (draw) BFObject_redraw(this);
+}
+/* warning: deleting outlets that are connected will cause pd to crash */
+void BFObject::noutlets_set (int n, bool draw) {
+ if (!te_binbuf) draw=false;
+ if (n<0) RAISE("noutlets_set: n=%d must be at least 0",n);
+ if (draw) BFObject_undrawio(this);
+ if (noutlets<n) {
+ t_outlet **noo = new t_outlet*[n>0?n:1];
+ memcpy(noo,outlets,noutlets*sizeof(t_outlet*));
+ delete[] outlets;
+ outlets = noo;
+ while (noutlets<n) outlets[noutlets++] = outlet_new(this,&s_anything);
+ } else {
+ while (noutlets>n) outlet_free(outlets[--noutlets]);
+ }
+ if (draw) BFObject_redraw(this);
+}
+
+string BFObject::binbuf_string () {
+ if (!te_binbuf) return "[???]";
+ std::ostringstream s;
+ int n = binbuf_getnatom(te_binbuf);
+ t_atom *at = binbuf_getvec(te_binbuf);
+ for (int i=0; i<n; i++) s << (i ? " " : "[") << at[i];
+ s << "]";
+ return s.str();
+}
+
+void add_creator2(FClass *fclass, const char *name) {
+ fclasses[string(name)] = fclass;
+ class_addcreator((t_newmethod)BFObject_new,gensym((char *)name),A_GIMME,0);
+}
+typedef struct _methodentry
+{
+ t_symbol *me_name;
+ t_gotfn me_fun;
+ t_atomtype me_arg[MAXPDARG+1];
+} t_methodentry;
+struct _class {
+ t_symbol *c_name; /* name (mostly for error reporting) */
+ t_symbol *c_helpname; /* name of help file */
+ t_symbol *c_externdir; /* directory extern was loaded from */
+ size_t c_size; /* size of an instance */
+ t_methodentry *c_methods; /* methods other than bang, etc below */
+ int c_nmethod; /* number of methods */
+ // ...
+};
+void add_creator3(FClass *fclass, const char *name) {
+ fclasses[string(name)] = fclass;
+ t_class *c = pd_objectmaker;
+ t_symbol *want = gensym(name);
+ for (int i=c->c_nmethod-1; i>=0; i--) {
+ t_methodentry *m = c->c_methods+i;
+ if (m->me_name==want) {m->me_fun = t_gotfn(BFObject_new); m->me_arg[0]=A_GIMME; m->me_arg[1]=A_NULL; break;}
+ }
+}
+
+//****************************************************************
+
+struct t_namelist;
+extern t_namelist *sys_searchpath, *sys_helppath;
+extern "C" t_namelist *namelist_append_files(t_namelist *, char *);
+static void add_to_path(char *dir) {
+ static bool debug = false;
+ char bof[1024];
+ if (debug) post("gridflow was found in %s",dir);
+ gf_data_path.push_back(string(dir)+"/images");
+ if (debug) post("adding gf_data_path %s/images",dir);
+ sprintf(bof,"%s/abstractions",dir); sys_searchpath = namelist_append_files(sys_searchpath,bof);
+ if (debug) post("adding -path %s",bof);
+ sprintf(bof,"%s/deprecated",dir); sys_searchpath = namelist_append_files(sys_searchpath,bof);
+ if (debug) post("adding -path %s",bof);
+ sprintf(bof,"%s/doc/flow_classes",dir); sys_helppath = namelist_append_files(sys_helppath, bof);
+ if (debug) post("adding -helppath %s",bof);
+}
+
+//----------------------------------------------------------------
+
+t_list *list_new (int argc, t_atom *argv) {
+ t_list *b = binbuf_new();
+ binbuf_add(b,argc,argv);
+ return b;
+}
+void list_free (t_list *self) {binbuf_free(self);}
+
+//----------------------------------------------------------------
+
+void fclass_install(FClass *fclass, FClass *super, size_t bytes) {
+ fclass->super = super;
+ if (fclass->startup) fclass->startup(fclass);
+ fclass->bytes = bytes;
+}
+
+void install2(FClass *fclass, const char *name, int inlets, int outlets) {
+ fclass->ninlets = inlets;
+ fclass->noutlets = outlets;
+ fclass->name = string(name);
+ fclass->bfclass = class_new(gensym((char *)name), (t_newmethod)BFObject_new, (t_method)BFObject_delete,
+ sizeof(BFObject), CLASS_DEFAULT, A_GIMME,0);
+ fclasses[string(name)] = fclass;
+ fclasses_pd[fclass->bfclass] = fclass;
+ t_class *b = fclass->bfclass;
+ class_addanything(b,t_method(BFObject_anything0));
+ FMethod m = funcall_lookup(fclass,"_0_loadbang");
+ //post("class %s loadbang %08x",name,long(m));
+ if (m) class_addmethod(fclass->bfclass,t_method(BFObject_loadbang),gensym("loadbang"),A_NULL);
+}
+
+/* This code handles nested lists because PureData (all versions including 0.40) doesn't do it */
+int handle_braces(int ac, t_atom *av) {
+ int stack[16];
+ int stackn=0;
+ int j=0;
+ t_binbuf *buf = binbuf_new();
+ for (int i=0; i<ac; ) {
+ int close=0;
+ if (av[i].a_type==A_SYMBOL) {
+ const char *s = av[i].a_symbol->s_name;
+ while (*s=='(') {
+ if (stackn==16) {binbuf_free(buf); RAISE("too many nested lists (>16)");}
+ stack[stackn++]=j;
+ s++;
+ }
+ const char *se = s+strlen(s);
+ while (se>s && se[-1]==')') {se--; close++;}
+ if (s!=se) {
+ binbuf_text(buf,(char *)s,se-s);
+ if ((binbuf_getnatom(buf)==1 && binbuf_getvec(buf)[0].a_type==A_FLOAT) || binbuf_getvec(buf)[0].a_type==A_COMMA) {
+ av[j++] = binbuf_getvec(buf)[0];
+ } else {
+ char ss[MAXPDSTRING];
+ int n = min(long(se-s),long(MAXPDSTRING-1));
+ sprintf(ss,"%.*s",n,s);
+ SETSYMBOL(av+j,gensym(ss)); j++; // av[j++] = gensym(s);
+ }
+ }
+ } else av[j++]=av[i];
+ i++;
+ while (close--) {
+ if (!stackn) {binbuf_free(buf); RAISE("close-paren without open-paren",av[i]);}
+ t_binbuf *a2 = binbuf_new(); /* leak because there is no deallocation mechanism whatsoever */
+ int j2 = stack[--stackn];
+ binbuf_add(a2,j-j2,av+j2);
+ j=j2;
+ SETLIST(av+j,a2);
+ j++;
+ }
+ }
+ binbuf_free(buf);
+ if (stackn) RAISE("too many open-paren (%d)",stackn);
+ return j;
+}
+
+// foreach macro from desiredata:
+#define foreach(ITER,COLL) for(typeof(COLL.begin()) ITER = COLL.begin(); ITER != (COLL).end(); ITER++)
+
+\class FObject
+\def 0 get (t_symbol *s=0) {
+ FClass *fc = fclasses_pd[pd_class(bself)];
+ if (!s) {
+ t_atom a[1];
+ foreach(attr,fc->attrs) {
+ SETSYMBOL(a,gensym((char *)attr->second->name.data()));
+ pd_typedmess((t_pd *)bself,gensym("get"),1,a);
+ }
+ } else {
+ //t_atom a[1];
+ //outlet_anything(bself->outlets[bself->noutlets-1],s,1,a);
+ FMethod m = funcall_lookup(bself,"___get");
+ t_atom2 a[1];
+ SETSYMBOL(a,s);
+ if (m) m(this,1,a);
+ }
+}
+\def 0 help () {
+ FClass *fc = fclasses_pd[pd_class(bself)];
+ post("attributes (");
+ foreach(attr,fc->attrs) post(" %s %s;",attr->second->type.data(),attr->second->name.data());
+ post(")");
+ post("methods (");
+ for (int i=0; i<fc->methodsn; i++) post(" %s",fc->methods[i].selector);
+ post(")");
+}
+\classinfo {}
+\end class
+
+void startup_number();
+void startup_flow_objects();
+void startup_flow_objects2();
+void startup_format();
+STARTUP_LIST(void)
+
+void blargh () {
+#ifdef MACOSX
+ fprintf(stderr,"unhandled exception\n");
+#else
+ void *array[25];
+ int nSize = backtrace(array, 25);
+ char **symbols = backtrace_symbols(array, nSize);
+ for (int i=0; i<nSize; i++) fprintf(stderr,"%d: %s\n",i,symbols[i]);
+ free(symbols);
+#endif
+}
+
+static t_gobj *canvas_last (t_canvas *self) {
+#ifdef DESIRE
+ t_gobj *g = canvas_first(self);
+ while (gobj_next(g)) g=gobj_next(g);
+#else
+ t_gobj *g = self->gl_list;
+ while (g->g_next) g=g->g_next;
+#endif
+ return g;
+}
+
+#ifdef DESIRE
+extern "C" void canvas_delete(t_canvas *, t_gobj *);
+#define glist_delete canvas_delete
+#endif
+
+static void canvas_else (t_canvas *self, t_symbol *s, int argc, t_atom *argv) {
+ t_gobj *g = canvas_last(self);
+ if (pd_newest()) return;
+ glist_delete(self,g);
+ if (argc<1 || argv[0].a_type!=A_SYMBOL) {error("$1 must be a symbol"); return;}
+ pd_typedmess((t_pd *)self,argv[0].a_w.w_symbol,argc-1,argv+1);
+}
+
+// those are not really leaks but deleting them make them disappear from valgrind
+// however, there's still a problem doing it, so, we won't do it.
+static void gridflow_unsetup () {
+/*
+ foreach(iter,fclasses_pd) {
+ FClass *fc = iter->second;
+ foreach(iter2,fc->attrs) delete iter2->second;
+ fc->FClass::~FClass();
+ }
+*/
+}
+
+void allow_big_stack () {
+ struct rlimit happy;
+ if (0>getrlimit(RLIMIT_STACK,&happy))
+ error("GF: getrlimit: %s",strerror(errno));
+ happy.rlim_cur = happy.rlim_max;
+ if (0>setrlimit(RLIMIT_STACK,&happy))
+ error("GF: setting stack size to %ld: %s",happy.rlim_cur,strerror(errno));
+ else
+ post( "GF: setting stack size to %ld",happy.rlim_cur);
+}
+
+// note: contrary to what m_pd.h says, pd_getfilename() and pd_getdirname()
+// don't exist; also, canvas_getcurrentdir() isn't available during setup
+// (segfaults), in addition to libraries not being canvases ;-)
+// AND ALSO, CONTRARY TO WHAT m_pd.h SAYS, open_via_path()'s args are reversed!!!
+extern "C" void gridflow_setup () {
+ post("GridFlow " GF_VERSION ", Copyright (c) 2001-2009 Mathieu Bouchard");
+ post("GridFlow was compiled on "__DATE__", "__TIME__);
+ //std::set_terminate(__gnu_cxx::__verbose_terminate_handler);
+ std::set_terminate(blargh);
+ allow_big_stack();
+ try {
+ char *dirname = new char[MAXPDSTRING];
+ char *dirresult = new char[MAXPDSTRING];
+ char *nameresult;
+ char *zz=getcwd(dirname,MAXPDSTRING); /* zz only exists because gcc 4.3.3 gives me a bogus warning otherwise. */
+ if (zz<0) {post("AAAARRRRGGGGHHHH!"); exit(69);}
+ int fd=open_via_path(dirname,"gridflow/gridflow",PDSUF,dirresult,&nameresult,MAXPDSTRING,1);
+ if (fd<0) fd=open_via_path(dirname, "gridflow",PDSUF,dirresult,&nameresult,MAXPDSTRING,1);
+ if (fd>=0) close(fd); else post("%s was not found via the -path!","gridflow"PDSUF);
+ /* nameresult is only a pointer in dirresult space so don't delete[] it. */
+ add_to_path(dirresult);
+ BFProxy_class = class_new(gensym("gf.proxy"),0,0,sizeof(BFProxy),CLASS_PD|CLASS_NOINLET, A_NULL);
+ class_addanything(BFProxy_class,BFProxy_anything);
+ srandom(rdtsc());
+#define FOO(_sym_,_name_) bsym._sym_ = gensym(_name_);
+BUILTIN_SYMBOLS(FOO)
+#undef FOO
+ startup_number();
+ \startall
+ startup_flow_objects();
+ startup_flow_objects2();
+ startup_format();
+ STARTUP_LIST()
+ //sys_gui("bind . <Motion> {puts %W}\n");
+ sys_vgui("proc gridflow_add_to_help {menu} {\n"
+ "$menu add separator\n"
+ "$menu add command -label {GridFlow About} -command {pd pd open about.pd %s/doc \\;}\n"
+ "$menu add command -label {GridFlow Index} -command {pd pd open index.pd %s/doc \\;}\n"
+ "}\n"
+ "gridflow_add_to_help .mbar.help\n"
+ "rename menu_addstd menu_addstd_old\n"
+ "proc menu_addstd {mbar} {menu_addstd_old $mbar; gridflow_add_to_help $mbar.help}\n",dirresult,dirresult);
+ delete[] dirresult;
+ delete[] dirname;
+ } catch (Barf &oozy) {oozy.error(0);}
+ signal(SIGSEGV,SIG_DFL);
+ signal(SIGABRT,SIG_DFL);
+ signal(SIGBUS, SIG_DFL);
+ atexit(gridflow_unsetup);
+ extern t_class *canvas_class;
+ class_addmethod(canvas_class,(t_method)canvas_else,gensym("else"),A_GIMME,0);
+}
diff --git a/externals/gridflow/src/gridflow.hxx b/externals/gridflow/src/gridflow.hxx
new file mode 100644
index 00000000..bf278ffe
--- /dev/null
+++ b/externals/gridflow/src/gridflow.hxx
@@ -0,0 +1,911 @@
+/*
+ $Id: gridflow.h 4535 2009-10-31 14:50:38Z matju $
+
+ GridFlow
+ Copyright (c) 2001-2009 by Mathieu Bouchard
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ See file ../COPYING for further informations on licensing terms.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __GRIDFLOW_H
+#define __GRIDFLOW_H
+
+#define GF_VERSION "0.9.6"
+
+#include "m_pd.h"
+#include "config.h"
+#include <vector>
+#include <string>
+#include <sstream>
+#include <map>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <math.h>
+#ifdef __APPLE__
+static inline void *memalign (size_t a, size_t n) {return malloc(n);}
+#else
+#include <malloc.h>
+#endif
+
+typedef std::string string;
+
+#ifndef a_float
+#define a_float a_w.w_float
+#define a_symbol a_w.w_symbol
+#define a_gpointer a_w.w_gpointer
+#endif
+
+#define gensym(s) gensym(const_cast<char *>(s))
+#define sys_vgui(FMT,ARGS...) sys_vgui(const_cast<char *>(FMT),ARGS)
+#define sys_gui(s) sys_gui(const_cast<char *>(s))
+
+#ifndef DESIREDATA
+#define A_LIST t_atomtype(13) /* (t_binbuf *) */
+#endif
+#define A_GRID t_atomtype(14) /* (Grid *) */
+#define A_GRIDOUT t_atomtype(15) /* (GridOut *) */
+// the use of w_gpointer here is fake, just because there's no suitable member in the union
+struct Grid;
+struct GridOutlet;
+static inline void SETLIST( t_atom *a, t_binbuf *b) {a->a_type = A_LIST; a->a_gpointer = (t_gpointer *)b;}
+static inline void SETGRID( t_atom *a, Grid *g) {a->a_type = A_GRID; a->a_gpointer = (t_gpointer *)g;}
+static inline void SETGRIDOUT(t_atom *a, GridOutlet *g) {a->a_type = A_GRIDOUT; a->a_gpointer = (t_gpointer *)g;}
+static inline void SETNULL( t_atom *a) {a->a_type = A_NULL; a->a_gpointer = 0;}
+
+typedef t_binbuf t_list;
+
+t_list *list_new (int argc, t_atom *argv);
+void list_free (t_list *self);
+
+typedef char int8; typedef unsigned char uint8;
+typedef short int16; typedef unsigned short uint16;
+typedef int int32; typedef unsigned int uint32;
+typedef long long int64; typedef unsigned long long uint64;
+typedef float float32;
+typedef double float64;
+
+// three-way comparison (T is assumed Comparable)
+template <class T> static inline T cmp(T a, T b) {return a<b ? -1 : a>b;}
+
+// a remainder function such that div2(a,b)*b+mod(a,b) = a and for which mod(a,b) is in [0;b) or (b;0].
+// in contrast to C-language builtin a%b, this one has uniform behaviour around zero,
+// that is, the same as around any other whole number.
+static inline int mod(int a, int b) {int c=a%b; c+=b&-(c&&(a<0)^(b<0)); return c;}
+
+// counterpart of mod(a,b), just like a/b and a%b are counterparts
+static inline int div2(int a, int b) {return (a/b)-((a<0)&&!!(a%b));}
+
+static inline int32 gf_abs( int32 a) {return a>0?a:-a;}
+static inline int64 gf_abs( int64 a) {return a>0?a:-a;}
+static inline float32 gf_abs(float32 a) {return fabs(a);}
+static inline float64 gf_abs(float64 a) {return fabs(a);}
+
+// integer powers in log(b) time. T is assumed Integer
+template <class T> static inline T ipow(T a, T b) {T r=1; for(;;) {if (b&1) r*=a; b>>=1; if (!b) return r; a*=a;}}
+static inline float32 ipow(float32 a, float32 b) {return pow(a,b);}
+static inline float64 ipow(float64 a, float64 b) {return pow(a,b);}
+
+#undef min
+#undef max
+// minimum/maximum functions; T is assumed to be Comparable
+template <class T> static inline T min(T a, T b) {return a<b?a:b;}
+template <class T> static inline T max(T a, T b) {return a>b?a:b;}
+template <class T> static inline T clip(T a, T lower, T upper) {return a<lower?lower:a>upper?upper:a;}
+//template <class T> inline T min(T a, T b) { T c = (a-b)>>31; return (a&c)|(b&~c); }
+
+// greatest common divisor, by euclid's algorithm
+// this runs in log(a+b) number operations
+template <class T> static T gcd (T a, T b) {
+ while (b) {T c=mod(a,b); a=b; b=c;}
+ return a;
+}
+
+// greatest common divisor, the binary algorithm. haven't tried yet.
+template <class T> static T gcd2 (T a, T b) {
+ int s=0;
+ while (((a|b)&1)==0) { a>>=1; b>>=1; s++; }
+ while (a) {
+ if ((a&1)==0) a>>=1;
+ else if ((b&1)==0) b>>=1;
+ else {T t=abs(a-b); if (a<b) b=t; else a=t;}
+ }
+ return b<<s;
+}
+
+// least common multiple; this runs in log(a+b) like gcd.
+template <class T> static inline T lcm (T a, T b) {return a*b/gcd(a,b);}
+
+// returns the position (0..63) of highest bit set in a word, or 0 if none.
+#define Z(N) if ((x>>N)&(((typeof(x))1<<N)-1)) { x>>=N; i+=N; }
+static int highest_bit(uint8 x) {int i=0; Z(4)Z(2)Z(1)return i;}
+static int highest_bit(uint16 x) {int i=0; Z(8)Z(4)Z(2)Z(1)return i;}
+static int highest_bit(uint32 x) {int i=0; Z(16)Z(8)Z(4)Z(2)Z(1)return i;}
+static int highest_bit(uint64 x) {int i=0;Z(32)Z(16)Z(8)Z(4)Z(2)Z(1)return i;}
+#undef Z
+// returns the position (0..63) of lowest bit set in a word, or 0 if none.
+template <class T> static int lowest_bit(T n) { return highest_bit((~n+1)&n); }
+
+static double drand() { return 1.0*rand()/(RAND_MAX+1.0); }
+
+// is little-endian
+static inline bool is_le() {int x=1; return ((char *)&x)[0];}
+
+static inline uint64 rdtsc()
+#if defined(HAVE_PENTIUM)
+{uint64 x; __asm__ volatile (".byte 0x0f, 0x31":"=A"(x)); return x;}
+#else
+{return 0;}
+#endif
+
+#ifdef HAVE_LITE
+#define EACH_INT_TYPE(MACRO) MACRO(uint8) MACRO(int16) MACRO(int32)
+#define EACH_FLOAT_TYPE(MACRO) MACRO(float32)
+#else
+#define EACH_INT_TYPE(MACRO) MACRO(uint8) MACRO(int16) MACRO(int32) MACRO(int64)
+#define EACH_FLOAT_TYPE(MACRO) MACRO(float32) MACRO(float64)
+#endif
+#define EACH_NUMBER_TYPE(MACRO) EACH_INT_TYPE(MACRO) EACH_FLOAT_TYPE(MACRO)
+
+// note: loop unrolling macros assume N!=0
+// btw this may cause alignment problems when 8 does not divide N
+#define UNROLL_8(MACRO,N,PTR,ARGS...) \
+ int n__=(-N)&7; PTR-=n__; N+=n__; \
+ switch (n__) { start: \
+ case 0:MACRO(0); case 1:MACRO(1); case 2:MACRO(2); case 3:MACRO(3); \
+ case 4:MACRO(4); case 5:MACRO(5); case 6:MACRO(6); case 7:MACRO(7); \
+ PTR+=8; N-=8; ARGS; if (N) goto start; }
+#define UNROLL_4(MACRO,N,PTR,ARGS...) \
+ int n__=(-N)&3; PTR-=n__; N+=n__; \
+ switch (n__) { start: \
+ case 0:MACRO(0); case 1:MACRO(1); case 2:MACRO(2); case 3:MACRO(3); \
+ PTR+=4; N-=4; ARGS; if (N) goto start; }
+
+struct BFObject;
+struct Barf {
+ string text;
+ Barf(const char *s, ...);
+ Barf(const char *file, int line, const char *func, const char *s, ...);
+ void error(BFObject *bself);
+ ~Barf() {}
+};
+
+#define NEWBUF(T,N) (new T[N])
+#define DELBUF(A) (delete[] A)
+
+#ifdef __WIN32__
+#define INT winINT
+#define random rand
+#undef send
+#undef close
+#define sigjmp_buf jmp_buf
+#define siglongjmp longjmp
+#endif
+
+//#define _L_ post("%s:%d in %s",__FILE__,__LINE__,__PRETTY_FUNCTION__);
+#define _L_ fprintf(stderr,"%s:%d in %s\n",__FILE__,__LINE__,__PRETTY_FUNCTION__);
+#define RAISE(args...) throw Barf(__FILE__,__LINE__,__PRETTY_FUNCTION__,args)
+#define VA int argc, t_atom2 *argv
+// returns the size of a statically defined array
+#define COUNT(_array_) ((int)(sizeof(_array_) / sizeof((_array_)[0])))
+#define WATCH(n,ar) { \
+ char foo[16*1024], *p=foo; p += sprintf(p,"%s: ",#ar); \
+ for (int q=0; q<n; q++) p += sprintf(p,"%lld ",(long long)ar[q]); \
+ post("%s",foo);}
+
+//****************************************************************
+
+struct FObject;
+struct t_atom2;
+typedef void (*FMethod)(FObject *, int, t_atom2 *);
+
+#define BUILTIN_SYMBOLS(MACRO) \
+ MACRO(_grid,"grid") MACRO(_bang,"bang") MACRO(_float,"float") \
+ MACRO(_list,"list") MACRO(_sharp,"#") \
+ MACRO(_in,"in") MACRO(_out,"out")
+
+extern struct BuiltinSymbols {
+#define FOO(_sym_,_str_) t_symbol *_sym_;
+BUILTIN_SYMBOLS(FOO)
+#undef FOO
+} bsym;
+
+struct Numop;
+struct Pointer;
+#define INT(x) convert(x,(int32*)0)
+#define TO(T,x) convert(x,(T*)0)
+
+// trick to be able to define methods in t_atom
+struct t_atom2 : t_atom {
+ bool operator == (t_symbol *b) {return this->a_type==A_SYMBOL && this->a_symbol==b;}
+ bool operator != (t_symbol *b) {return !(*this==b);}
+ operator float32 () const {if (a_type!=A_FLOAT) RAISE("expected float"); return a_float;}
+#define TYPECASTER(T,A,B) operator T () const { \
+ float f = round(float32(*this)); if (f<A || f>=B) RAISE("value %f is out of range",f); return (T)f;}
+ TYPECASTER( bool, 0 , 2 )
+ TYPECASTER( uint8, 0 , 0x100 )
+ TYPECASTER( int16, -0x8000 , 0x8000 )
+ TYPECASTER( uint16, 0 , 0x10000 )
+ TYPECASTER( int32, -0x80000000LL, 0x80000000LL)
+ TYPECASTER( uint32, 0 ,0x100000000LL)
+#undef TYPECASTER
+ operator uint64 () const {if (a_type!=A_FLOAT) RAISE("expected float"); return (uint64)round(a_float);}
+ operator int64 () const {if (a_type!=A_FLOAT) RAISE("expected float"); return (int64)round(a_float);}
+ operator float64 () const {if (a_type!=A_FLOAT) RAISE("expected float"); return a_float ;}
+
+#define TYPECASTER2(T,A,B,C) operator T () const {if (a_type!=A) RAISE("expected "B); return C;}
+ TYPECASTER2(std::string ,A_SYMBOL ,"symbol" ,std::string(a_symbol->s_name))
+ TYPECASTER2(t_symbol *,A_SYMBOL ,"symbol" , a_symbol )
+ TYPECASTER2(void *,A_POINTER,"pointer" , a_gpointer)
+ TYPECASTER2(t_binbuf *,A_LIST ,"nested list", (t_binbuf *)a_gpointer)
+ TYPECASTER2(Grid *,A_GRID ,"grid" , (Grid *)a_gpointer)
+ TYPECASTER2(GridOutlet *,A_GRIDOUT,"grid outlet", (GridOutlet *)a_gpointer)
+#undef TYPECASTER2
+};
+
+template <class T> T convert(const t_atom &x, T *foo) {const t_atom2 *xx = (const t_atom2 *)&x; return (T)*xx;}
+
+//****************************************************************
+
+//template <class T> class P : T * {};
+//a reference counting pointer class
+template <class T> class P {
+public:
+#define INCR if (p) p->refcount++;
+#define DECR if (p) {p->refcount--; if (!p->refcount) delete p;}
+ T *p;
+ P() {p=0;}
+ P(T *_p) {p=_p ; INCR;}
+ P(const P<T> &_p) {p=_p.p; INCR;}
+ P<T> &operator = (T * _p) {DECR; p=_p; INCR; return *this;}
+ P<T> &operator = (P<T> _p) {DECR; p=_p.p; INCR; return *this;}
+ bool operator == (P<T> _p) {return p==_p.p;}
+ bool operator != (P<T> _p) {return p!=_p.p;}
+ ~P() {DECR;}
+ bool operator !() {return !p;}
+ operator bool() {return !!p;}
+ T &operator *() {return *p;}
+ T *operator ->() {return p;}
+ operator T *() {return p;}
+//#undef INCR
+//#undef DECR
+};
+
+void gfmemcopy(uint8 *out, const uint8 *in, long n);
+template <class T> inline void COPY(T *dest, T *src, long n) {
+ gfmemcopy((uint8*)dest,(const uint8*)src,n*sizeof(T));
+}
+template <class T> inline void CLEAR(T *dest, long n) {
+ memset(dest,0,n*sizeof(T));
+}
+template <class T> static void memswap (T *a, T *b, long n) {
+ T c[n]; COPY(c,a,n); COPY(a,b,n); COPY(b,c,n);
+}
+
+//****************************************************************
+
+struct CObject {
+ int32 refcount;
+ CObject() : refcount(0) {}
+ virtual ~CObject() {}
+ virtual void changed (t_symbol *s=0) {}
+};
+
+// you shouldn't use MethodDecl directly (used by source_filter.rb)
+struct MethodDecl {const char *selector; FMethod method;};
+
+#undef check
+
+//****************************************************************
+// a Dim is a list of dimensions that describe the shape of a grid
+typedef int32 Card; /* should be switched to long int soon */
+struct Dim : CObject {
+ static const Card MAX_DIM=16; // maximum number of dimensions in a grid
+ Card n;
+ Card v[MAX_DIM]; // real stuff
+ void check(); // test invariants
+ Dim(Card n, Card *v){this->n=n; COPY(this->v,v,n); check();}
+ Dim() {n=0; check();}
+ Dim(Card a) {n=1;v[0]=a; check();}
+ Dim(Card a,Card b) {n=2;v[0]=a;v[1]=b; check();}
+ Dim(Card a,Card b,Card c){n=3;v[0]=a;v[1]=b;v[2]=c;check();}
+ Dim(Dim *a, Dim *b, Dim *c=0) {
+ n=a->n+b->n; if(c) n+=c->n;
+ if (n>Dim::MAX_DIM) RAISE("too many dims");
+ COPY(v ,a->v,a->n);
+ COPY(v+a->n,b->v,b->n);
+ if(c) COPY(v+a->n+b->n,c->v,c->n);
+ }
+ Card count() {return n;}
+ Card get(Card i) {return v[i];}
+/* Dim *range(Card i, Card j) {return new Dim(...);} */
+ Card prod(Card start=0, Card end=-1) {
+ if (start<0) start+=n;
+ if (end <0) end +=n;
+ Card tot=1;
+ for (Card i=start; i<=end; i++) tot *= v[i];
+ return tot;
+ }
+ char *to_s();
+ bool equal(P<Dim> o) {
+ if (n!=o->n) return false;
+ for (Card i=0; i<n; i++) if (v[i]!=o->v[i]) return false;
+ return true;
+ }
+};
+
+//****************************************************************
+//NumberTypeE is a very small int identifying the type of the (smallest) elements of a grid
+
+#define NT_UNSIGNED (1<<0)
+#define NT_FLOAT (1<<1)
+#define NT_UNIMPL (1<<2)
+#define NUMBER_TYPE_LIMITS(T,a,b,c) \
+ inline T nt_smallest(T *bogus) {return a;} \
+ inline T nt_greatest(T *bogus) {return b;} \
+ inline T nt_all_ones(T *bogus) {return c;}
+
+NUMBER_TYPE_LIMITS( uint8,0,255,255)
+NUMBER_TYPE_LIMITS( int16,-0x8000,0x7fff,-1)
+NUMBER_TYPE_LIMITS( int32,-0x80000000,0x7fffffff,-1)
+NUMBER_TYPE_LIMITS( int64,-0x8000000000000000LL,0x7fffffffffffffffLL,-1)
+NUMBER_TYPE_LIMITS(float32,-HUGE_VAL,+HUGE_VAL,(RAISE("all_ones"),0))
+NUMBER_TYPE_LIMITS(float64,-HUGE_VAL,+HUGE_VAL,(RAISE("all_ones"),0))
+
+#ifdef HAVE_LITE
+#define NT_NOTLITE NT_UNIMPL
+#define NONLITE(x...)
+#else
+#define NT_NOTLITE 0
+#define NONLITE(x...) x
+#endif
+#define NUMBER_TYPES(MACRO) \
+ MACRO(uint8, 8,NT_UNSIGNED, "u8,b") \
+ MACRO(int16,16,0, "i16,s") \
+ MACRO(int32,32,0, "i32,i") \
+ MACRO(int64,64,NT_NOTLITE, "i64,l") \
+ MACRO(float32,32,NT_FLOAT, "f32,f") \
+ MACRO(float64,64,NT_NOTLITE|NT_FLOAT, "f64,d")
+
+enum NumberTypeE {
+#define FOO(_sym_,args...) _sym_##_e,
+NUMBER_TYPES(FOO)
+#undef FOO
+number_type_table_end
+};
+
+#define FOO(_type_) \
+inline NumberTypeE NumberTypeE_type_of(_type_ *x) {return _type_##_e;}
+EACH_NUMBER_TYPE(FOO)
+#undef FOO
+
+struct NumberType : CObject {
+ const char *name;
+ int size;
+ int flags;
+ const char *aliases;
+ NumberTypeE index;
+ NumberType(const char *name_, int size_, int flags_, const char *aliases_) :
+ name(name_), size(size_), flags(flags_), aliases(aliases_) {}
+};
+
+NumberTypeE NumberTypeE_find (string sym);
+NumberTypeE NumberTypeE_find (const t_atom &sym);
+
+#define TYPESWITCH(T,C,E) switch (T) { \
+ case uint8_e: C(uint8) break; case int16_e: C(int16) break; \
+ case int32_e: C(int32) break; NONLITE(case int64_e: C(int64) break;) \
+ case float32_e: C(float32) break; NONLITE(case float64_e: C(float64) break;) \
+ default: E; RAISE("type '%s' not available here",number_type_table[T].name);}
+#define TYPESWITCH_JUSTINT(T,C,E) switch (T) { \
+ case uint8_e: C(uint8) break; case int16_e: C(int16) break; \
+ case int32_e: C(int32) break; NONLITE(case int64_e: C(int64) break;) \
+ default: E; RAISE("type '%s' not available here",number_type_table[T].name);}
+
+//****************************************************************
+//BitPacking objects encapsulate optimised loops of bitfield conversion (mostly for I/O)
+struct BitPacking;
+// those are the types of the optimised loops of conversion; inputs are const
+struct Packer {
+#define FOO(S) void (*as_##S)(BitPacking *self, long n, S *in, uint8 *out);
+EACH_INT_TYPE(FOO)
+#undef FOO
+};
+struct Unpacker {
+#define FOO(S) void (*as_##S)(BitPacking *self, long n, uint8 *in, S *out);
+EACH_INT_TYPE(FOO)
+#undef FOO
+};
+
+struct BitPacking : CObject {
+ Packer * packer;
+ Unpacker *unpacker;
+ unsigned int endian; // 0=big, 1=little, 2=same, 3=different
+ int bytes;
+ int size;
+ uint32 mask[4];
+ BitPacking(){::abort();} // don't call, but don't remove. sorry.
+ BitPacking(int endian, int bytes, int size, uint32 *mask,
+ Packer *packer=0, Unpacker *unpacker=0);
+ bool is_le();
+ bool eq(BitPacking *o);
+// main entrances to Packers/Unpackers
+ template <class T> void pack(long n, T *in, uint8 *out);
+ template <class T> void unpack(long n, uint8 *in, T *out);
+};
+
+int high_bit(uint32 n);
+int low_bit(uint32 n);
+void swap16(long n, uint16 *data);
+void swap32(long n, uint32 *data);
+void swap64(long n, uint64 *data);
+inline void swap_endian(long n, uint8 *data) {}
+inline void swap_endian(long n, int16 *data) {swap16(n,(uint16 *)data);}
+inline void swap_endian(long n, int32 *data) {swap32(n,(uint32 *)data);}
+inline void swap_endian(long n, int64 *data) {swap64(n,(uint64 *)data);}
+inline void swap_endian(long n, float32 *data) {swap32(n,(uint32 *)data);}
+inline void swap_endian(long n, float64 *data) {swap64(n,(uint64 *)data);}
+
+//****************************************************************
+// Numop objects encapsulate optimised loops of simple operations
+
+enum LeftRight { at_left, at_right };
+
+template <class T>
+struct NumopOn {
+ // Function Vectorisations
+ typedef void (*Map )( long n, T *as, T b ); Map map;
+ typedef void (*Zip )( long n, T *as, T *bs); Zip zip;
+ typedef void (*Fold)(long an, long n, T *as, T *bs); Fold fold;
+ typedef void (*Scan)(long an, long n, T *as, T *bs); Scan scan;
+ // Algebraic Properties (those involving simply numeric types)
+ typedef bool (*AlgebraicCheck)(T x, LeftRight side);
+ // neutral: right: forall y {f(x,y)=x}; left: forall x {f(x,y)=y};
+ // absorbent: right: exists a forall y {f(x,y)=a}; ...
+ void (*neutral)(T *,LeftRight); // default neutral: e.g. 0 for addition, 1 for multiplication
+ AlgebraicCheck is_neutral, is_absorbent;
+ NumopOn(Map m, Zip z, Fold f, Scan s,
+ void (*neu)(T *,LeftRight), AlgebraicCheck n, AlgebraicCheck a) :
+ map(m), zip(z), fold(f), scan(s), neutral(neu), is_neutral(n), is_absorbent(a) {}
+ NumopOn() : map(0),zip(0),fold(0),scan(0),neutral(0),is_neutral(0),is_absorbent(0) {}
+ NumopOn(const NumopOn &z) {
+ map=z.map; zip=z.zip; fold=z.fold; scan=z.scan;
+ is_neutral = z.is_neutral; neutral = z.neutral;
+ is_absorbent = z.is_absorbent; }
+};
+
+// semigroup property: associativity: f(a,f(b,c))=f(f(a,b),c)
+#define OP_ASSOC (1<<0)
+// abelian property: commutativity: f(a,b)=f(b,a)
+#define OP_COMM (1<<1)
+
+struct Numop {
+ const char *name;
+ t_symbol *sym;
+ int flags;
+ int size; // numop=1; vecop>1
+#define FOO(T) NumopOn<T> on_##T; \
+ NumopOn<T> *on(T &foo) { \
+ if (!on_##T.map) RAISE("operator %s does not support type "#T,name); \
+ return &on_##T;}
+EACH_NUMBER_TYPE(FOO)
+#undef FOO
+ template <class T> inline void map(long n, T *as, T b) {
+ on(*as)->map(n,(T *)as,b);}
+ template <class T> inline void zip(long n, T *as, T *bs) {
+ on(*as)->zip(n,(T *)as,(T *)bs);}
+ template <class T> inline void fold(long an, long n, T *as, T *bs) {
+ typename NumopOn<T>::Fold f = on(*as)->fold;
+ if (!f) RAISE("operator %s does not support fold",name);
+ f(an,n,(T *)as,(T *)bs);}
+ template <class T> inline void scan(long an, long n, T *as, T *bs) {
+ typename NumopOn<T>::Scan f = on(*as)->scan;
+ if (!f) RAISE("operator %s does not support scan",name);
+ f(an,n,(T *)as,(T *)bs);}
+
+ Numop(const char *name_,
+#define FOO(T) NumopOn<T> op_##T,
+EACH_NUMBER_TYPE(FOO)
+#undef FOO
+ int flags_, int size_) : name(name_), flags(flags_), size(size_) {
+#define FOO(T) on_##T = op_##T;
+EACH_NUMBER_TYPE(FOO)
+#undef FOO
+ sym=gensym((char *)name);
+ }
+};
+
+extern NumberType number_type_table[];
+extern std::map<string,NumberType *> number_type_dict;
+extern std::map<string,Numop *> op_dict;
+extern std::map<string,Numop *> vop_dict;
+
+static inline NumberTypeE convert(const t_atom &x, NumberTypeE *bogus) {
+ if (x.a_type!=A_SYMBOL) RAISE("expected number-type"); return NumberTypeE_find(string(x.a_symbol->s_name));}
+
+
+static Numop *convert(const t_atom &x, Numop **bogus) {
+ if (x.a_type!=A_SYMBOL) RAISE("expected numop (as symbol)");
+ string k = string(x.a_symbol->s_name);
+ if (op_dict.find(k)==op_dict.end()) {
+ if (vop_dict.find(k)==vop_dict.end()) RAISE("expected two-input-operator, not '%s'", k.data());
+ return vop_dict[k];
+ } else return op_dict[k];
+}
+
+// ****************************************************************
+struct Grid : CObject {
+ P<Dim> dim;
+ NumberTypeE nt;
+ void *data;
+ int state; /* 0:borrowing 1:owning -1:expired(TODO) */
+ Grid(P<Dim> dim, NumberTypeE nt, bool clear=false) {
+ state=1;
+ if (!dim) RAISE("hell");
+ init(dim,nt);
+ if (clear) {long size = bytes(); CLEAR((char *)data,size);}
+ }
+ Grid(const t_atom &x) {state=1; init_from_atom(x);}
+ Grid(int n, t_atom *a, NumberTypeE nt_=int32_e) {state=1; init_from_list(n,a,nt_);}
+ template <class T> Grid(P<Dim> dim, T *data) {
+ state=0; this->dim=dim;
+ this->nt=NumberTypeE_type_of((T *)0);
+ this->data = data;
+ }
+ // parens are necessary to prevent overflow at 1/16th of the word size (256 megs)
+ long bytes() { return dim->prod()*(number_type_table[nt].size/8); }
+ P<Dim> to_dim () { return new Dim(dim->prod(),(int32 *)*this); }
+#define FOO(T) operator T *() { return (T *)data; }
+EACH_NUMBER_TYPE(FOO)
+#undef FOO
+ Grid *dup () { /* always produce an owning grid even if from a borrowing grid */
+ Grid *foo=new Grid(dim,nt);
+ memcpy(foo->data,data,bytes());
+ return foo;
+ }
+ ~Grid() {if (state==1 && data) free(data);}
+private:
+ void init(P<Dim> dim, NumberTypeE nt) {
+ this->dim = dim;
+ this->nt = nt;
+ data = 0;
+ if (dim) {
+ data = memalign(16,bytes()+16);
+ if (!data) RAISE("out of memory (?) trying to get %ld bytes",bytes());
+ }
+ //fprintf(stderr,"rdata=%p data=%p align=%d\n",rdata,data,align);
+ }
+ void init_from_atom(const t_atom &x);
+ void init_from_list(int n, t_atom *a, NumberTypeE nt=int32_e);
+};
+static inline Grid *convert (const t_atom &r, Grid **bogus) {return new Grid(r);}
+
+// DimConstraint interface:
+// return if d is acceptable
+// else RAISE with proper descriptive message
+typedef void (*DimConstraint)(P<Dim> d);
+
+struct PtrGrid : public P<Grid> {
+ DimConstraint dc;
+ void constrain(DimConstraint dc_) { dc=dc_; }
+ P<Grid> next;
+ PtrGrid() : P<Grid>(), dc(0), next(0) {}
+ PtrGrid(const PtrGrid &_p) : P<Grid>(), dc(0), next(0) {dc=_p.dc; p=_p.p; INCR;}
+// PtrGrid( P<Grid> _p) : P<Grid>(), dc(0), next(0) {dc=_p.dc; p=_p.p; INCR;}
+ PtrGrid( Grid *_p) : P<Grid>(), dc(0), next(0) {
+ p=_p;
+INCR;}
+ PtrGrid &operator =( Grid *_p) {if(dc&&_p)dc(_p->dim);
+DECR; p=_p; INCR;
+return *this;}
+ PtrGrid &operator =(P<Grid> _p) {if(dc&&_p)dc(_p->dim); DECR; p=_p.p; INCR; return *this;}
+ PtrGrid &operator =(PtrGrid _p) {if(dc&&_p)dc(_p->dim); DECR; p=_p.p; INCR; return *this;}
+};
+#undef INCR
+#undef DECR
+
+static inline P<Dim> convert(const t_atom &x, P<Dim> *foo) {
+ Grid *d = convert(x,(Grid **)0);
+ if (!d) RAISE("urgh");
+ if (d->dim->n!=1) RAISE("dimension list must have only one dimension itself");
+ return new Dim(d->dim->v[0],(int32 *)(d->data));
+}
+static inline PtrGrid convert(const t_atom &x, PtrGrid *foo) {return PtrGrid(convert(x,(Grid **)0));}
+
+//****************************************************************
+// GridInlet represents a grid-aware inlet
+
+#define GRIDHANDLER_ARGS(T) GridInlet *in, long dex, long n, T *data
+
+// four-part macro for defining the behaviour of a gridinlet in a class
+// C:Class I:Inlet
+#define GRID_INLET(I) \
+ template <class T> void THISCLASS::grinw_##I (GRIDHANDLER_ARGS(T)) {\
+ ((THISCLASS*)in->parent)->grin_##I(in,dex,n,data);}\
+ template <class T> void THISCLASS::grin_##I (GRIDHANDLER_ARGS(T)) {if (n==-1)
+#define GRID_FLOW else if (n>=0)
+#define GRID_FINISH else if (n==-2)
+#define GRID_END }
+
+/* macro for defining a gridinlet's behaviour as just storage (no backstore) */
+// V is a PtrGrid instance-var
+#define GRID_INPUT(I,V) \
+ GRID_INLET(I) {V=new Grid(in->dim,NumberTypeE_type_of(data));} GRID_FLOW {COPY((T *)*(V)+dex,data,n);} GRID_FINISH
+
+// macro for defining a gridinlet's behaviour as just storage (with backstore)
+// V is a PtrGrid instance-var
+#define GRID_INPUT2(I,V) GRID_INLET(I) {V.next = new Grid(in->dim,NumberTypeE_type_of(data));} \
+ GRID_FLOW {COPY(((T *)*(V.next?V.next.p:&*V.p))+dex,data,n);} GRID_FINISH
+
+typedef struct GridInlet GridInlet;
+typedef struct GridHandler {
+#define FOO(T) void (*flow_##T)(GRIDHANDLER_ARGS(T)); \
+ void flow (GRIDHANDLER_ARGS(T)) const {flow_##T(in,dex,n,data);}
+EACH_NUMBER_TYPE(FOO)
+#undef FOO
+} GridHandler;
+
+struct FObject;
+struct GridInlet : CObject {
+ FObject *parent;
+ const GridHandler *gh;
+ GridOutlet *sender;
+ P<Dim> dim;
+ NumberTypeE nt; // kill this
+ long dex;
+ int chunk;
+ PtrGrid buf;// factor-chunk buffer
+ long bufi; // buffer index: how much of buf is filled
+ GridInlet(FObject *parent_, const GridHandler *gh_) :
+ parent(parent_), gh(gh_), sender(0), dim(0), nt(int32_e), dex(0), chunk(-1), bufi(0) {}
+ ~GridInlet() {}
+ void set_chunk(long whichdim);
+ int32 factor() {return buf?buf->dim->prod():1;} // which is usually not the same as this->dim->prod(chunk)
+ void begin(GridOutlet *sender);
+ void finish();
+ template <class T> void flow(long n, T *data); // n=-1 is begin, and n=-2 is finish.
+ void from_list(VA, NumberTypeE nt=int32_e) {Grid t(argc,argv,nt); from_grid(&t);}
+ void from_atom(VA) {Grid t(argv[0]); from_grid(&t);}
+ void from_grid(Grid *g);
+ bool supports_type(NumberTypeE nt);
+private:
+ template <class T> void from_grid2(Grid *g, T foo);
+};
+
+//****************************************************************
+// for use by source_filter.rb ONLY (for \grin)
+#ifndef HAVE_LITE
+#define GRIN(TB,TS,TI,TL,TF,TD) {TB,TS,TI,TL,TF,TD}
+#else
+#define GRIN(TB,TS,TI,TL,TF,TD) {TB,TS,TI,TF}
+#endif // HAVE_LITE
+#define MESSAGE t_symbol *sel, int argc, t_atom2 *argv
+#define MESSAGE2 sel,argc,argv
+#define MESSAGE3 t_symbol *, int, t_atom2 *
+struct AttrDecl {
+ string name;
+ string type;
+ AttrDecl(string name_, string type_) {name=name_; type=type_;}
+};
+typedef FObject *(*t_allocator)(BFObject *,MESSAGE3);
+struct FClass {
+ t_allocator allocator; // returns a new C++ object
+ void (*startup)(FClass *);
+ const char *cname; // C++ name (not PD name)
+ int methodsn; MethodDecl *methods;
+ FClass *super;
+ int ninlets;
+ int noutlets;
+ t_class *bfclass;
+ string name;
+ size_t bytes;
+ std::map<string,AttrDecl *> attrs;
+};
+
+void fclass_install(FClass *fc, FClass *super, size_t bytes);
+
+//****************************************************************
+// GridOutlet represents a grid-aware outlet
+struct GridOutlet : CObject {
+// number of (minimum,maximum) BYTES to send at once
+// starting with version 0.8, this is amount of BYTES, not amount of NUMBERS.
+ static const long MIN_PACKET_SIZE = 1<<8;
+ static const long MAX_PACKET_SIZE = 1<<12;
+// those are set only once
+ FObject *parent; // not a P<> because of circular refs
+ P<Dim> dim; // dimensions of the grid being sent
+ NumberTypeE nt;
+ std::vector<GridInlet *> inlets; // which inlets are we connected to
+// those are updated during transmission
+ long dex; // how many numbers were already sent in this connection
+
+ GridOutlet(FObject *parent_, int woutlet, P<Dim> dim_, NumberTypeE nt_=int32_e);
+ ~GridOutlet() {}
+ void callback(GridInlet *in);
+
+ // send/send_direct: data belongs to caller, may be stack-allocated,
+ // receiver doesn't modify the data; in send(), there is buffering;
+ // in send_direct(), there is not. When switching from buffered to
+ // unbuffered mode, flush() must be called
+ #define FOO(T) void send(long n, T *data) {send_2(n,data);}
+ EACH_NUMBER_TYPE(FOO)
+ #undef FOO
+ template <class T> void send_2(long n, T *data);
+ void flush(); // goes with send();
+ PtrGrid buf; // temporary buffer
+ long bufi; // number of bytes used in the buffer
+ template <class T> void send_direct(long n, T *data);
+ void finish();
+ void create_buf();
+};
+
+//****************************************************************
+
+#define CHECK_GRIN(class,i) \
+ if (in.size()<=i) in.resize(i+1); \
+ if (!in[i]) in[i]=new GridInlet((FObject *)this,&class##_grid_##i##_hand);
+
+#define CHECK_ALIGN16(d,nt) \
+ {int bytes = 16; \
+ int align = ((unsigned long)(void*)d)%bytes; \
+ if (align) {_L_;post("%s(%s): Alignment Warning: %s=%p is not %d-aligned: %d", \
+ ARGS(this), __PRETTY_FUNCTION__,#d,(void*)d,bytes,align);}}
+
+struct BFProxy;
+struct BFObject : t_object {
+ FObject *self;
+ int ninlets,noutlets; // per object settings (not class)
+ BFProxy **inlets; // direct access to inlets (not linked lists)
+ t_outlet **outlets; // direct access to outlets (not linked lists)
+ t_canvas *mom;
+ void ninlets_set(int n, bool draw=true);
+ void noutlets_set(int n, bool draw=true);
+ string binbuf_string ();
+};
+
+// represents objects that have inlets/outlets
+\class FObject : CObject {
+ BFObject *bself; // point to PD peer
+ std::vector<P<GridInlet> > in;
+ P<GridOutlet> out;
+ FObject(BFObject *bself, MESSAGE) : bself(bself) {bself->self = this;}
+ template <class T> void send_out(int outlet, int argc, T *argv) {
+ t_atom foo[argc];
+ for (int i=0; i<argc; i++) SETFLOAT(&foo[i],argv[i]);
+ outlet_list(bself->outlets[outlet],&s_list,argc,foo);
+ }
+ \decl 0 get (t_symbol *s=0);
+ \decl 0 help ();
+};
+\end class
+
+uint64 gf_timeofday();
+extern "C" void Init_gridflow ();
+extern Numop *op_add,*op_sub,*op_mul,*op_div,*op_mod,*op_shl,*op_and,*op_put;
+
+#undef ARGS
+#define ARGS(OBJ) ((OBJ) ? (OBJ)->bself->binbuf_string().data() : "[null]")
+#define NOTEMPTY(_a_) if (!(_a_)) RAISE("'%s' is empty",#_a_);
+#define SAME_TYPE(_a_,_b_) if ((_a_)->nt != (_b_)->nt) RAISE("same type please (%s has %s; %s has %s)", \
+ #_a_, number_type_table[(_a_)->nt].name, \
+ #_b_, number_type_table[(_b_)->nt].name);
+static void SAME_DIM(int n, P<Dim> a, int ai, P<Dim> b, int bi) {
+ if (ai+n > a->n) RAISE("left hand: not enough dimensions");
+ if (bi+n > b->n) RAISE("right hand: not enough dimensions");
+ for (int i=0; i<n; i++) {
+ if (a->v[ai+i] != b->v[bi+i]) {
+ RAISE("mismatch: left dim #%d is %d, right dim #%d is %d",
+ ai+i, a->v[ai+i],
+ bi+i, b->v[bi+i]);}}}
+
+void suffixes_are (const char *name, const char *suffixes);
+#define install(name,inlets,outlets) install2(fclass,name,inlets,outlets)
+void install2(FClass *fclass, const char *name, int inlets, int outlets);
+#define add_creator(name) add_creator2(fclass,name)
+void add_creator2(FClass *fclass, const char *name);
+void add_creator3(FClass *fclass, const char *name);
+#define install_format(name,mode,suffixes) do {install(name,1,1); suffixes_are(name,suffixes);} while(0)
+void call_super(int argc, t_atom *argv);
+#define SUPER call_super(argc,argv);
+
+\class Format : FObject {
+ int mode;
+ int fd;
+ FILE *f;
+ NumberTypeE cast;
+ long frame;
+ Format(BFObject *, MESSAGE);
+ \decl 0 open (t_symbol *mode, string filename);
+ \decl 0 close ();
+ \decl 0 cast (NumberTypeE nt);
+ \decl 0 seek(int frame);
+ \decl 0 rewind ();
+ ~Format ();
+};
+\end class
+
+extern std::vector<string> gf_data_path;
+string gf_find_file (string x);
+void pd_oprintf (std::ostream &o, const char *s, int argc, t_atom *argv);
+void pd_oprint (std::ostream &o, int argc, t_atom *argv);
+void pd_post (const char *s, int argc, t_atom *argv);
+
+inline void set_atom (t_atom *a, uint8 v) {SETFLOAT(a,(float)v);}
+inline void set_atom (t_atom *a, int16 v) {SETFLOAT(a,(float)v);}
+inline void set_atom (t_atom *a, int32 v) {SETFLOAT(a,(float)v);}
+inline void set_atom (t_atom *a, uint32 v) {SETFLOAT(a,(float)v);}
+inline void set_atom (t_atom *a, long v) {SETFLOAT(a,(float)v);}
+inline void set_atom (t_atom *a, float32 v) {SETFLOAT(a,v);}
+inline void set_atom (t_atom *a, float64 v) {SETFLOAT(a,v);}
+inline void set_atom (t_atom *a, t_symbol *v) {SETSYMBOL(a,v);}
+inline void set_atom (t_atom *a, Numop *v) {SETSYMBOL(a,v->sym);}
+inline void set_atom (t_atom *a, t_binbuf *v) {SETLIST(a,v);}
+
+extern std::map<string,FClass *> fclasses;
+int handle_braces(int ac, t_atom *av);
+
+extern FClass ciFObject, ciFormat;
+
+/* both oprintf are copied from desiredata */
+
+static inline int voprintf(std::ostream &buf, const char *s, va_list args) {
+ char *b;
+ int n = vasprintf(&b,s,args);
+ buf << b;
+ free(b);
+ return n;
+}
+static inline int oprintf(std::ostream &buf, const char *s, ...) {
+ va_list args;
+ va_start(args,s);
+ int n = voprintf(buf,s,args);
+ va_end(args);
+ return n;
+}
+
+/* this function was copied from desiredata */
+#ifndef DESIRE
+inline t_symbol *symprintf(const char *s, ...) {
+ char *buf;
+ va_list args;
+ va_start(args,s);
+ if (vasprintf(&buf,s,args)<0) {/*rien*/}
+ va_end(args);
+ t_symbol *r = gensym(buf);
+ free(buf);
+ return r;
+}
+#endif
+
+std::ostream &operator << (std::ostream &self, const t_atom &a);
+
+// from pd/src/g_canvas.c
+#ifdef DESIRE
+#define ce_argc argc
+#define ce_argv argv
+#else
+struct _canvasenvironment {
+ t_symbol *ce_dir; /* directory patch lives in */
+ int ce_argc; /* number of "$" arguments */
+ t_atom *ce_argv; /* array of "$" arguments */
+ int ce_dollarzero; /* value of "$0" */
+};
+#endif
+
+#endif // __GF_GRID_H
diff --git a/externals/gridflow/src/jpeg.cxx b/externals/gridflow/src/jpeg.cxx
new file mode 100644
index 00000000..97482223
--- /dev/null
+++ b/externals/gridflow/src/jpeg.cxx
@@ -0,0 +1,118 @@
+/*
+ $Id: jpeg.c 4620 2009-11-01 21:16:58Z matju $
+
+ GridFlow
+ Copyright (c) 2001-2009 by Mathieu Bouchard
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ See file ../COPYING for further informations on licensing terms.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+//!@#$ not handling abort on compress
+//!@#$ not handling abort on decompress
+
+#include "gridflow.hxx.fcs"
+/* removing macros (removing warnings) */
+#undef HAVE_PROTOTYPES
+#undef HAVE_STDLIB_H
+#undef EXTERN
+extern "C" {
+#include <jpeglib.h>
+};
+
+\class FormatJPEG : Format {
+ P<BitPacking> bit_packing;
+ struct jpeg_compress_struct cjpeg;
+ struct jpeg_decompress_struct djpeg;
+ struct jpeg_error_mgr jerr;
+ short quality;
+ \constructor (t_symbol *mode, string filename) {
+ Format::_0_open(0,0,mode,filename);
+ uint32 mask[3] = {0x0000ff,0x00ff00,0xff0000};
+ bit_packing = new BitPacking(is_le(),3,3,mask);
+ quality = 75;
+ }
+ \decl 0 bang ();
+ \decl 0 quality (short quality);
+ \grin 0 int
+};
+
+GRID_INLET(0) {
+ if (in->dim->n!=3) RAISE("expecting 3 dimensions: rows,columns,channels");
+ if (in->dim->get(2)!=3) RAISE("expecting 3 channels (got %d)",in->dim->get(2));
+ in->set_chunk(1);
+ cjpeg.err = jpeg_std_error(&jerr);
+ jpeg_create_compress(&cjpeg);
+ jpeg_stdio_dest(&cjpeg,f);
+ cjpeg.image_width = in->dim->get(1);
+ cjpeg.image_height = in->dim->get(0);
+ cjpeg.input_components = 3;
+ cjpeg.in_color_space = JCS_RGB;
+ jpeg_set_defaults(&cjpeg);
+ jpeg_set_quality(&cjpeg,quality,false);
+ jpeg_start_compress(&cjpeg,TRUE);
+} GRID_FLOW {
+ int rowsize = in->dim->get(1)*in->dim->get(2);
+ int rowsize2 = in->dim->get(1)*3;
+ uint8 row[rowsize2];
+ uint8 *rows[1] = {row};
+ while (n) {
+ bit_packing->pack(in->dim->get(1),data,row);
+ jpeg_write_scanlines(&cjpeg,rows,1);
+ n-=rowsize; data+=rowsize;
+ }
+} GRID_FINISH {
+ jpeg_finish_compress(&cjpeg);
+ jpeg_destroy_compress(&cjpeg);
+} GRID_END
+
+static bool gfeof(FILE *f) {
+ off_t cur,end;
+ cur = ftell(f);
+ fseek(f,0,SEEK_END);
+ end = ftell(f);
+ fseek(f,cur,SEEK_SET);
+ return cur==end;
+}
+
+\def 0 bang () {
+ //off_t off = ftell(f);
+ //fseek(f,off,SEEK_SET);
+ if (gfeof(f)) {outlet_bang(bself->te_outlet); return;}
+ djpeg.err = jpeg_std_error(&jerr);
+ jpeg_create_decompress(&djpeg);
+ jpeg_stdio_src(&djpeg,f);
+ jpeg_read_header(&djpeg,TRUE);
+ int sx=djpeg.image_width, sy=djpeg.image_height, chans=djpeg.num_components;
+ GridOutlet out(this,0,new Dim(sy,sx,chans),cast);
+ jpeg_start_decompress(&djpeg);
+ uint8 row[sx*chans];
+ uint8 *rows[1] = { row };
+ for (int n=0; n<sy; n++) {
+ jpeg_read_scanlines(&djpeg,rows,1);
+ out.send(sx*chans,row);
+ }
+ jpeg_finish_decompress(&djpeg);
+ jpeg_destroy_decompress(&djpeg);
+}
+
+\def 0 quality (short quality) {this->quality = min(max((int)quality,0),100);}
+
+\classinfo {install_format("#io.jpeg",6,"jpeg jpg");}
+\end class FormatJPEG
+void startup_jpeg () {
+ \startall
+}
diff --git a/externals/gridflow/src/mmx.rb b/externals/gridflow/src/mmx.rb
new file mode 100644
index 00000000..7427771d
--- /dev/null
+++ b/externals/gridflow/src/mmx.rb
@@ -0,0 +1,219 @@
+=begin
+ $Id: mmx.rb 3638 2008-04-21 04:31:20Z matju $
+
+ GridFlow
+ Copyright (c) 2001-2008 by Mathieu Bouchard
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ See file ../COPYING for further informations on licensing terms.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+=end
+
+STDOUT.reopen ARGV[0], "w"
+$loader = File.open ARGV[1], "w"
+$count = 0
+$lines = 0
+puts "; generated by/for GridFlow 0.9.2"
+$loader.puts "#include \"gridflow.hxx.fcs\"\nextern \"C\" {"
+
+# this class is not really used yet (only self.make)
+class AsmFunction
+ def initialize(name)
+ @name = name
+ @label_count = 1
+ end
+ def self.make(name)
+ puts "", "GLOBAL #{name}", "#{name}:"
+ puts "push ebp", "mov ebp,esp", "push esi", "push edi"
+ yield AsmFunction.new(name)
+ puts "pop edi", "pop esi", "leave", "ret", ""
+ end
+ def make_until(*ops)
+ a = @label_count
+ b = @label_count+1
+ @label_count+=2
+ ops[-1] << " #{@name}_#{b}"
+ puts "#{@name}_#{a}: ", *ops
+ yield
+ puts "jmp #{@name}_#{a}"
+ puts "#{@name}_#{b}:"
+ end
+end
+
+$sizeof = {
+ :uint8 => 1,
+ :int16 => 2,
+ :int32 => 4,
+ :int64 => 8,
+ :float32 => 4,
+ :float64 => 8,
+}
+$accum = {
+ :uint8 => "al",
+ :int16 => "ax",
+ :int32 => "eax",
+}
+$asm_type = {
+ :uint8 => "byte",
+ :int16 => "word",
+ :int32 => "dword",
+ :int64 => "qword",
+}
+
+# in the following, the opcode "_" means no such thing seems available.
+# also >> for x86 ought to be shr in the uint8 case.
+# btw, i got all of the MMX information from the NASM manual, Appendix B.
+$opcodes = {
+# [--GF--|--x86--|--mmx-et-al----------------------------------------]
+# [ | |-uint8-|-int16-|-int32-|-int64-|-float32-|-float64-]
+ :add => %w[ + add paddb paddw paddd paddq ],
+ :sub => %w[ - sub psubb psubw psubd psubq ],
+ :and => %w[ & and pand pand pand pand ],
+ :xor => %w[ ^ xor pxor pxor pxor pxor ],
+ :or => %w[ | or por por por por ],
+# :max => %w[ max _ pmaxub pmaxsw _ _ ], # not plain MMX !!! (req.Katmai)
+# :min => %w[ min _ pminub pminsw _ _ ], # not plain MMX !!! (req.Katmai)
+# :eq => %w[ == _ pcmpeqb pcmpeqw pcmpeqd _ ],
+# :gt => %w[ > _ pcmpgtb pcmpgtw pcmpgtd _ ],
+# :shl => %w[ << shl _ psllw pslld psllq ], # noncommutative
+# :shr => %w[ >> sar _ psraw psrad _ ], # noncommutative
+# :clipadd => %w[ clip+ _ paddusb paddsw _ _ ], # future use
+# :clipsub => %w[ clip- _ psubusb psubsw _ _ ], # future use
+# :andnot => %w[ &not _ pandn pandn pandn pandn ], # not planned
+}
+
+$opcodes.each {|k,op|
+ op.map! {|x| if x=="_" then nil else x end }
+ STDERR.puts op.inspect
+}
+$decls = ""
+$install = ""
+
+def make_fun_map(op,type)
+ s="mmx_#{type}_map_#{op}"
+ size = $sizeof[type]
+ accum = $accum[type]
+ sym = $opcodes[op][0]
+ opcode = $opcodes[op][1]
+ mopcode = $opcodes[op][size+(size<4 ? 1 : 0)]
+ return if not mopcode
+ AsmFunction.make(s) {|a|
+ puts "mov ecx,[ebp+8]", "mov esi,[ebp+12]", "mov eax,[ebp+16]"
+ puts "mov dx,ax", "shl eax,8", "mov al,dl" if size==1
+ puts "mov edx,eax", "shl eax,16", "mov ax,dx" if size<=2
+ puts "push eax", "push eax", "movq mm7,[esp]", "add esp,8"
+ foo = proc {|n|
+ a.make_until("cmp ecx,#{8/size*n}","jb near") {
+ 0.step(n,4) {|k|
+ nn=[n-k,4].min
+ o=(0..3).map{|x| 8*(x+k) }
+ for i in 0...nn do puts "movq mm#{i},[esi+#{o[i]}]" end
+ for i in 0...nn do puts "#{mopcode} mm#{i},mm7" end
+ for i in 0...nn do puts "movq [esi+#{o[i]}],mm#{i}" end
+ }
+ puts "lea esi,[esi+#{8*n}]", "lea ecx,[ecx-#{8 / size*n}]"
+ }
+ }
+ foo.call 4
+ foo.call 1
+ a.make_until("test ecx,ecx", "jz") {
+ puts "#{opcode} #{$asm_type[type]} [esi],#{accum}", "lea esi,[esi+#{size}]"
+ puts "dec ecx"
+ }
+ puts "emms"
+ }
+ $decls << "void #{s}(long,#{type}*,#{type});\n"
+ $install << "op_dict[string(\"#{sym}\")]->on_#{type}.map = #{s};\n"
+ $count += 1
+end
+
+def make_fun_zip(op,type)
+ s="mmx_#{type}_zip_#{op}"
+ size = $sizeof[type]
+ accum = $accum[type]
+ sym = $opcodes[op][0]
+ opcode = $opcodes[op][1]
+ mopcode = $opcodes[op][size+(size<4 ? 1 : 0)]
+ return if not mopcode
+ AsmFunction.make(s) {|a|
+ puts "mov ecx,[ebp+8]", "mov edi,[ebp+12]",
+ "mov esi,[ebp+16]"#, "mov ebx,[ebp+20]"
+ foo = proc {|n|
+ a.make_until("cmp ecx,#{8/size*n}","jb near") {
+ 0.step(n,4) {|k|
+ nn=[n-k,4].min
+ o=(0..3).map{|x| 8*(x+k) }
+ for i in 0...nn do puts "movq mm#{i},[edi+#{o[i]}]" end
+ for i in 0...nn do puts "movq mm#{i+4},[esi+#{o[i]}]" end
+ for i in 0...nn do puts "#{mopcode} mm#{i},mm#{i+4}" end
+ for i in 0...nn do puts "movq [edi+#{o[i]}],mm#{i}" end
+ }
+ #for i in 0...n do puts "movq [ebx+#{8*i}],mm#{i}" end
+ puts "lea edi,[edi+#{8*n}]"
+ puts "lea esi,[esi+#{8*n}]"
+ #puts "lea ebx,[ebx+#{8*n}]"
+ puts "lea ecx,[ecx-#{8/size*n}]"
+ }
+ }
+ foo.call 4
+ foo.call 1
+ a.make_until("test ecx,ecx", "jz") {
+ # requires commutativity ??? fails with shl, shr
+ puts "mov #{accum},[esi]"
+ puts "#{opcode} #{$asm_type[type]} [edi],#{accum}"
+ #puts "mov #{accum},[edi]"
+ #puts "#{opcode} #{accum},[esi]"
+ #puts "mov [ebx],#{accum}"
+ puts "lea edi,[edi+#{size}]"
+ puts "lea esi,[esi+#{size}]"
+ #puts "lea ebx,[ebx+#{size}]"
+ puts "dec ecx"
+ }
+ puts "emms"
+ }
+ #$decls << "void #{s}(long,#{type}*,#{type}*,#{type}*);\n"
+ $decls << "void #{s}(long,#{type}*,#{type}*);\n"
+ $install << "op_dict[string(\"#{sym}\")]->on_#{type}.zip = #{s};\n"
+ $count += 1
+end
+
+for op in $opcodes.keys do
+ for type in [:uint8, :int16#, :int32
+ ] do
+ make_fun_map(op,type)
+ make_fun_zip(op,type)
+ end
+end
+
+$loader.puts $decls
+$loader.puts %`
+}; /* extern */
+#include <stdlib.h>
+void startup_mmx_loader () {/*bogus*/}
+void startup_mmx () {
+ if (getenv("NO_MMX")) return;
+ post(\"startup_cpu: using MMX optimisations\");
+ #{$install}
+}`
+
+STDERR.puts "automatically generated #{$count} MMX asm functions"
+
+=begin notes:
+CPUID has a bit for detecting MMX
+PACKSSDW PACKSSWB PACKUSWB = saturation-casting
+PCMPxx: Compare Packed Integers
+PMULHW, PMULLW: Multiply Packed _unsigned_ 16-bit Integers, and Store
+PUNPCKxxx: Unpack and Interleave Data
+=end
diff --git a/externals/gridflow/src/mpeg3.cxx b/externals/gridflow/src/mpeg3.cxx
new file mode 100644
index 00000000..4ee5bf1f
--- /dev/null
+++ b/externals/gridflow/src/mpeg3.cxx
@@ -0,0 +1,83 @@
+/*
+ $Id: mpeg3.c 4620 2009-11-01 21:16:58Z matju $
+
+ GridFlow
+ Copyright (c) 2001-2009 by Mathieu Bouchard
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ See file ../COPYING for further informations on licensing terms.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#define LIBMPEG_INCLUDE_HERE
+#include "gridflow.hxx.fcs"
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+\class FormatMPEG3 : Format {
+ mpeg3_t *mpeg;
+ int track;
+ ~FormatMPEG3 () {if (mpeg) {mpeg3_close(mpeg); mpeg=0;}}
+ \constructor (t_symbol *mode, string filename) {
+ track=0;
+ // libmpeg3 may be nice, but it won't take a filehandle, only filename
+ if (mode!=gensym("in")) RAISE("read-only, sorry");
+ filename = gf_find_file(filename);
+ #ifdef MPEG3_UNDEFINED_ERROR
+ int err;
+ mpeg = mpeg3_open((char *)filename.data(),&err);
+ post("mpeg error code = %d",err);
+ #else
+ mpeg = mpeg3_open((char *)filename.data());
+ #endif
+ if (!mpeg) RAISE("IO Error: can't open file `%s': %s", filename.data(), strerror(errno));
+ }
+ \decl 0 seek (int32 frame);
+ \decl 0 rewind ();
+ \decl 0 bang ();
+};
+
+\def 0 seek (int32 frame) {
+ mpeg3_set_frame(mpeg,clip(frame,int32(0),int32(mpeg3_video_frames(mpeg,track)-1)),track);
+}
+\def 0 rewind () {_0_seek(0,0,0);}
+
+\def 0 bang () {
+ int nframe = mpeg3_get_frame(mpeg,track);
+ int nframes = mpeg3_video_frames(mpeg,track);
+ //post("track=%d; nframe=%d; nframes=%d",track,nframe,nframes);
+ if (nframe >= nframes) {outlet_bang(bself->te_outlet); return;}
+ int sx = mpeg3_video_width(mpeg,track);
+ int sy = mpeg3_video_height(mpeg,track);
+ int channels = 3;
+ /* !@#$ the doc says "You must allocate 4 extra bytes in the
+ last output_row. This is scratch area for the MMX routines." */
+ uint8 *buf = NEWBUF(uint8,sy*sx*channels+16);
+ uint8 *rows[sy];
+ for (int i=0; i<sy; i++) rows[i]=buf+i*sx*channels;
+ mpeg3_read_frame(mpeg,rows,0,0,sx,sy,sx,sy,MPEG3_RGB888,track);
+ GridOutlet out(this,0,new Dim(sy,sx,channels),cast);
+ int bs = out.dim->prod(1);
+ for(int y=0; y<sy; y++) out.send(bs,buf+channels*sx*y);
+ DELBUF(buf);
+// return INT2NUM(nframe);
+}
+
+\classinfo {install_format("#io.mpeg",4,"mpg mpeg");}
+\end class FormatMPEG3
+void startup_mpeg3 () {
+ \startall
+}
diff --git a/externals/gridflow/src/netpbm.cxx b/externals/gridflow/src/netpbm.cxx
new file mode 100644
index 00000000..32ef5645
--- /dev/null
+++ b/externals/gridflow/src/netpbm.cxx
@@ -0,0 +1,117 @@
+/*
+ $Id$
+
+ GridFlow
+ Copyright (c) 2001-2009 by Mathieu Bouchard
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ See file ../COPYING for further informations on licensing terms.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#define NETPBM_INCLUDE_HERE
+#include "gridflow.hxx.fcs"
+
+\class FormatNetPBM : Format {
+ struct pam inpam, outpam;
+ \grin 0
+ \constructor (t_symbol *mode, string filename) {
+ Format::_0_open(0,0,mode,filename);
+ memset(& inpam,0,sizeof(pam));
+ memset(&outpam,0,sizeof(pam));
+ }
+ \decl 0 bang ();
+};
+\def 0 bang () {
+ //inpam.allocation_depth = 3;
+ pnm_readpaminit(f, &inpam, /*PAM_STRUCT_SIZE(tuple_type)*/ sizeof(struct pam));
+ tuple *tuplerow = pnm_allocpamrow(&inpam);
+ if (inpam.depth!=3) RAISE("image has %d channels instead of 3 channels",inpam.depth);
+ GridOutlet out(this,0,new Dim(inpam.height,inpam.width,inpam.depth),cast);
+ uint8 buf[inpam.width*3];
+ for (int i=0; i<inpam.height; i++) {
+ pnm_readpamrow(&inpam, tuplerow);
+ for (int j=0; j<inpam.width; j++) {
+ buf[j*3+0] = tuplerow[j][0];
+ buf[j*3+1] = tuplerow[j][1];
+ buf[j*3+2] = tuplerow[j][2];
+ }
+ out.send(inpam.width*inpam.depth,buf);
+ }
+ pnm_freepamrow(tuplerow);
+}
+GRID_INLET(0) {
+ if (in->dim->n!=3) RAISE("need 3 dimensions");
+ if (in->dim->v[2]!=3) RAISE("need 3 channels");
+ outpam.size = sizeof(struct pam);
+ outpam.len = sizeof(struct pam);
+ outpam.file = f;
+ outpam.format = PPM_FORMAT;
+ outpam.height = in->dim->v[0];
+ outpam.width = in->dim->v[1];
+ outpam.depth = in->dim->v[2];
+ outpam.plainformat = false;
+ outpam.maxval = 255;
+ //outpam.allocation_depth = 3;
+ strcpy(outpam.tuple_type,PAM_PPM_TUPLETYPE);
+ pnm_writepaminit(&outpam);
+ in->set_chunk(1);
+} GRID_FLOW {
+ tuple *tuplerow = pnm_allocpamrow(&outpam);
+ int m = in->dim->v[1];
+ for (int i=0; i<n; i+=in->dim->prod(1)) {
+ for (int j=0; j<m; j++, data+=3) {
+ tuplerow[j][0] = int(data[0]);
+ tuplerow[j][1] = int(data[1]);
+ tuplerow[j][2] = int(data[2]);
+ }
+ pnm_writepamrow(&outpam, tuplerow);
+ }
+ pnm_freepamrow(tuplerow);
+} GRID_FINISH {
+ fflush(f);
+} GRID_END
+/* was supposed to be "#io.netpbm" but there's backwards compat. */
+\classinfo {install_format("#io.ppm",6,"ppm pgm pnm pam");}
+\end class FormatNetPBM
+
+/*FormatPPM.subclass("#io:tk",1,1) {
+ install_rgrid 0
+ def initialize(mode)
+ @id = sprintf("x%08x",object_id)
+ @filename = "/tmp/tk-#{$$}-#{@id}.ppm"
+ if mode!=:out then raise "only #out" end
+ super(mode,:file,@filename)
+ GridFlow.gui "toplevel .#{@id}\n"
+ GridFlow.gui "wm title . GridFlow/Tk\n"
+ GridFlow.gui "image create photo gf#{@id} -width 320 -height 240\n"
+ GridFlow.gui "pack [label .#{@id}.im -image #{@id}]\n"
+ end
+ def _0_rgrid_end
+ super
+ @stream.seek 0,IO::SEEK_SET
+ GridFlow.gui "image create photo #{@id} -file #{@filename}\n"
+ end
+ def delete
+ GridFlow.gui "destroy .#{@id}\n"
+ GridFlow.gui "image delete #{@id}\n"
+ end
+ alias close delete
+}*/
+
+void startup_netpbm () {
+ pm_init(0,0);
+ \startall
+}
diff --git a/externals/gridflow/src/number.cxx b/externals/gridflow/src/number.cxx
new file mode 100644
index 00000000..00acb645
--- /dev/null
+++ b/externals/gridflow/src/number.cxx
@@ -0,0 +1,446 @@
+/*
+ $Id: number.c 4452 2009-10-27 15:59:57Z matju $
+
+ GridFlow
+ Copyright (c) 2001-2009 by Mathieu Bouchard
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ See file ../COPYING for further informations on licensing terms.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "gridflow.hxx.fcs"
+#include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <limits.h>
+#include <complex>
+#include <assert.h>
+//using namespace std;
+
+static inline uint64 weight(uint64 x) {uint64 k;
+ k=0x5555555555555555ULL; x = (x&k) + ((x>> 1)&k); //(2**64-1)/(2**2**0-1)
+ k=0x3333333333333333ULL; x = (x&k) + ((x>> 2)&k); //(2**64-1)/(2**2**1-1)
+ k=0x0f0f0f0f0f0f0f0fULL; x = (x&k) + ((x>> 4)&k); //(2**64-1)/(2**2**2-1)
+ k=0x00ff00ff00ff00ffULL; x = (x&k) + ((x>> 8)&k); //(2**64-1)/(2**2**3-1)
+ k=0x0000ffff0000ffffULL; x = (x&k) + ((x>>16)&k); //(2**64-1)/(2**2**4-1)
+ k=0x00000000ffffffffULL; x = (x&k) + ((x>>32)&k); //(2**64-1)/(2**2**5-1)
+ return x;
+}
+
+#ifdef PASS1
+NumberType number_type_table[] = {
+#define FOO(_sym_,_size_,_flags_,args...) NumberType( #_sym_, _size_, _flags_, args ),
+NUMBER_TYPES(FOO)
+#undef FOO
+};
+const long number_type_table_n = COUNT(number_type_table);
+#endif
+
+// those are bogus class-templates in the sense that you don't create
+// objects from those, you just call static functions. The same kind
+// of pattern is present in STL to overcome some limitations of C++.
+
+template <class T> class Op {
+public:
+ // I call abort() on those because I can't say they're purevirtual.
+ static T f(T a, T b) {abort();}
+ static bool is_neutral (T x, LeftRight side) {assert(!"Op::is_neutral called?"); return false;}
+ static bool is_absorbent(T x, LeftRight side) {assert(!"Op::is_absorbent called?"); return false;}
+};
+
+template <class O, class T> class OpLoops: public NumopOn<T> {
+public:
+ static inline T f(T a, T b) {return O::f(a,b);}
+ #define FOO(I) as[I]=f(as[I],b);
+ static void _map (long n, T *as, T b) {if (!n) return; UNROLL_8(FOO,n,as)}
+ #undef FOO
+ #define FOO(I) as[I]=f(as[I],as[ba+I]);
+ static void _zip (long n, T *as, T *bs) {if (!n) return; ptrdiff_t ba=bs-as; UNROLL_8(FOO,n,as)}
+ #undef FOO
+ #define W(i) as[i]=f(as[i],bs[i]);
+ #define Z(i,j) as[i]=f(f(f(f(as[i],bs[i]),bs[i+j]),bs[i+j+j]),bs[i+j+j+j]);
+ static void _fold (long an, long n, T *as, T *bs) {
+ switch (an) {
+ case 1:for(;(n&3)!=0;bs+=1,n--){W(0) } for (;n;bs+= 4,n-=4){Z(0,1) } break;
+ case 2:for(;(n&3)!=0;bs+=2,n--){W(0)W(1) } for (;n;bs+= 8,n-=4){Z(0,2)Z(1,2) } break;
+ case 3:for(;(n&3)!=0;bs+=3,n--){W(0)W(1)W(2) } for (;n;bs+=12,n-=4){Z(0,3)Z(1,3)Z(2,3) } break;
+ case 4:for(;(n&3)!=0;bs+=4,n--){W(0)W(1)W(2)W(3)} for (;n;bs+=16,n-=4){Z(0,4)Z(1,4)Z(2,4)Z(3,4)} break;
+ default:while (n--) {int i=0;
+ for (; i<(an&-4); i+=4, bs+=4) {
+ as[i+0]=f(as[i+0],bs[0]);
+ as[i+1]=f(as[i+1],bs[1]);
+ as[i+2]=f(as[i+2],bs[2]);
+ as[i+3]=f(as[i+3],bs[3]);}
+ for (; i<an; i++, bs++) as[i] = f(as[i],*bs);}}}
+ #undef W
+ #undef Z
+ static void _scan (long an, long n, T *as, T *bs) {
+ for (; n--; as=bs-an) {
+ for (int i=0; i<an; i++, as++, bs++) *bs=f(*as,*bs);
+ }
+ }
+};
+
+template <class T>
+static void quick_mod_map (long n, T *as, T b) {
+ if (!b) return;
+#define FOO(I) as[I]=mod(as[I],b);
+ UNROLL_8(FOO,n,as)
+#undef FOO
+}
+
+template <class T> static void quick_ign_map (long n, T *as, T b) {}
+template <class T> static void quick_ign_zip (long n, T *as, T *bs) {}
+template <class T> static void quick_put_map (long n, T *as, T b) {
+#define FOO(I) as[I]=b;
+ UNROLL_8(FOO,n,as)
+#undef FOO
+}
+
+#ifdef PASS1
+void quick_put_map (long n, int16 *as, int16 b) {
+ if ((n&1)!=0 && ((long)as&4)!=0) {*as++=b; n--;}
+ quick_put_map(n>>1, (int32 *)as, (int32)(b<<16)+b);
+ if ((n&1)!=0) *as++=b;
+}
+void quick_put_map (long n, uint8 *as, uint8 b) {
+ while ((n&3)!=0 && ((long)as&4)!=0) {*as++=b; n--;}
+ int32 c=(b<<8)+b; c+=c<<16;
+ quick_put_map(n>>2, (int32 *)as, c);
+ while ((n&3)!=0) *as++=b;
+}
+#endif
+template <class T> static void quick_put_zip (long n, T *as, T *bs) {
+ gfmemcopy((uint8 *)as, (uint8 *)bs, n*sizeof(T));
+}
+
+#define Plex std::complex
+
+// classic two-input operator
+
+#define DEF_OP_COMMON(op,expr,neu,isneu,isorb,T) \
+ inline static T f(T a, T b) { return (T)(expr); } \
+ inline static void neutral (T *a, LeftRight side) {*a = neu;} \
+ inline static bool is_neutral (T x, LeftRight side) {return isneu;} \
+ inline static bool is_absorbent(T x, LeftRight side) {return isorb;}
+#define DEF_OP(op,expr,neu,isneu,isorb) template <class T> class Y##op : Op<T> { public: \
+ DEF_OP_COMMON(op,expr,neu,isneu,isorb,T);};
+#define DEF_OPFT(op,expr,neu,isneu,isorb,T) template <> class Y##op<T> : Op<T> { public: \
+ DEF_OP_COMMON(op,expr,neu,isneu,isorb,T);};
+// this macro is for operators that have different code for the float version
+#define DEF_OPF( op,expr,expr2,neu,isneu,isorb) \
+ DEF_OP( op,expr, neu,isneu,isorb) \
+ DEF_OPFT(op, expr2,neu,isneu,isorb,float32) \
+ DEF_OPFT(op, expr2,neu,isneu,isorb,float64)
+
+#define OL(O,T) OpLoops<Y##O<T>,T>
+#define VOL(O,T) OpLoops<Y##O<Plex<T> >,Plex<T> >
+#define DECL_OPON(L,O,T) NumopOn<T>( \
+ (NumopOn<T>::Map) L(O,T)::_map, (NumopOn<T>::Zip) L(O,T)::_zip, \
+ (NumopOn<T>::Fold)L(O,T)::_fold, (NumopOn<T>::Scan)L(O,T)::_scan, \
+ &Y##O<T>::neutral, &Y##O<T>::is_neutral, &Y##O<T>::is_absorbent)
+#define DECL_OPON_NOFOLD(L,O,T) NumopOn<T>( \
+ (NumopOn<T>::Map)L(O,T)::_map, (NumopOn<T>::Zip)L(O,T)::_zip, 0,0, \
+ &Y##O<T>::neutral, &Y##O<T>::is_neutral, &Y##O<T>::is_absorbent)
+#define DECLOP( L,M,O,sym,flags,dim) Numop(sym,M(L,O,uint8),M(L,O,int16),M(L,O,int32) \
+ NONLITE(,M(L,O,int64)), M(L,O,float32) NONLITE(,M(L,O,float64)),flags,dim)
+#define DECLOP_NOFLOAT(L,M,O,sym,flags,dim) Numop(sym,M(L,O,uint8),M(L,O,int16),M(L,O,int32) \
+ NONLITE(,M(L,O,int64)),NumopOn<float32>() NONLITE(,NumopOn<float64>()), flags,dim)
+// NONLITE(,M(L,O,int64),NumopOn<float32>(),NumopOn<float64>()), flags,dim)
+#define DECLOP_FLOAT( L,M,O,sym,flags,dim) Numop(sym,NumopOn<uint8>(),NumopOn<int16>(),NumopOn<int32>() \
+ NONLITE(,NumopOn<int64>()),M(L,O,float32) NONLITE(,M(L,O,float64)),flags,dim)
+
+#define DECL_OP( O,sym,flags) DECLOP( OL,DECL_OPON ,O,sym,flags,1)
+#define DECL_OP_NOFLOAT( O,sym,flags) DECLOP_NOFLOAT( OL,DECL_OPON ,O,sym,flags,1)
+#define DECL_OP_NOFOLD( O,sym,flags) DECLOP( OL,DECL_OPON_NOFOLD,O,sym,flags,1)
+#define DECL_OP_NOFOLD_NOFLOAT( O,sym,flags) DECLOP_NOFLOAT( OL,DECL_OPON_NOFOLD,O,sym,flags,1)
+#define DECL_OP_NOFOLD_FLOAT( O,sym,flags) DECLOP_FLOAT( OL,DECL_OPON_NOFOLD,O,sym,flags,1)
+
+#define DECL_VOP( O,sym,flags,dim) DECLOP( VOL,DECL_OPON ,O,sym,flags,dim)
+#define DECL_VOP_NOFLOAT( O,sym,flags,dim) DECLOP_NOFLOAT(VOL,DECL_OPON ,O,sym,flags,dim)
+#define DECL_VOP_NOFOLD( O,sym,flags,dim) DECLOP( VOL,DECL_OPON_NOFOLD,O,sym,flags,dim)
+#define DECL_VOP_NOFOLD_NOFLOAT(O,sym,flags,dim) DECLOP_NOFLOAT(VOL,DECL_OPON_NOFOLD,O,sym,flags,dim)
+#define DECL_VOP_NOFOLD_FLOAT( O,sym,flags,dim) DECLOP_FLOAT( VOL,DECL_OPON_NOFOLD,O,sym,flags,dim)
+
+template <class T> static inline T gf_floor (T a) {
+ return (T) floor((double)a); }
+template <class T> static inline T gf_trunc (T a) {
+ return (T) floor(abs((double)a)) * (a<0?-1:1); }
+
+#ifdef PASS1
+DEF_OP(ignore, a, 0, side==at_right, side==at_left)
+DEF_OP(put, b, 0, side==at_left, side==at_right)
+DEF_OP(add, a+b, 0, x==0, false)
+DEF_OP(sub, a-b, 0, side==at_right && x==0, false)
+DEF_OP(bus, b-a, 0, side==at_left && x==0, false)
+DEF_OP(mul, a*b, 1, x==1, x==0)
+DEF_OP(mulshr8, (a*b)>>8, 256, x==256, x==0)
+DEF_OP(div, b==0 ? (T)0 : a/b , 1, side==at_right && x==1, false)
+DEF_OP(div2, b==0 ? 0 : div2(a,b), 1, side==at_right && x==1, false)
+DEF_OP(vid, a==0 ? (T)0 : b/a , 1, side==at_left && x==1, false)
+DEF_OP(vid2, a==0 ? 0 : div2(b,a), 1, side==at_left && x==1, false)
+DEF_OPF(mod, b==0 ? 0 : mod(a,b), b==0 ? 0 : a-b*gf_floor(a/b), 0, false, (side==at_left && x==0) || (side==at_right && x==1))
+DEF_OPF(dom, a==0 ? 0 : mod(b,a), a==0 ? 0 : b-a*gf_floor(b/a), 0, false, (side==at_left && x==0) || (side==at_right && x==1))
+//DEF_OPF(rem, b==0 ? 0 : a%b, b==0 ? 0 : a-b*gf_trunc(a/b))
+//DEF_OPF(mer, a==0 ? 0 : b%a, a==0 ? 0 : b-a*gf_trunc(b/a))
+DEF_OP(rem, b==0?(T)0:a%b, 0, false, (side==at_left&&x==0) || (side==at_right&&x==1))
+DEF_OP(mer, a==0?(T)0:b%a, 0, false, (side==at_left&&x==0) || (side==at_right&&x==1))
+#endif
+#ifdef PASS2
+DEF_OP(gcd, gcd(a,b), 0, x==0, x==1)
+DEF_OP(gcd2, gcd2(a,b), 0, x==0, x==1) // should test those and pick one of the two
+DEF_OP(lcm, a==0 || b==0 ? (T)0 : lcm(a,b), 1, x==1, x==0)
+DEF_OPF(or , a|b, (float32)((int32)a | (int32)b), 0, x==0, x==nt_all_ones(&x))
+DEF_OPF(xor, a^b, (float32)((int32)a ^ (int32)b), 0, x==0, false)
+DEF_OPF(and, a&b, (float32)((int32)a & (int32)b), -1 /*nt_all_ones((T*)0)*/, x==nt_all_ones(&x), x==0)
+DEF_OPF(shl, a<<b, a*pow(2.0,+b), 0, side==at_right && x==0, false)
+DEF_OPF(shr, a>>b, a*pow(2.0,-b), 0, side==at_right && x==0, false)
+DEF_OP(sc_and, a ? b : a, 1, side==at_left && x!=0, side==at_left && x==0)
+DEF_OP(sc_or, a ? a : b, 0, side==at_left && x==0, side==at_left && x!=0)
+DEF_OP(min, min(a,b), nt_greatest((T*)0), x==nt_greatest(&x), x==nt_smallest(&x))
+DEF_OP(max, max(a,b), nt_smallest((T*)0), x==nt_smallest(&x), x==nt_greatest(&x))
+DEF_OP(cmp, cmp(a,b), 0, false, false)
+DEF_OP(eq, a == b, 0, false, false)
+DEF_OP(ne, a != b, 0, false, false)
+DEF_OP(gt, a > b, 0, false, (side==at_left && x==nt_smallest(&x)) || (side==at_right && x==nt_greatest(&x)))
+DEF_OP(le, a <= b, 0, false, (side==at_left && x==nt_smallest(&x)) || (side==at_right && x==nt_greatest(&x)))
+DEF_OP(lt, a < b, 0, false, (side==at_left && x==nt_greatest(&x)) || (side==at_right && x==nt_smallest(&x)))
+DEF_OP(ge, a >= b, 0, false, (side==at_left && x==nt_greatest(&x)) || (side==at_right && x==nt_smallest(&x)))
+#endif
+#ifdef PASS3
+DEF_OP(sinmul, (float64)b * sin((float64)a * (M_PI / 18000)), 0, false, false) // "LN=9000+36000n RA=0 LA=..."
+DEF_OP(cosmul, (float64)b * cos((float64)a * (M_PI / 18000)), 0, false, false) // "LN=36000n RA=0 LA=..."
+DEF_OP(atan, atan2(a,b) * (18000 / M_PI), 0, false, false) // "LA=0"
+DEF_OP(tanhmul, (float64)b * tanh((float64)a * (M_PI / 18000)), 0, false, x==0)
+DEF_OP(gamma, b<=0 ? (T)0 : (T)(0+floor(pow((float64)a/256.0,256.0/(float64)b)*256.0)), 0, false, false) // "RN=256"
+DEF_OPF(pow, ipow(a,b), pow(a,b), 0, false, false) // "RN=1"
+DEF_OP(logmul, a==0 ? (T)0 : (T)((float64)b * log((float64)gf_abs(a))), 0, false, false) // "RA=0"
+// 0.8
+DEF_OPF(clipadd, clipadd(a,b), a+b, 0, x==0, false)
+DEF_OPF(clipsub, clipsub(a,b), a-b, 0, side==at_right && x==0, false)
+DEF_OP(abssub, gf_abs(a-b), 0, false, false)
+DEF_OP(sqsub, (a-b)*(a-b), 0, false, false)
+DEF_OP(avg, (a+b)/2, 0, false, false)
+DEF_OPF(hypot, floor(sqrt(a*a+b*b)), sqrt(a*a+b*b), 0, false, false)
+DEF_OPF(sqrt, floor(sqrt(a)), sqrt(a), 0, false, false)
+DEF_OP(rand, a==0 ? (T)0 : (T)(random()%(int32)a), 0, false, false)
+//DEF_OP(erf,"erf*", 0)
+DEF_OP(weight,weight((uint64)(a^b) & (0xFFFFFFFFFFFFFFFFULL>>(64-sizeof(T)*8))),0,false,false)
+#define BITS(T) (sizeof(T)*8)
+DEF_OP(rol,((uint64)a<<b)|((uint64)a>>(T)((-b)&(BITS(T)-1))),0,false,false)
+DEF_OP(ror,((uint64)a>>b)|((uint64)a<<(T)((-b)&(BITS(T)-1))),0,false,false)
+
+DEF_OP(sin, sin(a-b), 0, false, false)
+DEF_OP(cos, cos(a-b), 0, false, false)
+DEF_OP(atan2,atan2(a,b), 0, false, false)
+DEF_OP(tanh, tanh(a-b), 0, false, false)
+DEF_OP(exp, exp(a-b), 0, false, false)
+DEF_OP(log, log(a-b), 0, false, false)
+
+#endif
+#ifdef PASS4
+
+template <class T> inline T gf_sqrt(T a) {return (T)floor(sqrt( a));}
+inline float32 gf_sqrt(float32 a) {return sqrtf(a) ;}
+inline float64 gf_sqrt(float64 a) {return sqrt( a) ;}
+
+template <class T> inline Plex<T> cx_sqsub(const Plex<T>& a, const Plex<T>& b) { Plex<T> v=a-b; return v*v; }
+template <class T> inline Plex<T> cx_abssub(const Plex<T>& a, const Plex<T>& b) { Plex<T> v=a-b; return norm(v); }
+
+template <class T> inline Plex<T> gf_c2p(const Plex<T>& a) {
+ return Plex<T>(hypot(a.real(),a.imag()),atan2(a.real(),a.imag())*(18000 / M_PI));
+}
+template <class T> inline Plex<T> gf_p2c(const Plex<T>& a) {
+ return Plex<T>((float64)a.real() * sin((float64)a.imag() * (M_PI / 18000)),
+ (float64)a.real() * cos((float64)a.imag() * (M_PI / 18000)));
+}
+/*
+template <class T> inline Plex<T> cx_atan2 (Plex<T>& a, Plex<T>& b) {
+ if (b==0) return 0;
+ Plex<T> v=a/b;
+ return (log(1+iz)-log(log(1-iz))/2i;
+ // but this is not taking care of sign stuff...
+ // and then what's the use of atan2 on complexes? (use C.log ...)
+}
+*/
+
+//!@#$ neutral,is_neutral,is_absorbent are impossible to use here
+DEF_OP(cx_mul, a*b, 1, false, false)
+DEF_OP(cx_mulconj, a*conj(b), 1, false, false)
+DEF_OP(cx_div, a/b, 1, false, false)
+DEF_OP(cx_divconj, a/conj(b), 1, false, false)
+DEF_OP(cx_sqsub, cx_sqsub(a,b), 0, false, false)
+DEF_OP(cx_abssub, cx_abssub(a,b), 0, false, false)
+DEF_OP(cx_sin, sin(a-b), 0, false, false)
+DEF_OP(cx_cos, cos(a-b), 0, false, false)
+//DEF_OP(cx_atan2,atan2(a,b), 0, false, false)
+DEF_OP(cx_tanh, tanh(a-b), 0, false, false)
+DEF_OP(cx_exp, exp(a-b), 0, false, false)
+DEF_OP(cx_log, log(a-b), 0, false, false)
+DEF_OP(c2p, gf_c2p(a-b), 0, false, false)
+DEF_OP(p2c, gf_p2c(a)+b, 0, false, false)
+#endif
+
+extern Numop op_table1[], op_table2[], op_table3[], op_table4[];
+extern const long op_table1_n, op_table2_n, op_table3_n, op_table4_n;
+
+#ifdef PASS1
+Numop op_table1[] = {
+ DECL_OP(ignore, "ignore", OP_ASSOC),
+ DECL_OP(put, "put", OP_ASSOC),
+ DECL_OP(add, "+", OP_ASSOC|OP_COMM), // "LINV=sub"
+ DECL_OP(sub, "-", 0),
+ DECL_OP(bus, "inv+", 0),
+ DECL_OP(mul, "*", OP_ASSOC|OP_COMM),
+ DECL_OP_NOFLOAT(mulshr8, "*>>8", OP_ASSOC|OP_COMM),
+ DECL_OP(div, "/", 0),
+ DECL_OP_NOFLOAT(div2, "div", 0),
+ DECL_OP(vid, "inv*", 0),
+ DECL_OP_NOFLOAT(vid2,"swapdiv", 0),
+ DECL_OP_NOFLOAT(mod, "%", 0),
+ DECL_OP_NOFLOAT(dom, "swap%", 0),
+ DECL_OP_NOFLOAT(rem, "rem", 0),
+ DECL_OP_NOFLOAT(mer, "swaprem", 0),
+};
+const long op_table1_n = COUNT(op_table1);
+#endif
+#ifdef PASS2
+Numop op_table2[] = {
+ DECL_OP_NOFLOAT(gcd, "gcd", OP_ASSOC|OP_COMM),
+ DECL_OP_NOFLOAT(gcd2, "gcd2", OP_ASSOC|OP_COMM),
+ DECL_OP_NOFLOAT(lcm, "lcm", OP_ASSOC|OP_COMM),
+ DECL_OP(or , "|", OP_ASSOC|OP_COMM),
+ DECL_OP(xor, "^", OP_ASSOC|OP_COMM),
+ DECL_OP(and, "&", OP_ASSOC|OP_COMM),
+ DECL_OP_NOFOLD(shl, "<<", 0),
+ DECL_OP_NOFOLD(shr, ">>", 0),
+ DECL_OP_NOFOLD(sc_and,"&&", 0),
+ DECL_OP_NOFOLD(sc_or, "||", 0),
+ DECL_OP(min, "min", OP_ASSOC|OP_COMM),
+ DECL_OP(max, "max", OP_ASSOC|OP_COMM),
+ DECL_OP_NOFOLD(eq, "==", OP_COMM),
+ DECL_OP_NOFOLD(ne, "!=", OP_COMM),
+ DECL_OP_NOFOLD(gt, ">", 0),
+ DECL_OP_NOFOLD(le, "<=", 0),
+ DECL_OP_NOFOLD(lt, "<", 0),
+ DECL_OP_NOFOLD(ge, ">=", 0),
+ DECL_OP_NOFOLD(cmp, "cmp",0),
+};
+const long op_table2_n = COUNT(op_table2);
+#endif
+#ifdef PASS3
+uint8 clipadd(uint8 a, uint8 b) { int32 c=a+b; return c<0?0:c>255?255:c; }
+int16 clipadd(int16 a, int16 b) { int32 c=a+b; return c<-0x8000?-0x8000:c>0x7fff?0x7fff:c; }
+int32 clipadd(int32 a, int32 b) { int64 c=a+b; return c<-0x80000000?-0x80000000:c>0x7fffffff?0x7fffffff:c; }
+int64 clipadd(int64 a, int64 b) { int64 c=(a>>1)+(b>>1)+(a&b&1), p=nt_smallest((int64 *)0), q=nt_greatest((int64 *)0);
+ return c<p/2?p:c>q/2?q:a+b; }
+uint8 clipsub(uint8 a, uint8 b) { int32 c=a-b; return c<0?0:c>255?255:c; }
+int16 clipsub(int16 a, int16 b) { int32 c=a-b; return c<-0x8000?-0x8000:c>0x7fff?0x7fff:c; }
+int32 clipsub(int32 a, int32 b) { int64 c=a-b; return c<-0x80000000?-0x80000000:c>0x7fffffff?0x7fffffff:c; }
+int64 clipsub(int64 a, int64 b) { int64 c=(a>>1)-(b>>1); //???
+ int64 p=nt_smallest((int64 *)0), q=nt_greatest((int64 *)0);
+ return c<p/2?p:c>q/2?q:a-b; }
+
+Numop op_table3[] = {
+ DECL_OP_NOFOLD(sinmul, "sin*", 0),
+ DECL_OP_NOFOLD(cosmul, "cos*", 0),
+ DECL_OP_NOFOLD(atan, "atan", 0),
+ DECL_OP_NOFOLD(tanhmul,"tanh*", 0),
+ DECL_OP_NOFOLD(gamma, "gamma", 0),
+ DECL_OP_NOFOLD(pow, "**", 0),
+ DECL_OP_NOFOLD(logmul, "log*", 0),
+// 0.8
+ DECL_OP(clipadd,"clip+", OP_ASSOC|OP_COMM),
+ DECL_OP(clipsub,"clip-", 0),
+ DECL_OP_NOFOLD(abssub,"abs-", OP_COMM),
+ DECL_OP_NOFOLD(sqsub, "sq-", OP_COMM),
+ DECL_OP_NOFOLD(avg, "avg", OP_COMM),
+ DECL_OP_NOFOLD(hypot, "hypot",OP_COMM), // huh, almost OP_ASSOC
+ DECL_OP_NOFOLD(sqrt, "sqrt", 0),
+ DECL_OP_NOFOLD(rand, "rand", 0),
+ //DECL_OP_NOFOLD(erf,"erf*", 0),
+ DECL_OP_NOFOLD_NOFLOAT(weight,"weight",OP_COMM),
+ DECL_OP_NOFOLD_NOFLOAT(rol,"rol",0),
+ DECL_OP_NOFOLD_NOFLOAT(ror,"ror",0),
+
+ DECL_OP_NOFOLD_FLOAT(sin, "sin", 0),
+ DECL_OP_NOFOLD_FLOAT(cos, "cos", 0),
+ DECL_OP_NOFOLD_FLOAT(atan2,"atan2", 0),
+ DECL_OP_NOFOLD_FLOAT(tanh, "tanh", 0),
+ DECL_OP_NOFOLD_FLOAT(exp, "exp", 0),
+ DECL_OP_NOFOLD_FLOAT(log, "log", 0),
+
+};
+const long op_table3_n = COUNT(op_table3);
+#endif
+#ifdef PASS4
+Numop op_table4[] = {
+ DECL_VOP(cx_mul, "C.*", OP_ASSOC|OP_COMM,2),
+ DECL_VOP(cx_mulconj, "C.*conj", OP_ASSOC|OP_COMM,2),
+ DECL_VOP(cx_div, "C./", 0,2),
+ DECL_VOP(cx_divconj, "C./conj", 0,2),
+ DECL_VOP(cx_sqsub, "C.sq-", OP_COMM,2),
+ DECL_VOP(cx_abssub, "C.abs-", OP_COMM,2),
+ DECL_VOP_NOFOLD_FLOAT(cx_sin, "C.sin", 0,2),
+ DECL_VOP_NOFOLD_FLOAT(cx_cos, "C.cos", 0,2),
+// DECL_VOP_NOFOLD_FLOAT(cx_atan2,"C.atan2",0,2),
+ DECL_VOP_NOFOLD_FLOAT(cx_tanh, "C.tanh", 0,2),
+ DECL_VOP_NOFOLD_FLOAT(cx_exp, "C.exp", 0,2),
+ DECL_VOP_NOFOLD_FLOAT(cx_log, "C.log", 0,2),
+ DECL_VOP_NOFOLD( c2p, "c2p", 0,2),
+ DECL_VOP_NOFOLD( p2c, "p2c", 0,2),
+};
+const long op_table4_n = COUNT(op_table4);
+#endif
+
+// D=dictionary, A=table, A##_n=table count.
+#define INIT_TABLE(D,A) for(int i=0; i<A##_n; i++) D[string(A[i].name)]=&A[i];
+
+#ifdef PASS1
+std::map<string,NumberType *> number_type_dict;
+std::map<string,Numop *> op_dict;
+std::map<string,Numop *> vop_dict;
+void startup_number () {
+ INIT_TABLE( op_dict,op_table1)
+ INIT_TABLE( op_dict,op_table2)
+ INIT_TABLE( op_dict,op_table3)
+ INIT_TABLE(vop_dict,op_table4)
+ INIT_TABLE(number_type_dict,number_type_table)
+
+ for (int i=0; i<COUNT(number_type_table); i++) {
+ number_type_table[i].index = (NumberTypeE) i;
+ char a[64];
+ strcpy(a,number_type_table[i].aliases);
+ char *b = strchr(a,',');
+ if (b) {
+ *b=0;
+ number_type_dict[string(b+1)]=&number_type_table[i];
+ }
+ number_type_dict[string(a)]=&number_type_table[i];
+ }
+// S:name; M:mode; F:replacement function;
+#define OVERRIDE_INT(S,M,F) { \
+ Numop *foo = op_dict[string(#S)]; \
+ foo->on_uint8.M=F; \
+ foo->on_int16.M=F; \
+ foo->on_int32.M=F; }
+ OVERRIDE_INT(ignore,map,quick_ign_map);
+ OVERRIDE_INT(ignore,zip,quick_ign_zip);
+ //OVERRIDE_INT(put,map,quick_put_map);
+ //OVERRIDE_INT(put,zip,quick_put_zip);
+ //OVERRIDE_INT(%,map,quick_mod_map); // !@#$ does that make an improvement at all?
+}
+#endif
diff --git a/externals/gridflow/src/opencv.cxx b/externals/gridflow/src/opencv.cxx
new file mode 100644
index 00000000..424d9bd0
--- /dev/null
+++ b/externals/gridflow/src/opencv.cxx
@@ -0,0 +1,537 @@
+/*
+ $Id: opencv.c 4556 2009-11-01 00:40:16Z matju $
+
+ GridFlow
+ Copyright (c) 2001-2009 by Mathieu Bouchard
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ See file ../COPYING for further informations on licensing terms.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "gridflow.hxx.fcs"
+#include <opencv/cv.h>
+#include <errno.h>
+
+#define cvRelease(euh) cvRelease((void **)(euh))
+#define binbuf_addv(SELF,FMT,ARGS...) binbuf_addv(SELF,const_cast<char *>(FMT),ARGS)
+#define USELIST \
+ if (a.a_type != A_LIST) RAISE("expected listatom"); \
+ t_list *b = (t_list *)a.a_gpointer; \
+ int argc = binbuf_getnatom(b); \
+ t_atom2 *argv = (t_atom2 *)binbuf_getvec(b);
+#define GETF(I) atom_getfloatarg(I,argc,argv)
+#define GETI(I) int(atom_getfloatarg(I,argc,argv))
+
+int ipl_eltype(NumberTypeE e) {
+ switch (e) {
+ case uint8_e: return IPL_DEPTH_8U;
+ // IPL_DEPTH_8S not supported
+ // IPL_DEPTH_16U not supported
+ case int16_e: return IPL_DEPTH_16S;
+ case int32_e: return IPL_DEPTH_32S;
+ case float32_e: return IPL_DEPTH_32F;
+ case float64_e: return IPL_DEPTH_64F;
+ default: RAISE("unsupported type %s",number_type_table[e].name);
+ }
+}
+
+NumberTypeE gf_ipltype(int e) {
+ switch (e) {
+ case IPL_DEPTH_8U: return uint8_e;
+ // IPL_DEPTH_8S not supported
+ // IPL_DEPTH_16U not supported
+ case IPL_DEPTH_16S: return int16_e;
+ case IPL_DEPTH_32S: return int32_e;
+ case IPL_DEPTH_32F: return float32_e;
+ case IPL_DEPTH_64F: return float64_e;
+ default: RAISE("unsupported IPL type %d",e);
+ }
+}
+
+int cv_eltype(NumberTypeE e) {
+ switch (e) {
+ case uint8_e: return CV_8U;
+ // CV_8S not supported
+ // CV_16U not supported
+ case int16_e: return CV_16S;
+ case int32_e: return CV_32S;
+ case float32_e: return CV_32F;
+ case float64_e: return CV_64F;
+ default: RAISE("unsupported type %s",number_type_table[e].name);
+ }
+}
+
+NumberTypeE gf_cveltype(int e) {
+ switch (e) {
+ case CV_8U: return uint8_e;
+ // CV_8S not supported
+ // CV_16U not supported
+ case CV_16S: return int16_e;
+ case CV_32S: return int32_e;
+ case CV_32F: return float32_e;
+ case CV_64F: return float64_e;
+ default: RAISE("unsupported CV type %d",e);
+ }
+}
+
+enum CvMode {
+ cv_mode_auto,
+ cv_mode_channels,
+ cv_mode_nochannels,
+};
+
+CvMode convert (const t_atom2 &x, CvMode *foo) {
+ if (x==gensym("auto")) return cv_mode_auto;
+ if (x==gensym("channels")) return cv_mode_channels;
+ if (x==gensym("nochannels")) return cv_mode_nochannels;
+ RAISE("invalid CvMode");
+}
+
+CvTermCriteria convert (const t_atom2 &a, CvTermCriteria *foo) {
+ USELIST;
+ CvTermCriteria tc;
+ tc.type = 0;
+ if (argc>0 && argv[0]!=gensym("nil")) {tc.type |= CV_TERMCRIT_ITER; tc.max_iter = GETI(0);}
+ if (argc>1 && argv[1]!=gensym("nil")) {tc.type |= CV_TERMCRIT_EPS ; tc.epsilon = GETF(1);}
+ if (argc>2) RAISE("invalid CvTermCriteria (too many args)");
+ //post("type=0x%08x max_iter=%d epsilon=%f",tc.type,tc.max_iter,tc.epsilon);
+ return tc;
+}
+
+void set_atom (t_atom *a, CvTermCriteria &tc) {
+ t_binbuf *b = binbuf_new();
+ if (tc.type & CV_TERMCRIT_ITER) binbuf_addv(b,"f",tc.max_iter); else binbuf_addv(b,"s",gensym("nil"));
+ if (tc.type & CV_TERMCRIT_EPS ) binbuf_addv(b,"f",tc.epsilon ); else binbuf_addv(b,"s",gensym("nil"));
+ SETLIST(a,b);
+}
+
+CvArr *cvGrid(PtrGrid g, CvMode mode, int reqdims=-1) {
+ P<Dim> d = g->dim;
+ int channels=1;
+ int dims=g->dim->n;
+ //post("mode=%d",(int)mode);
+ if (mode==cv_mode_channels && g->dim->n==0) RAISE("CV: channels dimension required for 'mode channels'");
+ if ((mode==cv_mode_auto && g->dim->n>=3) || mode==cv_mode_channels) channels=g->dim->v[--dims];
+ if (channels>64) RAISE("CV: too many channels. max 64, got %d",channels);
+ //post("channels=%d dims=%d nt=%d",channels,dims,g->nt);
+ //post("bits=%d",number_type_table[g->nt].size);
+ //if (dims==2) return cvMat(g->dim->v[0],g->dim->v[1],cv_eltype(g->nt),g->data);
+ if (reqdims>=0 && reqdims!=dims) RAISE("CV: wrong number of dimensions. expected %d, got %d", reqdims, dims);
+ if (dims==2) {
+ CvMat *a = cvCreateMatHeader(g->dim->v[0],g->dim->v[1],CV_MAKETYPE(cv_eltype(g->nt),channels));
+ cvSetData(a,g->data,g->dim->prod(1)*(number_type_table[g->nt].size/8));
+ return a;
+ }
+ if (dims==1) {
+ CvMat *a = cvCreateMatHeader(g->dim->v[0], 1,CV_MAKETYPE(cv_eltype(g->nt),channels));
+ cvSetData(a,g->data,g->dim->prod(1)*(number_type_table[g->nt].size/8));
+ return a;
+ }
+ RAISE("unsupported number of dimensions (got %d)",g->dim->n);
+ //return 0;
+}
+
+IplImage *cvImageGrid(PtrGrid g /*, CvMode mode */) {
+ P<Dim> d = g->dim;
+ if (d->n!=3) RAISE("expected 3 dimensions, got %s",d->to_s());
+ int channels=g->dim->v[2];
+ if (channels>64) RAISE("too many channels. max 64, got %d",channels);
+ CvSize size = {d->v[1],d->v[0]};
+ IplImage *a = cvCreateImageHeader(size,ipl_eltype(g->nt),channels);
+ cvSetData(a,g->data,g->dim->prod(1)*(number_type_table[g->nt].size/8));
+ return a;
+}
+
+void cvMatSend(const CvMat *self, FObject *obj, int outno, Dim *dim=0) {
+ int m = self->rows;
+ int n = self->cols;
+ int e = CV_MAT_TYPE(cvGetElemType(self));
+ int c = CV_MAT_CN( cvGetElemType(self));
+ GridOutlet *out = new GridOutlet(obj,0,dim?dim:new Dim(m,n));
+ for (int i=0; i<m; i++) {
+ uchar *meuh = cvPtr2D(self,i,0,0);
+ switch (e) {
+ case CV_8U: out->send(c*n, (uint8 *)meuh); break;
+ case CV_16S: out->send(c*n, (int16 *)meuh); break;
+ case CV_32S: out->send(c*n, (int32 *)meuh); break;
+ case CV_32F: out->send(c*n,(float32 *)meuh); break;
+ case CV_64F: out->send(c*n,(float64 *)meuh); break;
+ }
+ }
+}
+
+void set_atom (t_atom *a, CvPoint &v) {
+ t_binbuf *b = binbuf_new();
+ binbuf_addv(b,"ii",v.y,v.x);
+ SETLIST(a,b);
+}
+void set_atom (t_atom *a, CvSize &v) {
+ t_binbuf *b = binbuf_new();
+ binbuf_addv(b,"ii",v.height,v.width);
+ SETLIST(a,b);
+}
+void set_atom (t_atom *a, CvScalar &scal) {
+ t_binbuf *b = binbuf_new();
+ binbuf_addv(b,"ffff",scal.val[0],scal.val[1],scal.val[2],scal.val[3]);
+ SETLIST(a,b);
+}
+CvPoint convert (const t_atom &a, CvPoint *) {USELIST; return cvPoint( GETI(0),GETI(1));}
+CvSize convert (const t_atom &a, CvSize *) {USELIST; return cvSize( GETI(0),GETI(1));}
+CvScalar convert (const t_atom &a, CvScalar *) {USELIST; return cvScalar(GETF(0),GETF(1),GETF(2),GETF(3));}
+
+/* ******************************** CLASSES ******************************** */
+
+\class CvOp1 : FObject {
+ \attr CvMode mode;
+ \constructor (...) {mode = cv_mode_auto;}
+ /* has no default \grin 0 handler so far. */
+};
+\end class {}
+
+// from flow_objects.c
+static void snap_backstore (PtrGrid &r) {if (r.next) {r=r.next.p; r.next=0;}}
+
+\class CvOp2 : CvOp1 {
+ PtrGrid r;
+ \constructor (Grid *r=0) {this->r = r?r:new Grid(new Dim(),int32_e,true);}
+ virtual void func(CvArr *l, CvArr *r, CvArr *o) {/* rien */}
+ \grin 0
+ \grin 1
+};
+GRID_INLET(0) {
+ snap_backstore(r);
+ SAME_TYPE(in,r);
+ if (!in->dim->equal(r->dim)) RAISE("dimension mismatch: left:%s right:%s",in->dim->to_s(),r->dim->to_s());
+ in->set_chunk(0);
+} GRID_FLOW {
+ PtrGrid l = new Grid(in->dim,(T *)data);
+ PtrGrid o = new Grid(in->dim,in->nt);
+ CvArr *a = cvGrid(l,mode);
+ CvArr *b = cvGrid(r,mode);
+ CvArr *c = cvGrid(o,mode);
+ func(a,b,c);
+ cvRelease(&a);
+ cvRelease(&b);
+ cvRelease(&c);
+ out = new GridOutlet(this,0,in->dim,in->nt);
+ out->send(o->dim->prod(),(T *)o->data);
+} GRID_END
+GRID_INPUT2(1,r) {} GRID_END
+\end class {}
+
+#define FUNC(CLASS) CLASS(BFObject *bself, MESSAGE):CvOp2(bself,MESSAGE2) {} virtual void func(CvArr *l, CvArr *r, CvArr *o)
+#define HELP class_sethelpsymbol(fclass->bfclass,gensym("cv/#numop"));
+
+\class CvAdd : CvOp2 {FUNC(CvAdd) {cvAdd(l,r,o,0);}};
+\end class {install("cv/#Add",2,1); HELP}
+\class CvSub : CvOp2 {FUNC(CvSub) {cvSub(l,r,o,0);}};
+\end class {install("cv/#Sub",2,1); HELP}
+\class CvMul : CvOp2 {FUNC(CvMul) {cvMul(l,r,o,1);}};
+\end class {install("cv/#Mul",2,1); HELP}
+\class CvDiv : CvOp2 {FUNC(CvDiv) {cvDiv(l,r,o,1);}};
+\end class {install("cv/#Div",2,1); HELP}
+\class CvAnd : CvOp2 {FUNC(CvAnd) {cvAnd(l,r,o,0);}};
+\end class {install("cv/#And",2,1); HELP}
+\class CvOr : CvOp2 {FUNC(CvOr ) {cvOr( l,r,o,0);}};
+\end class {install("cv/#Or" ,2,1); HELP}
+\class CvXor : CvOp2 {FUNC(CvXor) {cvXor(l,r,o,0);}};
+\end class {install("cv/#Xor",2,1); HELP}
+
+\class CvInvert : CvOp1 {
+ \constructor () {}
+ \grin 0
+};
+GRID_INLET(0) {
+ if (in->dim->n!=2) RAISE("should have 2 dimensions");
+ if (in->dim->v[0] != in->dim->v[1]) RAISE("matrix should be square");
+ in->set_chunk(0);
+} GRID_FLOW {
+ //post("l=%p, r=%p", &*l, &*r);
+ PtrGrid l = new Grid(in->dim,(T *)data);
+ PtrGrid o = new Grid(in->dim,in->nt);
+ CvArr *a = cvGrid(l,mode);
+ CvArr *c = cvGrid(o,mode);
+ //post("a=%p, b=%p", a, b);
+ cvInvert(a,c);
+ cvRelease(&a);
+ cvRelease(&c);
+ out = new GridOutlet(this,0,in->dim,in->nt);
+ out->send(o->dim->prod(),(T *)o->data);
+} GRID_END
+\end class {install("cv/#Invert",1,1);}
+
+\class CvSVD : CvOp1 {
+ \grin 0
+ \constructor () {}
+};
+GRID_INLET(0) {
+ if (in->dim->n!=2) RAISE("should have 2 dimensions");
+ if (in->dim->v[0] != in->dim->v[1]) RAISE("matrix should be square");
+ in->set_chunk(0);
+} GRID_FLOW {
+ PtrGrid l = new Grid(in->dim,(T *)data);
+ PtrGrid o0 = new Grid(in->dim,in->nt);
+ PtrGrid o1 = new Grid(in->dim,in->nt);
+ PtrGrid o2 = new Grid(in->dim,in->nt);
+ CvArr *a = cvGrid(l,mode);
+ CvArr *c0 = cvGrid(o0,mode);
+ CvArr *c1 = cvGrid(o1,mode);
+ CvArr *c2 = cvGrid(o2,mode);
+ cvSVD(a,c0,c1,c2);
+ cvRelease(&a);
+ cvRelease(&c0);
+ cvRelease(&c1);
+ cvRelease(&c2);
+ out = new GridOutlet(this,2,in->dim,in->nt); out->send(o2->dim->prod(),(T *)o2->data);
+ out = new GridOutlet(this,1,in->dim,in->nt); out->send(o1->dim->prod(),(T *)o1->data);
+ out = new GridOutlet(this,0,in->dim,in->nt); out->send(o0->dim->prod(),(T *)o0->data);
+} GRID_END
+\end class {install("cv/#SVD",1,3);}
+
+\class CvEllipse : FObject {
+ \grin 0
+ \attr CvPoint center;
+ \attr CvSize axes;
+ \attr double angle;
+ \attr double start_angle;
+ \attr double end_angle;
+ \attr CvScalar color;
+ \attr int thickness;
+ \attr int line_type;
+ \attr int shift;
+ \constructor () {
+ center=cvPoint(0,0); axes=cvSize(0,0); angle=0; start_angle=0; end_angle=360; color=cvScalar(0);
+ thickness=1; line_type=8; shift=0;
+ }
+};
+GRID_INLET(0) {
+ in->set_chunk(0);
+} GRID_FLOW {
+ PtrGrid l = new Grid(in->dim,in->nt); COPY((T *)*l,data,in->dim->prod());
+ IplImage *img = cvImageGrid(l);
+ cvEllipse(img,center,axes,angle,start_angle,end_angle,color,thickness,line_type,shift);
+ cvReleaseImageHeader(&img);
+ out = new GridOutlet(this,0,in->dim,in->nt); out->send(in->dim->prod(),(T *)*l);
+} GRID_END
+\end class {install("cv/#Ellipse",1,2);}
+
+\class CvApproxPoly : CvOp1 {
+ \grin 0
+ \attr int accuracy;
+ \attr bool closed;
+ CvMemStorage* storage;
+ \constructor () {closed=true; storage = cvCreateMemStorage(0);}
+ ~CvApproxPoly () {cvReleaseMemStorage(&storage);}
+};
+GRID_INLET(0) {
+ in->set_chunk(0);
+} GRID_FLOW {
+ PtrGrid l = new Grid(in->dim,(T *)data); CvArr *a = cvGrid(l,mode);
+ CvSeq *seq = cvApproxPoly(a,sizeof(CvMat),storage,CV_POLY_APPROX_DP,accuracy,closed);
+ seq=seq; //blah
+} GRID_END
+\end class {install("cv/#ApproxPoly",1,1);}
+
+\class CvCalcOpticalFlowHS : CvOp1 {
+ \grin 0
+ \attr double lambda;
+ //\attr CvTermCriteria criteria;
+ \constructor () {}
+};
+GRID_INLET(0) {
+ in->set_chunk(0);
+} GRID_FLOW {
+// cvCalcOpticalFlowHS(prev,curr,use_previous, CvArr* velx, CvArr* vely, lambda, CvTermCriteria criteria );
+} GRID_END
+\end class {install("cv/#CalcOpticalFlowHS",1,1);}
+\class CvCalcOpticalFlowLK : CvOp1 {
+ \grin 0
+ \constructor () {}
+};
+GRID_INLET(0) {
+ in->set_chunk(0);
+} GRID_FLOW {
+} GRID_END
+\end class {install("cv/#CalcOpticalFlowLK",1,1);}
+\class CvCalcOpticalFlowBM : CvOp1 {
+ \grin 0
+ \constructor () {}
+};
+GRID_INLET(0) {
+ in->set_chunk(0);
+} GRID_FLOW {
+} GRID_END
+\end class {install("cv/#CalcOpticalFlowBM",1,1);}
+\class CvCalcOpticalFlowPyrLK : CvOp1 {
+ \grin 0
+ \constructor () {}
+};
+GRID_INLET(0) {
+ in->set_chunk(0);
+} GRID_FLOW {
+} GRID_END
+\end class {install("cv/#CalcOpticalFlowPyrLK",1,1);}
+
+/*
+void cvCalcOpticalFlowLK(const CvArr* prev, const CvArr* curr, CvSize win_size, CvArr* velx, CvArr* vely);
+void cvCalcOpticalFlowBM(const CvArr* prev, const CvArr* curr, CvSize block_size, CvSize shift_size, CvSize max_range, int use_previous,
+ CvArr* velx, CvArr* vely);
+void cvCalcOpticalFlowPyrLK(const CvArr* prev, const CvArr* curr, CvArr* prev_pyr, CvArr* curr_pyr,
+ const CvPoint2D32f* prev_features, CvPoint2D32f* curr_features,
+ int count, CvSize win_size, int level, char* status,
+ float* track_error, CvTermCriteria criteria, int flags );
+void cvCalcBackProject( IplImage** image, CvArr* back_project, const CvHistogram* hist );
+void cvCalcHist( IplImage** image, CvHistogram* hist, int accumulate=0, const CvArr* mask=NULL );
+CvHistogram* cvCreateHist( int dims, int* sizes, int type, float** ranges=NULL, int uniform=1 );
+void cvSnakeImage( const IplImage* image, CvPoint* points, int length, float* alpha, float* beta, float* gamma, int coeff_usage,
+ CvSize win, CvTermCriteria criteria, int calc_gradient=1 );
+int cvMeanShift( const CvArr* prob_image, CvRect window, CvTermCriteria criteria, CvConnectedComp* comp );
+int cvCamShift( const CvArr* prob_image, CvRect window, CvTermCriteria criteria, CvConnectedComp* comp, CvBox2D* box=NULL );
+*/
+
+/* ******************************** UNFINISHED ******************************** */
+
+\class CvSplit : CvOp1 {
+ int channels;
+ \constructor (int channels) {
+ if (channels<0 || channels>64) RAISE("channels=%d is not in 1..64",channels);
+ this->channels = channels;
+ bself->noutlets_set(channels);
+ }
+};
+\end class {}
+
+\class CvHaarDetectObjects : FObject {
+ \attr double scale_factor; /*=1.1*/
+ \attr int min_neighbors; /*=3*/
+ \attr int flags; /*=0*/
+ \constructor () {
+ scale_factor=1.1;
+ min_neighbors=3;
+ flags=0;
+ //cascade = cvLoadHaarClassifierCascade("<default_face_cascade>",cvSize(24,24));
+ const char *filename = OPENCV_SHARE_PATH "/haarcascades/haarcascade_frontalface_alt2.xml";
+ FILE *f = fopen(filename,"r");
+ if (!f) RAISE("error opening %s: %s",filename,strerror(errno));
+ fclose(f);
+ cascade = (CvHaarClassifierCascade *)cvLoad(filename,0,0,0);
+ int s = cvGetErrStatus();
+ post("cascade=%p, cvGetErrStatus=%d cvErrorStr=%s",cascade,s,cvErrorStr(s));
+ //cascade = cvLoadHaarClassifierCascade(OPENCV_SHARE_PATH "/data/haarcascades/haarcascade_frontalface_alt2.xml",cvSize(24,24));
+ storage = cvCreateMemStorage(0);
+ }
+ CvHaarClassifierCascade *cascade;
+ CvMemStorage *storage;
+ \grin 0
+};
+GRID_INLET(0) {
+ in->set_chunk(0);
+} GRID_FLOW {
+ PtrGrid l = new Grid(in->dim,(T *)data);
+ IplImage *img = cvImageGrid(l);
+ CvSeq *ret = cvHaarDetectObjects(img,cascade,storage,scale_factor,min_neighbors,flags);
+ int n = ret ? ret->total : 0;
+ out = new GridOutlet(this,0,new Dim(n,2,2));
+ for (int i=0; i<n; i++) {
+ CvRect *r = (CvRect *)cvGetSeqElem(ret,i);
+ int32 duh[] = {r->y,r->x,r->y+r->height,r->x+r->width};
+ out->send(4,duh);
+ }
+} GRID_END
+\end class {install("cv/#HaarDetectObjects",2,1);}
+
+/* **************************************************************** */
+
+\class CvKMeans : CvOp1 {
+ \attr int numClusters;
+ \attr CvTermCriteria termcrit;
+ \grin 0 float32
+ \decl 1 float (int v);
+ \constructor (int v) {
+ _1_float(0,0,v);
+ termcrit = CvTermCriteria();
+ }
+};
+
+\def 1 float (int v) {numClusters = v;}
+
+//post("typeof(a)=%p typeof(c)=%p typeof(CvMat)=%p",cvTypeOf(a),cvTypeOf(c),cvFindType("opencv-matrix"));
+//for (CvTypeInfo *t = cvFirstType(); t; t=t->next) post("type %s",t->type_name);
+
+GRID_INLET(0) {
+ if (in->dim->n<1) RAISE("should have at least 1 dimension");
+ in->set_chunk(0);
+} GRID_FLOW {
+ int32 v[] = {in->dim->prod(0)/in->dim->prod(-1),in->dim->prod(-1)};
+ PtrGrid l = new Grid(new Dim(2,v),(T *)data);
+ CvArr *a = (CvMat *)cvGrid(l,mode,2);
+ PtrGrid o = new Grid(new Dim(1,v),int32_e);
+ CvArr *c = (CvMat *)cvGrid(o,mode);
+ cvKMeans2(a,numClusters,c,termcrit);
+ int w[in->dim->n];
+ COPY(w,in->dim->v,in->dim->n);
+ w[in->dim->n-1] = 1;
+ P<Dim> d = new Dim(in->dim->n,w);
+ out = new GridOutlet(this,0,d);
+ out->send(v[0],(int32 *)*o);
+ cvRelease(&a);
+ cvRelease(&c);
+} GRID_END
+
+\end class {install("cv/#KMeans",2,1);}
+
+\class CvCornerHarris : CvOp1 {
+ \attr int block_size;
+ \attr int aperture_size;
+ \attr double k;
+ \constructor () {
+ block_size = 3;
+ aperture_size = 3;
+ k = 0.04;
+ }
+ \grin 0
+};
+
+GRID_INLET(0) {
+ in->set_chunk(0);
+} GRID_FLOW {
+ PtrGrid l = new Grid(in->dim,(T *)data);
+ CvArr *a = (CvMat *)cvGrid(l,mode,2);
+ PtrGrid o = new Grid(in->dim,float32_e);
+ CvArr *c = (CvMat *)cvGrid(o,mode);
+ cvCornerHarris(a,c,block_size,aperture_size,k);
+ cvRelease(&a);
+ cvRelease(&c);
+ out = new GridOutlet(this,0,in->dim,in->nt); out->send(o->dim->prod(),(T *)o->data);
+} GRID_END
+
+\end class {install("cv/#CornerHarris",1,1);}
+
+/* **************************************************************** */
+
+static int erreur_handleur (int status, const char* func_name, const char* err_msg, const char* file_name, int line, void *userdata) {
+ cvSetErrStatus(CV_StsOk);
+ // we might be looking for trouble because we don't know whether OpenCV is throw-proof.
+ RAISE("OpenCV error: status='%s' func_name=%s err_msg=\"%s\" file_name=%s line=%d",cvErrorStr(status),func_name,err_msg,file_name,line);
+ // if this breaks OpenCV, then we will have to use post() or a custom hybrid of post() and RAISE() that does not cause a
+ // longjmp when any OpenCV functions are on the stack.
+ return 0;
+}
+
+void startup_opencv() {
+ /* CvErrorCallback z = */ cvRedirectError(erreur_handleur);
+ \startall
+}
diff --git a/externals/gridflow/src/png.cxx b/externals/gridflow/src/png.cxx
new file mode 100644
index 00000000..d61361c5
--- /dev/null
+++ b/externals/gridflow/src/png.cxx
@@ -0,0 +1,143 @@
+/*
+ $Id: png.c 4620 2009-11-01 21:16:58Z matju $
+
+ GridFlow
+ Copyright (c) 2001-2009 by Mathieu Bouchard
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ See file ../COPYING for further informations on licensing terms.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+/* !@#$ not handling abort on compress */
+/* !@#$ not handling abort on decompress */
+
+#include "gridflow.hxx.fcs"
+extern "C" {
+#include <libpng12/png.h>
+};
+
+\class FormatPNG : Format {
+ P<BitPacking> bit_packing;
+ png_structp png;
+ png_infop info;
+ \constructor (t_symbol *mode, string filename) {
+ Format::_0_open(0,0,mode,filename);
+ uint32 mask[3] = {0x0000ff,0x00ff00,0xff0000};
+ bit_packing = new BitPacking(is_le(),3,3,mask);
+ }
+ \decl 0 bang ();
+ \grin 0 int
+};
+
+GRID_INLET(0) {
+ if (in->dim->n!=3) RAISE("expecting 3 dimensions: rows,columns,channels");
+ int c = in->dim->get(2);
+ if (c!=3) RAISE("expecting 3 channels (got %d)",in->dim->get(2));
+ in->set_chunk(0);
+} GRID_FLOW {
+ png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ if (!png) RAISE("!png");
+ info = png_create_info_struct(png);
+ if (!info) {if (png) png_destroy_write_struct(&png, NULL); RAISE("!info");}
+ if (setjmp(png_jmpbuf(png))) {png_destroy_write_struct(&png, &info); RAISE("png write error");}
+ if (setjmp(png->jmpbuf)) {png_write_destroy(png); free(png); free(info); RAISE("png write error");}
+ png_init_io(png, f);
+ info->width = in->dim->get(1);
+ info->height = in->dim->get(0);
+ info->bit_depth = 8;
+// info->color_type = channels==3 ? PNG_COLOR_TYPE_RGB : PNG_COLOR_TYPE_GRAY;
+ info->color_type = PNG_COLOR_TYPE_RGB;
+// info->color_type |= PNG_COLOR_MASK_ALPHA;
+ info->interlace_type = 1;
+ png_write_info(png,info);
+ png_set_packing(png);
+// this would have been the GRID_FLOW section
+ int rowsize = in->dim->get(1)*in->dim->get(2);
+ int rowsize2 = in->dim->get(1)*3;
+ uint8 row[rowsize2];
+ while (n) {
+ post("n=%ld",long(n));
+ bit_packing->pack(in->dim->get(1),data,row);
+ png_write_row(png,row);
+ n-=rowsize; data+=rowsize;
+ }
+// this would have been the GRID_FINISH section
+ post("GRID FINISH 1");
+ png_write_end(png,info);
+ post("GRID FINISH 2");
+ png_write_destroy(png);
+ post("GRID FINISH 3");
+ fflush(f);
+ free(png);
+ free(info);
+ fclose(f);
+} GRID_FINISH {
+} GRID_END
+
+\def 0 bang () {
+ uint8 sig[8];
+ if (!fread(sig, 1, 8, f)) {outlet_bang(bself->te_outlet); return;}
+ if (!png_check_sig(sig, 8)) RAISE("bad signature");
+ png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ if (!png) RAISE("!png");
+ info = png_create_info_struct(png);
+ if (!info) {png_destroy_read_struct(&png, NULL, NULL); RAISE("!info");}
+ if (setjmp(png_jmpbuf(png))) {png_destroy_read_struct(&png, &info, NULL); RAISE("png read error");}
+ png_init_io(png, f);
+ png_set_sig_bytes(png, 8); // we already read the 8 signature bytes
+ png_read_info(png, info); // read all PNG info up to image data
+ png_uint_32 width, height;
+ int bit_depth, color_type;
+ png_get_IHDR(png, info, &width, &height, &bit_depth, &color_type, 0,0,0);
+
+ png_bytepp row_pointers = 0;
+ if (color_type == PNG_COLOR_TYPE_PALETTE
+ || (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
+ || png_get_valid(png, info, PNG_INFO_tRNS))
+ png_set_expand(png);
+ // 16bpp y, 32bpp ya, 48bpp rgb, 64bpp rgba...
+ if (bit_depth == 16) png_set_strip_16(png);
+
+ double display_gamma = 2.2;
+ double gamma;
+ if (png_get_gAMA(png, info, &gamma))
+ png_set_gamma(png, display_gamma, gamma);
+ png_read_update_info(png, info);
+
+ int rowbytes = png_get_rowbytes(png, info);
+ int channels = (int)png_get_channels(png, info);
+ uint8 *image_data = new uint8[rowbytes*height];
+ row_pointers = new png_bytep[height];
+ //gfpost("png: color_type=%d channels=%d, width=%d, rowbytes=%ld, height=%ld, gamma=%f",
+ // color_type, channels, width, rowbytes, height, gamma);
+ for (int i=0; i<(int)height; i++) row_pointers[i] = image_data + i*rowbytes;
+ if ((uint32)rowbytes != width*channels)
+ RAISE("rowbytes mismatch: %d is not %d*%d=%d", rowbytes, width, channels, width*channels);
+ png_read_image(png, row_pointers);
+ delete[] row_pointers;
+ row_pointers = 0;
+ png_read_end(png, 0);
+ GridOutlet out(this,0,new Dim(height, width, channels), cast);
+ out.send(rowbytes*height,image_data);
+ delete[] image_data;
+ png_destroy_read_struct(&png, &info, NULL);
+}
+
+\classinfo {install_format("#io.png",4,"png");}
+\end class FormatPNG
+void startup_png () {
+ \startall
+}
diff --git a/externals/gridflow/src/pwc-ioctl.h b/externals/gridflow/src/pwc-ioctl.h
new file mode 100644
index 00000000..65805eaa
--- /dev/null
+++ b/externals/gridflow/src/pwc-ioctl.h
@@ -0,0 +1,292 @@
+#ifndef PWC_IOCTL_H
+#define PWC_IOCTL_H
+
+/* (C) 2001-2004 Nemosoft Unv.
+ (C) 2004 Luc Saillard (luc@saillard.org)
+
+ NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+ driver and thus may have bugs that are not present in the original version.
+ Please send bug reports and support requests to <luc@saillard.org>.
+ The decompression routines have been implemented by reverse-engineering the
+ Nemosoft binary pwcx module. Caveat emptor.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+/* This is pwc-ioctl.h belonging to PWC 8.12.1
+ It contains structures and defines to communicate from user space
+ directly to the driver.
+ */
+
+/*
+ Changes
+ 2001/08/03 Alvarado Added ioctl constants to access methods for
+ changing white balance and red/blue gains
+ 2002/12/15 G. H. Fernandez-Toribio VIDIOCGREALSIZE
+ 2003/12/13 Nemosft Unv. Some modifications to make interfacing to
+ PWCX easier
+ */
+
+/* These are private ioctl() commands, specific for the Philips webcams.
+ They contain functions not found in other webcams, and settings not
+ specified in the Video4Linux API.
+
+ The #define names are built up like follows:
+ VIDIOC VIDeo IOCtl prefix
+ PWC Philps WebCam
+ G optional: Get
+ S optional: Set
+ ... the function
+ */
+
+
+ /* Enumeration of image sizes */
+#define PSZ_SQCIF 0x00
+#define PSZ_QSIF 0x01
+#define PSZ_QCIF 0x02
+#define PSZ_SIF 0x03
+#define PSZ_CIF 0x04
+#define PSZ_VGA 0x05
+#define PSZ_MAX 6
+
+
+/* The frame rate is encoded in the video_window.flags parameter using
+ the upper 16 bits, since some flags are defined nowadays. The following
+ defines provide a mask and shift to filter out this value.
+
+ In 'Snapshot' mode the camera freezes its automatic exposure and colour
+ balance controls.
+ */
+#define PWC_FPS_SHIFT 16
+#define PWC_FPS_MASK 0x00FF0000
+#define PWC_FPS_FRMASK 0x003F0000
+#define PWC_FPS_SNAPSHOT 0x00400000
+
+
+/* structure for transfering x & y coordinates */
+struct pwc_coord
+{
+ int x, y; /* guess what */
+ int size; /* size, or offset */
+};
+
+
+/* Used with VIDIOCPWCPROBE */
+struct pwc_probe
+{
+ char name[32];
+ int type;
+};
+
+struct pwc_serial
+{
+ char serial[30]; /* String with serial number. Contains terminating 0 */
+};
+
+/* pwc_whitebalance.mode values */
+#define PWC_WB_INDOOR 0
+#define PWC_WB_OUTDOOR 1
+#define PWC_WB_FL 2
+#define PWC_WB_MANUAL 3
+#define PWC_WB_AUTO 4
+
+/* Used with VIDIOCPWC[SG]AWB (Auto White Balance).
+ Set mode to one of the PWC_WB_* values above.
+ *red and *blue are the respective gains of these colour components inside
+ the camera; range 0..65535
+ When 'mode' == PWC_WB_MANUAL, 'manual_red' and 'manual_blue' are set or read;
+ otherwise undefined.
+ 'read_red' and 'read_blue' are read-only.
+*/
+struct pwc_whitebalance
+{
+ int mode;
+ int manual_red, manual_blue; /* R/W */
+ int read_red, read_blue; /* R/O */
+};
+
+/*
+ 'control_speed' and 'control_delay' are used in automatic whitebalance mode,
+ and tell the camera how fast it should react to changes in lighting, and
+ with how much delay. Valid values are 0..65535.
+*/
+struct pwc_wb_speed
+{
+ int control_speed;
+ int control_delay;
+
+};
+
+/* Used with VIDIOCPWC[SG]LED */
+struct pwc_leds
+{
+ int led_on; /* Led on-time; range = 0..25000 */
+ int led_off; /* Led off-time; range = 0..25000 */
+};
+
+/* Image size (used with GREALSIZE) */
+struct pwc_imagesize
+{
+ int width;
+ int height;
+};
+
+/* Defines and structures for Motorized Pan & Tilt */
+#define PWC_MPT_PAN 0x01
+#define PWC_MPT_TILT 0x02
+#define PWC_MPT_TIMEOUT 0x04 /* for status */
+
+/* Set angles; when absolute != 0, the angle is absolute and the
+ driver calculates the relative offset for you. This can only
+ be used with VIDIOCPWCSANGLE; VIDIOCPWCGANGLE always returns
+ absolute angles.
+ */
+struct pwc_mpt_angles
+{
+ int absolute; /* write-only */
+ int pan; /* degrees * 100 */
+ int tilt; /* degress * 100 */
+};
+
+/* Range of angles of the camera, both horizontally and vertically.
+ */
+struct pwc_mpt_range
+{
+ int pan_min, pan_max; /* degrees * 100 */
+ int tilt_min, tilt_max;
+};
+
+struct pwc_mpt_status
+{
+ int status;
+ int time_pan;
+ int time_tilt;
+};
+
+
+/* This is used for out-of-kernel decompression. With it, you can get
+ all the necessary information to initialize and use the decompressor
+ routines in standalone applications.
+ */
+struct pwc_video_command
+{
+ int type; /* camera type (645, 675, 730, etc.) */
+ int release; /* release number */
+
+ int size; /* one of PSZ_* */
+ int alternate;
+ int command_len; /* length of USB video command */
+ unsigned char command_buf[13]; /* Actual USB video command */
+ int bandlength; /* >0 = compressed */
+ int frame_size; /* Size of one (un)compressed frame */
+};
+
+/* Flags for PWCX subroutines. Not all modules honour all flags. */
+#define PWCX_FLAG_PLANAR 0x0001
+#define PWCX_FLAG_BAYER 0x0008
+
+
+/* IOCTL definitions */
+
+ /* Restore user settings */
+#define VIDIOCPWCRUSER _IO('v', 192)
+ /* Save user settings */
+#define VIDIOCPWCSUSER _IO('v', 193)
+ /* Restore factory settings */
+#define VIDIOCPWCFACTORY _IO('v', 194)
+
+ /* You can manipulate the compression factor. A compression preference of 0
+ means use uncompressed modes when available; 1 is low compression, 2 is
+ medium and 3 is high compression preferred. Of course, the higher the
+ compression, the lower the bandwidth used but more chance of artefacts
+ in the image. The driver automatically chooses a higher compression when
+ the preferred mode is not available.
+ */
+ /* Set preferred compression quality (0 = uncompressed, 3 = highest compression) */
+#define VIDIOCPWCSCQUAL _IOW('v', 195, int)
+ /* Get preferred compression quality */
+#define VIDIOCPWCGCQUAL _IOR('v', 195, int)
+
+
+/* Retrieve serial number of camera */
+#define VIDIOCPWCGSERIAL _IOR('v', 198, struct pwc_serial)
+
+ /* This is a probe function; since so many devices are supported, it
+ becomes difficult to include all the names in programs that want to
+ check for the enhanced Philips stuff. So in stead, try this PROBE;
+ it returns a structure with the original name, and the corresponding
+ Philips type.
+ To use, fill the structure with zeroes, call PROBE and if that succeeds,
+ compare the name with that returned from VIDIOCGCAP; they should be the
+ same. If so, you can be assured it is a Philips (OEM) cam and the type
+ is valid.
+ */
+#define VIDIOCPWCPROBE _IOR('v', 199, struct pwc_probe)
+
+ /* Set AGC (Automatic Gain Control); int < 0 = auto, 0..65535 = fixed */
+#define VIDIOCPWCSAGC _IOW('v', 200, int)
+ /* Get AGC; int < 0 = auto; >= 0 = fixed, range 0..65535 */
+#define VIDIOCPWCGAGC _IOR('v', 200, int)
+ /* Set shutter speed; int < 0 = auto; >= 0 = fixed, range 0..65535 */
+#define VIDIOCPWCSSHUTTER _IOW('v', 201, int)
+
+ /* Color compensation (Auto White Balance) */
+#define VIDIOCPWCSAWB _IOW('v', 202, struct pwc_whitebalance)
+#define VIDIOCPWCGAWB _IOR('v', 202, struct pwc_whitebalance)
+
+ /* Auto WB speed */
+#define VIDIOCPWCSAWBSPEED _IOW('v', 203, struct pwc_wb_speed)
+#define VIDIOCPWCGAWBSPEED _IOR('v', 203, struct pwc_wb_speed)
+
+ /* LEDs on/off/blink; int range 0..65535 */
+#define VIDIOCPWCSLED _IOW('v', 205, struct pwc_leds)
+#define VIDIOCPWCGLED _IOR('v', 205, struct pwc_leds)
+
+ /* Contour (sharpness); int < 0 = auto, 0..65536 = fixed */
+#define VIDIOCPWCSCONTOUR _IOW('v', 206, int)
+#define VIDIOCPWCGCONTOUR _IOR('v', 206, int)
+
+ /* Backlight compensation; 0 = off, otherwise on */
+#define VIDIOCPWCSBACKLIGHT _IOW('v', 207, int)
+#define VIDIOCPWCGBACKLIGHT _IOR('v', 207, int)
+
+ /* Flickerless mode; = 0 off, otherwise on */
+#define VIDIOCPWCSFLICKER _IOW('v', 208, int)
+#define VIDIOCPWCGFLICKER _IOR('v', 208, int)
+
+ /* Dynamic noise reduction; 0 off, 3 = high noise reduction */
+#define VIDIOCPWCSDYNNOISE _IOW('v', 209, int)
+#define VIDIOCPWCGDYNNOISE _IOR('v', 209, int)
+
+ /* Real image size as used by the camera; tells you whether or not there's a gray border around the image */
+#define VIDIOCPWCGREALSIZE _IOR('v', 210, struct pwc_imagesize)
+
+ /* Motorized pan & tilt functions */
+#define VIDIOCPWCMPTRESET _IOW('v', 211, int)
+#define VIDIOCPWCMPTGRANGE _IOR('v', 211, struct pwc_mpt_range)
+#define VIDIOCPWCMPTSANGLE _IOW('v', 212, struct pwc_mpt_angles)
+#define VIDIOCPWCMPTGANGLE _IOR('v', 212, struct pwc_mpt_angles)
+#define VIDIOCPWCMPTSTATUS _IOR('v', 213, struct pwc_mpt_status)
+
+ /* Get the USB set-video command; needed for initializing libpwcx */
+#define VIDIOCPWCGVIDCMD _IOR('v', 215, struct pwc_video_command)
+struct pwc_table_init_buffer {
+ int len;
+ char *buffer;
+
+};
+#define VIDIOCPWCGVIDTABLE _IOR('v', 216, struct pwc_table_init_buffer)
+
+#endif
diff --git a/externals/gridflow/src/quartz.m b/externals/gridflow/src/quartz.m
new file mode 100644
index 00000000..91bcb84d
--- /dev/null
+++ b/externals/gridflow/src/quartz.m
@@ -0,0 +1,224 @@
+/*
+ $Id: quartz.m 4517 2009-10-30 16:01:30Z matju $
+
+ GridFlow
+ Copyright (c) 2001-2008 by Mathieu Bouchard
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ See file ../COPYING for further informations on licensing terms.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+/*
+ This is written in Objective C++, which is the union of C++ and Objective C;
+ Their intersection is C or almost. They add quite different sets of features.
+ I need Objective C here because the Cocoa API is for Objective C and Java only,
+ and the Objective C one was the easiest to integrate in GridFlow.
+
+ The next best possibility may be using RubyCocoa, a port of the Cocoa API to Ruby;
+ However I haven't checked whether Quartz is wrapped, and how easy it is to
+ process images.
+*/
+
+#include <stdio.h>
+#include <objc/Object.h>
+#include <Cocoa/Cocoa.h>
+
+#include "gridflow.hxx.fcs"
+
+@interface GFView: NSView {
+ uint8 *imdata;
+ int imwidth;
+ int imheight;
+}
+- (id) drawRect: (NSRect)rect;
+- (id) imageHeight: (int)w width: (int)h;
+- (int) imageHeight;
+- (int) imageWidth;
+- (uint8 *) imageData;
+- (int) imageDataSize;
+@end
+
+@implementation GFView
+
+- (uint8 *) imageData {return imdata;}
+- (int) imageDataSize {return imwidth*imheight*4;}
+- (int) imageHeight {return imheight;}
+- (int) imageWidth {return imwidth;}
+
+- (id) imageHeight: (int)h width: (int)w {
+ if (imheight==h && imwidth==w) return self;
+ //post("new size: y=%d x=%d",h,w);
+ imheight=h;
+ imwidth=w;
+ if (imdata) delete imdata;
+ int size = [self imageDataSize];
+ imdata = new uint8[size];
+ CLEAR(imdata,size);
+ NSSize s = {w,h};
+ [[self window] setContentSize: s];
+ return self;
+}
+
+- (id) initWithFrame: (NSRect)r {
+ [super initWithFrame: r];
+ imdata=0; imwidth=-1; imheight=-1;
+ [self imageHeight: 240 width: 320];
+ return self;
+}
+
+- (id) drawRect: (NSRect)rect {
+ [super drawRect: rect];
+ if (![self lockFocusIfCanDraw]) return self;
+ CGContextRef g = (CGContextRef)
+ [[NSGraphicsContext graphicsContextWithWindow: [self window]]
+ graphicsPort];
+ CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB();
+ CGDataProviderRef dp = CGDataProviderCreateWithData(
+ NULL, imdata, imheight*imwidth*4, NULL);
+ CGImageRef image = CGImageCreate(imwidth, imheight, 8, 32, imwidth*4,
+ cs, kCGImageAlphaFirst, dp, NULL, 0, kCGRenderingIntentDefault);
+ CGDataProviderRelease(dp);
+ CGColorSpaceRelease(cs);
+ CGRect rectangle = CGRectMake(0,0,imwidth,imheight);
+ CGContextDrawImage(g,rectangle,image);
+ CGImageRelease(image);
+ [self unlockFocus];
+ return self;
+}
+@end
+
+/* workaround: bus error in gcc */
+uint8 *GFView_imageData(GFView *self) {return (uint8 *)[self imageData];}
+
+void GFView_imageHeight_width(GFView *self, int height, int width) {
+ [self imageHeight: height width: width];
+}
+
+void GFView_display(GFView *self) {
+ NSRect r = {{0,0},{[self imageHeight],[self imageWidth]}};
+ [self displayRect: r];
+ [self setNeedsDisplay: YES];
+ [self display];
+}
+
+struct FormatQuartz;
+void FormatQuartz_call(FormatQuartz *self);
+
+\class FormatQuartz : Format {
+ NSWindow *window;
+ NSWindowController *wc;
+ GFView *widget; /* GridFlow's Cocoa widget */
+ t_clock *clock;
+ \constructor (t_symbol *mode) {
+ NSRect r = {{0,0}, {320,240}};
+ window = [[NSWindow alloc]
+ initWithContentRect: r
+ styleMask: NSTitledWindowMask | NSMiniaturizableWindowMask | NSClosableWindowMask
+ backing: NSBackingStoreBuffered
+ defer: YES];
+ widget = [[GFView alloc] initWithFrame: r];
+ [window setContentView: widget];
+ [window setTitle: @"GridFlow"];
+ [window makeKeyAndOrderFront: NSApp];
+ [window orderFrontRegardless];
+ wc = [[NSWindowController alloc] initWithWindow: window];
+ clock = clock_new(this,(t_method)FormatQuartz_call);
+ [window makeFirstResponder: widget];
+ //post("mainWindow = %08lx",(long)[NSApp mainWindow]);
+ //post(" keyWindow = %08lx",(long)[NSApp keyWindow]);
+ NSColor *color = [NSColor clearColor];
+ [window setBackgroundColor: color];
+ }
+ ~FormatQuartz () {
+ clock_unset(clock);
+ clock_free(clock);
+ clock = 0;
+ [window autorelease];
+ [window setReleasedWhenClosed: YES];
+ [window close];
+ }
+ void call ();
+ \grin 0
+};
+
+static NSDate *distantFuture, *distantPast;
+
+void FormatQuartz::call() {
+ NSEvent *e = [NSApp nextEventMatchingMask: NSAnyEventMask
+ // untilDate: distantFuture // blocking
+ untilDate: distantPast // nonblocking
+ inMode: NSDefaultRunLoopMode
+ dequeue: YES];
+ if (e) {
+ NSLog(@"%@", e);
+ [NSApp sendEvent: e];
+ }
+ [NSApp updateWindows];
+ [this->window flushWindowIfNeeded];
+ clock_delay(clock,20);
+}
+void FormatQuartz_call(FormatQuartz *self) {self->call();}
+
+template <class T, class S>
+static void convert_number_type(int n, T *out, S *in) {
+ for (int i=0; i<n; i++) out[i]=(T)in[i];
+}
+
+GRID_INLET(0) {
+ if (in->dim->n!=3) RAISE("expecting 3 dims, not %d", in->dim->n);
+ int c=in->dim->get(2);
+ if (c!=3&&c!=4) RAISE("expecting 3 or 4 channels, not %d", in->dim->get(2));
+// [widget imageHeight: in->dim->get(0) width: in->dim->get(1) ];
+ GFView_imageHeight_width(widget,in->dim->get(0),in->dim->get(1));
+ in->set_chunk(1);
+} GRID_FLOW {
+ int off = dex/in->dim->prod(2);
+ int c=in->dim->get(2);
+ NSView *w = widget;
+ uint8 *data2 = GFView_imageData(w)+off*4;
+// convert_number_type(n,data2,data);
+ if (c==3) {
+ while(n) {
+ data2[0]=255;
+ data2[1]=(uint8)data[0];
+ data2[2]=(uint8)data[1];
+ data2[3]=(uint8)data[2];
+ data+=3; data2+=4; n-=3;
+ }
+ } else {
+ while(n) {
+ data2[0]=255;
+ data2[1]=(uint8)data[0];
+ data2[2]=(uint8)data[1];
+ data2[3]=(uint8)data[2];
+ data+=4; data2+=4; n-=4;
+ }
+ }
+} GRID_FINISH {
+ GFView_display(widget);
+} GRID_END
+
+\end class FormatQuartz {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ distantFuture = [NSDate distantFuture];
+ distantPast = [NSDate distantPast];
+ [NSApplication sharedApplication];
+ install_format("#io.quartz",2,"");
+}
+void startup_quartz () {
+ \startall
+}
+
diff --git a/externals/gridflow/src/quicktimeapple.cxx b/externals/gridflow/src/quicktimeapple.cxx
new file mode 100644
index 00000000..9b32b85e
--- /dev/null
+++ b/externals/gridflow/src/quicktimeapple.cxx
@@ -0,0 +1,456 @@
+/*
+ $Id: quicktimeapple.c 4620 2009-11-01 21:16:58Z matju $
+
+ GridFlow
+ Copyright (c) 2001-2009 by Mathieu Bouchard
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ See file ../COPYING for further informations on licensing terms.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include <QuickTime/QuickTime.h>
+#include <QuickTime/Movies.h>
+#include <QuickTime/QuickTimeComponents.h>
+#include "gridflow.hxx.fcs"
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <CoreServices/CoreServices.h>
+
+typedef ComponentInstance VideoDigitizerComponent, VDC;
+typedef ComponentResult VideoDigitizerError, VDE;
+
+#if 0
+//enum {VDCType='vdig', vdigInterfaceRev=2 };
+//enum {ntscIn=0, currentIn=0, palIn, secamIn, ntscReallyIn };
+//enum {compositeIn, sVideoIn, rgbComponentIn, rgbComponentSyncIn, yuvComponentIn, yuvComponentSyncIn, tvTunerIn, sdiIn};
+//enum {vdPlayThruOff, vdPlayThruOn};
+//enum {vdDigitizerBW, vdDigitizerRGB};
+//enum {vdBroadcastMode, vdVTRMode};
+//enum {vdUseAnyField, vdUseOddField, vdUseEvenField};
+//enum {vdTypeBasic, vdTypeAlpha, vdTypeMask, vdTypeKey};
+/*enum {digiInDoesNTSC, digiInDoesPAL, digiInDoesSECAM, skip 4,
+ digiInDoesGenLock, digiInDoesComposite, digiInDoesSVideo, digiInDoesComponent,
+ digiInVTR_Broadcast, digiInDoesColor, digiInDoesBW, skip 17,
+ digiInSignalLock};*/
+/*bitset {digiOutDoes1, digiOutDoes2, digiOutDoes4,
+ digiOutDoes8, digiOutDoes16, digiOutDoes32,
+ digiOutDoesDither, digiOutDoesStretch, digiOutDoesShrink,
+ digiOutDoesMask, skip 1,
+ digiOutDoesDouble, digiOutDoesQuad, digiOutDoesQuarter, digiOutDoesSixteenth,
+ digiOutDoesRotate, digiOutDoesHorizFlip, digiOutDoesVertFlip, digiOutDoesSkew,
+ digiOutDoesBlend, digiOutDoesWarp, digiOutDoesHW_DMA,
+ digiOutDoesHWPlayThru, digiOutDoesILUT, digiOutDoesKeyColor,
+ digiOutDoesAsyncGrabs, digiOutDoesUnreadableScreenBits,
+ digiOutDoesCompress, digiOutDoesCompressOnly,
+ digiOutDoesPlayThruDuringCompress, digiOutDoesCompressPartiallyVisible,
+ digiOutDoesNotNeedCopyOfCompressData};*/
+/*struct DigitizerInfo {
+ short vdigType;
+ long inputCapabilityFlags, outputCapabilityFlags;
+ long inputCurrentFlags, outputCurrentFlags;
+ short slot;
+ GDHandle gdh, maskgdh;
+ short minDestHeight, minDestWidth;
+ short maxDestHeight, maxDestWidth;
+ short blendLevels;
+ long reserved;};*/
+/*struct VdigType { long digType, reserved;};*/
+/*struct VdigTypeList { short count; VdigType list[1];};*/
+/*struct VdigBufferRec { PixMapHandle dest; Point location; long reserved;};*/
+/*struct VdigBufferRecList {
+ short count; MatrixRecordPtr matrix; RgnHandle mask; VdigBufferRec list[1];};*/
+//typedef VdigBufferRecList *VdigBufferRecListPtr;
+//typedef VdigBufferRecListPtr *VdigBufferRecListHandle;
+//typedef CALLBACK_API(void,VdigIntProcPtr)(long flags, long refcon);
+//typedef STACK_UPP_TYPE(VdigIntProcPtr);
+/*struct VDCompressionList {
+ CodecComponent codec; CodecType cType; Str63 typeName, name;
+ long formatFlags, compressFlags, reserved;};*/
+//typedef VDCompressionList * VDCompressionListPtr;
+//typedef VDCompressionListPtr *VDCompressionListHandle;
+/*bitset {
+ dmaDepth1, dmaDepth2, dmaDepth4, dmaDepth8, dmaDepth16, dmaDepth32,
+ dmaDepth2Gray, dmaDepth4Gray, dmaDepth8Gray};*/
+//enum {kVDIGControlledFrameRate=-1};
+//bitset {vdDeviceFlagShowInputsAsDevices, vdDeviceFlagHideDevice};
+/*bitset {
+ vdFlagCaptureStarting, vdFlagCaptureStopping,
+ vdFlagCaptureIsForPreview, vdFlagCaptureIsForRecord,
+ vdFlagCaptureLowLatency, vdFlagCaptureAlwaysUseTimeBase,
+ vdFlagCaptureSetSettingsBegin, vdFlagCaptureSetSettingsEnd};*/
+/*\class VDC
+VDE VDGetMaxSrcRect (short inputStd, Rect *maxSrcRect)
+VDE VDGetActiveSrcRect(short inputStd, Rect *activeSrcRect)
+VDE VD[GS]etDigitizerRect(Rect *digitizerRect)
+VDE VDGetVBlankRect(short inputStd, Rect *vBlankRect)
+VDE VDGetMaskPixMap(PixMapHandlemaskPixMap)
+VDE VDGetPlayThruDestination(PixMapHandle * dest, Rect *destRect, MatrixRecord * m, RgnHandle *mask)
+VDE VDUseThisCLUT(CTabHandle colorTableHandle)
+VDE VD[SG*]etInputGammaValue(Fixed channel1, Fixed channel2, Fixed channel3)
+VDE VD[GS]etBrightness(uint16 *)
+VDE VD[GS]etContrast(uint16 *)
+VDE VD[GS]etHue(uint16 *)
+VDE VD[GS]etSharpness(uint16 *)
+VDE VD[GS]etSaturation(uint16 *)
+VDE VDGrabOneFrame(VDC ci)
+VDE VDGetMaxAuxBuffer(PixMapHandle *pm, Rect *r)
+VDE VDGetDigitizerInfo(DigitizerInfo *info)
+VDE VDGetCurrentFlags(long *inputCurrentFlag, long *outputCurrentFlag)
+VDE VD[SG*]etKeyColor(long index)
+VDE VDAddKeyColor(long *index)
+VDE VDGetNextKeyColor(long index)
+VDE VD[GS]etKeyColorRange(RGBColor minRGB, RGBColor maxRGB)
+VDE VDSetDigitizerUserInterrupt(long flags, VdigIntUPP userInterruptProc, long refcon)
+VDE VD[SG*]etInputColorSpaceMode(short colorSpaceMode)
+VDE VD[SG*]etClipState(short clipEnable)
+VDE VDSetClipRgn(RgnHandle clipRegion)
+VDE VDClearClipRgn(RgnHandle clipRegion)
+VDE VDGetCLUTInUse(CTabHandle *colorTableHandle)
+VDE VD[SG*]etPLLFilterType(short pllType)
+VDE VDGetMaskandValue(uint16 blendLevel, long *mask, long *value)
+VDE VDSetMasterBlendLevel(uint16 *blendLevel)
+VDE VDSetPlayThruDestination(PixMapHandledest, RectPtr destRect, MatrixRecordPtr m, RgnHandle mask)
+VDE VDSetPlayThruOnOff(short state)
+VDE VD[SG*]etFieldPreference(short fieldFlag)
+VDE VDPreflightDestination(Rect *digitizerRect, PixMap **dest, RectPtr destRect, MatrixRecordPtr m)
+VDE VDPreflightGlobalRect(GrafPtr theWindow, Rect *globalRect)
+VDE VDSetPlayThruGlobalRect(GrafPtr theWindow, Rect *globalRect)
+VDE VDSetInputGammaRecord(VDGamRecPtrinputGammaPtr)
+VDE VDGetInputGammaRecord(VDGamRecPtr *inputGammaPtr)
+VDE VD[SG]etBlackLevelValue(uint16 *)
+VDE VD[SG]etWhiteLevelValue(uint16 *)
+VDE VDGetVideoDefaults(uint16 *blackLevel, uint16 *whiteLevel, uint16 *brightness, uint16 *hue, uint16 *saturation, uint16 *contrast, uint16 *sharpness)
+VDE VDGetNumberOfInputs(short *inputs)
+VDE VDGetInputFormat(short input, short *format)
+VDE VD[SG*]etInput(short input)
+VDE VDSetInputStandard(short inputStandard)
+VDE VDSetupBuffers(VdigBufferRecListHandle bufferList)
+VDE VDGrabOneFrameAsync(short buffer)
+VDE VDDone(short buffer)
+VDE VDSetCompression(OSTypecompressType, short depth, Rect *bounds, CodecQspatialQuality, CodecQtemporalQuality, long keyFrameRate)
+VDE VDCompressOneFrameAsync(VDC ci)
+VDE VDCompressDone(UInt8 *queuedFrameCount, Ptr *theData, long *dataSize, UInt8 *similarity, TimeRecord *t)
+VDE VDReleaseCompressBuffer(Ptr bufferAddr)
+VDE VDGetImageDescription(ImageDescriptionHandle desc)
+VDE VDResetCompressSequence(VDC ci)
+VDE VDSetCompressionOnOff(Boolean)
+VDE VDGetCompressionTypes(VDCompressionListHandle h)
+VDE VDSetTimeBase(TimeBase t)
+VDE VDSetFrameRate(Fixed framesPerSecond)
+VDE VDGetDataRate(long *milliSecPerFrame, Fixed *framesPerSecond, long *bytesPerSecond)
+VDE VDGetSoundInputDriver(Str255 soundDriverName)
+VDE VDGetDMADepths(long *depthArray, long *preferredDepth)
+VDE VDGetPreferredTimeScale(TimeScale *preferred)
+VDE VDReleaseAsyncBuffers(VDC ci)
+VDE VDSetDataRate(long bytesPerSecond)
+VDE VDGetTimeCode(TimeRecord *atTime, void *timeCodeFormat, void *timeCodeTime)
+VDE VDUseSafeBuffers(Boolean useSafeBuffers)
+VDE VDGetSoundInputSource(long videoInput, long *soundInput)
+VDE VDGetCompressionTime(OSTypecompressionType, short depth, Rect *srcRect, CodecQ *spatialQuality, CodecQ *temporalQuality, ulong *compressTime)
+VDE VDSetPreferredPacketSize(long preferredPacketSizeInBytes)
+VDE VD[SG*]etPreferredImageDimensions(long width, long height)
+VDE VDGetInputName(long videoInput, Str255 name)
+VDE VDSetDestinationPort(CGrafPtr destPort)
+VDE VDGetDeviceNameAndFlags(Str255 outName, UInt32 *outNameFlags)
+VDE VDCaptureStateChanging(UInt32inStateFlags)
+VDE VDGetUniqueIDs(UInt64 *outDeviceID, UInt64 *outInputID)
+VDE VDSelectUniqueIDs(const UInt64 *inDeviceID, const UInt64 *inInputID)
+*/
+#endif
+
+static OSErr callback(ComponentInstanceRecord*, char*, long int, long int*, long int, TimeValue, short int, long int) {
+ post("FormatQuickTimeCamera callback");
+ return noErr;
+}
+
+\class FormatQuickTimeCamera : Format {
+ P<Dim> dim;
+ uint8 *buf;
+ uint8 *buf2;
+ VDC vdc;
+ int m_newFrame;
+ SeqGrabComponent m_sg;
+ SGChannel m_vc;
+ short m_pixelDepth;
+ Rect rect;
+ GWorldPtr m_srcGWorld;
+ PixMapHandle m_pixMap;
+ Ptr m_baseAddr;
+ long m_rowBytes;
+ int m_quality;
+//int m_colorspace;
+ \constructor (t_symbol *mode) {
+ //vdc = SGGetVideoDigitizerComponent(c);
+ dim = new Dim(240,320,4);
+ OSErr e;
+ rect.top=rect.left=0;
+ rect.bottom=dim->v[0]; rect.right=dim->v[1];
+ int n=0;
+ Component c = 0;
+ ComponentDescription cd;
+ cd.componentType = SeqGrabComponentType;
+ cd.componentSubType = 0;
+ cd.componentManufacturer = 0;
+ cd.componentFlags = 0;
+ cd.componentFlagsMask = 0;
+ for(;;) {
+ c = FindNextComponent(c, &cd);
+ if (!c) break;
+ ComponentDescription cd2;
+ Ptr name=0,info=0,icon=0;
+ GetComponentInfo(c,&cd2,&name,&info,&icon);
+ post("Component #%d",n);
+ char *t = (char *)&cd.componentType;
+ post(" type='%c%c%c%c'",t[3],t[2],t[1],t[0]);
+ t = (char *)&cd.componentSubType;
+ post(" subtype='%c%c%c%c'",t[3],t[2],t[1],t[0]);
+ post(" name=%08x, *name='%*s'",name, *name, name+1);
+ post(" info=%08x, *info='%*s'",info, *name, info+1);
+ n++;
+ }
+ post("number of components: %d",n);
+ m_sg = OpenDefaultComponent(SeqGrabComponentType, 0);
+ if(!m_sg) RAISE("could not open default component");
+ e=SGInitialize(m_sg);
+ if(e!=noErr) RAISE("could not initialize SG");
+ e=SGSetDataRef(m_sg, 0, 0, seqGrabDontMakeMovie);
+ if (e!=noErr) RAISE("dataref failed");
+ e=SGNewChannel(m_sg, VideoMediaType, &m_vc);
+ if(e!=noErr) post("could not make new SG channel");
+ e=SGSetChannelBounds(m_vc, &rect);
+ if(e!=noErr) post("could not set SG ChannelBounds");
+ e=SGSetChannelUsage(m_vc, seqGrabPreview);
+ if(e!=noErr) post("could not set SG ChannelUsage");
+ e=SGSetDataProc(m_sg,NewSGDataUPP(callback),0);
+ if (e!=noErr) post("could not set SG DataProc");
+ // m_rowBytes = m_vidXSize*4;
+ switch (3) {
+ case 0: e=SGSetChannelPlayFlags(m_vc, channelPlayNormal); break;
+ case 1: e=SGSetChannelPlayFlags(m_vc, channelPlayHighQuality); break;
+ case 2: e=SGSetChannelPlayFlags(m_vc, channelPlayFast); break;
+ case 3: e=SGSetChannelPlayFlags(m_vc, channelPlayAllData); break;
+ }
+ int dataSize = dim->prod();
+ buf = new uint8[dataSize];
+ buf2 = new uint8[dataSize];
+ m_rowBytes = dim->prod(1);
+ e=QTNewGWorldFromPtr (&m_srcGWorld,k32ARGBPixelFormat,&rect,NULL,NULL,0,buf,m_rowBytes);
+ if (0/*yuv*/) {
+ int dataSize = dim->prod()*2/4;
+ buf = new uint8[dataSize];
+ m_rowBytes = dim->prod(1)*2/4;
+ e=QTNewGWorldFromPtr (&m_srcGWorld,k422YpCbCr8CodecType,&rect,NULL,NULL,0,buf,m_rowBytes);
+ }
+ if (e!=noErr) RAISE("error #%d at QTNewGWorldFromPtr",e);
+ if (!m_srcGWorld) RAISE("Could not allocate off screen");
+ SGSetGWorld(m_sg,(CGrafPtr)m_srcGWorld, NULL);
+ //SGStartPreview(m_sg);
+ e=SGStartRecord(m_sg);
+ if (e!=noErr) RAISE("error #%d at SGStartRecord",e);
+ }
+ ~FormatQuickTimeCamera() {
+ if (m_vc) if (::SGDisposeChannel(m_sg, m_vc)) RAISE("SGDisposeChannel");
+ if (m_sg) {
+ if (::CloseComponent(m_sg)) RAISE("CloseComponent");
+ if (m_srcGWorld) ::DisposeGWorld(m_srcGWorld);
+ }
+ }
+ \decl 0 bang ();
+ \grin 0 int
+};
+
+// /System/Library/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Headers/Components.h
+
+static int nn(int c) {return c?c:' ';}
+
+/*
+pascal Boolean pix_videoDarwin :: SeqGrabberModalFilterProc (DialogPtr theDialog, const EventRecord *theEvent, short *itemHit, long refCon){
+ Boolean handled = false;
+ if ((theEvent->what == updateEvt) &&
+ ((WindowPtr) theEvent->message == (WindowPtr) refCon)) {
+ BeginUpdate ((WindowPtr) refCon);
+ EndUpdate ((WindowPtr) refCon);
+ handled = true;
+ }
+ WindowRef awin = GetDialogWindow(theDialog);
+ ShowWindow (awin);
+ SetWindowClass(awin,kUtilityWindowClass);
+ //ChangeWindowAttributes(awin,kWindowStandardHandlerAttribute,0);
+ //SGPanelEvent(m_sg,m_vc,theDialog,0,theEvent,itemHit,&handled);
+ //AEProcessAppleEvent (theEvent);
+ return handled;
+}
+void pix_videoDarwin :: DoVideoSettings() {
+ Rect newActiveVideoRect;
+ Rect curBounds, curVideoRect, newVideoRect;
+ ComponentResult err;
+ SGModalFilterUPP seqGragModalFilterUPP;
+ err = SGGetChannelBounds (m_vc, &curBounds);
+ err = SGGetVideoRect (m_vc, &curVideoRect);
+ err = SGPause (m_sg, true);
+ seqGragModalFilterUPP = (SGModalFilterUPP)NewSGModalFilterUPP(SeqGrabberModalFilterProc);
+ err = SGSettingsDialog(m_sg, m_vc, 0, NULL, seqGrabSettingsPreviewOnly, seqGragModalFilterUPP, (long)m_srcGWorld);
+ DisposeSGModalFilterUPP(seqGragModalFilterUPP);
+ err = SGGetVideoRect (m_vc, &newVideoRect);
+ err = SGGetSrcVideoBounds (m_vc, &newActiveVideoRect);
+ err = SGPause (m_sg, false);
+}
+*/
+
+\def 0 bang () {
+ GridOutlet out(this,0,dim);
+ int n = dim->prod()/4;
+ for (int i=0; i<n; i++) ((uint32 *)buf2)[i] = ((uint32 *)buf)[i] >> 8;
+ out.send(dim->prod(),buf2);
+ SGIdle(m_sg);
+}
+
+GRID_INLET(0) {
+ RAISE("Unimplemented. Sorry.");
+//!@#$
+ if (in->dim->n != 3) RAISE("expecting 3 dimensions: rows,columns,channels");
+ if (in->dim->get(2) != 3) RAISE("expecting 3 channels (got %d)",in->dim->get(2));
+ in->set_chunk(0);
+} GRID_FLOW {
+} GRID_FINISH {
+} GRID_END
+\end class FormatQuickTimeCamera {install_format("#io.quicktimecamera",4,"");}
+
+\class FormatQuickTimeApple : Format {
+ Movie movie;
+ TimeValue time;
+ short movie_file;
+ GWorldPtr gw; /* just like an X11 Image or Pixmap, maybe. */
+ uint8 *buffer;
+ P<Dim> dim;
+ int nframe, nframes;
+ \constructor (t_symbol *mode, string filename) {
+ /*vdc=0;*/ movie=0; time=0; movie_file=0; gw=0; buffer=0; dim=0; nframe=0; nframes=0;
+ int err;
+ filename = gf_find_file(filename);
+ FSSpec fss;
+ FSRef fsr;
+ err = FSPathMakeRef((const UInt8 *)filename.data(), &fsr, NULL); if (err) goto err;
+ err = FSGetCatalogInfo(&fsr, kFSCatInfoNone, NULL, NULL, &fss, NULL); if (err) goto err;
+ err = OpenMovieFile(&fss,&movie_file,fsRdPerm); if (err) goto err;
+ NewMovieFromFile(&movie, movie_file, NULL, NULL, newMovieActive, NULL);
+ Rect r;
+ GetMovieBox(movie, &r);
+ post("handle=%d movie=%d tracks=%d", movie_file, movie, GetMovieTrackCount(movie));
+ post("duration=%d; timescale=%d cHz", (long)GetMovieDuration(movie), (long)GetMovieTimeScale(movie));
+ nframes = GetMovieDuration(movie); /* i don't think so */
+ post("rect=((%d..%d),(%d..%d))", r.top, r.bottom, r.left, r.right);
+ OffsetRect(&r, -r.left, -r.top);
+ SetMovieBox(movie, &r);
+ dim = new Dim(r.bottom-r.top, r.right-r.left, 4);
+ SetMoviePlayHints(movie, hintsHighQuality, hintsHighQuality);
+ buffer = new uint8[dim->prod()];
+ err = QTNewGWorldFromPtr(&gw, k32ARGBPixelFormat, &r, NULL, NULL, 0, buffer, dim->prod(1));
+ if (err) goto err;
+ return;
+ err:
+ // RAISE("can't open file `%s': error #%d (%s)", filename.data(), err, rb_str_ptr(rb_funcall(mGridFlow,SI(macerr),1,INT2NUM(err))));
+ RAISE("can't open file `%s': error #%d (0x%08x)", filename.data(), err, err);
+ }
+ ~FormatQuickTimeApple() {
+ if (movie) {
+ DisposeMovie(movie);
+ DisposeGWorld(gw);
+ CloseMovieFile(movie_file);
+ }
+ }
+ \decl 0 codec (string c);
+ \decl 0 colorspace (string c);
+ \decl 0 bang ();
+ \decl 0 seek (int frame);
+ \decl 0 rewind ();
+ \grin 0
+};
+
+\def 0 seek (int frame) {nframe=frame;}
+\def 0 rewind () {_0_seek(0,0,0);}
+
+\def 0 bang () {
+ CGrafPtr savedPort;
+ GDHandle savedDevice;
+ SetMovieGWorld(movie,gw,GetGWorldDevice(gw));
+ Rect r;
+ GetMovieBox(movie,&r);
+ PixMapHandle pixmap = GetGWorldPixMap(gw);
+ short flags = nextTimeStep;
+ if (nframe>=nframes) {outlet_bang(bself->te_outlet); return;}
+ if (nframe==0) flags |= nextTimeEdgeOK;
+ TimeValue duration;
+ OSType mediaType = VisualMediaCharacteristic;
+ GetMovieNextInterestingTime(movie,
+ flags,1,&mediaType,time,0,&time,&duration);
+ if (time<0) {
+ time=0;
+ outlet_bang(bself->te_outlet);
+ return;
+ }
+// post("quicktime frame #%d; time=%d duration=%d", nframe, (long)time, (long)duration);
+ SetMovieTimeValue(movie,nframe*duration);
+ MoviesTask(movie,0);
+ GridOutlet out(this,0,dim);
+ uint32 *bufu32 = (uint32 *)buffer;
+ int n = dim->prod()/4;
+ int i;
+ if (is_le()) {
+ for (; i<n; i++) {
+ bufu32[i+0]=bufu32[i+0]>>8;
+ }
+ } else {
+ for (i=0; i<n&-4; i+=4) {
+ bufu32[i+0]=(bufu32[i+0]<<8)+(bufu32[i+0]>>24);
+ bufu32[i+1]=(bufu32[i+1]<<8)+(bufu32[i+1]>>24);
+ bufu32[i+2]=(bufu32[i+2]<<8)+(bufu32[i+2]>>24);
+ bufu32[i+3]=(bufu32[i+3]<<8)+(bufu32[i+3]>>24);
+ }
+ for (; i<n; i++) {
+ bufu32[i+0]=(bufu32[i+0]<<8)+(bufu32[i+0]>>24);
+ }
+ }
+ out.send(dim->prod(),buffer);
+ int nf=nframe;
+ nframe++;
+ //return INT2NUM(nf);
+}
+
+GRID_INLET(0) {
+ RAISE("Unimplemented. Sorry.");
+//!@#$
+ if (in->dim->n != 3)
+ RAISE("expecting 3 dimensions: rows,columns,channels");
+ if (in->dim->get(2) != 3)
+ RAISE("expecting 3 channels (got %d)",in->dim->get(2));
+ in->set_chunk(0);
+} GRID_FLOW {
+} GRID_FINISH {
+} GRID_END
+
+\def 0 codec (string c) { RAISE("Unimplemented. Sorry."); }
+\def 0 colorspace (string c) { RAISE("Unimplemented. Sorry."); }
+
+\classinfo {
+ EnterMovies();
+ install_format("#io.quicktime",4,"mov");
+}
+\end class FormatQuickTimeApple
+void startup_quicktimeapple () {
+ \startall
+}
diff --git a/externals/gridflow/src/quicktimehw.cxx b/externals/gridflow/src/quicktimehw.cxx
new file mode 100644
index 00000000..38dfcbbb
--- /dev/null
+++ b/externals/gridflow/src/quicktimehw.cxx
@@ -0,0 +1,246 @@
+/*
+ $Id: quicktimehw.c 4620 2009-11-01 21:16:58Z matju $
+
+ GridFlow
+ Copyright (c) 2001-2009 by Mathieu Bouchard
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ See file ../COPYING for further informations on licensing terms.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#define QUICKTIMEHW_INCLUDE_HERE
+#include "gridflow.hxx.fcs"
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <map>
+#include <vector>
+
+static std::map<string,std::vector<string> *> codecs;
+static std::map<string,string> fourccs;
+
+\class FormatQuickTimeHW : Format {
+ quicktime_t *anim;
+ int track;
+ P<Dim> dim;
+ char *codec;
+ int colorspace;
+ int channels;
+ bool started;
+ P<Dim> force;
+ float64 framerate;
+ P<BitPacking> bit_packing;
+ int jpeg_quality; // in theory we shouldn't need this, but...
+ ~FormatQuickTimeHW() {if (anim) quicktime_close(anim);}
+ \constructor (t_symbol *mode, string filename) {
+ track=0; dim=0; codec=const_cast<char *>(QUICKTIME_RAW);
+ started=false; force=0; framerate=29.97; bit_packing=0; jpeg_quality=75;
+// libquicktime may be nice, but it won't take a filehandle, only filename
+ filename = gf_find_file(filename);
+ anim = quicktime_open((char *)filename.data(),mode==gensym("in"),mode==gensym("out"));
+ if (!anim) RAISE("can't open file `%s': %s (or some other reason that libquicktime won't tell us)",
+ filename.data(), strerror(errno));
+ if (mode==gensym("in")) {
+ /* This doesn't really work: (is it just for encoding?)
+ if (!quicktime_supported_video(anim,track))
+ RAISE("quicktime: unsupported codec: %s",
+ quicktime_video_compressor(anim,track));
+ */
+ }
+ _0_colorspace(0,0,string("rgb"));
+ quicktime_set_cpus(anim,1);
+ uint32 mask[3] = {0x0000ff,0x00ff00,0xff0000};
+ bit_packing = new BitPacking(is_le(),3,3,mask);
+ }
+ \decl 0 bang ();
+ \decl 0 seek (int32 frame);
+ \decl 0 rewind ();
+ \decl 0 force_size (int32 height, int32 width);
+ \decl 0 codec (string c);
+ \decl 0 colorspace (string c);
+ \decl 0 parameter (string name, int32 value);
+ \decl 0 framerate (float64 f);
+ \decl 0 size (int32 height, int32 width);
+ \decl 0 get ();
+ \grin 0 int
+};
+
+\def 0 force_size (int32 height, int32 width) { force = new Dim(height, width); }
+\def 0 seek (int32 frame) {
+ quicktime_set_video_position(anim,clip(frame,int32(0),int32(quicktime_video_length(anim,track)-1)),track);
+}
+\def 0 rewind () {_0_seek(0,0,0);}
+
+\def 0 bang () {
+ long length = quicktime_video_length(anim,track);
+ long nframe = quicktime_video_position(anim,track);
+ if (nframe >= length) {outlet_bang(bself->te_outlet); return;}
+ /* if it works, only do it once, to avoid silly stderr messages forgotten in LQT */
+ if (!quicktime_reads_cmodel(anim,colorspace,0) && !started) {
+ RAISE("LQT says this video cannot be decoded into the chosen colorspace");
+ }
+ int sx = quicktime_video_width(anim,track);
+ int sy = quicktime_video_height(anim,track);
+ int sz = quicktime_video_depth(anim,track);
+ channels = sz/8; // hack. how do i get the video's native colormodel ?
+ switch (sz) {
+ case 24: colorspace=BC_RGB888; break;
+ case 32: colorspace=BC_RGBA8888; break;
+ default: post("strange quicktime. ask matju."); break;
+ }
+ if (force) {
+ sy = force->get(0);
+ sx = force->get(1);
+ }
+ uint8 buf[sy*sx*channels];
+ uint8 *rows[sy]; for (int i=0; i<sy; i++) rows[i]=buf+i*sx*channels;
+ quicktime_decode_scaled(anim,0,0,sx,sy,sx,sy,colorspace,rows,track);
+ GridOutlet out(this,0,new Dim(sy,sx,channels),cast);
+ out.send(sy*sx*channels,buf);
+ started=true;
+// return INT2NUM(nframe);
+}
+
+//!@#$ should also support symbol values (how?)
+\def 0 parameter (string name, int32 value) {
+ int val = value;
+ //post("quicktime_set_parameter %s %d",name.data(), val);
+ quicktime_set_parameter(anim, const_cast<char *>(name.data()), &val);
+ if (name=="jpeg_quality") jpeg_quality=value;
+}
+
+\def 0 framerate (float64 f) {
+ framerate=f;
+ quicktime_set_framerate(anim, f);
+}
+
+\def 0 size (int32 height, int32 width) {
+ if (dim) RAISE("video size already set!");
+ // first frame: have to do setup
+ dim = new Dim(height, width, 3);
+ quicktime_set_video(anim,1,dim->get(1),dim->get(0),framerate,codec);
+ quicktime_set_cmodel(anim,colorspace);
+}
+
+GRID_INLET(0) {
+ if (in->dim->n != 3) RAISE("expecting 3 dimensions: rows,columns,channels");
+ if (in->dim->get(2)!=channels) RAISE("expecting %d channels (got %d)",channels,in->dim->get(2));
+ in->set_chunk(0);
+ if (dim) {
+ if (!dim->equal(in->dim)) RAISE("all frames should be same size");
+ } else {
+ // first frame: have to do setup
+ dim = in->dim;
+ quicktime_set_video(anim,1,dim->get(1),dim->get(0),framerate,codec);
+ quicktime_set_cmodel(anim,colorspace);
+ quicktime_set_depth(anim,8*channels,track);
+ }
+ //post("quicktime jpeg_quality %d", jpeg_quality);
+ quicktime_set_parameter(anim, (char*)"jpeg_quality", &jpeg_quality);
+} GRID_FLOW {
+ int sx = quicktime_video_width(anim,track);
+ int sy = quicktime_video_height(anim,track);
+ uint8 *rows[sy];
+ if (sizeof(T)>1) {
+ uint8 data2[n];
+ bit_packing->pack(sx*sy,data,(uint8 *)data2);
+ for (int i=0; i<sy; i++) rows[i]=data2+i*sx*channels;
+ quicktime_encode_video(anim,rows,track);
+ } else {
+ for (int i=0; i<sy; i++) rows[i]=(uint8 *)data+i*sx*channels;
+ quicktime_encode_video(anim,rows,track);
+ }
+} GRID_FINISH {
+} GRID_END
+
+\def 0 codec (string c) {
+#ifdef LQT_VERSION
+ char buf[5];
+ strncpy(buf,c.data(),4);
+ for (int i=c.length(); i<4; i++) buf[i]=' ';
+ buf[4]=0;
+ if (fourccs.find(string(buf))==fourccs.end())
+ RAISE("warning: unknown fourcc '%s'" /*" (%s)"*/, buf /*, rb_str_ptr(rb_inspect(rb_funcall(fourccs,SI(keys),0)))*/);
+#endif
+ codec = strdup(buf);
+}
+
+\def 0 colorspace (string c) {
+ if (0) {
+ } else if (c=="rgb") { channels=3; colorspace=BC_RGB888;
+ } else if (c=="rgba") { channels=4; colorspace=BC_RGBA8888;
+ } else if (c=="bgr") { channels=3; colorspace=BC_BGR888;
+ } else if (c=="bgrn") { channels=4; colorspace=BC_BGR8888;
+// } else if (c=="yuv") { channels=3; colorspace=BC_YUV888;
+ } else if (c=="yuva") { channels=4; colorspace=BC_YUVA8888;
+ } else if (c=="YUV420P") { channels=3; colorspace=BC_YUV420P;
+ } else RAISE("unknown colorspace '%s' (supported: rgb, rgba, bgr, bgrn, yuv, yuva)",c.data());
+}
+
+\def 0 get () {
+/* t_atom a[1];
+ SETFLOAT(a,(float)length);
+ outlet_anything(bself->te_outlet,gensym("frames"),1,a);
+*/
+ t_atom a[1];
+ SETFLOAT(a,quicktime_video_length(anim,track));
+ outlet_anything(bself->outlets[0],gensym("frames"),1,a);
+ SETFLOAT(a,quicktime_frame_rate(anim,track));
+ outlet_anything(bself->outlets[0],gensym("framerate"),1,a);
+ SETFLOAT(a,quicktime_video_height(anim,track));
+ outlet_anything(bself->outlets[0],gensym("height"),1,a);
+ SETFLOAT(a,quicktime_video_width(anim,track));
+ outlet_anything(bself->outlets[0],gensym("width"),1,a);
+ SETFLOAT(a,quicktime_video_depth(anim,track));
+ outlet_anything(bself->outlets[0],gensym("depth"),1,a);
+ SETSYMBOL(a,gensym(quicktime_video_compressor(anim,track)));
+ outlet_anything(bself->outlets[0],gensym("codec"),1,a);
+ //SUPER;
+}
+
+\classinfo {install_format("#io.quicktime",6,"mov avi");
+// def self.info; %[codecs: #{@codecs.keys.join' '}] end
+//#define L fprintf(stderr,"%s:%d in %s\n",__FILE__,__LINE__,__PRETTY_FUNCTION__);
+#ifdef LQT_VERSION
+ lqt_registry_init();
+ int n = lqt_get_num_video_codecs();
+ for (int i=0; i<n; i++) {
+ const lqt_codec_info_t *s = lqt_get_video_codec_info(i);
+ if (!s->name) {
+ fprintf(stderr,"[#in quicktime]: skipping codec with null name!\n");
+ continue;
+ }
+ string name = string(s->name);
+ std::vector<string> *f = new std::vector<string>(s->num_fourccs);
+ if (!s->fourccs) {
+ post("WARNING: no fourccs (quicktime library is broken?)");
+ goto hell;
+ }
+ //fprintf(stderr,"num_fourccs=%d fourccs=%p\n",s->num_fourccs,s->fourccs);
+ for (int j=0; j<s->num_fourccs; j++) {
+ string fn = string(s->fourccs[j]);
+ f->push_back(fn);
+ fourccs[fn]=name;
+ }
+ codecs[name]=f;
+ hell:;
+ }
+#endif
+}
+\end class FormatQuickTimeHW
+void startup_quicktimehw () {
+ \startall
+}
diff --git a/externals/gridflow/src/sdl.cxx b/externals/gridflow/src/sdl.cxx
new file mode 100644
index 00000000..7406611c
--- /dev/null
+++ b/externals/gridflow/src/sdl.cxx
@@ -0,0 +1,209 @@
+/*
+ $Id: sdl.c 4620 2009-11-01 21:16:58Z matju $
+
+ GridFlow
+ Copyright (c) 2001-2009 by Mathieu Bouchard
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ See file ../COPYING for further informations on licensing terms.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "gridflow.hxx.fcs"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <signal.h>
+#include <SDL/SDL.h>
+
+struct FormatSDL;
+void FormatSDL_call(FormatSDL *self);
+static bool in_use = false;
+static bool full_screen = false;
+static int mousex,mousey,mousem;
+SDL_Surface *screen;
+FObject *instance;
+
+static t_symbol *keyboard[SDLK_LAST];
+
+static void KEYS_ARE (int i, const char *s__) {
+ char *s_ = strdup(s__);
+ char *s = s_;
+ while (*s) {
+ char *t = strchr(s,' ');
+ if (t) *t=0;
+ keyboard[i] = gensym(s);
+ if (!t) break;
+ s=t+1; i++;
+ }
+ free(s_);
+}
+
+static void build_keyboard () {
+ KEYS_ARE(8,"BackSpace Tab");
+ KEYS_ARE(13,"Return");
+ KEYS_ARE(27,"Escape");
+ KEYS_ARE(32,"space exclam quotedbl numbersign dollar percent ampersand apostrophe");
+ KEYS_ARE(40,"parenleft parenright asterisk plus comma minus period slash");
+ KEYS_ARE(48,"D0 D1 D2 D3 D4 D5 D6 D7 D8 D9");
+ KEYS_ARE(58,"colon semicolon less equal greater question at");
+ //KEYS_ARE(65,"A B C D E F G H I J K L M N O P Q R S T U V W X Y Z");
+ KEYS_ARE(91,"bracketleft backslash bracketright asciicircum underscore grave quoteleft");
+ KEYS_ARE(97,"a b c d e f g h i j k l m n o p q r s t u v w x y z");
+ //SDLK_DELETE = 127
+ KEYS_ARE(256,"KP_0 KP_1 KP_2 KP_3 KP_4 KP_5 KP_6 KP_7 KP_8 KP_9");
+ KEYS_ARE(266,"KP_Decimal KP_Divide KP_Multiply KP_Subtract KP_Add KP_Enter KP_Equal");
+ KEYS_ARE(273,"KP_Up KP_Down KP_Right KP_Left KP_Insert KP_Home KP_End KP_Prior KP_Next");
+ KEYS_ARE(282,"F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15");
+ KEYS_ARE(300,"Num_Lock Caps_Lock Scroll_Lock");
+ KEYS_ARE(303,"Shift_R Shift_L Control_R Control_L Alt_R Alt_L Meta_L Meta_R");
+ KEYS_ARE(311,"Super_L Super_R Mode_switch Multi_key");
+}
+
+static void report_pointer () {
+ t_atom a[3];
+ SETFLOAT(a+0,mousey);
+ SETFLOAT(a+1,mousex);
+ SETFLOAT(a+2,mousem);
+ outlet_anything(instance->bself->outlets[0],gensym("position"),COUNT(a),a);
+}
+
+static void HandleEvent () {
+ SDL_Event event;
+ while (SDL_PollEvent(&event)) {
+ switch (event.type) {
+ case SDL_KEYDOWN: case SDL_KEYUP: {
+ int key = event.key.keysym.sym;
+ int mod = event.key.keysym.mod;
+ if (event.type==SDL_KEYDOWN && (key==SDLK_F11 || key==SDLK_ESCAPE || key=='f')) {
+ full_screen = !full_screen;
+ SDL_WM_ToggleFullScreen(screen);
+ break;
+ }
+ t_symbol *sel = gensym(const_cast<char *>(event.type==SDL_KEYDOWN ? "keypress" : "keyrelease"));
+ t_atom at[4];
+ mousem &= ~0xFF;
+ mousem |= mod;
+ SETFLOAT(at+0,mousey);
+ SETFLOAT(at+1,mousex);
+ SETFLOAT(at+2,mousem);
+ SETSYMBOL(at+3,keyboard[event.key.keysym.sym]);
+ outlet_anything(instance->bself->outlets[0],sel,4,at);
+ } break;
+ case SDL_MOUSEBUTTONDOWN: SDL_MOUSEBUTTONUP: {
+ if (SDL_MOUSEBUTTONDOWN) mousem |= (128<<event.button.button);
+ else mousem &= ~(128<<event.button.button);
+ //post("mousem=%d",mousem);
+ report_pointer();
+ } break;
+ case SDL_MOUSEMOTION: {
+ mousey = event.motion.y;
+ mousex = event.motion.x;
+ report_pointer();
+ } break;
+ case SDL_VIDEORESIZE: {
+ } break;
+ }
+ }
+}
+
+\class FormatSDL : Format {
+ P<BitPacking> bit_packing;
+ P<Dim> dim;
+ t_clock *clock;
+ void resize_window (int sx, int sy);
+ void call ();
+ \decl 0 setcursor (int shape);
+ \decl 0 hidecursor ();
+ \decl 0 title (string title);
+ \constructor (t_symbol *mode) {
+ dim=0;screen=0;
+ if (in_use) RAISE("only one FormatSDL object at a time; sorry");
+ in_use=true;
+ if (SDL_Init(SDL_INIT_VIDEO)<0) RAISE("SDL_Init() error: %s",SDL_GetError());
+ atexit(SDL_Quit);
+ resize_window(320,240);
+ SDL_PixelFormat *f = screen->format;
+ uint32 mask[3] = {f->Rmask,f->Gmask,f->Bmask};
+ switch (f->BytesPerPixel) {
+ case 1: RAISE("8 bpp not supported"); break;
+ case 2: case 3: case 4:
+ bit_packing = new BitPacking(is_le(),f->BytesPerPixel,3,mask);
+ break;
+ default: RAISE("%d bytes/pixel: how do I deal with that?",f->BytesPerPixel); break;
+ }
+ instance=this;
+ clock = clock_new(this,(t_method)FormatSDL_call);
+ clock_delay(clock,0);
+ _0_title(0,0,string("GridFlow SDL"));
+ }
+ \grin 0 int
+ ~FormatSDL () {
+ clock_unset(clock);
+ clock_free(clock);
+ SDL_Quit();
+ instance=0;
+ in_use=false;
+ }
+};
+
+\def 0 title (string title) {
+ SDL_WM_SetCaption(title.data(),title.data());
+}
+
+void FormatSDL::call() {HandleEvent(); clock_delay(clock,20);}
+void FormatSDL_call(FormatSDL *self) {self->call();}
+
+void FormatSDL::resize_window (int sx, int sy) {
+ dim = new Dim(sy,sx,3);
+ screen = SDL_SetVideoMode(sx,sy,0,SDL_SWSURFACE);
+ if (!screen)
+ RAISE("Can't switch to (%d,%d,%dbpp): %s", sy,sx,24, SDL_GetError());
+}
+
+GRID_INLET(0) {
+ if (in->dim->n != 3)
+ RAISE("expecting 3 dimensions: rows,columns,channels");
+ if (in->dim->get(2) != 3)
+ RAISE("expecting 3 channels: red,green,blue (got %d)",in->dim->get(2));
+ int sx = in->dim->get(1), osx = dim->get(1);
+ int sy = in->dim->get(0), osy = dim->get(0);
+ in->set_chunk(1);
+ if (sx!=osx || sy!=osy) resize_window(sx,sy);
+} GRID_FLOW {
+ int bypl = screen->pitch;
+ int sxc = in->dim->prod(1);
+ int sx = in->dim->get(1);
+ int y = dex/sxc;
+ if (SDL_MUSTLOCK(screen)) if (SDL_LockSurface(screen) < 0) return; //???
+ for (; n>0; y++, data+=sxc, n-=sxc) {
+ /* convert line */
+ bit_packing->pack(sx, data, (uint8 *)screen->pixels+y*bypl);
+ }
+ if (SDL_MUSTLOCK(screen)) SDL_UnlockSurface(screen);
+} GRID_FINISH {
+ SDL_UpdateRect(screen,0,0,in->dim->get(1),in->dim->get(0));
+} GRID_END
+
+\def 0 setcursor (int shape) {SDL_ShowCursor(SDL_ENABLE);}
+\def 0 hidecursor () {SDL_ShowCursor(SDL_DISABLE);}
+
+\end class FormatSDL {install_format("#io.sdl",2,"");}
+void startup_sdl () {
+ \startall
+ build_keyboard();
+}
diff --git a/externals/gridflow/src/source_filter.rb b/externals/gridflow/src/source_filter.rb
new file mode 100644
index 00000000..9dfef776
--- /dev/null
+++ b/externals/gridflow/src/source_filter.rb
@@ -0,0 +1,311 @@
+#!/usr/bin/env ruby
+=begin
+ $Id: source_filter.rb 4452 2009-10-27 15:59:57Z matju $
+
+ GridFlow
+ Copyright (c) 2001-2009 by Mathieu Bouchard
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ See file ../COPYING for further informations on licensing terms.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+=end
+
+$stack = []
+$classes = []
+$exit = 0
+
+ClassDecl = Struct.new(:name,:supername,:methods,:grins,:attrs,:info)
+MethodDecl = Struct.new(:rettype,:selector,:arglist,:minargs,:maxargs,:where)
+Arg = Struct.new(:type,:name,:default)
+Attr = Struct.new(:type,:name,:default,:virtual)
+
+class MethodDecl
+ def ==(o)
+ return false unless rettype==o.rettype && maxargs==o.maxargs
+ arglist.each_index{|i| arglist[i] == o.arglist[i] or return false }
+ return true
+ end
+ def ===(o)
+ return false unless rettype==o.rettype && maxargs==o.maxargs
+ arglist.each_index{|i| arglist[i].type == o.arglist[i].type and arglist[i].default == o.arglist[i].default or return false }
+ return true
+ end
+ attr_accessor :done
+end
+
+class Arg
+ def canon(type)
+ type="Grid *" if type=="PtrGrid"
+ type
+ end
+ def ==(o) canon(type)==canon(o.type) && name==o.name end
+end
+
+In = File.open ARGV[0], "r"
+Out = File.open ARGV[1], "w"
+
+def handle_class(line)
+ raise "already in class #{where}" if $stack[-1] and ClassDecl===$stack[-1]
+ /^(\w+)(?:\s*[:<]\s*(\w+))?\s*(\{.*)?/.match line or raise "syntax error #{where}"
+ classname = $1
+ superclassname = $2
+ rest = $3
+ q=ClassDecl.new(classname,superclassname,{},{},{},false)
+ $stack << q
+ $classes << q
+ Out.print "#define THISCLASS #{classname}\n\# #{$linenumber}\n"
+ if rest and /^\{/ =~ rest then
+ Out.print "struct #{classname} "
+ Out.print ": #{superclassname}" if superclassname
+ Out.print rest
+ end
+end
+
+def parse_methoddecl(line,term)
+ /^(\w+(?:\s*\*)?)\s+(\w+)\s*\(([^\)]*)\)\s*#{term}/.match line or
+ raise "syntax error #{where} #{line}"
+ rettype,selector,arglist = $1,$2,$3,$4
+ if /^\d+$/ =~ rettype then
+ selector = "_"+rettype+"_"+selector
+ rettype = "void"
+ end
+ arglist,minargs,maxargs = parse_arglist arglist
+ MethodDecl.new(rettype,selector,arglist,minargs,maxargs,where)
+end
+
+def parse_arglist(arglist)
+ arglist = arglist.split(/,/)
+ maxargs = arglist.length
+ args = arglist.map {|arg|
+ if /^\s*\.\.\.\s*$/.match arg then maxargs=-1; next end
+ /^\s*([\w\s\*<>]+)\s*\b(\w+)\s*(?:\=(.*))?/.match arg or
+ raise "syntax error in \"#{arg}\" #{where}"
+ type,name,default=$1,$2,$3
+ Arg.new(type.sub(/\s+$/,""),name,default)
+ }.compact
+ minargs = args.length
+ minargs-=1 while minargs>0 and args[minargs-1].default
+ [args,minargs,maxargs]
+end
+
+def unparse_arglist(arglist,with_default=true)
+ arglist.map {|arg|
+ x="#{arg.type} #{arg.name}"
+ x << '=' << arg.default if with_default and arg.default
+ x
+ }.join(", ")
+end
+
+def where; "[#{ARGV[0]}:#{$linenumber}]" end
+
+def handle_attr(line)
+ line.gsub!(/\/\/.*$/,"") # remove comment
+ frame = $stack[-1]
+ type = line.gsub(%r"//.*$","").gsub(%r"/\*.*\*/","").gsub(%r";?\s*$","")
+ virtual = !!type.slice!(/\(\)$/)
+ name = type.slice!(/\w+$/)
+ raise "missing \\class #{where}" if not $stack[-1] or not ClassDecl===frame
+ handle_decl "void ___get(t_symbol *s);" if frame.attrs.size==0
+ frame.attrs[name]=Attr.new(type,name,nil,virtual)
+ if virtual then
+ handle_decl "#{type} #{name}();"
+ else
+ Out.print line
+ end
+ type.gsub!(/\s+$/,"")
+ type.gsub!(/^\s+/,"")
+ if type=="bool" then
+ handle_decl "0 #{name} (#{type} #{name}=true);"
+ else
+ handle_decl "0 #{name} (#{type} #{name});"
+ end
+end
+
+def handle_decl(line)
+ frame = $stack[-1]
+ raise "missing \\class #{where}" if not frame or not ClassDecl===frame
+ classname = frame.name
+ m = parse_methoddecl(line,";\s*$")
+ frame.methods[m.selector] = m
+ Out.print "#{m.rettype} #{m.selector}(VA"
+ Out.print ", #{unparse_arglist m.arglist}" if m.arglist.length>0
+ Out.print "); static void #{m.selector}_wrap(#{classname} *self, VA); "
+end
+
+def handle_def(line)
+ m = parse_methoddecl(line,"\\{?.*$")
+ term = line[/\{.*/]
+ qlass = $stack[-1]
+ raise "missing \\class #{where}" if not qlass or not ClassDecl===qlass
+ classname = qlass.name
+ n = m
+ if qlass.methods[m.selector]
+ m = qlass.methods[m.selector]
+ if !m===n then
+ STDERR.puts "ERROR: def does not match decl:"
+ STDERR.puts "#{m.where}: \\decl #{m.inspect}"
+ STDERR.puts "#{n.where}: \\def #{n.inspect}"
+ $exit = 1
+ end
+ else
+ qlass.methods[m.selector] = m
+ end
+ Out.print "void #{classname}::#{m.selector}_wrap(#{classname} *self, VA) {"
+ Out.print "static const char *methodspec = \"#{qlass.name}::#{m.selector}(#{unparse_arglist m.arglist,false})\";"
+ Out.print "#{m.rettype} foo;" if m.rettype!="void"
+ Out.print "if (argc<#{m.minargs}"
+ Out.print "||argc>#{m.maxargs}" if m.maxargs!=-1
+ Out.print ") RAISE(\"got %d args instead of %d..%d in %s\",argc,#{m.minargs},#{m.maxargs},methodspec);"
+ Out.print "foo = " if m.rettype!="void"
+ Out.print " self->#{m.selector}(argc,argv"
+ m.arglist.each_with_index{|arg,i|
+ if arg.default then
+ Out.print ",argc<#{i+1}?#{arg.default}:convert(argv[#{i}],(#{arg.type}*)0)"
+ else
+ Out.print ",convert(argv[#{i}],(#{arg.type}*)0)"
+ end
+ }
+ Out.print ");} #{m.rettype} #{classname}::#{m.selector}(VA"
+ #puts "m=#{m} n=#{n}"
+ Out.print ","+unparse_arglist(n.arglist,false) if m.arglist.length>0
+ Out.print ")#{term} "
+ qlass.methods[m.selector].done=true
+end
+
+def handle_constructor(line)
+ frame = $stack[-1]
+ raise "missing \\class #{where}" if not frame or not ClassDecl===frame
+ m = parse_methoddecl("void constructor"+line,"(.*)$")
+ Out.print "#{frame.name}(BFObject *bself, MESSAGE) : #{frame.supername}(bself,MESSAGE2) {"
+ Out.print "static const char *methodspec = \"#{frame.name}::#{m.selector}(#{unparse_arglist m.arglist,false})\";"
+
+ Out.print "if (argc<#{m.minargs}"
+ Out.print "||argc>#{m.maxargs}" if m.maxargs!=-1
+ Out.print ") RAISE(\"got %d args instead of %d..%d in %s\",argc,#{m.minargs},#{m.maxargs},methodspec);"
+ Out.print "#{m.selector}(sel,argc,argv"
+ m.arglist.each_with_index{|arg,i|
+ if arg.default then
+ Out.print ",argc<#{i+1}?#{arg.default}:convert(argv[#{i}],(#{arg.type}*)0)"
+ else
+ Out.print ",convert(argv[#{i}],(#{arg.type}*)0)"
+ end
+ }
+ Out.print ");}"
+ Out.print "#{m.rettype} #{m.selector}(MESSAGE"
+ Out.print ", #{unparse_arglist m.arglist}" if m.arglist.length>0
+ Out.print ") "+line[/\{.*/]
+end
+
+def handle_classinfo(line)
+ frame = $stack[-1]
+ cl = frame.name
+ line="{}" if /^\s*$/ =~ line
+ Out.print "static void #{cl}_startup (FClass *fclass);"
+ Out.print "static FObject *#{cl}_allocator (BFObject *bself, MESSAGE) {return new #{cl}(bself,sel,argc,argv);}"
+ Out.print "static MethodDecl #{cl}_methods[] = {"
+ Out.print frame.methods.map {|foo,method| "{ \"#{method.selector}\",(FMethod)#{frame.name}::#{method.selector}_wrap }" }.join(",")
+ Out.print "}; FClass ci#{cl} = {#{cl}_allocator,#{cl}_startup,#{cl.inspect},COUNT(#{cl}_methods),#{cl}_methods};"
+ get="void ___get(t_symbol *s=0) {t_atom a[1];"
+ frame.attrs.each {|name,attr|
+ virtual = if attr.virtual then "(0,0)" else "" end
+ get << "if (s==gensym(\"#{name}\")) set_atom(a,#{name}#{virtual}); else "
+ if frame.methods["_0_"+name].done then
+ #STDERR.puts "skipping already defined \\attr #{name}"
+ next
+ end
+ type,name,default = attr.to_a
+ handle_def "0 #{name} (#{type} #{name}) {this->#{name}=#{name}; changed(gensym(\"#{name}\"));}"
+ }
+ line.gsub!(/^\s*(\w+\s*)?\{/,"")
+ get << "RAISE(\"unknown attr %s\",s->s_name); outlet_anything(bself->outlets[bself->noutlets-1],s,1,a);}"
+ handle_def get if frame.attrs.size>0
+ Out.print "void #{frame.name}_startup (FClass *fclass) {"
+ frame.attrs.each {|name,attr| Out.print "fclass->attrs[\"#{name}\"] = new AttrDecl(\"#{name}\",\"#{attr.type}\");" }
+ Out.print line.chomp
+end
+
+def handle_grin(line)
+ fields = line.split(/\s+/)
+ i = fields[0].to_i
+ c = $stack[-1].name
+ frame = $stack[-1]
+ Out.print "template <class T> void grin_#{i}(GRIDHANDLER_ARGS(T));"
+ Out.print "template <class T> static void grinw_#{i} (GRIDHANDLER_ARGS(T));"
+ Out.print "static GridHandler grid_#{i}_hand;"
+ handle_decl "#{i} grid(GridOutlet *foo);"
+ handle_decl "#{i} list(...);"
+ handle_decl "#{i} float(float f);"
+ $stack[-1].grins[i] = fields.dup
+end
+
+def handle_end(line)
+ frame = $stack.pop
+ fields = line.split(/\s+/)
+ n = fields.length
+ if not ClassDecl===frame then raise "\\end: frame is not a \\class" end
+ cl = frame.name
+ if fields[0]!="class" or (n>1 and not /^\{/ =~ fields[1] and fields[1]!=cl) then raise "end not matching #{where}" end
+ $stack.push frame
+ frame.grins.each {|i,v|
+ cli = "#{cl}::grinw_#{i}"
+ k = case v[1]
+ when nil ; [1,1,1,1,1,1]
+ when 'int32'; [0,0,1,0,0,0]
+ when 'int' ; [1,1,1,1,0,0]
+ when 'float' ; [0,0,0,0,1,1]
+ when 'float32'; [0,0,0,0,1,0]
+ when 'float64'; [0,0,0,0,0,1]
+ else raise 'BORK BORK BORK' end
+ ks = k.map{|ke| if ke==0 then 0 else cli end}.join(",")
+ Out.print "static GridHandler #{cl}_grid_#{i}_hand = GRIN(#{ks});"
+ handle_def "#{i} grid(GridOutlet *foo) {CHECK_GRIN(#{cl},#{i});"+
+ "in[#{i}]->begin(foo);}"
+ handle_def "#{i} list(...) {CHECK_GRIN(#{cl},#{i});"+
+ "in[#{i}]->from_list(argc,argv,int32_e);}" if not frame.methods["_#{i}_list"].done
+ handle_def "#{i} float(float f) {CHECK_GRIN(#{cl},#{i});"+
+ "t_atom2 a[1]; SETFLOAT(a,f);"+
+ "in[#{i}]->from_atom(1,a);}" if not frame.methods["_#{i}_float"].done
+ }
+ if /^class\s*(\w+\s+)?\{(.*)/ =~ line then handle_classinfo("{"+$2) end
+ $stack.pop
+ Out.print "\n#undef THISCLASS\n\# #{$linenumber}\n"
+end
+
+def handle_startall(line)
+ $classes.each {|q|
+ Out.print "fclass_install(&ci#{q.name},"
+ if q.supername then Out.print "&ci#{q.supername}" else Out.print "0" end
+ Out.print ",sizeof(#{q.name}));"
+ }
+end
+
+$linenumber=1
+loop{
+ x = In.gets
+ break if not x
+ if /^\s*\\(\w+)\s*(.*)$/.match x then
+ begin
+ send("handle_#{$1}",$2)
+ Out.puts "//FCS"
+ rescue StandardError => e
+ STDERR.puts e.inspect, "at line #{$linenumber}", e.backtrace
+ File.unlink ARGV[1]
+ exit 1
+ end
+ else Out.puts x end
+ $linenumber+=1
+}
+
+exit $exit
diff --git a/externals/gridflow/src/videodev.cxx b/externals/gridflow/src/videodev.cxx
new file mode 100644
index 00000000..d908cecf
--- /dev/null
+++ b/externals/gridflow/src/videodev.cxx
@@ -0,0 +1,793 @@
+/*
+ $Id: videodev.c 4620 2009-11-01 21:16:58Z matju $
+
+ GridFlow
+ Copyright (c) 2001-2009 by Mathieu Bouchard
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ See file ../COPYING for further informations on licensing terms.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+/* bt878 on matju's comp supports only palette 4 */
+/* bt878 on heri's comp supports palettes 3, 6, 7, 8, 9, 13 */
+/* pwc supports palettes 12 and 15 */
+
+#include "gridflow.hxx.fcs"
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <linux/videodev.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include "pwc-ioctl.h"
+
+//#define error post
+static bool debug=0;
+
+/* **************************************************************** */
+
+typedef video_capability VideoCapability;
+typedef video_channel VideoChannel ;
+typedef video_tuner VideoTuner ;
+typedef video_window VideoWindow ;
+typedef video_picture VideoPicture ;
+typedef video_mbuf VideoMbuf ;
+typedef video_mmap VideoMmap ;
+
+#define FLAG(_num_,_name_,_desc_) #_name_,
+#define OPT(_num_,_name_,_desc_) #_name_,
+
+/*
+static const char *video_type_flags[] = {
+ FLAG( 0,CAPTURE, "Can capture")
+ FLAG( 1,TUNER, "Can tune")
+ FLAG( 2,TELETEXT, "Does teletext")
+ FLAG( 3,OVERLAY, "Overlay onto frame buffer")
+ FLAG( 4,CHROMAKEY, "Overlay by chromakey")
+ FLAG( 5,CLIPPING, "Can clip")
+ FLAG( 6,FRAMERAM, "Uses the frame buffer memory")
+ FLAG( 7,SCALES, "Scalable")
+ FLAG( 8,MONOCHROME, "Monochrome only")
+ FLAG( 9,SUBCAPTURE, "Can capture subareas of the image")
+ FLAG(10,MPEG_DECODER, "Can decode MPEG streams")
+ FLAG(11,MPEG_ENCODER, "Can encode MPEG streams")
+ FLAG(12,MJPEG_DECODER, "Can decode MJPEG streams")
+ FLAG(13,MJPEG_ENCODER, "Can encode MJPEG streams")
+};
+*/
+
+static const char *tuner_flags[] = {
+ FLAG(0,PAL, "")
+ FLAG(1,NTSC, "")
+ FLAG(2,SECAM, "")
+ FLAG(3,LOW, "Uses KHz not MHz")
+ FLAG(4,NORM, "Tuner can set norm")
+ FLAG(5,DUMMY5, "")
+ FLAG(6,DUMMY6, "")
+ FLAG(7,STEREO_ON,"Tuner is seeing stereo")
+ FLAG(8,RDS_ON, "Tuner is seeing an RDS datastream")
+ FLAG(9,MBS_ON, "Tuner is seeing an MBS datastream")
+};
+
+static const char *channel_flags[] = {
+ FLAG(0,TUNER,"")
+ FLAG(1,AUDIO,"")
+ FLAG(2,NORM ,"")
+};
+
+static const char *video_palette_choice[] = {
+ OPT( 0,NIL, "(nil)")
+ OPT( 1,GREY, "Linear greyscale")
+ OPT( 2,HI240, "High 240 cube (BT848)")
+ OPT( 3,RGB565, "565 16 bit RGB")
+ OPT( 4,RGB24, "24bit RGB")
+ OPT( 5,RGB32, "32bit RGB")
+ OPT( 6,RGB555, "555 15bit RGB")
+ OPT( 7,YUV422, "YUV422 capture")
+ OPT( 8,YUYV, "")
+ OPT( 9,UYVY, "The great thing about standards is ...")
+ OPT(10,YUV420, "")
+ OPT(11,YUV411, "YUV411 capture")
+ OPT(12,RAW, "RAW capture (BT848)")
+ OPT(13,YUV422P, "YUV 4:2:2 Planar")
+ OPT(14,YUV411P, "YUV 4:1:1 Planar")
+ OPT(15,YUV420P, "YUV 4:2:0 Planar")
+ OPT(16,YUV410P, "YUV 4:1:0 Planar")
+};
+
+static const char *video_mode_choice[] = {
+ OPT( 0,PAL, "pal")
+ OPT( 1,NTSC, "ntsc")
+ OPT( 2,SECAM,"secam")
+ OPT( 3,AUTO, "auto")
+};
+
+#define WH(_field_,_spec_) \
+ sprintf(buf+strlen(buf), "%s=" _spec_ " ", #_field_, self->_field_);
+#define WHYX(_name_,_fieldy_,_fieldx_) \
+ sprintf(buf+strlen(buf), "%s=(%d %d) ", #_name_, self->_fieldy_, self->_fieldx_);
+#define WHFLAGS(_field_,_table_) { \
+ char *foo; \
+ sprintf(buf+strlen(buf), "%s:%s ", #_field_, \
+ foo=flags_to_s(self->_field_,COUNT(_table_),_table_)); \
+ free(foo);}
+#define WHCHOICE(_field_,_table_) { \
+ char *foo; \
+ sprintf(buf+strlen(buf), "%s=%s; ", #_field_, \
+ foo=choice_to_s(self->_field_,COUNT(_table_),_table_));\
+ free(foo);}
+
+static char *flags_to_s(int value, int n, const char **table) {
+ char foo[256];
+ *foo = 0;
+ for(int i=0; i<n; i++) {
+ if ((value & (1<<i)) == 0) continue;
+ if (*foo) strcat(foo," | ");
+ strcat(foo,table[i]);
+ }
+ if (!*foo) strcat(foo,"0");
+ return strdup(foo);
+}
+static char *choice_to_s(int value, int n, const char **table) {
+ if (value < 0 || value >= n) {
+ char foo[64];
+ sprintf(foo,"(Unknown #%d)",value);
+ return strdup(foo);
+ } else {
+ return strdup(table[value]);
+ }
+}
+static void gfpost(VideoChannel *self) {
+ char buf[256] = "[VideoChannel] ";
+ WH(channel,"%d");
+ WH(name,"\"%.32s\"");
+ WH(tuners,"%d");
+ WHFLAGS(flags,channel_flags);
+ WH(type,"0x%04x");
+ WH(norm,"%d");
+ post("%s",buf);
+}
+static void gfpost(VideoTuner *self) {
+ char buf[256] = "[VideoTuner] ";
+ WH(tuner,"%d");
+ WH(name,"\"%.32s\"");
+ WH(rangelow,"%lu");
+ WH(rangehigh,"%lu");
+ WHFLAGS(flags,tuner_flags);
+ WHCHOICE(mode,video_mode_choice);
+ WH(signal,"%d");
+ post("%s",buf);
+}
+static void gfpost(VideoWindow *self) {
+ char buf[256] = "[VideoWindow] ";
+ WHYX(pos,y,x);
+ WHYX(size,height,width);
+ WH(chromakey,"0x%08x");
+ WH(flags,"0x%08x");
+ WH(clipcount,"%d");
+ post("%s",buf);
+}
+static void gfpost(VideoMbuf *self) {
+ char buf[256] = "[VideoMBuf] ";
+ WH(size,"%d");
+ WH(frames,"%d");
+ sprintf(buf+strlen(buf), "offsets=[");
+ for (int i=0; i<self->frames; i++) {
+ /* WH(offsets[i],"%d"); */
+ sprintf(buf+strlen(buf), "%d%s", self->offsets[i],
+ i+1==self->frames?"]":", ");
+ }
+ post("%s",buf);
+}
+static void gfpost(VideoMmap *self) {
+ char buf[256] = "[VideoMMap] ";
+ WH(frame,"%u");
+ WHYX(size,height,width);
+ WHCHOICE(format,video_palette_choice);
+ post("%s",buf);
+};
+
+/* **************************************************************** */
+
+\class FormatVideoDev : Format {
+ VideoCapability vcaps;
+ VideoPicture vp;
+ VideoMbuf vmbuf;
+ VideoMmap vmmap;
+ uint8 *image;
+ int queue[8], queuesize, queuemax, next_frame;
+ int current_channel, current_tuner;
+ bool use_mmap, use_pwc;
+ P<BitPacking> bit_packing;
+ P<Dim> dim;
+ bool has_frequency, has_tuner, has_norm;
+ int fd;
+ int palettes; /* bitfield */
+
+ \constructor (string mode, string filename) {
+ queuesize=0; queuemax=2; next_frame=0; use_mmap=true; use_pwc=false; bit_packing=0; dim=0;
+ has_frequency=false;
+ has_tuner=false;
+ has_norm=false;
+ image=0;
+ f = fopen(filename.data(),"r+");
+ if (!f) RAISE("can't open device '%s': %s",filename.data(),strerror(errno));
+ fd = fileno(f);
+ initialize2();
+ }
+ void frame_finished (uint8 *buf);
+
+ void alloc_image ();
+ void dealloc_image ();
+ void frame_ask ();
+ void initialize2 ();
+ ~FormatVideoDev () {if (image) dealloc_image();}
+
+ \decl 0 bang ();
+ \grin 0 int
+
+ \attr int channel();
+ \attr int tuner();
+ \attr int norm();
+ \decl 0 size (int sy, int sx);
+ \decl 0 transfer (string sym, int queuemax=2);
+
+ \attr t_symbol *colorspace;
+ \attr int32 frequency();
+ \attr uint16 brightness();
+ \attr uint16 hue();
+ \attr uint16 colour();
+ \attr uint16 contrast();
+ \attr uint16 whiteness();
+
+ \attr bool pwc(); /* 0..1 */
+ \attr uint16 framerate();
+ \attr uint16 white_mode(); /* 0..1 */
+ \attr uint16 white_red();
+ \attr uint16 white_blue();
+ \attr uint16 white_speed();
+ \attr uint16 white_delay();
+ \attr int auto_gain();
+ \attr int noise_reduction(); /* 0..3 */
+ \attr int compression(); /* 0..3 */
+ \attr t_symbol *name;
+
+ \decl 0 get (t_symbol *s=0);
+};
+
+#define DEBUG(args...) 42
+//#define DEBUG(args...) post(args)
+
+#define IOCTL( F,NAME,ARG) \
+ (DEBUG("fd%d.ioctl(0x%08x,0x%08x)",F,NAME,ARG), ioctl(F,NAME,ARG))
+#define WIOCTL( F,NAME,ARG) \
+ (IOCTL(F,NAME,ARG)<0 && (error("ioctl %s: %s",#NAME,strerror(errno)),1))
+#define WIOCTL2(F,NAME,ARG) \
+ (IOCTL(F,NAME,ARG)<0 && (error("ioctl %s: %s",#NAME,strerror(errno)), RAISE("ioctl error"), 0))
+
+\def 0 get (t_symbol *s=0) {
+ // this is abnormal for a get-function
+ if (s==gensym("frequency") && !has_frequency ) return;
+ if (s==gensym("tuner") && !has_tuner ) return;
+ if (s==gensym("norm") && !has_norm ) return;
+ if (s==gensym("channel") && vcaps.channels<2) return;
+ if (!use_pwc && (s==gensym("white_mode") || s==gensym("white_red") || s==gensym("white_blue") ||
+ s==gensym("white_speed") || s==gensym("white_delay") || s==gensym("auto_gain") ||
+ s==gensym("noise_reduction") || s==gensym("compression") || s==gensym("framerate"))) return;
+ FObject::_0_get(argc,argv,s);
+ if (!s) {
+ t_atom a[2];
+ SETFLOAT(a+0,vcaps.minheight);
+ SETFLOAT(a+1,vcaps.minwidth);
+ outlet_anything(bself->outlets[0],gensym("minsize"),2,a);
+ SETFLOAT(a+0,vcaps.maxheight);
+ SETFLOAT(a+1,vcaps.maxwidth);
+ outlet_anything(bself->outlets[0],gensym("maxsize"),2,a);
+ char *foo = choice_to_s(vp.palette,COUNT(video_palette_choice),video_palette_choice);
+ SETSYMBOL(a,gensym(foo));
+ free(foo);
+ outlet_anything(bself->outlets[0],gensym("palette"),1,a);
+ SETSYMBOL(a,use_mmap ? gensym("mmap") : gensym("read"));
+ outlet_anything(bself->outlets[0],gensym("transfer"),1,a);
+ SETFLOAT(a+0,dim->v[0]);
+ SETFLOAT(a+1,dim->v[1]);
+ outlet_anything(bself->outlets[0],gensym("size"),2,a); // abnormal (does not use nested list)
+ }
+}
+
+\def 0 size (int sy, int sx) {
+ VideoWindow grab_win;
+ // !@#$ bug here: won't flush the frame queue
+ dim = new Dim(sy,sx,3);
+ WIOCTL(fd, VIDIOCGWIN, &grab_win);
+ if (debug) gfpost(&grab_win);
+ grab_win.clipcount = 0;
+ grab_win.flags = 0;
+ if (sy && sx) {
+ grab_win.height = sy;
+ grab_win.width = sx;
+ }
+ if (debug) gfpost(&grab_win);
+ WIOCTL(fd, VIDIOCSWIN, &grab_win);
+ WIOCTL(fd, VIDIOCGWIN, &grab_win);
+ if (debug) gfpost(&grab_win);
+}
+
+void FormatVideoDev::dealloc_image () {
+ if (!image) return;
+ if (use_mmap) {
+ munmap(image, vmbuf.size);
+ image=0;
+ } else {
+ delete[] (uint8 *)image;
+ }
+}
+
+void FormatVideoDev::alloc_image () {
+ if (use_mmap) {
+ WIOCTL2(fd, VIDIOCGMBUF, &vmbuf);
+ //gfpost(&vmbuf);
+ //size_t size = vmbuf.frames > 4 ? vmbuf.offsets[4] : vmbuf.size;
+ image = (uint8 *)mmap(0,vmbuf.size,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
+ if (((long)image)==-1) {image=0; RAISE("mmap: %s", strerror(errno));}
+ } else {
+ image = new uint8[dim->prod(0,1)*bit_packing->bytes];
+ }
+}
+
+void FormatVideoDev::frame_ask () {
+ if (queuesize>=queuemax) RAISE("queue is full (queuemax=%d)",queuemax);
+ if (queuesize>=vmbuf.frames) RAISE("queue is full (vmbuf.frames=%d)",vmbuf.frames);
+ vmmap.frame = queue[queuesize++] = next_frame;
+ vmmap.format = vp.palette;
+ vmmap.width = dim->get(1);
+ vmmap.height = dim->get(0);
+ WIOCTL2(fd, VIDIOCMCAPTURE, &vmmap);
+ //gfpost(&vmmap);
+ next_frame = (next_frame+1) % vmbuf.frames;
+}
+
+static uint8 clip(int x) {return x<0?0 : x>255?255 : x;}
+
+void FormatVideoDev::frame_finished (uint8 *buf) {
+ string cs = colorspace->s_name;
+ int downscale = cs=="magic";
+ /* picture is converted here. */
+ int sy = dim->get(0)>>downscale;
+ int sx = dim->get(1)>>downscale;
+ int bs = dim->prod(1)>>downscale;
+ uint8 b2[bs];
+ //post("sy=%d sx=%d bs=%d",sy,sx,bs);
+ //post("frame_finished, vp.palette = %d; colorspace = %s",vp.palette,cs.data());
+ if (vp.palette==VIDEO_PALETTE_YUV420P) {
+ GridOutlet out(this,0,cs=="magic"?new Dim(sy,sx,3):(Dim *)dim,cast);
+ if (cs=="y") {
+ out.send(sy*sx,buf);
+ } else if (cs=="rgb") {
+ for(int y=0; y<sy; y++) {
+ uint8 *bufy = buf+sx* y;
+ uint8 *bufu = buf+sx*sy +(sx/2)*(y/2);
+ uint8 *bufv = buf+sx*sy*5/4+(sx/2)*(y/2);
+ int Y1,Y2,U,V;
+ for (int x=0,xx=0; x<sx; x+=2,xx+=6) {
+ Y1=bufy[x] - 16;
+ Y2=bufy[x+1] - 16;
+ U=bufu[x/2] - 128;
+ V=bufv[x/2] - 128;
+ b2[xx+0]=clip((298*Y1 + 409*V)>>8);
+ b2[xx+1]=clip((298*Y1 - 100*U - 208*V)>>8);
+ b2[xx+2]=clip((298*Y1 + 516*U )>>8);
+ b2[xx+3]=clip((298*Y2 + 409*V)>>8);
+ b2[xx+4]=clip((298*Y2 - 100*U - 208*V)>>8);
+ b2[xx+5]=clip((298*Y2 + 516*U )>>8);
+ }
+ out.send(bs,b2);
+ }
+ } else if (cs=="yuv") {
+ for(int y=0; y<sy; y++) {
+ uint8 *bufy = buf+sx* y;
+ uint8 *bufu = buf+sx*sy +(sx/2)*(y/2);
+ uint8 *bufv = buf+sx*sy*5/4+(sx/2)*(y/2);
+ int U,V;
+ for (int x=0,xx=0; x<sx; x+=2,xx+=6) {
+ U=bufu[x/2];
+ V=bufv[x/2];
+ b2[xx+0]=clip(((bufy[x+0]-16)*298)>>8);
+ b2[xx+1]=clip(128+(((U-128)*293)>>8));
+ b2[xx+2]=clip(128+(((V-128)*293)>>8));
+ b2[xx+3]=clip(((bufy[x+1]-16)*298)>>8);
+ b2[xx+4]=clip(128+(((U-128)*293)>>8));
+ b2[xx+5]=clip(128+(((V-128)*293)>>8));
+ }
+ out.send(bs,b2);
+ }
+ } else if (cs=="magic") {
+ for(int y=0; y<sy; y++) {
+ uint8 *bufy = buf +4*sx*y;
+ uint8 *bufu = buf+4*sx*sy+ sx*y;
+ uint8 *bufv = buf+5*sx*sy+ sx*y;
+ for (int x=0,xx=0; x<sx; x++,xx+=3) {
+ b2[xx+0]=bufy[x+x];
+ b2[xx+1]=bufu[x];
+ b2[xx+2]=bufv[x];
+ }
+ out.send(bs,b2);
+ }
+ }
+ } else if (vp.palette==VIDEO_PALETTE_RGB32 || vp.palette==VIDEO_PALETTE_RGB24 || vp.palette==VIDEO_PALETTE_RGB565) {
+ GridOutlet out(this,0,dim,cast);
+ uint8 rgb[sx*3];
+ uint8 b2[sx*3];
+ if (cs=="y") {
+ for(int y=0; y<sy; y++) {
+ bit_packing->unpack(sx,buf+y*sx*bit_packing->bytes,rgb);
+ for (int x=0,xx=0; x<sx; x+=2,xx+=6) {
+ b2[x+0] = (76*rgb[xx+0]+150*rgb[xx+1]+29*rgb[xx+2])>>8;
+ b2[x+1] = (76*rgb[xx+3]+150*rgb[xx+4]+29*rgb[xx+5])>>8;
+ }
+ out.send(bs,b2);
+ }
+ } else if (cs=="rgb") {
+ for(int y=0; y<sy; y++) {
+ bit_packing->unpack(sx,buf+y*sx*bit_packing->bytes,rgb);
+ out.send(bs,rgb);
+ }
+ } else if (cs=="yuv") {
+ for(int y=0; y<sy; y++) {
+ bit_packing->unpack(sx,buf+y*sx*bit_packing->bytes,rgb);
+ for (int x=0,xx=0; x<sx; x+=2,xx+=6) {
+ b2[xx+0] = clip( (( 76*rgb[xx+0] + 150*rgb[xx+1] + 29*rgb[xx+2])>>8));
+ b2[xx+1] = clip(128+((- 44*rgb[xx+0] - 85*rgb[xx+1] + 108*rgb[xx+2])>>8));
+ b2[xx+2] = clip(128+(( 128*rgb[xx+0] - 108*rgb[xx+1] - 21*rgb[xx+2])>>8));
+ b2[xx+3] = clip( (( 76*rgb[xx+3] + 150*rgb[xx+4] + 29*rgb[xx+5])>>8));
+ b2[xx+4] = clip(128+((- 44*rgb[xx+3] - 85*rgb[xx+4] + 108*rgb[xx+5])>>8));
+ b2[xx+5] = clip(128+(( 128*rgb[xx+3] - 108*rgb[xx+4] - 21*rgb[xx+5])>>8));
+ }
+ out.send(bs,b2);
+ }
+ } else if (cs=="magic") {
+ RAISE("magic colorspace not supported with a RGB palette");
+ }
+ } else {
+ RAISE("unsupported palette %d",vp.palette);
+ }
+}
+
+/* these are factors for RGB to analog YUV */
+// Y = 66*R + 129*G + 25*B
+// U = - 38*R - 74*G + 112*B
+// V = 112*R - 94*G - 18*B
+
+// strange that read2 is not used and read3 is used instead
+static int read2(int fd, uint8 *image, int n) {
+ int r=0;
+ while (n>0) {
+ int rr=read(fd,image,n);
+ if (rr<0) return rr; else {r+=rr; image+=rr; n-=rr;}
+ }
+ return r;
+}
+
+static int read3(int fd, uint8 *image, int n) {
+ int r=read(fd,image,n);
+ if (r<0) return r;
+ return n;
+}
+
+\def 0 bang () {
+ if (!image) alloc_image();
+ if (!use_mmap) {
+ /* picture is read at once by frame() to facilitate debugging. */
+ int tot = dim->prod(0,1) * bit_packing->bytes;
+ int n = (int) read3(fd,image,tot);
+ if (n==tot) frame_finished(image);
+ if (0> n) RAISE("error reading: %s", strerror(errno));
+ if (n < tot) RAISE("unexpectedly short picture: %d of %d",n,tot);
+ return;
+ }
+ while(queuesize<queuemax) frame_ask();
+ vmmap.frame = queue[0];
+ //uint64 t0 = gf_timeofday();
+ WIOCTL2(fd, VIDIOCSYNC, &vmmap);
+ //uint64 t1 = gf_timeofday();
+ //if (t1-t0 > 100) gfpost("VIDIOCSYNC delay: %d us",t1-t0);
+ frame_finished(image+vmbuf.offsets[queue[0]]);
+ queuesize--;
+ for (int i=0; i<queuesize; i++) queue[i]=queue[i+1];
+ frame_ask();
+}
+
+GRID_INLET(0) {
+ RAISE("can't write.");
+} GRID_FLOW {
+} GRID_FINISH {
+} GRID_END
+
+\def 0 norm (int value) {
+ VideoTuner vtuner;
+ vtuner.tuner = current_tuner;
+ if (value<0 || value>3) RAISE("norm must be in range 0..3");
+ if (0> IOCTL(fd, VIDIOCGTUNER, &vtuner)) {
+ post("no tuner #%d", value);
+ } else {
+ vtuner.mode = value;
+ gfpost(&vtuner);
+ WIOCTL(fd, VIDIOCSTUNER, &vtuner);
+ }
+}
+
+\def int norm () {
+ VideoTuner vtuner;
+ vtuner.tuner = current_tuner;
+ if (0> IOCTL(fd, VIDIOCGTUNER, &vtuner)) {post("no tuner #%d", current_tuner); return -1;}
+ return vtuner.mode;
+}
+
+\def 0 tuner (int value) {
+ VideoTuner vtuner;
+ vtuner.tuner = current_tuner = value;
+ if (0> IOCTL(fd, VIDIOCGTUNER, &vtuner)) RAISE("no tuner #%d", value);
+ vtuner.mode = VIDEO_MODE_NTSC; //???
+ gfpost(&vtuner);
+ WIOCTL(fd, VIDIOCSTUNER, &vtuner);
+ has_norm = (vtuner.mode<=3);
+ int meuh;
+ has_frequency = (ioctl(fd, VIDIOCGFREQ, &meuh)>=0);
+}
+\def int tuner () {return current_tuner;}
+
+#define warn(fmt,stuff...) post("warning: " fmt,stuff)
+
+\def 0 channel (int value) {
+ VideoChannel vchan;
+ vchan.channel = value;
+ current_channel = value;
+ if (0> IOCTL(fd, VIDIOCGCHAN, &vchan)) warn("no channel #%d", value);
+ //gfpost(&vchan);
+ WIOCTL(fd, VIDIOCSCHAN, &vchan);
+ if (vcaps.type & VID_TYPE_TUNER) _0_tuner(0,0,0);
+ has_tuner = (vcaps.type & VID_TYPE_TUNER && vchan.tuners > 1);
+}
+\def int channel () {return current_channel;}
+
+\def 0 transfer (string sym, int queuemax=2) {
+ if (sym=="read") {
+ dealloc_image();
+ use_mmap = false;
+ post("transfer read");
+ } else if (sym=="mmap") {
+ dealloc_image();
+ use_mmap = true;
+ alloc_image();
+ queuemax=min(8,min(queuemax,vmbuf.frames));
+ post("transfer mmap with queuemax=%d (max max is vmbuf.frames=%d)", queuemax,vmbuf.frames);
+ this->queuemax=queuemax;
+ } else RAISE("don't know that transfer mode");
+}
+
+#define PICTURE_ATTR(_name_) {\
+ WIOCTL(fd, VIDIOCGPICT, &vp); \
+ vp._name_ = _name_; \
+ WIOCTL(fd, VIDIOCSPICT, &vp);}
+
+#define PICTURE_ATTRGET(_name_) { \
+ WIOCTL(fd, VIDIOCGPICT, &vp); \
+ /*gfpost("getting %s=%d",#_name_,vp._name_);*/ \
+ return vp._name_;}
+
+\def uint16 brightness () {PICTURE_ATTRGET(brightness)}
+\def 0 brightness (uint16 brightness){PICTURE_ATTR( brightness)}
+\def uint16 hue () {PICTURE_ATTRGET(hue)}
+\def 0 hue (uint16 hue) {PICTURE_ATTR( hue)}
+\def uint16 colour () {PICTURE_ATTRGET(colour)}
+\def 0 colour (uint16 colour) {PICTURE_ATTR( colour)}
+\def uint16 contrast () {PICTURE_ATTRGET(contrast)}
+\def 0 contrast (uint16 contrast) {PICTURE_ATTR( contrast)}
+\def uint16 whiteness () {PICTURE_ATTRGET(whiteness)}
+\def 0 whiteness (uint16 whiteness) {PICTURE_ATTR( whiteness)}
+\def int32 frequency () {
+ int32 value;
+ //if (ioctl(fd, VIDIOCGFREQ, &value)<0) {has_frequency=false; return 0;}
+ WIOCTL(fd, VIDIOCGFREQ, &value);
+ return value;
+}
+\def 0 frequency (int32 frequency) {
+ long frequency_ = frequency;
+ WIOCTL(fd, VIDIOCSFREQ, &frequency_);
+}
+
+\def 0 colorspace (t_symbol *colorspace) { /* y yuv rgb magic */
+ string c = colorspace->s_name;
+ if (c=="y") {}
+ else if (c=="yuv") {}
+ else if (c=="rgb") {}
+ else if (c=="magic") {}
+ else RAISE("got '%s' but supported colorspaces are: y yuv rgb magic",c.data());
+ WIOCTL(fd, VIDIOCGPICT, &vp);
+ int palette = (palettes&(1<<VIDEO_PALETTE_RGB24)) ? VIDEO_PALETTE_RGB24 :
+ (palettes&(1<<VIDEO_PALETTE_RGB32)) ? VIDEO_PALETTE_RGB32 :
+ (palettes&(1<<VIDEO_PALETTE_RGB565)) ? VIDEO_PALETTE_RGB565 :
+ VIDEO_PALETTE_YUV420P;
+ vp.palette = palette;
+ WIOCTL(fd, VIDIOCSPICT, &vp);
+ WIOCTL(fd, VIDIOCGPICT, &vp);
+ if (vp.palette != palette) {
+ post("this driver is unsupported: it wants palette %d instead of %d",vp.palette,palette);
+ return;
+ }
+ if (palette == VIDEO_PALETTE_RGB565) {
+ //uint32 masks[3] = { 0x00fc00,0x003e00,0x00001f };
+ uint32 masks[3] = { 0x00f800,0x007e0,0x00001f };
+ bit_packing = new BitPacking(is_le(),2,3,masks);
+ } else if (palette == VIDEO_PALETTE_RGB32) {
+ uint32 masks[3] = { 0xff0000,0x00ff00,0x0000ff };
+ bit_packing = new BitPacking(is_le(),4,3,masks);
+ } else {
+ uint32 masks[3] = { 0xff0000,0x00ff00,0x0000ff };
+ bit_packing = new BitPacking(is_le(),3,3,masks);
+ }
+ this->colorspace=gensym(c.data());
+ dim = new Dim(dim->v[0],dim->v[1],c=="y"?1:3);
+}
+
+\def bool pwc () {return use_pwc;}
+\def 0 pwc (bool pwc) {use_pwc=pwc;}
+
+void set_pan_and_tilt(int fd, char what, int pan, int tilt) { /*unused*/
+ // if (!use_pwc) return;
+ struct pwc_mpt_angles pma;
+ pma.absolute=1;
+ WIOCTL(fd, VIDIOCPWCMPTGANGLE, &pma);
+ pma.pan = pan;
+ pma.tilt = tilt;
+ WIOCTL(fd, VIDIOCPWCMPTSANGLE, &pma);
+}
+
+\def uint16 framerate() {
+ if (!use_pwc) return 0;
+ struct video_window vwin;
+ WIOCTL(fd, VIDIOCGWIN, &vwin);
+ return (vwin.flags & PWC_FPS_MASK) >> PWC_FPS_SHIFT;
+}
+
+\def 0 framerate(uint16 framerate) {
+ if (!use_pwc) return;
+ struct video_window vwin;
+ WIOCTL(fd, VIDIOCGWIN, &vwin);
+ vwin.flags &= ~PWC_FPS_FRMASK;
+ vwin.flags |= (framerate << PWC_FPS_SHIFT) & PWC_FPS_FRMASK;
+ WIOCTL(fd, VIDIOCSWIN, &vwin);
+}
+
+/* those functions are still mostly unused */
+//void set_compression_preference(int fd, int pref) {if (use_pwc) WIOCTL(fd, VIDIOCPWCSCQUAL, &pref);}
+
+\def int auto_gain() {int auto_gain=0; if (use_pwc) WIOCTL(fd, VIDIOCPWCGAGC, &auto_gain); return auto_gain;}
+\def 0 auto_gain (int auto_gain) {if (use_pwc) WIOCTL(fd, VIDIOCPWCSAGC, &auto_gain);}
+
+//void set_shutter_speed(int fd, int pref) {if (use_pwc) WIOCTL(fd, VIDIOCPWCSSHUTTER, &pref);}
+
+\def uint16 white_mode () {
+ if (!use_pwc) return 0;
+ struct pwc_whitebalance pwcwb;
+ WIOCTL(fd, VIDIOCPWCGAWB, &pwcwb);
+ if (pwcwb.mode==PWC_WB_AUTO) return 0;
+ if (pwcwb.mode==PWC_WB_MANUAL) return 1;
+ return 2;
+}
+
+\def 0 white_mode (uint16 white_mode) {
+ if (!use_pwc) return;
+ struct pwc_whitebalance pwcwb;
+ WIOCTL(fd, VIDIOCPWCGAWB, &pwcwb);
+ if (white_mode==0) pwcwb.mode = PWC_WB_AUTO;
+ else if (white_mode==1) pwcwb.mode = PWC_WB_MANUAL;
+ /*else if (strcasecmp(mode, "indoor") == 0) pwcwb.mode = PWC_WB_INDOOR;*/
+ /*else if (strcasecmp(mode, "outdoor") == 0) pwcwb.mode = PWC_WB_OUTDOOR;*/
+ /*else if (strcasecmp(mode, "fl") == 0) pwcwb.mode = PWC_WB_FL;*/
+ else {error("unknown mode number %d", white_mode); return;}
+ WIOCTL(fd, VIDIOCPWCSAWB, &pwcwb);}
+
+\def uint16 white_red() {if (!use_pwc) return 0;
+ struct pwc_whitebalance pwcwb; WIOCTL(fd, VIDIOCPWCGAWB, &pwcwb); return pwcwb.manual_red;}
+\def uint16 white_blue() {if (!use_pwc) return 0;
+ struct pwc_whitebalance pwcwb; WIOCTL(fd, VIDIOCPWCGAWB, &pwcwb); return pwcwb.manual_blue;}
+\def 0 white_red(uint16 white_red) {if (!use_pwc) return;
+ struct pwc_whitebalance pwcwb; WIOCTL(fd, VIDIOCPWCGAWB, &pwcwb);
+ pwcwb.manual_red = white_red; WIOCTL(fd, VIDIOCPWCSAWB, &pwcwb);}
+\def 0 white_blue(uint16 white_blue) {if (!use_pwc) return;
+ struct pwc_whitebalance pwcwb; WIOCTL(fd, VIDIOCPWCGAWB, &pwcwb);
+ pwcwb.manual_blue = white_blue;WIOCTL(fd, VIDIOCPWCSAWB, &pwcwb);}
+
+\def uint16 white_speed() {if (!use_pwc) return 0;
+ struct pwc_wb_speed pwcwbs; WIOCTL(fd, VIDIOCPWCGAWBSPEED, &pwcwbs); return pwcwbs.control_speed;}
+\def uint16 white_delay() {if (!use_pwc) return 0;
+ struct pwc_wb_speed pwcwbs; WIOCTL(fd, VIDIOCPWCGAWBSPEED, &pwcwbs); return pwcwbs.control_delay;}
+\def 0 white_speed(uint16 white_speed) {if (!use_pwc) return;
+ struct pwc_wb_speed pwcwbs; WIOCTL(fd, VIDIOCPWCGAWBSPEED, &pwcwbs);
+ pwcwbs.control_speed = white_speed; WIOCTL(fd, VIDIOCPWCSAWBSPEED, &pwcwbs);}
+\def 0 white_delay(uint16 white_delay) {if (!use_pwc) return;
+ struct pwc_wb_speed pwcwbs; WIOCTL(fd, VIDIOCPWCGAWBSPEED, &pwcwbs);
+ pwcwbs.control_delay = white_delay; WIOCTL(fd, VIDIOCPWCSAWBSPEED, &pwcwbs);}
+
+void set_led_on_time(int fd, int val) {
+ struct pwc_leds pwcl; WIOCTL(fd, VIDIOCPWCGLED, &pwcl);
+ pwcl.led_on = val; WIOCTL(fd, VIDIOCPWCSLED, &pwcl);}
+void set_led_off_time(int fd, int val) {
+ struct pwc_leds pwcl; WIOCTL(fd, VIDIOCPWCGLED, &pwcl);
+ pwcl.led_off = val; WIOCTL(fd, VIDIOCPWCSLED, &pwcl);}
+void set_sharpness(int fd, int val) {WIOCTL(fd, VIDIOCPWCSCONTOUR, &val);}
+void set_backlight_compensation(int fd, int val) {WIOCTL(fd, VIDIOCPWCSBACKLIGHT, &val);}
+void set_antiflicker_mode(int fd, int val) {WIOCTL(fd, VIDIOCPWCSFLICKER, &val);}
+
+\def int noise_reduction() {
+ if (!use_pwc) return 0;
+ int noise_reduction;
+ WIOCTL(fd, VIDIOCPWCGDYNNOISE, &noise_reduction);
+ return noise_reduction;
+}
+\def 0 noise_reduction(int noise_reduction) {
+ if (!use_pwc) return;
+ WIOCTL(fd, VIDIOCPWCSDYNNOISE, &noise_reduction);
+}
+\def int compression() {
+ if (!use_pwc) return 0;
+ int compression;
+ WIOCTL(fd, VIDIOCPWCSCQUAL, &compression);
+ return compression;
+}
+\def 0 compression(int compression) {
+ if (!use_pwc) return;
+ WIOCTL(fd, VIDIOCPWCGCQUAL, &compression);
+}
+
+void FormatVideoDev::initialize2 () {
+ WIOCTL(fd, VIDIOCGCAP, &vcaps);
+ _0_size(0,0,vcaps.maxheight,vcaps.maxwidth);
+ char namebuf[33];
+ memcpy(namebuf,vcaps.name,sizeof(vcaps.name));
+ int i;
+ for (i=32; i>=1; i--) if (!namebuf[i] || !isspace(namebuf[i])) break;
+ namebuf[i]=0;
+ while (--i>=0) if (isspace(namebuf[i])) namebuf[i]='_';
+ name = gensym(namebuf);
+ WIOCTL(fd, VIDIOCGPICT,&vp);
+ palettes=0;
+ int checklist[] = {VIDEO_PALETTE_RGB565,VIDEO_PALETTE_RGB24,VIDEO_PALETTE_RGB32,VIDEO_PALETTE_YUV420P};
+#if 1
+ for (size_t i=0; i<sizeof(checklist)/sizeof(*checklist); i++) {
+ int p = checklist[i];
+#else
+ for (size_t p=0; p<17; p++) {
+#endif
+ vp.palette = p;
+ ioctl(fd, VIDIOCSPICT,&vp);
+ ioctl(fd, VIDIOCGPICT,&vp);
+ if (vp.palette == p) {
+ palettes |= 1<<p;
+ post("palette %d supported",p);
+ }
+ }
+ _0_colorspace(0,0,gensym("rgb"));
+ _0_channel(0,0,0);
+}
+
+\end class FormatVideoDev {install_format("#io.videodev",4,"");}
+void startup_videodev () {
+ \startall
+}
diff --git a/externals/gridflow/src/x11.cxx b/externals/gridflow/src/x11.cxx
new file mode 100644
index 00000000..46778089
--- /dev/null
+++ b/externals/gridflow/src/x11.cxx
@@ -0,0 +1,664 @@
+/*
+ $Id: x11.c 4620 2009-11-01 21:16:58Z matju $
+
+ GridFlow
+ Copyright (c) 2001-2009 by Mathieu Bouchard
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ See file ../COPYING for further informations on licensing terms.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Note: some of the code was adapted from PDP's (the XVideo stuff).
+*/
+#include "gridflow.hxx.fcs"
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <string>
+#include <sys/time.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+//#include <X11/StringDefs.h>
+#ifdef HAVE_X11_SHARED_MEMORY
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <X11/extensions/XShm.h>
+#endif
+#ifdef HAVE_X11_XVIDEO
+#include <X11/extensions/Xv.h>
+#include <X11/extensions/Xvlib.h>
+#endif
+
+/* X11 Error Handler type */
+typedef int (*XEH)(Display *, XErrorEvent *);
+
+struct FormatX11;
+void FormatX11_call(FormatX11 *p);
+
+\class FormatX11 : Format {
+/* at the Display/Screen level */
+ Display *display; /* connection to xserver */
+ Visual *visual; /* screen properties */
+ Window root_window;
+ Colormap colormap;/* for 256-color mode */
+ short depth;
+ bool use_stripes; /* use alternate conversion in 256-color mode */
+ bool shared_memory;
+ bool xvideo;
+/* at the Window level */
+ Window window; /* X11 window number */
+ Window parent; /* X11 window number of the parent */
+ GC imagegc; /* X11 graphics context (like java.awt.Graphics) */
+ XImage *ximage; /* X11 image descriptor */
+ uint8 *image; /* the real data (that XImage binds to) */
+ bool is_owner;
+ int32 pos[2];
+ P<BitPacking> bit_packing;
+ P<Dim> dim;
+ bool lock_size;
+ bool override_redirect;
+ t_clock *clock;
+ std::string title;
+#ifdef HAVE_X11_SHARED_MEMORY
+ XShmSegmentInfo *shm_info; /* to share memory with X11/Unix */
+#endif
+#ifdef HAVE_X11_XVIDEO
+ int xv_format;
+ int xv_port;
+ XvImage *xvi; /* ils sont fous ces romains */
+ unsigned char *data;
+ int last_encoding;
+#endif
+ ~FormatX11 () {
+ clock_unset(clock);
+ if (is_owner) XDestroyWindow(display,window);
+ XSync(display,0);
+ dealloc_image();
+ if (imagegc) XFreeGC(display,imagegc);
+ XCloseDisplay(display);
+ }
+ template <class T> void frame_by_type (T bogus);
+ void show_section(int x, int y, int sx, int sy);
+ void set_wm_hints ();
+ void dealloc_image ();
+ bool alloc_image (int sx, int sy);
+ void resize_window (int sx, int sy);
+ void open_display(const char *disp_string);
+ void report_pointer(int y, int x, int state);
+ void prepare_colormap();
+ Window search_window_tree (Window xid, Atom key, const char *value, int level=0);
+ \constructor (...) {
+ shared_memory=false; xvideo=false; use_stripes=false; window=0; ximage=0; image=0; is_owner=true;
+ dim=0; lock_size=false; override_redirect=false; clock=0; imagegc=0;
+#ifdef HAVE_X11_SHARED_MEMORY
+ shm_info=0;
+#endif
+ int sy=240, sx=320; // defaults
+ argv++, argc--;
+ t_symbol *domain = argc<1 ? gensym("here") : argv[0];
+ int i;
+ char host[256];
+ if (domain==gensym("here")) {
+ open_display(0);
+ i=1;
+ } else if (domain==gensym("local")) {
+ if (argc<2) RAISE("open x11 local: not enough args");
+ sprintf(host,":%d",int32(argv[1]));
+ open_display(host);
+ i=2;
+ } else if (domain==gensym("remote")) {
+ if (argc<3) RAISE("open x11 remote: not enough args");
+ sprintf(host,"%s:%d",string(argv[1]).data(),int32(argv[2]));
+ open_display(host);
+ i=3;
+ } else if (domain==gensym("display")) {
+ if (argc<2) RAISE("open x11 display: not enough args");
+ strcpy(host,string(argv[1]).data());
+ for (int k=0; host[k]; k++) if (host[k]=='%') host[k]==':';
+ post("mode `display', DISPLAY=`%s'",host);
+ open_display(host);
+ i=2;
+ } else RAISE("x11 destination syntax error");
+ for(;i<argc;i++) {
+ if (argv[i]==gensym("override_redirect")) override_redirect = true;
+ else if (argv[i]==gensym("use_stripes")) use_stripes = true;
+ else break; /*RAISE("argument '%s' not recognized",string(argv[i]).data());*/
+ }
+ pos[1]=pos[0]=0;
+ parent = root_window;
+ if (i>=argc) {
+ } else {
+ const t_atom2 &winspec = argv[i];
+ if (winspec==gensym("root")) {
+ window = root_window;
+ is_owner = false;
+ } else if (winspec==gensym("embed")) {
+ string title = argv[i+1];
+ sy = sx = pos[0] = pos[1] = 0;
+ parent = search_window_tree(root_window,XInternAtom(display,"WM_NAME",0),title.data());
+ if (parent == 0xDeadBeef) RAISE("Window not found.");
+ } else if (winspec==gensym("embed_by_id")) {
+ const char *winspec2 = string(argv[i+1]).data();
+ if (strncmp(winspec2,"0x",2)==0) {
+ parent = strtol(winspec2+2,0,16);
+ } else {
+ parent = atoi(winspec2);
+ }
+ } else {
+ if (winspec.a_type==A_SYMBOL) {
+ const char *winspec2 = string(winspec).data();
+ if (strncmp(winspec2,"0x",2)==0) {
+ window = strtol(winspec2+2,0,16);
+ } else {
+ window = atoi(winspec2); // huh?
+ }
+ } else {
+ window = INT(winspec);
+ }
+ is_owner = false;
+ sy = sx = pos[0] = pos[1] = 0;
+ }
+ }
+ resize_window(sx,sy); // "resize" also takes care of creation
+ if (is_owner) {
+ Atom wmDeleteAtom = XInternAtom(display, "WM_DELETE_WINDOW", False);
+ XSetWMProtocols(display,window,&wmDeleteAtom,1);
+ }
+ Visual *v = visual;
+ int disp_is_le = !ImageByteOrder(display);
+ int bpp = ximage->bits_per_pixel;
+ switch(visual->c_class) {
+ case TrueColor: case DirectColor: {
+ uint32 masks[3] = { v->red_mask, v->green_mask, v->blue_mask };
+ bit_packing = new BitPacking(disp_is_le, bpp/8, 3, masks);
+ } break;
+ case PseudoColor: {
+ uint32 masks[3] = { 0x07, 0x38, 0xC0 }; // BBGGGRRR
+ bit_packing = new BitPacking(disp_is_le, bpp/8, 3, masks);
+ } break;
+ default: RAISE("huh?");
+ }
+ clock = clock_new(this,(t_method)FormatX11_call);
+ clock_delay(clock,0);
+ show_section(0,0,sx,sy);
+ if ((mode&4)!=0) {
+ Window root; int x,y; unsigned sx,sy,sb,depth;
+ XGetGeometry(display,window,&root,&x,&y,&sx,&sy,&sb,&depth);
+ post("sx=%d sy=%d",sx,sy);
+ _0_out_size(argc,argv,sy,sx);
+ }
+ }
+
+ \decl 0 bang ();
+ void call ();
+ \decl 0 out_size (int sy, int sx);
+ \decl 0 setcursor (int shape);
+ \decl 0 hidecursor ();
+ \decl 0 set_geometry (int y, int x, int sy, int sx);
+ \decl 0 move (int y, int x);
+ \decl 0 shared_memory (bool toggle);
+ \decl 0 xvideo (bool toggle);
+ \decl 0 title (string title="");
+ \decl 0 warp (int y, int x);
+ \grin 0 int
+};
+
+/* ---------------------------------------------------------------- */
+
+void FormatX11::show_section(int x, int y, int sx, int sy) {
+ if ((mode&2)==0) return;
+ int zy=dim->get(0), zx=dim->get(1);
+ if (y>zy||x>zx) return;
+ if (y+sy>zy) sy=zy-y;
+ if (x+sx>zx) sx=zx-x;
+#ifndef HAVE_X11_XVIDEO
+ if (xvideo) RAISE("xvideo not available (recompile)");
+#endif
+#ifndef HAVE_X11_SHARED_MEMORY
+ if (shared_memory) RAISE("xshm not available (recompile)");
+#endif
+ if (xvideo) {
+#ifdef HAVE_X11_XVIDEO
+ if (shared_memory) {
+#ifdef HAVE_X11_SHARED_MEMORY
+
+#endif // shm
+ } else {
+ XvPutImage(display,port,window,imagegc,ximage,
+ xvi, 0, 0, image_width, image_height,
+ drwX - (vo_panscan_x >> 1), drwY - (vo_panscan_y >> 1),
+ vo_dwidth + vo_panscan_x,
+ vo_dheight + vo_panscan_y);
+
+ }
+#endif // xvideo
+ } else {
+ if (shared_memory) {
+#ifdef HAVE_X11_SHARED_MEMORY
+ XSync(display,False);
+ XShmPutImage(display,window,imagegc,ximage,x,y,x,y,sx,sy,False);
+ XFlush(display);
+ //XPutImage( display,window,imagegc,ximage,x,y,x,y,sx,sy);
+ // should completion events be waited for? looks like a bug
+#endif // xshm
+ } else {
+ XPutImage(display,window,imagegc,ximage,x,y,x,y,sx,sy);
+ XFlush(display);
+ }
+ }
+}
+
+/* window manager hints, defines the window as non-resizable */
+void FormatX11::set_wm_hints () {
+ if (!is_owner) return;
+ XWMHints wmh;
+ char buf[256],*bufp=buf;
+ if (title=="") {
+ sprintf(buf,"GridFlow (%d,%d,%d)",dim->get(0),dim->get(1),dim->get(2));
+ } else {
+ sprintf(buf,"%.255s",title.data());
+ }
+ XTextProperty wtitle; XStringListToTextProperty((char **)&bufp, 1, &wtitle);
+ XSizeHints sh;
+ sh.flags=PSize|PMaxSize|PMinSize;
+ sh.min_width = sh.max_width = sh.width = dim->get(1);
+ sh.min_height = sh.max_height = sh.height = dim->get(0);
+ wmh.input = True;
+ wmh.flags = InputHint;
+ XSetWMProperties(display,window,&wtitle,&wtitle,0,0,&sh,&wmh,0);
+ XFree(wtitle.value); // do i really have to do that?
+}
+
+void FormatX11::report_pointer(int y, int x, int state) {
+ t_atom a[3];
+ SETFLOAT(a+0,y);
+ SETFLOAT(a+1,x);
+ SETFLOAT(a+2,state);
+ outlet_anything(bself->outlets[0],gensym("position"),COUNT(a),a);
+}
+
+void FormatX11::call() {
+ XEvent e;
+ for (;;) {
+ int xpending = XEventsQueued(display, QueuedAfterFlush);
+ if (!xpending) break;
+ XNextEvent(display,&e);
+ switch (e.type) {
+ case Expose:{
+ XExposeEvent *ex = (XExposeEvent *)&e;
+ if (mode==2) show_section(ex->x,ex->y,ex->width,ex->height);
+ }break;
+ case ButtonPress:{
+ XButtonEvent *eb = (XButtonEvent *)&e;
+ eb->state |= 128<<eb->button;
+ report_pointer(eb->y,eb->x,eb->state);
+ }break;
+ case ButtonRelease:{
+ XButtonEvent *eb = (XButtonEvent *)&e;
+ eb->state &= ~(128<<eb->button);
+ report_pointer(eb->y,eb->x,eb->state);
+ }break;
+ case KeyPress:
+ case KeyRelease:{
+ XKeyEvent *ek = (XKeyEvent *)&e;
+ //XLookupString(ek, buf, 63, 0, 0);
+ char *kss = XKeysymToString(XLookupKeysym(ek, 0));
+ char buf[64];
+ if (!kss) return; /* unknown keys ignored */
+ if (isdigit(*kss)) sprintf(buf,"D%s",kss); else strcpy(buf,kss);
+ t_atom at[4];
+ t_symbol *sel = gensym(const_cast<char *>(e.type==KeyPress ? "keypress" : "keyrelease"));
+ SETFLOAT(at+0,ek->y);
+ SETFLOAT(at+1,ek->x);
+ SETFLOAT(at+2,ek->state);
+ SETSYMBOL(at+3,gensym(buf));
+ outlet_anything(bself->outlets[0],sel,4,at);
+ //XFree(kss);
+ }break;
+ case MotionNotify:{
+ XMotionEvent *em = (XMotionEvent *)&e;
+ report_pointer(em->y,em->x,em->state);
+ }break;
+ case DestroyNotify:{
+ post("This window is being closed, so this handler will close too!");
+ delete this; /* really! what else could i do here anyway? */
+ return;
+ }break;
+ case ConfigureNotify:break; // as if we cared
+ }
+ }
+ clock_delay(clock,20);
+}
+void FormatX11_call(FormatX11 *p) {p->call();}
+
+\def 0 bang () {
+ XGetSubImage(display, window, 0, 0, dim->get(1), dim->get(0), (unsigned)-1, ZPixmap, ximage, 0, 0);
+ GridOutlet out(this,0,dim,cast);
+ int sy=dim->get(0), sx=dim->get(1), bs=dim->prod(1);
+ uint8 b2[bs];
+ for(int y=0; y<sy; y++) {
+ uint8 *b1 = image + ximage->bytes_per_line * y;
+ bit_packing->unpack(sx,b1,b2);
+ out.send(bs,b2);
+ }
+}
+
+/* loathe Xlib's error handlers */
+static FormatX11 *current_x11;
+static int FormatX11_error_handler (Display *d, XErrorEvent *xee) {
+ post("XErrorEvent: type=0x%08x display=0x%08x xid=0x%08x",
+ xee->type, xee->display, xee->resourceid);
+ post("... serial=0x%08x error=0x%08x request=0x%08lx minor=0x%08x",
+ xee->serial, xee->error_code, xee->request_code, xee->minor_code);
+ if (current_x11->shared_memory==1) {
+ post("(note: turning shm off)");
+ current_x11->shared_memory = 0;
+ }
+ return 42; /* it seems that the return value is ignored. */
+}
+
+bool FormatX11::alloc_image (int sx, int sy) {
+ dim = new Dim(sy,sx,3);
+ dealloc_image();
+ if (sx==0 || sy==0) return false;
+ current_x11 = this;
+ if (!shared_memory) {
+ ximage = XCreateImage(display,visual,depth,ZPixmap,0,0,sx,sy,8,0);
+ int size = ximage->bytes_per_line*ximage->height;
+ if (!ximage) RAISE("can't create image");
+ image = new uint8[size];
+ ximage->data = (int8 *)image;
+ } else {
+#ifdef HAVE_X11_SHARED_MEMORY
+ shm_info = new XShmSegmentInfo;
+ ximage = XShmCreateImage(display,visual,depth,ZPixmap,0,shm_info,sx,sy);
+ if (!ximage) {post("x11: will retry without shared memory"); shared_memory=false;}
+ XSync(display,0);
+ if (!shared_memory) return alloc_image(sx,sy);
+ int size = ximage->bytes_per_line*ximage->height;
+ shm_info->shmid = shmget(IPC_PRIVATE,size,IPC_CREAT|0777);
+ if(shm_info->shmid < 0) RAISE("shmget() failed: %s",strerror(errno));
+ ximage->data = shm_info->shmaddr = (char *)shmat(shm_info->shmid,0,0);
+ if ((long)(shm_info->shmaddr) == -1) RAISE("shmat() failed: %s",strerror(errno));
+ image = (uint8 *)ximage->data;
+ shm_info->readOnly = False;
+ if (!XShmAttach(display, shm_info)) RAISE("ERROR: XShmAttach: big problem");
+ XSync(display,0); // make sure the server picks it up
+ // yes, this can be done now. should cause auto-cleanup.
+ shmctl(shm_info->shmid,IPC_RMID,0);
+ if (!shared_memory) return alloc_image(sx,sy);
+#endif
+ }
+#ifdef HAVE_X11_XVIDEO
+ if (xvideo) {
+ unsigned int ver, rel, req, ev, err, i, j, adaptors, formats;
+ XvAdaptorInfo *ai;
+ if (Success != XvQueryExtension(display,&ver,&rel,&req,&ev,&err)) RAISE("XvQueryExtension problem");
+ /* find + lock port */
+ if (Success != XvQueryAdaptors(display,DefaultRootWindow(display),&adaptors,&ai)) RAISE("XvQueryAdaptors problem");
+ for (i = 0; i < adaptors; i++) {
+ if (ai[i].type&XvInputMask && ai[i].type&XvImageMask) {
+ for (j=0; j<ai[i].num_ports; j++) {
+ if (Success != XvGrabPort(display,ai[i].base_id+j,CurrentTime)) RAISE("XvGrabPort problem");
+ xv_port = ai[i].base_id + j;
+ goto breakout;
+ }
+ }
+ }
+ breakout:
+ XFree(ai);
+ if (!xv_port) RAISE("no xv_port");
+/*
+ unsigned int encn;
+ XvEncodingInfo *enc;
+ XvQueryEncodings(display,xv_port,&encn,&enc);
+ for (i=0; i<encn; i++) post("XvEncodingInfo: name='%s' encoding_id=0x%08x",enc[i].name,enc[i].encoding_id);
+ post("pdp_xvideo: grabbed port %d on adaptor %d",xv_port,i);
+ size_t size = sx*sy*4;
+ data = new uint8[size];
+ for (i=0; i<size; i++) data[i]=0;
+ xvi = XvCreateImage(display,xv_port,0x51525762,(char *)data,sx,sy);
+ last_encoding=-1;
+ if (!xvi) RAISE("XvCreateImage problem");
+*/
+ }
+#endif
+ int status = XInitImage(ximage);
+ if (status!=1) post("XInitImage returned: %d", status);
+ return true;
+retry:
+ post("couldn't allocate image buffer for output... retrying...");
+ return alloc_image(sx,sy);
+}
+
+void FormatX11::dealloc_image () {
+ if (!ximage) return;
+ if (!shared_memory) {
+ XFree(ximage); ximage=0; image=0;
+ } else {
+#ifdef HAVE_X11_SHARED_MEMORY
+ shmdt(ximage->data);
+ XShmDetach(display,shm_info);
+ if (shm_info) {delete shm_info; shm_info=0;}
+ XFree(ximage);
+ ximage = 0;
+ image = 0;
+#endif
+ }
+ if (xvideo) {
+#ifdef HAVE_X11_XVIDEO
+ //if (data) delete[] data;
+ if (xvi) XFree(xvi);
+ xvi=0;
+ //data=0;
+#endif
+ }
+}
+
+void FormatX11::resize_window (int sx, int sy) {
+ if (sy<16) sy=16; if (sy>4096) RAISE("height too big");
+ if (sx<16) sx=16; if (sx>4096) RAISE("width too big");
+ alloc_image(sx,sy);
+ if (window) {
+ if (is_owner && !lock_size) {
+ set_wm_hints();
+ XResizeWindow(display,window,sx,sy);
+ }
+ } else {
+ XSetWindowAttributes xswa;
+ xswa.do_not_propagate_mask = 0; //?
+ xswa.override_redirect = override_redirect; //#!@#$
+ window = XCreateWindow(display,
+ parent, pos[1], pos[0], sx, sy, 0,
+ CopyFromParent, InputOutput, CopyFromParent,
+ CWOverrideRedirect|CWDontPropagate, &xswa);
+ if(!window) RAISE("can't create window");
+ set_wm_hints();
+
+ XSelectInput(display, window,
+ ExposureMask|StructureNotifyMask|PointerMotionMask|
+ ButtonPressMask|ButtonReleaseMask|ButtonMotionMask|
+ KeyPressMask|KeyReleaseMask);
+
+ if (is_owner) XMapRaised(display, window);
+ imagegc = XCreateGC(display, window, 0, NULL);
+ if (visual->c_class == PseudoColor) prepare_colormap();
+ }
+ XSync(display,0);
+}
+
+GRID_INLET(0) {
+ if (in->dim->n != 3)
+ RAISE("expecting 3 dimensions: rows,columns,channels");
+ if (in->dim->get(2)!=3 && in->dim->get(2)!=4)
+ RAISE("expecting 3 or 4 channels: red,green,blue,ignored (got %d)",in->dim->get(2));
+ int sx = in->dim->get(1), osx = dim->get(1);
+ int sy = in->dim->get(0), osy = dim->get(0);
+ in->set_chunk(1);
+ if (sx!=osx || sy!=osy) resize_window(sx,sy);
+ if (in->dim->get(2)!=bit_packing->size) {
+ bit_packing->mask[3]=0;
+ bit_packing = new BitPacking(bit_packing->endian,
+ bit_packing->bytes, in->dim->get(2), bit_packing->mask);
+ }
+} GRID_FLOW {
+ int bypl = ximage->bytes_per_line;
+ int sxc = in->dim->prod(1);
+ int sx = in->dim->get(1);
+ int y = dex/sxc;
+ for (; n>0; y++, data+=sxc, n-=sxc) {
+ // convert line
+ if (use_stripes) {
+ int o=y*bypl;
+ for (int x=0, i=0, k=y%3; x<sx; x++, i+=3, k=(k+1)%3) {
+ image[o+x] = (k<<6) | data[i+k]>>2;
+ }
+ } else {
+ bit_packing->pack(sx, data, image+y*bypl);
+ }
+ }
+} GRID_FINISH {
+ show_section(0,0,in->dim->get(1),in->dim->get(0));
+} GRID_END
+
+\def 0 out_size (int sy, int sx) { resize_window(sx,sy); }
+
+\def 0 setcursor (int shape) {
+ shape = 2*(shape&63);
+ Cursor c = XCreateFontCursor(display,shape);
+ XDefineCursor(display,window,c);
+ XFlush(display);
+}
+
+\def 0 hidecursor () {
+ Font font = XLoadFont(display,"fixed");
+ XColor color; /* bogus */
+ Cursor c = XCreateGlyphCursor(display,font,font,' ',' ',&color,&color);
+ XDefineCursor(display,window,c);
+ XFlush(display);
+}
+
+void FormatX11::prepare_colormap() {
+ Colormap colormap = XCreateColormap(display,window,visual,AllocAll);
+ XColor colors[256];
+ if (use_stripes) {
+ for (int i=0; i<192; i++) {
+ int k=(i&63)*0xffff/63;
+ colors[i].pixel = i;
+ colors[i].red = (i>>6)==0 ? k : 0;
+ colors[i].green = (i>>6)==1 ? k : 0;
+ colors[i].blue = (i>>6)==2 ? k : 0;
+ colors[i].flags = DoRed | DoGreen | DoBlue;
+ }
+ XStoreColors(display,colormap,colors,192);
+ } else {
+ for (int i=0; i<256; i++) {
+ colors[i].pixel = i;
+ colors[i].red = ((i>>0)&7)*0xffff/7;
+ colors[i].green = ((i>>3)&7)*0xffff/7;
+ colors[i].blue = ((i>>6)&3)*0xffff/3;
+ colors[i].flags = DoRed | DoGreen | DoBlue;
+ }
+ XStoreColors(display,colormap,colors,256);
+ }
+ XSetWindowColormap(display,window,colormap);
+}
+
+void FormatX11::open_display(const char *disp_string) {
+ display = XOpenDisplay(disp_string);
+ if(!display) RAISE("ERROR: opening X11 display: %s",strerror(errno));
+ // btw don't expect too much from Xlib error handling.
+ // Xlib, you are so free of the ravages of intelligence...
+ XSetErrorHandler(FormatX11_error_handler);
+ Screen *screen = DefaultScreenOfDisplay(display);
+ int screen_num = DefaultScreen(display);
+ visual = DefaultVisual(display, screen_num);
+ root_window = DefaultRootWindow(display);
+ depth = DefaultDepthOfScreen(screen);
+ colormap = 0;
+
+ switch(visual->c_class) {
+ // without colormap
+ case TrueColor: case DirectColor: break;
+ // with colormap
+ case PseudoColor: if (depth!=8) RAISE("ERROR: with colormap, only supported depth is 8 (got %d)", depth); break;
+ default: RAISE("ERROR: visual type not supported (got %d)", visual->c_class);
+ }
+
+#if defined(HAVE_X11_XVIDEO)
+ xvideo = true;
+#elif defined(HAVE_X11_SHARED_MEMORY)
+ shared_memory = !! XShmQueryExtension(display);
+#else
+ shared_memory = false;
+#endif
+}
+
+Window FormatX11::search_window_tree (Window xid, Atom key, const char *value, int level) {
+ if (level>2) return 0xDeadBeef;
+ Window root_r, parent_r;
+ Window *children_r;
+ unsigned int nchildren_r;
+ XQueryTree(display,xid,&root_r,&parent_r,&children_r,&nchildren_r);
+ Window target = 0xDeadBeef;
+ for (int i=0; i<(int)nchildren_r; i++) {
+ Atom actual_type_r;
+ int actual_format_r;
+ unsigned long nitems_r, bytes_after_r;
+ unsigned char *prop_r;
+ XGetWindowProperty(display,children_r[i],key,0,666,0,AnyPropertyType,
+ &actual_type_r,&actual_format_r,&nitems_r,&bytes_after_r,&prop_r);
+ uint32 value_l = strlen(value);
+ bool match = prop_r && nitems_r>=value_l &&
+ strncmp((char *)prop_r+nitems_r-value_l,value,value_l)==0;
+ XFree(prop_r);
+ if (match) {target=children_r[i]; break;}
+ target = search_window_tree(children_r[i],key,value,level+1);
+ if (target != 0xDeadBeef) break;
+ }
+ if (children_r) XFree(children_r);
+ return target;
+}
+
+\def 0 move (int y, int x) {
+ pos[0]=y; pos[1]=x;
+ XMoveWindow(display,window,x,y);
+ XFlush(display);
+}
+
+\def 0 set_geometry (int y, int x, int sy, int sx) {
+ pos[0]=y; pos[1]=x;
+ XMoveWindow(display,window,x,y);
+ resize_window(sx,sy);
+ XFlush(display);
+}
+
+\def 0 shared_memory (bool toggle) {shared_memory = toggle;}
+\def 0 xvideo (bool toggle) {xvideo = toggle;}
+
+\def 0 warp (int y, int x) {
+ XWarpPointer(display,None,None,0,0,0,0,x,y);
+ XFlush(display);
+}
+
+\def 0 title (string title="") {this->title = title; set_wm_hints();}
+
+\end class FormatX11 {install_format("#io.x11",6,"");}
+void startup_x11 () {
+ \startall
+}
+
diff --git a/externals/gridflow/tests/#ann_som-test.pd b/externals/gridflow/tests/#ann_som-test.pd
new file mode 100644
index 00000000..69be1d23
--- /dev/null
+++ b/externals/gridflow/tests/#ann_som-test.pd
@@ -0,0 +1,107 @@
+#N canvas 770 0 450 689 10;
+#X msg 153 349 rule KOHONEN;
+#X obj 153 330 loadbang;
+#X obj 17 579 #out window;
+#X obj 17 560 #outer * (29 17 11);
+#X obj 135 123 t b b b b;
+#X obj 94 23 t b b b;
+#X obj 96 45 realtime;
+#X obj 102 68 nbx 5 14 -1e+37 1e+37 0 0 empty empty empty 0 -8 0 10
+-24198 -1 -1 849.086 256;
+#X obj 96 123 t b b;
+#X obj 94 6 bng 15 250 50 0 empty empty empty 17 7 0 10 -24198 -1 -1
+;
+#X obj 138 493 spigot;
+#X obj 184 493 r \$0-show;
+#X obj 242 297 \$0;
+#X msg 125 215 test \; \$1-show 1;
+#X obj 125 196 \$0;
+#X obj 245 179 #t;
+#X obj 245 217 # +;
+#X obj 138 512 #import (240 320);
+#X obj 17 541 #store (240 320 #);
+#X obj 15 171 #for (0 0) (240 320) (1 1);
+#X obj 270 179 # * 2000;
+#X obj 245 160 #for (0 0) (48 64) (1 1);
+#X obj 245 198 # * 5;
+#X msg 241 316 train \; \$1-show 0;
+#X obj 15 209 #to_list;
+#X obj 15 190 #import (2);
+#X obj 245 255 #to_list;
+#X obj 245 236 #import (2);
+#X obj 245 274 t l b;
+#X obj 330 273 f;
+#X obj 355 273 + 1;
+#X msg 346 129 0;
+#X msg 355 311 learn \$1;
+#X obj 138 434 t a a;
+#X obj 17 501 t b b;
+#X obj 177 579 #out window;
+#X obj 177 560 #outer * (29 17 11);
+#X obj 298 493 spigot;
+#X obj 344 493 r \$0-show;
+#X obj 298 512 #import (240 320);
+#X obj 177 541 #store (240 320 #);
+#X obj 270 217 # cos* 0;
+#X obj 245 103 bang;
+#X obj 355 292 pow -1;
+#X msg 322 364 neighbour 0.1;
+#X obj 245 84 for 0 1 1;
+#X obj 298 465 #ann_som 2 10 10;
+#X obj 138 465 ann_som 2 4 40;
+#X connect 0 0 33 0;
+#X connect 1 0 0 0;
+#X connect 3 0 2 0;
+#X connect 4 0 19 0;
+#X connect 4 1 14 0;
+#X connect 4 2 45 0;
+#X connect 4 3 12 0;
+#X connect 4 3 31 0;
+#X connect 5 0 6 1;
+#X connect 5 1 8 0;
+#X connect 5 2 6 0;
+#X connect 6 0 7 0;
+#X connect 8 0 34 0;
+#X connect 8 1 4 0;
+#X connect 9 0 5 0;
+#X connect 10 0 17 0;
+#X connect 11 0 10 1;
+#X connect 12 0 23 0;
+#X connect 13 0 33 0;
+#X connect 14 0 13 0;
+#X connect 15 0 22 0;
+#X connect 15 1 20 0;
+#X connect 16 0 27 0;
+#X connect 17 0 18 1;
+#X connect 18 0 3 0;
+#X connect 19 0 25 0;
+#X connect 20 0 41 0;
+#X connect 21 0 15 0;
+#X connect 22 0 16 0;
+#X connect 23 0 33 0;
+#X connect 24 0 33 0;
+#X connect 25 0 24 0;
+#X connect 26 0 28 0;
+#X connect 27 0 26 0;
+#X connect 28 0 33 0;
+#X connect 28 1 29 0;
+#X connect 29 0 30 0;
+#X connect 30 0 29 1;
+#X connect 30 0 43 0;
+#X connect 31 0 29 1;
+#X connect 32 0 33 0;
+#X connect 33 0 47 0;
+#X connect 34 0 18 0;
+#X connect 34 1 40 0;
+#X connect 36 0 35 0;
+#X connect 37 0 39 0;
+#X connect 38 0 37 1;
+#X connect 39 0 40 1;
+#X connect 40 0 36 0;
+#X connect 41 0 16 1;
+#X connect 42 0 21 0;
+#X connect 43 0 32 0;
+#X connect 44 0 33 0;
+#X connect 45 0 42 0;
+#X connect 46 0 37 0;
+#X connect 47 0 10 0;
diff --git a/externals/gridflow/tests/#inner-test2.pd b/externals/gridflow/tests/#inner-test2.pd
new file mode 100644
index 00000000..0014dba5
--- /dev/null
+++ b/externals/gridflow/tests/#inner-test2.pd
@@ -0,0 +1,11 @@
+#N canvas 672 46 450 300 10;
+#X obj 51 121 #inner;
+#X obj 76 92 #transpose;
+#X obj 51 92 #t;
+#X obj 51 140 #print;
+#X msg 51 32 9 456 # 1 2 3 4 5;
+#X connect 0 0 3 0;
+#X connect 1 0 0 1;
+#X connect 2 0 0 0;
+#X connect 2 1 1 0;
+#X connect 4 0 2 0;
diff --git a/externals/gridflow/tests/#print-test.pd b/externals/gridflow/tests/#print-test.pd
new file mode 100644
index 00000000..c1625618
--- /dev/null
+++ b/externals/gridflow/tests/#print-test.pd
@@ -0,0 +1,30 @@
+#N canvas 770 206 450 483 10;
+#X msg 32 29 0 #;
+#X msg 48 67 2 3 5;
+#X msg 56 86 2 2 # 2 3 5 7;
+#X msg 63 105 2 2 2 # 2 3 5 7 11 13 17 19;
+#X msg 40 48 list # 2;
+#X msg 211 222 base 8;
+#X msg 228 281 trunc 10;
+#X msg 236 300 maxrows 0;
+#X msg 202 203 base 2;
+#X msg 221 241 base 16;
+#X msg 73 125 2 2 2 # 2 -3 5 -7 -11 13 -17 19;
+#X msg 83 145 2 2 2 s # 2 -3 5 -7 -11 13 -17 19;
+#X msg 93 165 2 2 2 f # 2 -3 5 -7 -11 13 -17 19;
+#X obj 32 379 #print;
+#X obj 32 360 t a;
+#X connect 0 0 14 0;
+#X connect 1 0 14 0;
+#X connect 2 0 14 0;
+#X connect 3 0 14 0;
+#X connect 4 0 14 0;
+#X connect 5 0 14 0;
+#X connect 6 0 14 0;
+#X connect 7 0 14 0;
+#X connect 8 0 14 0;
+#X connect 9 0 14 0;
+#X connect 10 0 14 0;
+#X connect 11 0 14 0;
+#X connect 12 0 14 0;
+#X connect 14 0 13 0;
diff --git a/externals/gridflow/tests/Makefile b/externals/gridflow/tests/Makefile
new file mode 100644
index 00000000..6f81ac9f
--- /dev/null
+++ b/externals/gridflow/tests/Makefile
@@ -0,0 +1,7 @@
+all:: malloc-test
+
+COMMON = Makefile
+
+malloc-test: malloc-test.c $(COMMON)
+ g++ -xc++ -O3 malloc-test.c -o malloc-test
+
diff --git a/externals/gridflow/tests/args-2-test.pd b/externals/gridflow/tests/args-2-test.pd
new file mode 100644
index 00000000..66bada4c
--- /dev/null
+++ b/externals/gridflow/tests/args-2-test.pd
@@ -0,0 +1,17 @@
+#N canvas 460 0 760 300 10;
+#X obj 36 19 loadbang;
+#X obj 36 38 args (first s foo) (second f 42) (third s bar) (fourth
+f 23) *;
+#X obj 36 87 print o1;
+#X obj 113 87 print o2;
+#X obj 190 87 print o3;
+#X obj 268 88 print o4;
+#X obj 345 87 print o5;
+#X obj 423 87 print o6;
+#X connect 0 0 1 0;
+#X connect 1 0 2 0;
+#X connect 1 1 3 0;
+#X connect 1 2 4 0;
+#X connect 1 3 5 0;
+#X connect 1 4 6 0;
+#X connect 1 5 7 0;
diff --git a/externals/gridflow/tests/args-test.pd b/externals/gridflow/tests/args-test.pd
new file mode 100644
index 00000000..8fd716ba
--- /dev/null
+++ b/externals/gridflow/tests/args-test.pd
@@ -0,0 +1,23 @@
+#N canvas 128 60 450 464 10;
+#X obj 14 36 args-2-test a 1 b 2 c 3 d 4 \, canadiens 5 \, nordiques
+2;
+#X text 12 257 o5: bang;
+#X text 12 270 o4: 23;
+#X text 12 101 o5: list c 3 d 4;
+#X text 12 114 o4: 2;
+#X text 12 127 o3: symbol b;
+#X text 12 140 o2: 1;
+#X text 12 153 o1: symbol a;
+#X text 12 166 o6: canadiens 5;
+#X text 12 179 o6: nordiques 2;
+#X text 12 192 o5: bang;
+#X text 12 205 o4: 23;
+#X text 12 231 o2: 1;
+#X text 12 244 o1: symbol a;
+#X text 12 283 o3: symbol bar;
+#X text 12 296 o2: 42;
+#X text 12 309 o1: symbol foo;
+#X obj 14 56 args-2-test a 1 (a b c);
+#X obj 14 76 args-2-test;
+#X text 15 14 order of those 3 objects is important;
+#X text 12 218 o3: list a b c;
diff --git a/externals/gridflow/tests/cv.SVD-test.pd b/externals/gridflow/tests/cv.SVD-test.pd
new file mode 100644
index 00000000..9d1c1ddd
--- /dev/null
+++ b/externals/gridflow/tests/cv.SVD-test.pd
@@ -0,0 +1,37 @@
+#N canvas 770 0 450 464 10;
+#X obj 48 105 cv.SVD;
+#X obj 49 320 display;
+#X floatatom 49 27 5 0 0 0 - - -;
+#X floatatom 88 27 5 0 0 0 - - -;
+#X floatatom 49 43 5 0 0 0 - - -;
+#X floatatom 88 43 5 0 0 0 - - -;
+#X obj 48 86 #redim (2 2);
+#X msg 160 33 4 f # 2 3 5 7;
+#X obj 48 67 #pack 4 f;
+#X obj 161 191 display;
+#X obj 12 185 display;
+#X obj 48 280 #inner \, seed (f #);
+#X obj 178 280 #inner \, seed (f #);
+#X obj 48 261 #store;
+#X obj 48 238 #finished;
+#X obj 48 145 t a a;
+#X obj 307 189 display;
+#X connect 0 0 10 0;
+#X connect 0 0 15 0;
+#X connect 0 1 9 0;
+#X connect 0 1 13 1;
+#X connect 0 2 16 0;
+#X connect 0 2 12 1;
+#X connect 2 0 8 0;
+#X connect 3 0 8 1;
+#X connect 4 0 8 2;
+#X connect 5 0 8 3;
+#X connect 6 0 0 0;
+#X connect 7 0 6 0;
+#X connect 8 0 6 0;
+#X connect 11 0 1 0;
+#X connect 12 0 11 1;
+#X connect 13 0 11 0;
+#X connect 14 0 13 0;
+#X connect 15 0 14 0;
+#X connect 15 1 12 0;
diff --git a/externals/gridflow/tests/foreach-test.pd b/externals/gridflow/tests/foreach-test.pd
new file mode 100644
index 00000000..e5ad35d3
--- /dev/null
+++ b/externals/gridflow/tests/foreach-test.pd
@@ -0,0 +1,8 @@
+#N canvas 496 228 450 300 10;
+#X obj 51 64 foreach;
+#X msg 51 45 2 3 5 7;
+#X obj 51 83 print;
+#X msg 86 22 2 foo bar 7 11 foo;
+#X connect 0 0 2 0;
+#X connect 1 0 0 0;
+#X connect 3 0 0 0;
diff --git a/externals/gridflow/tests/fps-test.pd b/externals/gridflow/tests/fps-test.pd
new file mode 100644
index 00000000..c92b5940
--- /dev/null
+++ b/externals/gridflow/tests/fps-test.pd
@@ -0,0 +1,75 @@
+#N canvas 750 206 450 427 10;
+#X obj 32 13 metro;
+#X obj 32 -4 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1
+;
+#X obj 32 125 t b b;
+#X obj 32 212 print a;
+#X obj 71 193 print b;
+#X obj 32 38 random 400;
+#X msg 148 5 mode real;
+#X msg 148 25 mode user;
+#X msg 148 45 mode system;
+#X msg 148 65 mode cpu;
+#X obj 80 99 t a;
+#X msg 148 85 mode logical;
+#X msg 148 105 mode process;
+#X obj 319 105 print user;
+#X obj 319 151 print system;
+#X obj 327 46 t b b;
+#X obj 327 20 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
+-1;
+#X obj 319 86 usertime;
+#X obj 162 239 #out window;
+#X obj 162 184 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0
+1;
+#X msg 162 220 240 320 3 # 255 0 0;
+#X obj 319 132 systemtime;
+#X obj 319 181 tsctime;
+#X obj 319 200 print tsc;
+#X obj 319 223 timer;
+#X obj 319 242 print logical;
+#X obj 319 263 realtime;
+#X obj 319 303 cputime;
+#X obj 319 322 print process;
+#X obj 319 282 print real;
+#X obj 162 201 metro 10;
+#X obj 71 125 fps_ruby detailed;
+#X obj 32 144 fps detailed;
+#X connect 0 0 5 0;
+#X connect 1 0 0 0;
+#X connect 2 0 32 0;
+#X connect 2 1 31 0;
+#X connect 5 0 0 1;
+#X connect 5 0 2 0;
+#X connect 6 0 10 0;
+#X connect 7 0 10 0;
+#X connect 8 0 10 0;
+#X connect 9 0 10 0;
+#X connect 10 0 31 0;
+#X connect 10 0 32 0;
+#X connect 11 0 10 0;
+#X connect 12 0 10 0;
+#X connect 15 0 17 0;
+#X connect 15 0 21 0;
+#X connect 15 0 22 0;
+#X connect 15 0 24 0;
+#X connect 15 0 26 0;
+#X connect 15 0 27 0;
+#X connect 15 1 17 1;
+#X connect 15 1 21 1;
+#X connect 15 1 22 1;
+#X connect 15 1 24 1;
+#X connect 15 1 26 1;
+#X connect 15 1 27 1;
+#X connect 16 0 15 0;
+#X connect 17 0 13 0;
+#X connect 19 0 30 0;
+#X connect 20 0 18 0;
+#X connect 21 0 14 0;
+#X connect 22 0 23 0;
+#X connect 24 0 25 0;
+#X connect 26 0 29 0;
+#X connect 27 0 28 0;
+#X connect 30 0 20 0;
+#X connect 31 0 4 0;
+#X connect 32 0 3 0;
diff --git a/externals/gridflow/tests/gf.error-2-test.pd b/externals/gridflow/tests/gf.error-2-test.pd
new file mode 100644
index 00000000..644b92c3
--- /dev/null
+++ b/externals/gridflow/tests/gf.error-2-test.pd
@@ -0,0 +1,6 @@
+#N canvas 145 95 450 300 10;
+#X obj 47 65 gf.error file not open;
+#X msg 47 46 bang;
+#X obj 47 27 inlet;
+#X connect 1 0 0 0;
+#X connect 2 0 1 0;
diff --git a/externals/gridflow/tests/gf.error-test.pd b/externals/gridflow/tests/gf.error-test.pd
new file mode 100644
index 00000000..7c7ef395
--- /dev/null
+++ b/externals/gridflow/tests/gf.error-test.pd
@@ -0,0 +1,4 @@
+#N canvas 630 126 450 300 10;
+#X obj 17 37 gf.error-2-test;
+#X msg 17 18 bang;
+#X connect 1 0 0 0;
diff --git a/externals/gridflow/tests/listflatten-test.pd b/externals/gridflow/tests/listflatten-test.pd
new file mode 100644
index 00000000..8685c87b
--- /dev/null
+++ b/externals/gridflow/tests/listflatten-test.pd
@@ -0,0 +1,16 @@
+#N canvas 0 0 450 300 10;
+#X obj 102 138 listread ( 480 640 3 #);
+#X floatatom 102 122 5 0 0 0 - - -;
+#X obj 102 157 listflatten;
+#X obj 103 216 display;
+#X obj 158 182 print;
+#X msg 129 91 2 (3 5 (7) ()) 11;
+#X obj 160 206 list length;
+#X floatatom 160 228 5 0 0 0 - - -;
+#X connect 0 0 2 0;
+#X connect 1 0 0 0;
+#X connect 2 0 4 0;
+#X connect 2 0 6 0;
+#X connect 2 0 3 0;
+#X connect 5 0 2 0;
+#X connect 6 0 7 0;
diff --git a/externals/gridflow/tests/malloc-test.c b/externals/gridflow/tests/malloc-test.c
new file mode 100644
index 00000000..d5445dcc
--- /dev/null
+++ b/externals/gridflow/tests/malloc-test.c
@@ -0,0 +1,36 @@
+#include <stdlib.h>
+#include <time.h>
+#include <sys/time.h>
+#include <stdio.h>
+
+typedef long long uint64;
+
+uint64 gf_timeofday () {
+ timeval t;
+ gettimeofday(&t,0);
+ return t.tv_sec*1000000+t.tv_usec;
+}
+static void test1 (size_t n) {
+ uint64 t = gf_timeofday();
+ for (int i=0; i<10000; i++) free(malloc(n));
+ t = gf_timeofday() - t;
+ printf("10000 mallocs of %7ld bytes takes %7ld us (%f us/malloc)\n",n,(long)t,t/(float)10000);
+}
+static void test2 (size_t n) {
+ uint64 t = gf_timeofday();
+ // the real calloc is lazy, let's try a manual (strict) calloc
+ //for (int i=0; i<10000; i++) free(calloc(1,n));
+ for (int i=0; i<10000; i++) {
+ long *p = (long *)malloc(n);
+ size_t nn=n/sizeof(long);
+ for (size_t j=0; j<nn; j++) p[j] = 0;
+ free(p);
+ }
+ t = gf_timeofday() - t;
+ printf("10000 callocs of %7ld bytes takes %7ld us (%f us/calloc)\n",n,(long)t,t/(float)10000);
+}
+int main () {
+ for (int i=0; i<20; i++) {test1(4<<i); test2(4<<i);}
+ //for (int i=0; i<20; i++) test1(4096*(32+i));
+ return 0;
+}
diff --git a/externals/gridflow/tests/opencv-test1.pd b/externals/gridflow/tests/opencv-test1.pd
new file mode 100644
index 00000000..7bc67a57
--- /dev/null
+++ b/externals/gridflow/tests/opencv-test1.pd
@@ -0,0 +1,72 @@
+#N canvas 435 74 620 429 10;
+#X obj 332 41 #in g001.jpg;
+#X obj 275 316 #out window;
+#X obj 105 7 t b b;
+#X obj 105 -10 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 190 339 #out window \, title cv;
+#X obj 399 277 # -;
+#X obj 399 296 # * 16;
+#X obj 399 315 # + 128;
+#X obj 399 334 #clip;
+#X obj 399 353 #out window;
+#X obj 105 31 #in b001.jpg;
+#X obj 190 301 spigot;
+#X obj 275 236 spigot;
+#X obj 415 238 spigot;
+#X obj 354 234 spigot;
+#X obj 451 182 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1
+1;
+#X obj 118 143 realtime;
+#X obj 178 142 #finished;
+#X obj 332 60 t a a;
+#X obj 118 162 nbx 8 14 -1e+37 1e+37 0 0 empty empty empty 0 -6 0 9
+-262144 -1 -1 26.297 256;
+#X obj 154 117 t a a b;
+#X obj 13 121 realtime;
+#X obj 73 120 #finished;
+#X obj 13 140 nbx 8 14 -1e+37 1e+37 0 0 empty empty empty 0 -6 0 9
+-262144 -1 -1 26.084 256;
+#X obj 49 95 t a a b;
+#X obj 105 50 t a a;
+#X obj 206 208 cv.Mul;
+#X obj 305 188 # *;
+#X obj 190 320 # >> 8;
+#X obj 275 296 # >> 8;
+#X connect 0 0 18 0;
+#X connect 2 0 10 0;
+#X connect 2 1 0 0;
+#X connect 3 0 2 0;
+#X connect 5 0 6 0;
+#X connect 6 0 7 0;
+#X connect 7 0 8 0;
+#X connect 8 0 9 0;
+#X connect 10 0 25 0;
+#X connect 11 0 28 0;
+#X connect 12 0 29 0;
+#X connect 13 0 5 1;
+#X connect 14 0 5 0;
+#X connect 15 0 13 1;
+#X connect 15 0 14 1;
+#X connect 15 0 12 1;
+#X connect 15 0 11 1;
+#X connect 16 0 19 0;
+#X connect 17 0 16 1;
+#X connect 18 0 26 1;
+#X connect 18 1 27 1;
+#X connect 20 0 17 0;
+#X connect 20 1 27 0;
+#X connect 20 2 16 0;
+#X connect 21 0 23 0;
+#X connect 22 0 21 1;
+#X connect 24 0 22 0;
+#X connect 24 1 26 0;
+#X connect 24 2 21 0;
+#X connect 25 0 24 0;
+#X connect 25 1 20 0;
+#X connect 26 0 11 0;
+#X connect 26 0 14 0;
+#X connect 27 0 12 0;
+#X connect 27 0 13 0;
+#X connect 28 0 4 0;
+#X connect 29 0 1 0;
diff --git a/externals/gridflow/tests/opencv-test2.pd b/externals/gridflow/tests/opencv-test2.pd
new file mode 100644
index 00000000..f1b67fd3
--- /dev/null
+++ b/externals/gridflow/tests/opencv-test2.pd
@@ -0,0 +1,49 @@
+#N canvas 532 160 585 459 10;
+#X obj 401 173 cv.Add (240 320 3 #);
+#X obj 414 212 cv.Sub (240 320 3 #);
+#X msg 412 145 3 3 3 #;
+#X obj 338 135 display;
+#X obj 337 91 #redim (1 1);
+#X obj 337 56 nbx 5 14 -1e+37 1e+37 0 0 empty empty empty 0 -6 0 10
+-262144 -1 -1 0 256;
+#X obj 337 72 #pack 1;
+#X floatatom 351 238 5 0 0 0 - - -;
+#X obj 351 274 display;
+#X obj 350 254 # / 3;
+#X obj 337 110 cv.Div (1 1 6 # 3);
+#X obj 22 211 cv.HaarDetectObjects;
+#X obj 22 20 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 1 1
+;
+#X obj 120 83 #in images/sewing.jpg;
+#X obj 179 189 #out window;
+#X obj 120 121 #cast b;
+#X obj 22 405 fps detailed;
+#X obj 22 424 print;
+#X obj 120 64 loadbang;
+#X obj 192 62 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
+-1;
+#X obj 22 386 bang;
+#X obj 120 102 #downscale_by 2 smoothly;
+#X obj 22 37 metro 100;
+#X obj 23 245 display;
+#X obj 22 102 #camera;
+#X obj 21 150 #cast b;
+#X connect 2 0 0 0;
+#X connect 4 0 10 0;
+#X connect 5 0 6 0;
+#X connect 6 0 4 0;
+#X connect 7 0 9 0;
+#X connect 9 0 8 0;
+#X connect 10 0 3 0;
+#X connect 11 0 23 0;
+#X connect 12 0 22 0;
+#X connect 13 0 21 0;
+#X connect 16 0 17 0;
+#X connect 18 0 13 0;
+#X connect 19 0 13 0;
+#X connect 20 0 16 0;
+#X connect 21 0 15 0;
+#X connect 22 0 24 0;
+#X connect 24 0 25 0;
+#X connect 25 0 11 0;
+#X connect 25 0 14 0;
diff --git a/externals/gridflow/tests/plotter_control-test.pd b/externals/gridflow/tests/plotter_control-test.pd
new file mode 100644
index 00000000..bff1e2ca
--- /dev/null
+++ b/externals/gridflow/tests/plotter_control-test.pd
@@ -0,0 +1,51 @@
+#N canvas 598 366 622 323 10;
+#X obj 34 101 plotter_control;
+#X obj 122 120 t a;
+#X msg 469 54 42 \, 100 \, -30;
+#X text 439 167 52 50 49 48 48 45 51 48;
+#X obj 34 120 list prepend;
+#X obj 12 12 loadbang;
+#X msg 12 31 bang;
+#X obj 469 73 ascii;
+#X obj 440 148 display;
+#X obj 499 128 list prepend;
+#X obj 439 35 t b b;
+#X obj 439 18 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
+-1;
+#X obj 439 128 seq_fold;
+#X obj 483 235 #to_symbol;
+#X obj 483 254 #import;
+#X obj 484 274 display;
+#X msg 483 216 65 13 10 66;
+#X msg 34 69 PU \, pd \, pa 200 300 \, SP 3 \, ip 1 2 3 \, other foo
+50 70 \, print hello world \, print_from_ascii 29 29 13 10;
+#X obj 12 158 expect 80 85 59 10 80 68 59 10 80 65 50 48 48 44 51 48
+48 59 10 83 80 51 59 10 73 80 49 44 50 44 51 59 10 70 79 79 53 48 44
+55 48 59 10 76 66 104 101 108 108 111 32 119 111 114 108 100 3 59 10
+76 66 29 29 13 10 3 59 10;
+#X obj 12 50 t b a b;
+#X obj 12 139 list;
+#X obj 13 217 display;
+#X connect 0 0 4 0;
+#X connect 1 0 4 1;
+#X connect 2 0 7 0;
+#X connect 4 0 1 0;
+#X connect 4 0 20 1;
+#X connect 5 0 6 0;
+#X connect 6 0 19 0;
+#X connect 7 0 12 1;
+#X connect 9 0 12 3;
+#X connect 10 1 2 0;
+#X connect 11 0 10 0;
+#X connect 12 0 8 0;
+#X connect 12 1 9 0;
+#X connect 12 2 9 1;
+#X connect 13 0 14 0;
+#X connect 14 0 15 0;
+#X connect 16 0 13 0;
+#X connect 17 0 0 0;
+#X connect 18 0 21 0;
+#X connect 19 0 20 0;
+#X connect 19 1 17 0;
+#X connect 19 2 4 1;
+#X connect 20 0 18 0;
diff --git a/externals/gridflow/tests/plotter_parser-test.pd b/externals/gridflow/tests/plotter_parser-test.pd
new file mode 100644
index 00000000..1c649836
--- /dev/null
+++ b/externals/gridflow/tests/plotter_parser-test.pd
@@ -0,0 +1,73 @@
+#N canvas 770 0 450 458 10;
+#X obj 75 101 plotter_parser;
+#X obj 267 102 display;
+#X obj 75 33 until;
+#X obj 75 16 bng 15 250 50 0 empty empty empty 17 7 0 10 -24198 -1
+-1;
+#X obj 8 16 tgl 15 0 empty empty empty 17 7 0 10 -24198 -1 -1 0 1;
+#X msg 82 60 rewind;
+#X obj 177 101 print bogus;
+#X obj 9 315 #draw_hpgl;
+#X obj 9 340 #out window;
+#X obj 255 238 listread ( 480 640 3 #);
+#X floatatom 255 222 5 0 0 0 - - -;
+#X obj 255 257 listflatten;
+#X obj 256 316 display;
+#X obj 311 282 print;
+#X msg 282 191 2 (3 5 (7) ()) 11;
+#X obj 313 306 list length;
+#X floatatom 313 328 5 0 0 0 - - -;
+#X msg 41 236 255 255 255;
+#X obj 41 217 loadbang;
+#X obj 86 144 print command;
+#X obj 8 33 metro 1;
+#X msg 55 192 480 640 3 #;
+#X obj 9 192 #store;
+#X obj 55 173 loadbang;
+#X obj 86 125 spigot;
+#X obj 132 126 tgl 15 0 empty empty empty 17 7 0 10 -241291 -1 -1 0
+1;
+#X obj 9 359 fps;
+#X floatatom 9 380 5 0 0 0 - - -;
+#X obj 166 18 bng 15 250 50 0 empty empty empty 17 7 0 10 -258699 -1
+-1;
+#X obj 74 82 #in grid reverse_engineered/plotte/98.hpgl \, headerless
+\, type b;
+#X msg 68 256 0 150;
+#X msg 101 275 100 250;
+#X connect 0 0 7 2;
+#X connect 0 0 24 0;
+#X connect 2 0 29 0;
+#X connect 3 0 2 0;
+#X connect 4 0 20 0;
+#X connect 5 0 29 0;
+#X connect 7 0 8 0;
+#X connect 7 0 22 1;
+#X connect 7 1 22 0;
+#X connect 8 0 26 0;
+#X connect 9 0 11 0;
+#X connect 10 0 9 0;
+#X connect 11 0 13 0;
+#X connect 11 0 15 0;
+#X connect 11 0 12 0;
+#X connect 14 0 11 0;
+#X connect 15 0 16 0;
+#X connect 17 0 7 1;
+#X connect 18 0 17 0;
+#X connect 18 0 30 0;
+#X connect 18 0 31 0;
+#X connect 20 0 29 0;
+#X connect 21 0 22 1;
+#X connect 22 0 7 0;
+#X connect 23 0 21 0;
+#X connect 24 0 19 0;
+#X connect 25 0 24 1;
+#X connect 26 0 27 0;
+#X connect 28 0 5 0;
+#X connect 28 0 21 0;
+#X connect 29 0 0 0;
+#X connect 29 1 1 0;
+#X connect 29 1 2 1;
+#X connect 29 1 4 0;
+#X connect 30 0 7 3;
+#X connect 31 0 7 4;
diff --git a/externals/gridflow/tests/range-test.pd b/externals/gridflow/tests/range-test.pd
new file mode 100644
index 00000000..74689f97
--- /dev/null
+++ b/externals/gridflow/tests/range-test.pd
@@ -0,0 +1,39 @@
+#N canvas 425 235 452 370 10;
+#X obj 136 153 range 20 50 100;
+#X obj 83 25 vsl 15 128 0 127 0 0 empty empty empty -2 -6 0 8 -262144
+-1 -1 0 1;
+#X obj 157 71 nbx 5 14 -1e+37 1e+37 0 0 empty empty empty 0 -6 0 10
+-262144 -1 -1 25 256;
+#X floatatom 138 48 5 0 0 0 - - -;
+#X obj 236 179 print d;
+#X obj 202 199 print c;
+#X obj 169 220 print b;
+#X obj 136 240 print a;
+#X msg 125 27 -1000 \, -1 \, 0 \, 19 \, 20 \, 49 \, 50 \, 99 \, 100
+\, 1000;
+#X obj 125 8 loadbang;
+#X text 17 186 a: -1000;
+#X text 17 199 a: -1;
+#X text 17 212 a: 0;
+#X text 17 224 a: 19;
+#X text 17 236 b: 20;
+#X text 17 249 b: 49;
+#X text 17 262 c: 50;
+#X text 17 276 c: 99;
+#X text 17 290 d: 100;
+#X text 17 303 d: 1000;
+#X msg 236 72 500;
+#X obj 136 95 t a;
+#X msg 133 127 list \$1 42;
+#X connect 0 0 7 0;
+#X connect 0 1 6 0;
+#X connect 0 2 5 0;
+#X connect 0 3 4 0;
+#X connect 1 0 21 0;
+#X connect 2 0 21 0;
+#X connect 3 0 21 0;
+#X connect 8 0 21 0;
+#X connect 9 0 8 0;
+#X connect 20 0 0 3;
+#X connect 21 0 22 0;
+#X connect 22 0 0 0;
diff --git a/externals/gridflow/tests/suppressions.valg3 b/externals/gridflow/tests/suppressions.valg3
new file mode 100644
index 00000000..3a425765
--- /dev/null
+++ b/externals/gridflow/tests/suppressions.valg3
@@ -0,0 +1,201 @@
+{
+ dl1
+ Memcheck:Addr8
+ obj:/lib/ld-2.3.5.so
+ obj:/lib/ld-2.3.5.so
+ obj:/lib/ld-2.3.5.so
+}
+{
+ unknown1
+ Memcheck:Cond
+ obj:/lib/ld-2.3.5.so
+ obj:/lib/ld-2.3.5.so
+ obj:/lib/ld-2.3.5.so
+ obj:/lib/ld-2.3.5.so
+ obj:/lib/ld-2.3.5.so
+}
+{
+ unknown2
+ Memcheck:Cond
+ obj:/lib/ld-2.3.5.so
+ obj:/lib/tls/i686/cmov/libc-2.3.5.so
+ obj:/lib/ld-2.3.5.so
+ fun:_dl_open
+ obj:/lib/tls/i686/cmov/libdl-2.3.5.so
+}
+{
+ unknown3
+ Memcheck:Cond
+ obj:/lib/ld-2.3.5.so
+ obj:/lib/ld-2.3.5.so
+ obj:/lib/tls/i686/cmov/libc-2.3.5.so
+ obj:/lib/ld-2.3.5.so
+ fun:_dl_open
+}
+{
+ libX11
+ Memcheck:Param
+ write(buf)
+ obj:/lib/ld-2.3.5.so
+ fun:__write_nocancel
+ obj:/usr/lib/libX11.so.6.2.0
+ fun:_X11TransWrite
+}
+{
+ alsa1
+ Memcheck:Addr1
+ fun:strlen
+ fun:vfprintf
+ fun:vsprintf
+ fun:sprintf
+ fun:alsa_getdevs
+}
+{
+ alsa2
+ Memcheck:Addr1
+ fun:_IO_default_xsputn
+ fun:vfprintf
+ fun:vsprintf
+ fun:sprintf
+ fun:alsa_getdevs
+}
+{
+ alsa3
+ Memcheck:Addr2
+ fun:mempcpy
+ fun:vfprintf
+ fun:vsprintf
+ fun:sprintf
+ fun:alsa_getdevs
+}
+{
+ alsa4
+ Memcheck:Param
+ ioctl(arg)
+ obj:/lib/ld-2.3.6.so
+ fun:snd_pcm_prepare
+ fun:snd_pcm_hw_params
+ fun:alsaio_setup
+ fun:alsa_open_audio
+ obj:*
+}
+{
+ alsa5
+ Memcheck:Param
+ ioctl(generic)
+ obj:/lib/ld-2.3.6.so
+ fun:snd_pcm_link
+ fun:alsa_open_audio
+ obj:*
+}
+{
+ alsa6
+ Memcheck:Param
+ ioctl(arg)
+ obj:/lib/ld-2.3.6.so
+ fun:snd_pcm_prepare
+ fun:alsa_send_dacs
+}
+{
+ alsa7
+ Memcheck:Addr4
+ fun:mempcpy
+ fun:vfprintf
+ fun:vsprintf
+ fun:sprintf
+ fun:alsa_getdevs
+}
+{
+ alsa8
+ Memcheck:Param
+ ioctl(arg)
+ obj:/lib/ld-2.3.6.so
+ fun:snd_pcm_prepare
+ fun:alsa_open_audio
+ obj:*
+}
+{
+ alsa9
+ Memcheck:Leak
+ fun:malloc
+ fun:snd_dlobj_cache_add
+ obj:/usr/lib/libasound.so.2.0.0
+ fun:alsa_getdevs
+}
+{
+ alsa10
+ Memcheck:Leak
+ fun:calloc
+ fun:snd_ctl_new
+ fun:snd_ctl_hw_open
+ fun:_snd_ctl_hw_open
+ obj:/usr/lib/libasound.so.2.0.0
+ fun:alsa_getdevs
+}
+{
+ alsa11
+ Memcheck:Leak
+ fun:calloc
+ obj:/usr/lib/libasound.so.2.0.0
+ obj:/usr/lib/libasound.so.2.0.0
+ obj:/usr/lib/libasound.so.2.0.0
+ obj:/usr/lib/libasound.so.2.0.0
+ obj:/usr/lib/libasound.so.2.0.0
+ obj:/usr/lib/libasound.so.2.0.0
+ obj:/usr/lib/libasound.so.2.0.0
+ fun:snd_config_update_r
+ fun:snd_config_update
+ fun:snd_ctl_open
+ fun:alsa_getdevs
+}
+{
+ dlopen1
+ Memcheck:Cond
+ obj:/lib/ld-2.3.6.so
+ obj:/lib/tls/i686/cmov/libc-2.3.6.so
+ obj:/lib/ld-2.3.6.so
+ fun:_dl_open
+}
+{
+ dlopen2
+ Memcheck:Cond
+ obj:/lib/ld-2.3.6.so
+ obj:/lib/ld-2.3.6.so
+ obj:/lib/ld-2.3.6.so
+ obj:/lib/tls/i686/cmov/libc-2.3.6.so
+ obj:/lib/ld-2.3.6.so
+ fun:_dl_open
+}
+{
+ fclass1
+ Memcheck:Leak
+ fun:*
+ fun:*
+ fun:_Z14fclass_installP6FClassS0_j
+}
+{
+ fclass2
+ Memcheck:Leak
+ fun:malloc
+ fun:strdup
+ fun:_Z12suffixes_arePKcS0_
+ fun:_Z17FormatX11_startupP6FClass
+ fun:_Z14fclass_installP6FClassS0_j
+ fun:_Z11startup_x11v
+}
+{
+ cv1
+ Memcheck:Leak
+ fun:malloc
+ obj:/lib/ld-2.3.6.so
+ fun:_dl_open
+ obj:/lib/tls/i686/cmov/libdl-2.3.6.so
+ obj:/lib/ld-2.3.6.so
+ obj:/lib/tls/i686/cmov/libdl-2.3.6.so
+ fun:dlopen
+ fun:cvUseOptimized
+ fun:cvRegisterModule
+ fun:_ZN8CvModuleC1EP12CvModuleInfo
+ obj:/home/matju/lib/libcxcore.so.2.0.0
+ obj:/lib/ld-2.3.6.so
+}