diff --git a/.gitmodules b/.gitmodules
index 11579c24bd8b7b83c99a00710c151204b9edf354..5ea9241213d7cafd59acb40c0cbd4d31488326c8 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -16,3 +16,6 @@
 [submodule "l2ork_addons/raspberry_pi/disis_gpio/wiringPi"]
 	path = l2ork_addons/raspberry_pi/disis_gpio/wiringPi
 	url = https://git.purrdata.net/jwilkes/wiringPi.git
+[submodule "externals/pd-lua"]
+	path = externals/pd-lua
+	url = https://git.purrdata.net/jwilkes/pd-lua.git
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..16ab28a85a698d3210740ba354f13ebc9f3fd3f6
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,195 @@
+
+# Toplevel Makefile for Purr Data. Please note that at present this is just a
+# thin wrapper around l2ork_addons/tar_em_up.sh, the traditional Pd-l2ork
+# build script.
+
+# The Pd-l2ork build system is very arcane and intricate. Its main purpose is
+# putting together a staging area with a complete Pd-l2ork installation and
+# then building installers for the supported platforms from that, pulling
+# together a bunch of separate packages, each with their own build system.
+# Compiling sources is just one of the tasks that the builder does. Therefore
+# you'll notice that, unlike with other less complicated source packages,
+# `make` will rebuild lots of things even if you just finished another build.
+
+# The available build targets are:
+
+# all: produce a native installer for the host platform (equivalent to
+# `tar_em_up.sh -Tk`); note that in order to force a complete rebuild (like
+# what `tar_em_up.sh -T` does), you'll have to run `make clean` first
+
+# incremental: like `all`, but does an "incremental build" (equivalent to
+# `tar_em_up.sh -tk`), bypassing Gem which takes an eternity to compile; please
+# check the tar_em_up.sh script for details
+
+# light: like `incremental`, but does a light build (equivalent to
+# `tar_em_up.sh -tkl`) which only includes the most essential externals;
+# please check the tar_em_up.sh script for details
+
+# checkout: convenience target to check out all submodules in preparation for
+# a subsequent build (the `all`, `incremental` and `dist` targets also do this
+# automatically when needed)
+
+# clean: does something similar to what `tar_em_up.sh` does in order to start
+# from a clean slate, so that a subsequent build starts from scratch again
+
+# realclean: put the sources into pristine state again (WARNING: this will get
+# rid of any uncommitted source changes, too); use this as a last resort to
+# get the sources into a compilable state again after things have gone awry
+
+# dist: create a self-contained distribution tarball of the source
+
+# NOTES:
+
+# The realclean and dist targets use git commands and thus only work in a
+# working copy of the git repo, not in the static tarball snapshots produced
+# by the dist target.
+
+# On Linux systems running `make` will try to produce a Debian package. On
+# Linux distributions like Arch which are no Debian derivatives, the Debian
+# packaging tools are not available. In this case, `make` will stop right
+# before creating the actual package and leave the ready-made staged
+# installation tree under `packages/linux_make/build` from where it can be
+# copied or packaged up in any desired way.
+
+# The incremental and light builds assume an existing staging area
+# (packages/*/build directory) which is *not* cleaned before installing. This
+# makes it possible to update the existing staging area after recompiling just
+# a part of the system (all but Gem in the case of "incremental", only the
+# Pd core and a few essential externals in the case of "light"). Use `make
+# clean` beforehand if you want to install into a clean staging area.
+
+# When doing a `light` build, which only includes the most essential
+# externals, it may be desirable to manually include additional abstractions
+# and externals in the build. To these ends, after running `make light` you
+# can run `make` with the `foo_abs` or `foo_ext` target, where `foo` is the
+# name of the desired abstraction or external, respectively. E.g., you can run
+# `make light memento_abs pdlua_ext` to get a light build with the `memento`
+# abstraction and the `pdlua` external included. (This will not rebuild the
+# Debian package, though, so you'll have to install manually with `make
+# install` instead.) The names of the desired addons must be specified as
+# given in abstractions/Makefile and externals/Makefile, respectively (look
+# for targets looking like `foo_install`). Also note that even though a
+# subsequent `make install` will then include your addons, they won't be
+# enabled by default, so you'll have to do that manually in Purr Data's
+# `Startup` dialog. Simply adding the name of the addon in the `Libraries`
+# list should normally do the trick. Or you can add an option like `-lib foo`
+# when running Purr Data from the command line.
+
+.PHONY: all incremental checkout clean realclean dist
+
+# Installation prefix under which Pd-l2ork is installed (Linux only). If this
+# isn't set, a default location will be used (usually /usr/local). NOTE: We
+# *always* assume that this variable is set properly in the install targets
+# (see below).
+prefix = /usr
+
+ifneq ($(prefix),)
+env = inst_dir="$(prefix)"
+endif
+
+all:
+	cd l2ork_addons && $(env) ./tar_em_up.sh -Tk
+
+incremental:
+	cd l2ork_addons && $(env) ./tar_em_up.sh -tk
+
+light:
+	cd l2ork_addons && $(env) ./tar_em_up.sh -tkl
+
+%_abs:
+	make -C abstractions $(@:%_abs=%_install) DESTDIR=$(firstword $(wildcard $(CURDIR)/packages/*/build)) prefix=$(prefix)
+
+%_ext:
+	make -C externals $(@:%_ext=%_install) DESTDIR=$(firstword $(wildcard $(CURDIR)/packages/*/build)) prefix=$(prefix)
+
+checkout:
+	git submodule update --init
+
+clean:
+	test "$(shell uname -s)" = "Darwin" && make -C packages/darwin_app clean || true
+	cd pd/src && aclocal && autoconf && make clean || true
+	cd externals/miXed && make clean || true
+	cd Gem/src/ && test -f Makefile && make distclean || true
+	cd Gem/src/ && rm -rf ./.libs && rm -rf ./*/.libs || true
+	cd Gem/ && test -f Makefile && make distclean || true
+	cd Gem/ && rm -f gemglutwindow.pd_linux Gem.pd_linux || true
+	rm -rf packages/*/build/
+
+realclean:
+# This requires a working copy of the git repo.
+	@test -d .git || (echo "Not a git repository, bailing out." && false)
+	git submodule deinit --all -f
+	git checkout .
+	git clean -dffx -e pd/nw/nw/
+
+# Installation targets. These don't work on Mac and Windows right now, you
+# should use the generated installers on these systems instead. Also,
+# $(prefix) must be set. $(DESTDIR) is supported as well, so you can do staged
+# installs (but then again presumably you already have a staged install
+# sitting in packages/*/build, so you might as well use that instead).
+
+# Note that these targets simply (un)install whatever is in the
+# packages/*/build directory at the time they're invoked. If no build
+# directory is present then nothing will happen, so you need to run `make` (or
+# `make incremental`, etc.) before running these targets. Also note that some
+# old cruft under build/etc (all but the bash auto-completions) isn't
+# installed as it isn't needed on modern Linux systems any more.
+
+builddir = $(firstword $(wildcard packages/*/build))
+ifneq ($(builddir),)
+manifest = etc/bash_completion.d/pd-l2ork $(prefix:/%=%)/include/pd-l2ork $(prefix:/%=%)/lib/pd-l2ork $(patsubst $(builddir)/%,%, $(wildcard $(builddir)/$(prefix:/%=%)/bin/*) $(shell find $(builddir)/usr/share -type f))
+endif
+
+ifneq ($(manifest),)
+install:
+	test -z "$(DESTDIR)" || (rm -rf "$(DESTDIR)" && mkdir -p "$(DESTDIR)")
+	tar -c -C $(builddir) $(manifest) | tar -x -C $(DESTDIR)/
+# Edit the library paths in the default user.settings file so that it matches
+# our installation prefix.
+	test -f "$(DESTDIR)"$(prefix)/lib/pd-l2ork/default.settings && cd "$(DESTDIR)"$(prefix)/lib/pd-l2ork && sed -e "s!/usr/lib/pd-l2ork!$(prefix)/lib/pd-l2ork!g" -i default.settings || true
+
+uninstall:
+	rm -rf $(addprefix $(DESTDIR)/, $(manifest))
+else
+install:
+	@echo "no build directory, run make first" && false
+
+uninstall:
+	@echo "no build directory, run make first" && false
+endif
+
+# Build a self-contained distribution tarball (snapshot). This is pretty much
+# the same as in debuild/Makefile and must be run in a working copy of the git
+# repo.
+
+# The Debian version gets derived from the date and serial number of the last
+# commit.
+debversion = $(shell grep PD_L2ORK_VERSION pd/src/m_pd.h | sed 's|^.define *PD_L2ORK_VERSION *"\(.*\)".*|\1|')+git$(shell test -d .git && git rev-list --count HEAD)+$(shell test -d .git && git rev-parse --short HEAD)
+# Source tarball and folder.
+debsrc = purr-data_$(debversion).orig.tar.gz
+debdist = purr-data-$(debversion)
+
+# Submodules (Gem, etc.).
+submodules = $(sort $(shell test -d .git && (git config --file .gitmodules --get-regexp path | awk '{ print $$2 }')))
+
+dist: $(debsrc)
+
+# Determine the build version which needs git to be computed, so we can't do
+# it in a stand-alone build from a tarball.
+PD_BUILD_VERSION := $(shell test -d .git && (git log -1 --format=%cd --date=short | sed -e 's/-//g'))-rev.$(shell test -d .git && git rev-parse --short HEAD)
+
+$(debsrc):
+	@test -d .git || (echo "Not a git repository, bailing out." && false)
+	rm -rf $(debdist)
+# Make sure that the submodules are initialized.
+	git submodule update --init
+# Grab the main source.
+	git archive --format=tar.gz --prefix=$(debdist)/ HEAD | tar xfz -
+# Grab the submodules.
+	for x in $(submodules); do (cd $(debdist) && rm -rf $$x && git -C ../$$x archive --format=tar.gz --prefix=$$x/ HEAD | tar xfz -); done
+# Pre-generate and put s_stuff.h into the tarball (see above; the build
+# version is generated using git which can't be done outside the git repo).
+	sed 's|^\(#define PD_BUILD_VERSION "\).*"|\1$(PD_BUILD_VERSION)"|' pd/src/s_stuff.h.in > $(debdist)/pd/src/s_stuff.h
+# Create the source tarball.
+	tar cfz $(debsrc) $(debdist)
+	rm -rf $(debdist)
diff --git a/README.md b/README.md
index 4a114c292c116c01373617ddbcd53fbb8038b710..6ee59eef09226f1742e2677e83f4d326f3209659 100644
--- a/README.md
+++ b/README.md
@@ -87,6 +87,15 @@ from the following site:
 
 ### Build Guide
 
+**NOTE:** The instructions below talk about running the `tar_em_up.sh` build
+script, which is still the recommended way to build Purr Data right now.
+However, Purr Data also has a new (and experimental) toplevel Makefile so that
+just typing `make` will build the package. You may find this easier. The
+Makefile also offers the customary targets to clean (`make clean`, or
+`make realclean` to put the sources in pristine state again) and to roll a
+self-contained distribution tarball (`make dist`). Please check the comments
+at the beginning of the Makefile for more information.
+
 #### Linux
 
 Time to build: *40 minutes to 1.5 hours*  
@@ -104,7 +113,7 @@ Hard drive space required: *roughly 2.5 GB*
              swh-plugins mcp-plugins cmt blop slv2-jack omins rev-plugins \
              libslv2-dev dssi-utils vco-plugins wah-plugins fil-plugins \
              mda-lv2 libmp3lame-dev libspeex-dev libgsl0-dev \
-             portaudio19-dev python-dev libsmpeg0 libjpeg62-turbo \
+             portaudio19-dev liblua5.3-dev python-dev libsmpeg0 libjpeg62-turbo \
              flite1-dev libgsm1-dev libgtk2.0-dev git libstk0-dev \
              libsndobj-dev libfluidsynth-dev fluid-soundfont-gm byacc
 
@@ -155,6 +164,7 @@ Hard drive space required: *roughly 2 GB*
         brew install libtool
         brew install fftw
         brew install python
+        brew install lua
         brew install fluidsynth
         brew install lame
         brew install libvorbis
@@ -259,22 +269,35 @@ Contributing is easy:
 
 1. Join the development list:
    http://disis.music.vt.edu/cgi-bin/mailman/listinfo/l2ork-dev
-2. Tell us what you'd like to work on. There are lots of possibilities. For 
-   example, there are _lots_ of externals and even core features that are
-   poorly documented.
-3. _No prototypes, please_. Purr Data's biggest strength is that users can
-   turn an idea into working code very quickly. But a prototyping language that 
-   is itself a prototype isn't very useful. That means Purr Data's core code
-   and libraries must be stable, consistent, well-documented, and easy to use.
-4. Develop incrementally. Small, solid improvements to the software are
-   preferable to large, disruptive ones.
-5. Make sure you aren't duplicating existing functionality, especially core
-   functionality. For backwards compatibility Purr Data ships many legacy
-   libraries which unfortunately duplicate the same functionality. This makes
-   it harder to learn how to use Pd, and makes it burdensome to read patches
-   and keep track of all the disparate implementations.
-6. Send us a merge request and we'll test it. If it's well-documented and
-   there aren't any bugs we'll add it to the software.
+2. Fork Purr Data using the gitlab UI and then try to build it from source
+   for your own platform using the [Build Guide](#build-guide) above. 
+   If you run into problems ask on the development list for help.
+3. Once you have successfully built Purr Data, install it and make sure it
+   runs correctly.
+4. Start making changes to the code with brief, clear commit messages. If you
+   want some practice you can try fixing one of the bugs on the issue tracker
+   labeled
+   ["good-first-bug"](https://git.purrdata.net/jwilkes/purr-data/issues?label_name%5B%5D=good-first-bug)
+5. One you are done fixing the bug or adding your feature, make a merge request
+   in the Gitlab UI so we can merge the fix for the next release.
+
+A few guidelines:
+* _No prototypes, please_. Purr Data's biggest strength is that users can
+  turn an idea into working code very quickly. But a prototyping language that 
+  is itself a prototype isn't very useful. That means Purr Data's core code
+  and libraries must be stable, consistent, well-documented, and easy to use.
+* Develop incrementally. Small, solid improvements to the software are
+  preferable to large, disruptive ones.
+* Try not to duplicate existing functionality.
+  For backwards compatibility Purr Data ships many legacy
+  libraries which unfortunately duplicate the same functionality. This makes
+  it harder to learn how to use Pd, and makes it burdensome to read patches
+  and keep track of all the disparate implementations.
+* Keep dependencies to a minimum. Cross-platform dependency handling is
+  unfortunately still an open research problem. In the even that you need
+  an external library dependency, please mirror it at git.purrdata.net
+  so that the build system doesn't depend on the availability of external
+  infrastructure.
 
 Here are some of the current tasks:
 
@@ -296,6 +319,8 @@ Here are some of the current tasks:
   * status: some externals have their own testing environments, but they are
     limited as they require manual intervention to run and read the
     results inside a graphical window.
+    We currently have a crude test system that at least ensures that each
+    external library instantiates without crashing.
     Here's an email thread with Katja Vetter's design, which looks to
     be automatable:
     http://markmail.org/message/t7yitfc55anus76i#query:+page:1+mid:chb56ve7kea2qumn+state:results
diff --git a/debuild/Makefile b/debuild/Makefile
index ff171f00cafde27987201bb4a5d07b82a73ab32c..fa7724a110e4ef33bc95b68e7772b5e9bd1c1ae3 100644
--- a/debuild/Makefile
+++ b/debuild/Makefile
@@ -76,13 +76,6 @@ deb: $(debsrc) $(addprefix debian/nwjs/, $(nwjs))
 	tar xfz $(debsrc)
 # Add the NW.js binaries to the source package.
 	cd debian/source && rm -f include-binaries && for x in $(addprefix debian/nwjs/, $(nwjs)); do echo "$$x" >> include-binaries; done
-# This works around some problems compiling externals on Precise and earlier
-# (patch from pd-extended by Hans-Christoph Steiner, modified for pd-l2ork).
-# This can be removed once Ubuntu 12.04 finally goes the way of the dodo.
-#	cd $(debdist) && patch -p1 < ../precise-configure.patch
-# Patch the user config dir name so that purr-data can coexist with pd-l2ork.
-# Not needed with purr-data 2.4.5+ any more.
-#	cd $(debdist) && patch -Np1 < ../userconfig.patch
 # Make sure to copy the Debian files which may have uncommitted changes.
 # Then run debuild to create the package.
 	cd $(debdist) && cp -R ../debian . && debuild $(DEBUILD_FLAGS)
@@ -90,13 +83,13 @@ deb: $(debsrc) $(addprefix debian/nwjs/, $(nwjs))
 	rm -rf $(debdist)
 
 debsrc:
-	$(MAKE) deb DEBUILD_FLAGS=-S
+	$(MAKE) deb DEBUILD_FLAGS="-S -d"
 
 deb-us:
 	$(MAKE) deb DEBUILD_FLAGS="-us -uc"
 
 debsrc-us:
-	$(MAKE) deb DEBUILD_FLAGS="-S -us -uc"
+	$(MAKE) deb DEBUILD_FLAGS="-S -d -us -uc"
 
 # Determine the build version which needs git to be computed, so we can't do
 # it in a stand-alone build from a tarball.
@@ -113,9 +106,6 @@ $(debsrc):
 # Pre-generate and put s_stuff.h into the tarball (see above; the build
 # version is generated using git which can't be done outside the git repo).
 	sed 's|^\(#define PD_BUILD_VERSION "\).*"|\1$(PD_BUILD_VERSION)"|' ../pd/src/s_stuff.h.in > $(debdist)/pd/src/s_stuff.h
-# Patch packages/Makefile so that we do *not* try to regenerate s_stuff.h
-# during the build.
-	cd $(debdist) && patch -p1 < ../packages-Makefile.patch
 # Create the source tarball.
 	tar cfz $(debsrc) $(debdist)
 	rm -rf $(debdist)
diff --git a/debuild/debian/changelog b/debuild/debian/changelog
index d4079005d5e014fbd74fda6267cfdedd65eebf7e..7d08958bd10c1fc109a3775736c348924eac8d5c 100644
--- a/debuild/debian/changelog
+++ b/debuild/debian/changelog
@@ -1,3 +1,9 @@
+purr-data (2.4.9+git3840+b9f17566-1) bionic; urgency=low
+
+  * Build from latest upstream source.
+
+ -- Albert Graef <aggraef@gmail.com>  Fri, 09 Mar 2018 10:45:41 +0100
+
 purr-data (2.0+git3322+50e3805-1) xenial; urgency=low
 
   * Build from latest upstream source.
diff --git a/debuild/debian/control b/debuild/debian/control
index 28c0e4b06507e44d3b418ef130ec6451adc05326..3172e2adf97966aa119f83364b4559272df887d7 100644
--- a/debuild/debian/control
+++ b/debuild/debian/control
@@ -2,7 +2,7 @@ Source: purr-data
 Section: sound
 Priority: extra
 Maintainer: Albert Graef <aggraef@gmail.com>
-Build-Depends: debhelper (>= 7.0.50~), autoconf, automake, libtool, pkg-config, bison, flex, libgtk2.0-dev, python-dev, dh-python | python-support, flite1-dev, ladspa-sdk, libasound2-dev, libjack-dev, libbluetooth-dev, libcairo2-dev, libgl1-mesa-dev | libgl-dev, libglew1.6-dev | libglew-dev, libgsl-dev | libgsl0-dev, libmagick++-dev, libavifile-0.7-dev, libdc1394-22-dev, libfftw3-dev, libfluidsynth-dev, libftgl-dev, libgmerlin-avdec-dev, libgsm1-dev, libjpeg-dev, libmp3lame-dev, libmpeg3-dev, libquicktime-dev, libraw1394-dev, libsmpeg-dev, libsndobj-dev, libspeex-dev, libstk0-dev, libtiff5-dev, libv4l-dev, libdv4-dev, libiec61883-dev, libxv-dev, libxxf86vm-dev, libunicap2-dev, libvorbis-dev, zlib1g-dev (>= 1:1.1.3), rsync, libgconf2-dev, libnss3-dev, libxtst-dev, libxss-dev
+Build-Depends: debhelper (>= 7.0.50~), autoconf, automake, libtool, pkg-config, bison, flex, libgtk2.0-dev, python-dev, dh-python | python-support, flite1-dev, ladspa-sdk, libasound2-dev, libjack-dev, libbluetooth-dev, libcairo2-dev, libgl1-mesa-dev | libgl-dev, libglew1.6-dev | libglew-dev, libgsl-dev | libgsl0-dev, libmagick++-dev, libavifile-0.7-dev, libdc1394-22-dev, libfftw3-dev, libfluidsynth-dev, libftgl-dev, libgmerlin-avdec-dev, libgsm1-dev, libjpeg-dev, liblua5.3-dev | liblua5.2-dev, libmp3lame-dev, libmpeg3-dev, libquicktime-dev, libraw1394-dev, libsmpeg-dev, libsndobj-dev, libspeex-dev, libstk0-dev, libtiff5-dev, libv4l-dev, libdv4-dev, libiec61883-dev, libxv-dev, libxxf86vm-dev, libunicap2-dev, libvorbis-dev, zlib1g-dev (>= 1:1.1.3), rsync, libgconf2-dev, libnss3-dev, libxtst-dev, libxss-dev
 Standards-Version: 3.9.5
 Homepage: https://git.purrdata.net/jwilkes/purr-data
 
diff --git a/debuild/debian/rules b/debuild/debian/rules
index 6e2b910b6bb841d7aed9ff0ca032c38c29c289d8..139c20169e4ac84d61639f2b6ba79d2fa185e386 100755
--- a/debuild/debian/rules
+++ b/debuild/debian/rules
@@ -25,6 +25,8 @@ prefix = /opt/purr-data
 
 override_dh_auto_configure:
 
+override_dh_auto_clean:
+
 override_dh_auto_build:
 # Copy the nw.js sources to where purr-data wants them.
 	tar -xf debian/nwjs/$(nwjspkg)-$(arch).tar.gz && rm -rf pd/nw/nw && mv $(nwjspkg)-$(arch) pd/nw/nw
diff --git a/debuild/packages-Makefile.patch b/debuild/packages-Makefile.patch
deleted file mode 100644
index ad3e9ac7d61ef11481d3f78a99a904b205cc7e08..0000000000000000000000000000000000000000
--- a/debuild/packages-Makefile.patch
+++ /dev/null
@@ -1,32 +0,0 @@
-diff --git a/packages/Makefile b/packages/Makefile
-index f5c1f8c0..0a285b52 100644
---- a/packages/Makefile
-+++ b/packages/Makefile
-@@ -373,12 +373,14 @@ doc_format:
- # AG: The set_version target is broken since it modifies m_pd.h in-place
- # during the build, which is a bad thing to do to files which are supposed to
- # be kept in a source code repository. Instead, we create s_stuff.h from
--# s_stuff.h.in, where the latter is kept in the repo and the former gets created
--# from the latter by substituting PD_BUILD_VERSION.
-+# s_stuff.h.in, where the latter is kept in the repo and the former gets
-+# created from the latter by substituting PD_BUILD_VERSION. (Only try to do
-+# this if we're actually in the git repo, otherwise we'll get an empty
-+# revision number.)
- 
- git_version: $(pd_src)/src/s_stuff.h.in
--	cd $(pd_src)/src/ && \
--	sed 's|^\(#define PD_BUILD_VERSION "\).*"|\1$(PD_BUILD_VERSION)"|' s_stuff.h.in > s_stuff.h
-+	test -d $(cvs_root_dir)/.git && cd $(pd_src)/src/ && \
-+	sed 's|^\(#define PD_BUILD_VERSION "\).*"|\1$(PD_BUILD_VERSION)"|' s_stuff.h.in > s_stuff.h || true
- 
- set_version:
- # change Pd's version number to reflect the extended build
-@@ -421,7 +423,7 @@ distclean: cruft_clean
- 	$(MAKE) -C $(abstractions_src) distclean
- 	$(MAKE) -C $(extensions_src) distclean
- 	$(MAKE) -C $(externals_src) distclean
--	-$(MAKE) -C $(pd_src) distclean
-+	-$(MAKE) -C $(pd_src) clean
- 
- test_locations:
- 	@echo "PD_VERSION: $(PD_VERSION)"
diff --git a/debuild/precise-configure.patch b/debuild/precise-configure.patch
deleted file mode 100644
index e4bb19126f774da25457c405b9344bf32fa2f14b..0000000000000000000000000000000000000000
--- a/debuild/precise-configure.patch
+++ /dev/null
@@ -1,96 +0,0 @@
-Fix up LDFLAGS for Precise and earlier (patch by Hans-Christoph Steiner,
-updated to pd-l2ork by Albert Graef).
-Description: fix ./configure dying thinking we're cross-compiling
- When building using debuild on Debian/squeeze or Ubuntu < quantal,
- ./configure somehow gets some LDFLAGS for shared libraries and uses them in
- the gcc tests.  The executable then fails to run since its a shared library,
- and ./configure thinks we're cross-compiling.  This patch forces no LDFLAGS.
-
-diff --git a/externals/Makefile b/externals/Makefile
-index 7b64f45..6b7c49b 100644
---- a/externals/Makefile
-+++ b/externals/Makefile
-@@ -611,6 +611,7 @@ $(gem_src)/Gem.pd_linux: $(gem_src)/configure
- 	test -s $(gem_src)/Gem.pd_linux || \
- 		cd $(gem_src) && ./configure \
- 			CXXFLAGS="-DHAVE_S_STUFF_H" \
-+			LDFLAGS= \
- 			--prefix=$(prefix) \
- 			--with-video=plugins \
- 			--with-film=plugins \
-@@ -649,7 +650,7 @@ $(externals_src)/gem2pdp/configure: $(externals_src)/gem2pdp/configure.ac
- 	cd $(externals_src)/gem2pdp && aclocal && autoconf
- 
- $(externals_src)/gem2pdp/Makefile: $(externals_src)/gem2pdp/Makefile.in
--	cd $(externals_src)/gem2pdp && ./configure --with-pddir=$(pd_src) \
-+	cd $(externals_src)/gem2pdp && ./configure LDFLAGS= --with-pddir=$(pd_src) \
- 		--with-gemdir=$(gem_src)  --with-pdpdir=$(externals_src)/pdp
- 
- gem2pdp: $(externals_src)/gem2pdp/configure $(externals_src)/gem2pdp/Makefile
-@@ -885,7 +886,7 @@ $(IEM16_DIR)/configure: $(IEM16_DIR)/configure.ac $(IEM16_DIR)/aclocal.m4
- 
- $(IEM16_DIR)/Make.config: $(IEM16_DIR)/Make.config.in \
- $(IEM16_DIR)/configure
--	cd $(IEM16_DIR) && ./configure --disable-library \
-+	cd $(IEM16_DIR) && ./configure LDFLAGS= --disable-library \
- 		--with-pd=$(pd_src)
- 
- iem16: $(IEM16_DIR)/Make.config
-@@ -1269,11 +1270,11 @@ $(externals_src)/OSCx/configure: $(externals_src)/OSCx/configure.ac
- 	cd $(externals_src)/OSCx && autoconf
- 
- $(externals_src)/OSCx/Makefile: $(externals_src)/OSCx/Makefile.in
--	cd $(externals_src)/OSCx && ./configure
-+	cd $(externals_src)/OSCx && ./configure LDFLAGS=
- $(externals_src)/OSCx/libOSC/Makefile: $(externals_src)/OSCx/libOSC/Makefile.in
--	cd $(externals_src)/OSCx && ./configure
-+	cd $(externals_src)/OSCx && ./configure LDFLAGS=
- $(externals_src)/OSCx/src/Makefile: $(externals_src)/OSCx/src/Makefile.in
--	cd $(externals_src)/OSCx && ./configure
-+	cd $(externals_src)/OSCx && ./configure LDFLAGS=
- 
- $(externals_src)/OSCx/src/OSCroute.$(EXTENSION):  $(externals_src)/OSCx/configure \
- $(externals_src)/OSCx/Makefile
-@@ -1356,7 +1357,7 @@ $(externals_src)/pdp/configure: $(externals_src)/pdp/configure.ac
- 	cd $(externals_src)/pdp && autoconf
- 
- $(externals_src)/pdp/Makefile.config: $(externals_src)/pdp/configure $(externals_src)/pdp/Makefile.config.in
--	cd $(externals_src)/pdp && ./configure PD_CPPFLAGS="-I$(pd_src)/src" \
-+	cd $(externals_src)/pdp && ./configure LDFLAGS= PD_CPPFLAGS="-I$(pd_src)/src" \
- 		$(PDP_OPTIONS)
- 
- $(externals_src)/pdp/pdp.$(EXTENSION): $(externals_src)/pdp/Makefile.config 
-@@ -1770,6 +1771,7 @@ $(zexy_src)/configure: $(zexy_src)/configure.ac
- 
- $(zexy_src)/Makefile: $(zexy_src)/configure $(zexy_src)/Makefile.am $(zexy_src)/src/Makefile.am
- 	cd $(zexy_src) && ./configure --disable-library \
-+		LDFLAGS= \
- 		--with-extension=$(EXTENSION) \
- 		--prefix=$(prefix) \
- 		--libdir=$(objectsdir) \
-diff --git a/externals/iem16/src/Makefile b/externals/iem16/src/Makefile
-index 25e5bbe..5be876d 100644
---- a/externals/iem16/src/Makefile
-+++ b/externals/iem16/src/Makefile
-@@ -22,7 +22,7 @@ aclocal.m4: acinclude.m4
- 	aclocal
- 
- Make.config: Make.config.in configure
--	./configure $(CONFIGUREFLAGS)
-+	./configure $(CONFIGUREFLAGS) LDFLAGS=
- 
- -include $(SOURCES:.c=.d)
- 
-diff --git a/externals/moocow/extended/Makefile b/externals/moocow/extended/Makefile
-index 2726d1a..9da4944 100644
---- a/externals/moocow/extended/Makefile
-+++ b/externals/moocow/extended/Makefile
-@@ -36,7 +36,7 @@ MOOCOW_BUILD_VERSION ?=2009-04-27.002
- #	CFLAGS="$(shell echo $(CFLAGS))" ##-- works
- CONFIGURE_ARGS=\
- 	CFLAGS="$(CFLAGS) -I/sw/include" \
--	LDFLAGS="$(LDFLAGS) -L$(pd_src)/src -L$(pd_src)/bin -L$(pd_src)/obj -L/sw/lib" \
-+	LDFLAGS="-L$(pd_src)/src -L$(pd_src)/bin -L$(pd_src)/obj -L/sw/lib" \
- 	--with-pd-include="$(pd_src)/src" \
- 	--with-pd-dir="$(MOOCOW_BUILD)" \
- 	--disable-dependency-tracking
diff --git a/debuild/userconfig.patch b/debuild/userconfig.patch
deleted file mode 100644
index 0e41714e92fc6c76a24db2856d846a4740fcd1ca..0000000000000000000000000000000000000000
--- a/debuild/userconfig.patch
+++ /dev/null
@@ -1,13 +0,0 @@
-diff --git a/pd/src/s_file.c b/pd/src/s_file.c
-index 32f54c31..304524d5 100644
---- a/pd/src/s_file.c
-+++ b/pd/src/s_file.c
-@@ -46,7 +46,7 @@ void sys_doflags( void);
- 
- #ifdef UNIX
- 
--#define USER_CONFIG_DIR ".pd-l2ork"
-+#define USER_CONFIG_DIR ".purr-data"
- 
- static char *sys_prefbuf;
- 
diff --git a/externals/Makefile b/externals/Makefile
index e60a73c990d0b1ea8c67d95289f2d3724ecfb8d6..414e1e2e8e17639db4b6f310a21e4960623150cc 100644
--- a/externals/Makefile
+++ b/externals/Makefile
@@ -129,7 +129,13 @@ CXXFLAGS = $(CFLAGS)
 #
 # WARNING!  this MUST be all on one line because the automatic package
 # building scripts rely on it being that way.
-LIB_TARGETS = adaptive arraysize autotune bassemu boids bsaylor comport creb cxc cyclone disis earplug ekext ext13 fftease fluid freeverb ggee hcs iem_ambi iem_bin_ambi iemlib iemgui iemguts iem_adaptfilt iemmatrix iemxmlrpc iem_delay iem_roomsim iem_spec2 iem_tab jasch_lib loaders-libdir lyonpotpourri mapping markex maxlib mjlib moocow moonlib motex mrpeach oscx pan pdcontainer pddp pdogg plugin pmpd rjlib sigpack smlib tof unauthorized vbap windowing zexy
+ifeq ($(LIGHT),yes)
+# minimal set of extensions for the "light" build
+LIB_TARGETS = loaders-libdir pddp
+INCREMENTAL = yes
+else
+LIB_TARGETS = adaptive arraysize autotune bassemu boids bsaylor comport creb cxc cyclone disis earplug ekext ext13 fftease fluid freeverb ggee hcs iem_ambi iem_bin_ambi iemlib iemgui iemguts iem_adaptfilt iemmatrix iemxmlrpc iem_delay iem_roomsim iem_spec2 iem_tab jasch_lib loaders-libdir lyonpotpourri mapping markex maxlib mjlib moocow moonlib motex mrpeach oscx pan pdcontainer pddp pdlua pdogg plugin pmpd rjlib sigpack smlib tof unauthorized vbap windowing zexy
+endif
 
 # DISABLED: flatgui
 
@@ -137,7 +143,9 @@ LIB_TARGETS = adaptive arraysize autotune bassemu boids bsaylor comport creb cxc
 
 # this is for libraries that don't compile (yet) on all platforms
 ifeq ($(OS_NAME),windows)
-  LIB_TARGETS += gem
+  ifneq ($(INCREMENTAL),yes)
+    LIB_TARGETS += gem
+  endif
 else
   ifeq ($(OS_NAME),darwin)
 # on Mac OS X 10.6/Snow Leopard don't build hid since it needs Carbon
@@ -145,8 +153,9 @@ else
     ifneq ($(shell uname -r | sed 's|10\.[0-9][0-9]*\.[0-9][0-9]*|10|'),10)
       LIB_TARGETS +=
     endif
-  else
-    # GNU/Linux, BSD, IRIX, etc. (we use exported variable INCREMENTAL to avoid rebuilding entire Gem lib that takes a long time to compile)
+  else ifneq ($(LIGHT),yes)
+    # GNU/Linux, BSD, IRIX, etc. (we use exported variable INCREMENTAL to
+    # avoid rebuilding entire Gem lib that takes a long time to compile)
     ifeq ($(INCREMENTAL),yes)
 	LIB_TARGETS += hid pdp iem16
     else
@@ -1395,6 +1404,22 @@ pddp_clean:
 	make -C $(externals_src)/pddp clean
 
 
+#------------------------------------------------------------------------------#
+# PDLUA
+
+LUA_CFLAGS = $(shell (pkg-config --cflags lua5.3 || pkg-config --cflags lua5.2 || pkg-config --cflags lua) 2> /dev/null)
+LUA_LIBS = $(shell (pkg-config --libs lua5.3 || pkg-config --libs lua5.2 || pkg-config --libs lua) 2> /dev/null)
+
+pdlua:
+	make -C $(externals_src)/pd-lua LUA_CFLAGS="$(LUA_CFLAGS)" LUA_LIBS="$(LUA_LIBS)" PD_PATH="$(pd_src)" PD_LIB="$(pd_src)/src" CFLAGS="$(CFLAGS)"
+
+pdlua_install:
+	make -C $(externals_src)/pd-lua DESTDIR="$(DESTDIR)" objectsdir="$(objectsdir)" install
+
+pdlua_clean:
+	make -C $(externals_src)/pd-lua clean
+
+
 #------------------------------------------------------------------------------#
 # PDOGG
 pdogg:
diff --git a/externals/disis/ADSR.c b/externals/disis/ADSR.c
new file mode 100644
index 0000000000000000000000000000000000000000..e4282fd97edcc50fd6d6fb9fe604976ef3d61718
--- /dev/null
+++ b/externals/disis/ADSR.c
@@ -0,0 +1,190 @@
+#include "ADSR.h"
+
+t_float stk_ADSR_tick(t_stk_ADSR *x)
+{
+    switch (x->state)
+    {
+        case ATTACK:
+            x->value += x->attackRate;
+            if (x->value >= x->target)
+            {
+                x->value = x->target;
+                x->target = x->sustainLevel;
+                x->state = DECAY;
+            }
+            break;
+
+        case DECAY:
+            if (x->value > x->sustainLevel)
+            {
+                x->value -= x->decayRate;
+                if (x->value <= x->sustainLevel)
+                {
+                    x->value = x->sustainLevel;
+                    x->state = SUSTAIN;
+                }
+            }
+            else
+            {
+                x->value += x->decayRate; // attack target < sustain level
+                if (x->value >= x->sustainLevel)
+                {
+                    x->value = x->sustainLevel;
+                    x->state = SUSTAIN;
+                }
+            }
+            break;
+
+        case RELEASE:
+            x->value -= x->releaseRate;
+            if (x->value <= 0.0)
+            {
+                x->value = 0.0;
+                x->state = IDLE;
+            }
+    }
+    return x->value;
+}
+
+void stk_ADSR_init(t_stk_ADSR *x)
+{
+  x->target = 0.0;
+  x->value = 0.0;
+  x->attackRate = 0.001;
+  x->decayRate = 0.001;
+  x->releaseRate = 0.005;
+  x->releaseTime = -1.0;
+  x->sustainLevel = 0.5;
+  x->state = IDLE;
+  x->sampleRate = 44100;
+}
+
+t_env_state stk_ADSR_getState(t_stk_ADSR *x)
+{
+    return x->state;
+}
+
+void stk_ADSR_sampleRateChanged(t_stk_ADSR *x, t_float newRate,
+    t_float oldRate)
+{
+    x->attackRate = oldRate * x->attackRate / newRate;
+    x->decayRate = oldRate * x->decayRate / newRate;
+    x->releaseRate = oldRate * x->releaseRate / newRate;
+}
+
+void stk_ADSR_setSampleRate(t_stk_ADSR *x, t_float newRate)
+{
+    x->sampleRate = newRate;
+}
+
+void stk_ADSR_keyOn(t_stk_ADSR *x)
+{
+    if (x->target <= 0.0) x->target = 1.0;
+    x->state = ATTACK;
+}
+
+void stk_ADSR_keyOff(t_stk_ADSR *x)
+{
+    x->target = 0.0;
+    x->state = RELEASE;
+
+    // FIXED October 2010 - Nick Donaldson
+    // Need to make release rate relative to current value!!
+    // Only update if we have set a TIME rather than a RATE,
+    // in which case releaseTime will be -1
+    if (x->releaseTime > 0.0)
+	  x->releaseRate = x->value / (x->releaseTime * x->sampleRate);
+}
+
+void stk_ADSR_setAttackRate(t_stk_ADSR *x, t_float rate)
+{
+    if (rate < 0.0)
+        fprintf(stderr, "stk_ADSR_setAttackRate: argument must be >= 0.0!");
+    x->attackRate = rate;
+}
+
+void stk_ADSR_setAttackTarget(t_stk_ADSR *x, t_float target)
+{
+    if (target < 0.0)
+    {
+        fprintf(stderr, "ADSR::setAttackTarget: negative target not allowed!");
+    }
+    x->target = target;
+}
+
+void stk_ADSR_setDecayRate(t_stk_ADSR *x, t_float rate)
+{
+    if (rate < 0.0)
+        fprintf(stderr, "ADSR::setDecayRate: negative rates not allowed!");
+    x->decayRate = rate;
+}
+
+void stk_ADSR_setSustainLevel(t_stk_ADSR *x, t_float level)
+{
+    if (level < 0.0)
+        fprintf(stderr, "ADSR::setSustainLevel: negative level not allowed!");
+    x->sustainLevel = level;
+}
+
+void stk_ADSR_setReleaseRate(t_stk_ADSR *x, t_float rate)
+{
+    if (rate < 0.0)
+        fprintf(stderr, "ADSR::setReleaseRate: negative rates not allowed!");
+    x->releaseRate = rate;
+
+    // Set to negative value so we don't update the release rate on keyOff()
+    x->releaseTime = -1.0;
+}
+
+void stk_ADSR_setAttackTime(t_stk_ADSR *x, t_float time)
+{
+    if (time <= 0.0)
+        fprintf(stderr,
+            "ADSR::setAttackTime: negative or zero times not allowed!");
+    x->attackRate = 1.0 / (time * x->sampleRate);
+}
+
+void stk_ADSR_setDecayTime(t_stk_ADSR *x, t_float time)
+{
+    if (time <= 0.0)
+        fprintf(stderr,
+            "ADSR::setDecayTime: negative or zero times not allowed!");
+    x->decayRate = (1.0 - x->sustainLevel) / (time * x->sampleRate);
+}
+
+void stk_ADSR_setReleaseTime(t_stk_ADSR *x, t_float time)
+{
+    if (time <= 0.0)
+        fprintf(stderr,
+            "ADSR::setReleaseTime: negative or zero times not allowed!");
+    x->releaseRate = x->sustainLevel / (time * x->sampleRate);
+    x->releaseTime = time;
+}
+
+void stk_ADSR_setAllTimes(t_stk_ADSR *x, t_float aTime, t_float dTime,
+    t_float sLevel, t_float rTime)
+{
+    stk_ADSR_setAttackTime(x, aTime);
+    stk_ADSR_setSustainLevel(x, sLevel);
+    stk_ADSR_setDecayTime(x, dTime);
+    stk_ADSR_setReleaseTime(x, rTime);
+}
+
+void stk_ADSR_setTarget(t_stk_ADSR *x, t_float target)
+{
+    if (target < 0.0)
+        fprintf(stderr, "ADSR::setTarget: negative target not allowed!");
+    x->target = target;
+
+    stk_ADSR_setSustainLevel(x, x->target);
+    if (x->value < x->target) x->state = ATTACK;
+    if (x->value > x->target) x->state = DECAY;
+}
+
+void stk_ADSR_setValue(t_stk_ADSR *x, t_float value)
+{
+    x->state = SUSTAIN;
+    x->target = value;
+    x->value = value;
+    stk_ADSR_setSustainLevel(x, value);
+}
diff --git a/externals/disis/ADSR.h b/externals/disis/ADSR.h
new file mode 100644
index 0000000000000000000000000000000000000000..f4071071518ec55cb172852468b2ad5f5da54eeb
--- /dev/null
+++ b/externals/disis/ADSR.h
@@ -0,0 +1,94 @@
+#include "m_pd.h"
+
+/* port of stk's ADSR class to C */
+
+/* original class notes */
+
+/***************************************************/
+/*! \class ADSR
+    \brief STK ADSR envelope class.
+    This class implements a traditional ADSR (Attack, Decay, Sustain,
+    Release) envelope.  It responds to simple keyOn and keyOff
+    messages, keeping track of its state.  The \e state = ADSR::IDLE
+    before being triggered and after the envelope value reaches 0.0 in
+    the ADSR::RELEASE state.  All rate, target and level settings must
+    be non-negative.  All time settings are in seconds and must be
+    positive.
+    by Perry R. Cook and Gary P. Scavone, 1995--2017.
+*/
+/***************************************************/
+
+/* ADSR envelope states. */
+typedef enum {
+    ATTACK,   /* Attack */
+    DECAY,    /* Decay */
+    SUSTAIN,  /* Sustain */
+    RELEASE,  /* Release */
+    IDLE      /* Before attack / after release */
+} t_env_state;
+
+typedef struct _stk_ADSR {
+    t_env_state state;
+    t_float value;
+    t_float target;
+    t_float attackRate;
+    t_float decayRate;
+    t_float releaseRate;
+    t_float releaseTime;
+    t_float sustainLevel;
+    // Currently setting this is dsp_add routine...
+    t_float sampleRate;
+} t_stk_ADSR;
+
+/* initialize the struct members to sane values */
+void stk_ADSR_init(t_stk_ADSR *x);
+
+/* set the sample rate */
+void stk_ADSR_setSampleRate(t_stk_ADSR *x, t_float newRate);
+
+/* Set target = 1, state = ATTACK. */
+void stk_ADSR_keyOn(t_stk_ADSR *x);
+
+/* Set target = 0, state = RELEASE. */
+void stk_ADSR_keyOff(t_stk_ADSR *x);
+
+/* Set the attack rate (gain / sample). */
+void stk_ADSR_setAttackRate(t_stk_ADSR *x, t_float rate);
+
+/* Set the target value for the attack (default = 1.0). */
+void stk_ADSR_setAttackTarget(t_stk_ADSR *x, t_float target);
+
+/* Set the decay rate (gain / sample). */
+void stk_ADSR_setDecayRate(t_stk_ADSR *x, t_float rate);
+
+/* Set the sustain level. */
+void stk_ADSR_setSustainLevel(t_stk_ADSR *x, t_float level);
+
+/* Set the release rate (gain / sample). */
+void stk_ADSR_setReleaseRate(t_stk_ADSR *x, t_float rate);
+
+/* Set the attack rate based on a time duration (seconds). */
+void stk_ADSR_setAttackTime(t_stk_ADSR *x, t_float time);
+
+/* Set the decay rate based on a time duration (seconds). */
+void stk_ADSR_setDecayTime(t_stk_ADSR *x, t_float time);
+
+/* Set the release rate based on a time duration (seconds). */
+void stk_ADSR_setReleaseTime(t_stk_ADSR *x, t_float time);
+
+/* Set sustain level and attack, decay, and release time durations (seconds). */
+void stk_ADSR_setAllTimes(t_stk_ADSR *x, t_float aTime, t_float dTime,
+    t_float sLevel, t_float rTime);
+
+/* Set a sustain target value and attack or decay from current value
+    to target. */
+void stk_ADSR_setTarget(t_stk_ADSR *x, t_float target);
+
+/* Return the current envelope state (ATTACK, DECAY, SUSTAIN, RELEASE, IDLE).*/
+t_env_state stk_ADSR_getState(t_stk_ADSR *x);
+
+/* Set to state = ADSR::SUSTAIN with current and target values of value. */
+void stk_ADSR_setValue(t_stk_ADSR *x, t_float value);
+
+/* Compute and return one output sample. */
+t_float stk_ADSR_tick(t_stk_ADSR *x);
diff --git a/externals/disis/disis_munger.c b/externals/disis/disis_munger.c
new file mode 100644
index 0000000000000000000000000000000000000000..504617843f83ac7c6462d7e672da84ba3d6e6d48
--- /dev/null
+++ b/externals/disis/disis_munger.c
@@ -0,0 +1,1816 @@
+/*
+disis.munger~ 1.4.3
+a realtime multichannel granulator
+
+a flext (cross-platform PD & Max/MSP) port of
+the munger~ object from the PeRColate library (0.9 beta6)
+http://www.music.columbia.edu/PeRColate/
+
+Original PeRColate library by:
+
+Dan Trueman http://www.music.princeton.edu/~dan/
+R. Luke DuBois's http://www.lukedubois.com/
+
+Flext port and additions by:
+Ivica Ico Bukvic http://ico.bukvic.net
+Ji-Sun Kim hideaway@vt.edu
+http://disis.music.vt.edu
+
+Released under GPL license
+(whichever is the latest version--as of this release, version 2)
+For more info on the GPL license please visit:
+http://www.gnu.org/copyleft/gpl.html
+
+For latest changes please see changelog
+*/
+
+#include "m_pd.h"
+#include "ADSR.h" /* small C library ported from stk */
+#include <math.h>
+#include <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+//version
+#define MUNGER_MAJOR 1
+#define MUNGER_MINOR 4
+#define MUNGER_REV 3
+
+/* MSVC doesn't know RANDOM(), while GCC's
+   (at least on Linux) has rand() limit much higher */
+#if !defined(__GNUC__) || defined(__MINGW32__)
+#define RANDOM() (rand())
+#else
+#define RANDOM() (random()%32768)
+#endif
+
+#define ONE_OVER_HALFRAND 0.00006103516	/* constant = 1. / 16384.0 */
+#define ONE_OVER_MAXRAND 0.000030517578	/* 1 / 32768 */
+#define MINSPEED .001 /* minimum speed through buffer on playback */
+#define ENVSIZE 32
+#define ONE_OVER_ENVSIZE .0078125
+#define MINSIZE 64 /* twice ENVSIZE. minimum grainsize in samples */
+#define RAND01 (((long)RANDOM() * ONE_OVER_MAXRAND) /* RANDOM() numbers 0-1 */
+
+/* RANDOM() numbers -1 to 1 */
+#define RAND11 (((long)RANDOM() - 16384.) * ONE_OVER_HALFRAND)
+#define WINLENGTH 1024
+
+/* max number of transpositions for the "scale" message */
+#define PITCHTABLESIZE 1000
+#define RECORDRAMP 1000
+#define RECORDRAMP_INV 0.001
+
+/* these are arbitrary-- can we trust users not to
+   do something silly and remove these? */
+#define MAXCHANNELS 64
+#define MAXVOICES 1000
+
+/* useful define */
+#ifndef TWOPI
+#define TWOPI 6.28318530717958647692
+#endif
+
+static t_class *disis_munger_class;
+
+typedef struct _disis_munger {
+    t_object x_obj;
+    t_float x_f;
+    t_float x_srate;
+    t_float x_one_over_srate;
+    t_float x_srate_ms;
+    t_float x_one_over_srate_ms;
+    t_float x_initbuflen;
+    int x_buflen;
+    t_float x_maxdelay;
+    int x_num_channels;
+    int x_numvoices;
+    t_symbol *x_munger_name;
+    t_float x_maxsize;
+    t_float x_minsize;
+    t_float x_twothirdBufsize;
+    t_float x_onethirdBufsize;
+    int x_verbose;
+
+    /* Ancillary inlet vars */
+    t_float x_grate;
+    t_float x_grate_var;
+    t_float x_glen;
+    t_float x_glen_var;
+    t_float x_gpitch;
+    t_float x_gpitch_var;
+    t_float x_gpan_spread;
+
+    /* Heap allocated based on number of voices */
+    t_float *x_recordBuf;
+    t_float *x_winTime;
+    t_float *x_winRate;
+    long *x_gvoiceSize;
+    double *x_gvoiceSpeed;
+    double *x_gvoiceCurrent;
+    int *x_gvoiceDirection;
+    int *x_gvoiceOn;
+    long *x_gvoiceDone;
+    t_float *x_gvoiceLPan;
+    t_float *x_gvoiceRPan;
+    t_float *x_gvoiceRamp;
+    t_float *x_gvoiceOneOverRamp;
+    t_float *x_gvoiceGain;
+    t_stk_ADSR *x_gvoiceADSR;
+    int *x_gvoiceADSRon;
+    t_float *x_noteTransp;
+    t_float *x_noteSize;
+    t_float *x_notePan;
+    t_float *x_noteGain;
+    t_float *x_noteAttack;
+    t_float *x_noteDecay;
+    t_float *x_noteSustain;
+    t_float *x_noteRelease;
+    int *x_noteDirection;
+
+    /* nvoices x nchannels */
+    t_float **x_gvoiceSpat;
+    t_float **x_notechannelGain;
+    t_float **x_notechannelGainSpread;
+
+    /* Heap allocated for signal vector x nchannels */
+    t_float **x_out;
+    /* Heap allocated x nchannels */
+    t_float *x_outsamp;
+    t_float *x_channelGain;
+    t_float *x_channelGainSpread;
+
+    /* Oh wow, there are more... */
+    int x_graincounter;
+    int x_countsamples;
+    int x_voices;
+    t_float x_gain;
+    t_float x_randgain;
+    t_float x_twelfth;
+    t_float x_semitone;
+    short x_smoothPitch;
+    int x_scale_len;
+
+    t_float x_tempgrate;
+    long x_time;
+    t_float x_position;
+    t_float x_gimme;
+    int x_power;
+    short x_ambi;
+    long x_maxvoices;
+
+    short x_oneshot;
+    int x_newnote;
+
+    short x_doHanning;
+    t_float x_winTable[WINLENGTH];
+    t_float x_pitchTable[PITCHTABLESIZE];
+    t_float x_rampLength;
+
+    int x_recordOn;
+    long x_recordCurrent;
+    int x_recordRampVal;   /* ramp for when toggling record on and off */
+    int x_rec_ramping;     /* -1 ramp down, 1 ramp up, 0 not ramping */
+
+    t_symbol *x_arrayname;
+    int x_arraylength;
+    t_word *x_arrayvec;      /* vec to use if we want an external buffer */
+    long x_l_chan;           /* is there any other choice? */
+    int x_discretepan;       /* off by default */
+} t_disis_munger;
+
+
+static void float_2d_alloc(t_float ***fp, int nrow, int ncol)
+{
+    int i;
+    *fp = t_getbytes(nrow * sizeof(t_float*));
+    for (i = 0; i < nrow; i++)
+        (*fp)[i] = t_getbytes(ncol * sizeof(t_float));
+}
+
+static void float_2d_free(t_float ***fp, int nrow, int ncol)
+{
+    int i;
+    for (i = 0; i < nrow; i++)
+        t_freebytes((*fp)[i], ncol * sizeof(t_float));
+    t_freebytes(*fp, nrow * sizeof(t_float*));
+}
+
+static t_disis_munger *munger_alloc(t_disis_munger *x)
+{
+    /* Heap allocated based on number of voices */
+    int nv = x->x_numvoices, nchan = x->x_num_channels;
+
+    x->x_recordBuf = (t_float *)t_getbytes((x->x_buflen + 1) * sizeof(t_float));
+
+    /* If recordBuf didn't get allocated, let's go ahead and bail. Otherwise
+       we just assume all the ones below will succeed. */
+
+    if (!x->x_recordBuf)
+    {
+        error("disis_munger~ %s: out of memory", x->x_munger_name->s_name);
+        return 0;
+    }
+    x->x_winTime = (t_float *)t_getbytes(nv * sizeof(t_float));
+    x->x_winRate = (t_float *)t_getbytes(nv * sizeof(t_float));
+    x->x_gvoiceSize = (long *)t_getbytes(nv * sizeof(long));
+    x->x_gvoiceSpeed = (double *)t_getbytes(nv * sizeof(double));
+    x->x_gvoiceCurrent = (double *)t_getbytes(nv * sizeof(double));
+    x->x_gvoiceDirection = (int *)t_getbytes(nv * sizeof(int));
+    x->x_gvoiceOn = (int *)t_getbytes(nv * sizeof(int));
+    x->x_gvoiceDone = (long *)t_getbytes(nv * sizeof(long));
+    x->x_gvoiceLPan = (t_float *)t_getbytes(nv * sizeof(t_float));
+    x->x_gvoiceRPan = (t_float *)t_getbytes(nv * sizeof(t_float));
+    x->x_gvoiceRamp = (t_float *)t_getbytes(nv * sizeof(t_float));
+    x->x_gvoiceOneOverRamp = (t_float *)t_getbytes(nv * sizeof(t_float));
+    x->x_gvoiceGain = (t_float *)t_getbytes(nv * sizeof(t_float));
+
+    /* This is its own type */
+    x->x_gvoiceADSR = (t_stk_ADSR *)t_getbytes(nv * sizeof(t_stk_ADSR)); 
+    x->x_gvoiceADSRon = (int *)t_getbytes(nv * sizeof(int));
+    x->x_noteTransp = (t_float *)t_getbytes(nv * sizeof(t_float));
+    x->x_noteSize = (t_float *)t_getbytes(nv * sizeof(t_float));
+    x->x_notePan = (t_float *)t_getbytes(nv * sizeof(t_float));
+    x->x_noteGain = (t_float *)t_getbytes(nv * sizeof(t_float));
+    x->x_noteAttack = (t_float *)t_getbytes(nv * sizeof(t_float));
+    x->x_noteDecay = (t_float *)t_getbytes(nv * sizeof(t_float));
+    x->x_noteSustain = (t_float *)t_getbytes(nv * sizeof(t_float));
+    x->x_noteRelease = (t_float *)t_getbytes(nv * sizeof(t_float));
+    x->x_noteDirection = (int *)t_getbytes(nv * sizeof(int));
+
+    /* nvoices x nchannels */
+    float_2d_alloc(&x->x_gvoiceSpat, nv, nchan);
+    float_2d_alloc(&x->x_notechannelGain, nv, nchan);
+    float_2d_alloc(&x->x_notechannelGainSpread, nv, nchan);
+
+    /* Heap allocated for signal vector x nchannels */
+    x->x_out = (t_float **)t_getbytes(nchan * sizeof(t_float*));
+    /* Heap allocated x nchannels */
+    x->x_outsamp = (t_float *)t_getbytes(nchan * sizeof(t_float));
+    x->x_channelGain = (t_float *)t_getbytes(nchan * sizeof(t_float));
+    x->x_channelGainSpread = (t_float *)t_getbytes(nchan * sizeof(t_float));
+    return x;
+}
+
+static void munger_free(t_disis_munger *x)
+{
+    /* Heap allocated based on number of voices */
+    int nv = x->x_numvoices, nchan = x->x_num_channels;
+
+    if (x->x_recordBuf)
+        t_freebytes(x->x_recordBuf, (x->x_buflen + 1) * sizeof(t_float));
+    if (x->x_winTime)
+        t_freebytes(x->x_winTime, nv * sizeof(t_float));
+    if (x->x_winRate)
+        t_freebytes(x->x_winRate, nv * sizeof(t_float));
+    if (x->x_gvoiceSize)
+        t_freebytes(x->x_gvoiceSize, nv * sizeof(long));
+    if (x->x_gvoiceSpeed)
+        t_freebytes(x->x_gvoiceSpeed, nv * sizeof(double));
+    if (x->x_gvoiceCurrent)
+        t_freebytes(x->x_gvoiceCurrent, nv * sizeof(double));
+    if (x->x_gvoiceDirection)
+        t_freebytes(x->x_gvoiceDirection, nv * sizeof(int));
+    if (x->x_gvoiceOn)
+        t_freebytes(x->x_gvoiceOn, nv * sizeof(int));
+    if (x->x_gvoiceDone)
+        t_freebytes(x->x_gvoiceDone, nv * sizeof(long));
+    if (x->x_gvoiceLPan)
+        t_freebytes(x->x_gvoiceLPan, nv * sizeof(t_float));
+    if (x->x_gvoiceRPan)
+        t_freebytes(x->x_gvoiceRPan, nv * sizeof(t_float));
+    if (x->x_gvoiceRamp)
+        t_freebytes(x->x_gvoiceRamp, nv * sizeof(t_float));
+    if (x->x_gvoiceOneOverRamp)
+        t_freebytes(x->x_gvoiceOneOverRamp, nv * sizeof(t_float));
+    if (x->x_gvoiceGain)
+        t_freebytes(x->x_gvoiceGain, nv * sizeof(t_float));
+
+    if (x->x_gvoiceADSR)
+        t_freebytes(x->x_gvoiceADSR, nv * sizeof(t_stk_ADSR)); 
+
+    if (x->x_gvoiceADSRon)
+        t_freebytes(x->x_gvoiceADSRon, nv * sizeof(int));
+    if (x->x_noteTransp)
+        t_freebytes(x->x_noteTransp, nv * sizeof(t_float));
+    if (x->x_noteSize)
+        t_freebytes(x->x_noteSize, nv * sizeof(t_float));
+    if (x->x_notePan)
+        t_freebytes(x->x_notePan, nv * sizeof(t_float));
+    if (x->x_noteGain)
+        t_freebytes(x->x_noteGain, nv * sizeof(t_float));
+    if (x->x_noteAttack)
+        t_freebytes(x->x_noteAttack, nv * sizeof(t_float));
+    if (x->x_noteDecay)
+        t_freebytes(x->x_noteDecay, nv * sizeof(t_float));
+    if (x->x_noteSustain)
+        t_freebytes(x->x_noteSustain, nv * sizeof(t_float));
+    if (x->x_noteRelease)
+        t_freebytes(x->x_noteRelease, nv * sizeof(t_float));
+    if (x->x_noteDirection)
+        t_freebytes(x->x_noteDirection, nv * sizeof(int));
+
+    /* nvoices x nchannels */
+    float_2d_free(&x->x_gvoiceSpat, nv, nchan);
+    float_2d_free(&x->x_notechannelGain, nv, nchan);
+    float_2d_free(&x->x_notechannelGainSpread, nv, nchan);
+
+    /* Heap allocated for signal vector x nchannels */
+    if (x->x_out)
+        t_freebytes(x->x_out, nchan * sizeof(t_float*));
+    /* Heap allocated x nchannels */
+    if (x->x_outsamp)
+        t_freebytes(x->x_outsamp, nchan * sizeof(t_float));
+    if (x->x_channelGain)
+        t_freebytes(x->x_channelGain, nchan * sizeof(t_float));
+    if (x->x_channelGainSpread)
+        t_freebytes(x->x_channelGainSpread, nchan * sizeof(t_float));
+}
+
+static void *munger_new(t_symbol *s, int argc, t_atom *argv)
+{
+    t_float maxdelay = 3000.;
+    int nchan = 2, nvoices = 50, i, j;
+    t_symbol *munger_name = gensym("default");
+
+    t_disis_munger *x = (t_disis_munger *)pd_new(disis_munger_class);
+
+    if (argc) /* 1st arg: maxdelay */
+    {
+        /* Special case-- the help file says that a single symbolic argument
+           is allowed for backward-compatibility. So we cover that here... */
+        if (argc == 1 && argv->a_type == A_SYMBOL)
+            munger_name = atom_getsymbolarg(0, argc--, argv++);
+        else
+        {
+            t_float tmp = atom_getfloatarg(0, argc--, argv++);
+            /* keep default if less than 100 */
+            if (tmp >= 100.) maxdelay = tmp;
+        }
+    }
+
+    if (argc) /* 2nd arg: no of channels */
+    {
+        nchan = (int)atom_getintarg(0, argc--, argv++);
+        if (nchan < 2) nchan = 2;
+        if (nchan > MAXCHANNELS) nchan = MAXCHANNELS;
+    }
+
+    if (argc) /* 3rd arg: either max voices OR a symbolic name IF this
+                 is the final arg */
+    {
+        if (argc == 1 && argv->a_type == A_SYMBOL)
+            munger_name = atom_getsymbolarg(0, argc--, argv++);
+        else
+        {
+            nvoices = atom_getfloatarg(0, argc--, argv++);
+            if (nvoices < 0) nvoices = 0;
+            if (nvoices > 1000) nvoices = 1000;
+        }
+    }
+
+    if (argc) /* 4th arg: name */
+    {
+        munger_name = atom_getsymbolarg(0, argc--, argv++);
+    }
+
+    x->x_maxdelay = maxdelay;
+    x->x_num_channels = nchan;
+    x->x_numvoices = nvoices;
+    x->x_munger_name = munger_name;
+    x->x_srate = sys_getsr();
+    x->x_one_over_srate = 1./x->x_srate;
+    x->x_srate_ms = x->x_srate/1000.;
+    x->x_one_over_srate_ms = 1./x->x_srate_ms;
+    x->x_initbuflen = maxdelay + 50. * x->x_srate_ms;
+    x->x_buflen = (int)x->x_initbuflen;
+    x->x_maxsize = x->x_buflen / 3;
+    x->x_twothirdBufsize = x->x_maxsize * 2;
+    x->x_onethirdBufsize = x->x_maxsize;
+    x->x_minsize = MINSIZE;
+
+    /* allocate a ton of fields */
+    x = munger_alloc(x);
+    /* bail if we couldn't allocate... */
+    if (!x) return 0;
+
+    x->x_verbose = 1;
+
+    floatinlet_new(&x->x_obj, &x->x_grate);
+    floatinlet_new(&x->x_obj, &x->x_grate_var);
+    floatinlet_new(&x->x_obj, &x->x_glen);
+    floatinlet_new(&x->x_obj, &x->x_glen_var);
+    floatinlet_new(&x->x_obj, &x->x_gpitch);
+    floatinlet_new(&x->x_obj, &x->x_gpitch_var);
+    floatinlet_new(&x->x_obj, &x->x_gpan_spread);
+
+    for (i = 0; i < nchan; i++)
+        outlet_new(&x->x_obj, &s_signal);
+
+    x->x_voices = 10;
+    x->x_gain = 1.1;
+    x->x_randgain = 0.;
+    x->x_twelfth = 1./12;
+    x->x_semitone  = pow(2., 1./12.);
+    x->x_smoothPitch = 1;
+    x->x_scale_len = PITCHTABLESIZE;
+
+    x->x_grate = 1.;
+    x->x_tempgrate = 1.;
+    x->x_grate_var = 0.;
+    x->x_glen = 1.;
+    x->x_glen_var = 0.;
+    x->x_gpitch = 1.;
+    x->x_gpitch_var = 0.;
+    x->x_gpan_spread = 0.;
+    x->x_time = 0;
+    x->x_position = -1.;
+    x->x_gimme = 0.;
+    x->x_power = 1;
+    x->x_ambi = 0;
+    x->x_maxvoices = x->x_numvoices;
+
+    x->x_oneshot = 0;
+    x->x_newnote = 0;
+
+    for (i = 0; i < nvoices; i++)
+    {
+        x->x_gvoiceSize[i] = 1000;
+        x->x_gvoiceSpeed[i] = 1.;
+        x->x_gvoiceCurrent[i] = 0.;
+        x->x_gvoiceDirection[i] = 1;
+        x->x_gvoiceOn[i] = 0;
+        x->x_gvoiceDone[i] = 0;
+        x->x_gvoiceRPan[i] = .5;
+        x->x_gvoiceLPan[i] = .5;
+        x->x_gvoiceGain[i] = 1.;
+        x->x_gvoiceADSRon[i] = 0;
+
+        /* init the stk_ADSR elements */
+        stk_ADSR_init(&x->x_gvoiceADSR[i]);
+        stk_ADSR_setSampleRate(&x->x_gvoiceADSR[i], sys_getsr());
+        for (j = 0; j < x->x_num_channels; j++)
+        {
+            x->x_gvoiceSpat[i][j] = 0.;
+            x->x_notechannelGain[i][j] = 0.;
+            x->x_notechannelGainSpread[i][j] = 0.;
+        }
+        //note and oneshot inits
+        x->x_noteTransp[i] = 0.;
+        x->x_noteSize[i] = 100.;
+        x->x_notePan[i] = 0.5;
+        x->x_noteGain[i] = 1.;
+        x->x_noteAttack[i] = 20.;
+        x->x_noteDecay[i] = 50.;
+        x->x_noteSustain[i] = 0.3;
+        x->x_noteRelease[i] = 200.;
+    }
+    for (i = 0; i < x->x_num_channels; i++)
+    {
+        x->x_channelGain[i] = 0.;
+        x->x_channelGainSpread[i] = 0.;
+    }
+
+    x->x_doHanning = 0; // init hanning window
+
+    for (i = 0; i < WINLENGTH; i++)
+    {
+        x->x_winTable[i] = 0.5 + 0.5 * cos(TWOPI * i / WINLENGTH + .5 * TWOPI);
+    }
+
+    for (i = 0; i < PITCHTABLESIZE; i++)
+    {
+        x->x_pitchTable[i] = 0.;
+    }
+
+    x->x_rampLength = 256.;
+
+    //sample buffer
+    for (i = 0; i < x->x_initbuflen; i++)
+        x->x_recordBuf[i] = 0;
+
+    x->x_recordOn = 1;           //boolean
+    x->x_recordCurrent = 0;
+    x->x_recordRampVal = 0;
+    x->x_rec_ramping = 0;
+
+    x->x_arrayname = NULL;
+    x->x_arrayvec = NULL;
+    x->x_arraylength = 0;         // use internal buffer by default
+    x->x_l_chan = 0;             //is there any other choice?
+    x->x_discretepan = 0;        //off by default
+
+    srand(54); //0.54?
+
+    return x;
+}
+
+/* creates a size for a new grain
+   actual number of samples PLAYED, regardless of pitch
+   might be shorter for higher pitches and long grains,
+   to avoid collisions with recordCurrent
+
+   size given now in milliseconds!
+
+   for oneshot notes, this will also scale the ADSR and
+   make it smaller, if the grainSpeed is high
+*/
+t_float munger_newNoteSize(t_disis_munger *x, int whichOne, int newNote)
+{
+    t_float newsize, temp, temp2, pitchExponent;
+
+    /* set grain pitch */
+    pitchExponent = x->x_noteTransp[newNote];
+    x->x_gvoiceSpeed[whichOne] =
+        x->x_gpitch * pow(x->x_semitone, pitchExponent);
+
+    if (x->x_gvoiceSpeed[whichOne] < MINSPEED)
+        x->x_gvoiceSpeed[whichOne] = MINSPEED;
+    newsize = x->x_srate_ms * (x->x_noteSize[newNote]);
+    //if(newsize > x->x_maxsize) newsize = maxsize;
+    if (newsize * x->x_gvoiceSpeed[whichOne] > x->x_maxsize)
+    {
+        temp2 = x->x_maxsize / x->x_gvoiceSpeed[whichOne]; //newsize
+        temp = temp2 / newsize;
+        x->x_noteAttack[newNote] *= temp;
+        x->x_noteDecay[newNote] *= temp;
+        x->x_noteRelease[newNote] *= temp;
+        newsize = temp2;
+    }
+    //if(newsize < minsize) newsize = minsize;
+    return newsize;
+}
+
+static int munger_newDirection(t_disis_munger *x)
+{
+    //-1 == always backwards
+    //0  == backwards and forwards (default)
+    //1  == only forwards
+    int dir;
+    if (x->x_ambi == 0)
+    {
+        dir = RANDOM()- 16384;
+        if (dir < 0) dir = -1;
+        else dir = 1;
+    }
+    else
+    {
+        if (x->x_ambi == -1) dir = -1;
+	else dir = 1;
+    }
+    return dir;
+}
+
+static t_float munger_newNote(t_disis_munger *x, int whichVoice, int newNote)
+{
+    t_float newPosition;
+    int i, temp;
+
+    x->x_gvoiceSize[whichVoice] =
+        (long)munger_newNoteSize(x, whichVoice, newNote);
+    //x->x_gvoiceDirection[whichVoice] = munger_newDirection(x);
+    x->x_gvoiceDirection[whichVoice] = x->x_noteDirection[newNote];
+
+    if (x->x_num_channels == 2)
+    {
+        //x->x_gvoiceLPan[whichVoice] = ((t_float)rand() - 16384.) *
+        //    ONE_OVER_MAXRAND * x->x_gpan_spread + 0.5;
+        //x->x_gvoiceRPan[whichVoice] = 1. - x->x_gvoiceLPan[whichVoice];
+        //make equal power panning....
+        //x->x_gvoiceLPan[whichVoice] = powf(x->x_gvoiceLPan[whichVoice], 0.5);
+        //x->x_gvoiceRPan[whichVoice] = powf(x->x_gvoiceRPan[whichVoice], 0.5);
+        x->x_gvoiceRPan[whichVoice] = powf(x->x_notePan[newNote], 0.5);
+        x->x_gvoiceLPan[whichVoice] = powf((1. - x->x_notePan[newNote]), 0.5);
+    }
+    else
+    {
+        if (x->x_notePan[newNote] == -1.)
+        {
+            for (i = 0; i < x->x_num_channels; i++)
+            {
+                x->x_notechannelGain[whichVoice][i] = 1.;
+                x->x_notechannelGainSpread[whichVoice][i] = 0.;
+            }
+        }
+        else
+        {
+            for (i = 0; i < x->x_num_channels; i++)
+            {
+                //initialize all to 0.
+                x->x_notechannelGain[whichVoice][i] = 0.;
+                x->x_notechannelGainSpread[whichVoice][i] = 0.;
+            }
+            temp = (int)x->x_notePan[newNote];
+            if (temp >= x->x_num_channels) temp=0;
+            //update the one we want
+            x->x_notechannelGain[whichVoice][temp] = 1.;
+        }
+        for (i = 0; i < x->x_num_channels; i++)
+        {
+            x->x_gvoiceSpat[whichVoice][i] =
+                x->x_notechannelGain[whichVoice][i] +
+                ((long)(RANDOM()) - 16384.) * ONE_OVER_HALFRAND *
+                x->x_notechannelGainSpread[whichVoice][i];
+        }
+    }
+
+    x->x_gvoiceOn[whichVoice] = 1;
+    x->x_gvoiceDone[whichVoice] = 0;
+    x->x_gvoiceGain[whichVoice] = x->x_noteGain[newNote];
+
+    x->x_gvoiceADSRon[whichVoice] = 1;
+    //post("adsr %f %f %f %f",
+    //x->x_noteAttack[newNote], x->x_noteDecay[newNote],
+    //x->x_noteSustain[newNote], x->x_noteRelease[newNote]);
+
+    stk_ADSR_setAllTimes(&x->x_gvoiceADSR[whichVoice],
+        x->x_noteAttack[newNote] / 1000.,
+        x->x_noteDecay[newNote] / 1000.,
+        x->x_noteSustain[newNote],
+        x->x_noteRelease[newNote] / 1000.);
+    stk_ADSR_keyOn(&x->x_gvoiceADSR[whichVoice]);
+
+    /*** set start point; tricky, cause of moving buffer,
+         variable playback rates, backwards/forwards, etc.... ***/
+
+    if (!x->x_arraylength)
+    {
+        // 1. RANDOM() positioning and moving buffer (default)
+        if (x->x_position == -1. && x->x_recordOn == 1)
+        {
+            if (x->x_gvoiceDirection[whichVoice] == 1) /* going forward */
+            {
+                if (x->x_gvoiceSpeed[whichVoice] > 1.)
+                    newPosition = x->x_recordCurrent - x->x_onethirdBufsize -
+                        (long)(RANDOM()) * ONE_OVER_MAXRAND *
+                        x->x_onethirdBufsize;
+                else
+                    newPosition = x->x_recordCurrent - (long)(RANDOM()) *
+                        ONE_OVER_MAXRAND * x->x_onethirdBufsize; // was 2/3rds
+            }
+            else //going backwards
+            {
+                newPosition = x->x_recordCurrent - (long)(RANDOM()) *
+                    ONE_OVER_MAXRAND * x->x_onethirdBufsize;
+            }
+        }
+
+        // 2. fixed positioning and moving buffer
+        else if (x->x_position >= 0. && x->x_recordOn == 1)
+        {
+            if (x->x_gvoiceDirection[whichVoice] == 1) /* going forward */
+            {
+                if (x->x_gvoiceSpeed[whichVoice] > 1.)
+                {
+                    //newPosition = x->x_recordCurrent - x->x_onethirdBufsize -
+                    //    x->x_position * x->x_onethirdBufsize;
+                    //this will follow more closely...
+                    newPosition = x->x_recordCurrent -
+                        x->x_gvoiceSize[whichVoice] *
+                        x->x_gvoiceSpeed[whichVoice] - x->x_position *
+                        x->x_onethirdBufsize;
+                }
+                else
+                {
+                    newPosition = x->x_recordCurrent - x->x_position *
+                        x->x_onethirdBufsize; //was 2/3rds
+                }
+            }
+            else //going backwards
+            {
+                newPosition = x->x_recordCurrent - x->x_position *
+                    x->x_onethirdBufsize;
+            }
+        }
+
+        // 3. RANDOM() positioning and fixed buffer
+        else if (x->x_position == -1. && x->x_recordOn == 0)
+        {
+            if (x->x_gvoiceDirection[whichVoice] == 1) // going forward
+            {
+                newPosition = x->x_recordCurrent - x->x_onethirdBufsize -
+                    (long)(RANDOM()) * ONE_OVER_MAXRAND * x->x_onethirdBufsize;
+            }
+            else //going backwards
+                newPosition = x->x_recordCurrent - (long)(RANDOM()) *
+                    ONE_OVER_MAXRAND * x->x_onethirdBufsize;
+        }
+
+        // 4. fixed positioning and fixed buffer
+        else if (x->x_position >= 0. && x->x_recordOn == 0)
+        {
+            if (x->x_gvoiceDirection[whichVoice] == 1) // going forward
+            {
+                newPosition = x->x_recordCurrent - x->x_onethirdBufsize -
+                    x->x_position * x->x_onethirdBufsize;
+            }
+            else //going backwards
+                newPosition = x->x_recordCurrent - x->x_position *
+                    x->x_onethirdBufsize;
+        }
+    }
+    else
+    {
+        if (x->x_position == -1.)
+        {
+            newPosition = (long)(RANDOM()) * ONE_OVER_MAXRAND * x->x_arraylength;
+        }
+        else if (x->x_position >= 0.) newPosition = x->x_position *
+            x->x_arraylength;
+    }
+    return newPosition;
+}
+
+static void munger_spat(t_disis_munger *x, t_symbol *s, int argc, t_atom *argv)
+{
+    int i, j;
+
+    if (argc)
+    {
+        for (i = j = 0; i < (argc - 1); i += 2)
+        {
+            x->x_channelGain[j] = atom_getfloatarg(i, argc, argv);
+            x->x_channelGainSpread[j] = atom_getfloatarg(i+1, argc, argv);
+            if (x->x_verbose > 1)
+                post("disis_munger~ %s: channel gain %d = %f, spread = %f",
+                    x->x_munger_name->s_name, j, x->x_channelGain[j],
+                    x->x_channelGainSpread[j]);
+            j++;
+        }
+    }
+}
+
+static void munger_note(t_disis_munger *x, t_symbol *s, int argc, t_atom *argv)
+{
+    if (x->x_oneshot)
+    {
+        int i, temp;
+
+        if(argc < 8)
+        {
+            post("disis_munger~ %s: need 8 args -- transposition, gain, pan, "
+                 "attkT, decayT, susLevel, relT, direction [-1/1]",
+                x->x_munger_name->s_name);
+            return;
+        }
+
+        x->x_newnote++;
+
+        if (x->x_newnote > x->x_voices)
+        {
+            if (x->x_verbose > 0)
+                post("disis_munger~ %s: too many notes amadeus.",
+                    x->x_munger_name->s_name);
+            return;
+        }
+
+        x->x_noteTransp[x->x_newnote] = atom_getfloatarg(0, argc, argv);
+        x->x_noteGain[x->x_newnote] = atom_getfloatarg(1, argc, argv);
+        x->x_notePan[x->x_newnote] = atom_getfloatarg(2, argc, argv);
+        x->x_noteAttack[x->x_newnote] = atom_getfloatarg(3, argc, argv);
+        x->x_noteDecay[x->x_newnote] = atom_getfloatarg(4, argc, argv);
+        x->x_noteSustain[x->x_newnote] = atom_getfloatarg(5, argc, argv);
+        x->x_noteRelease[x->x_newnote] = atom_getfloatarg(6, argc, argv);
+        x->x_noteDirection[x->x_newnote] = atom_getfloatarg(7, argc, argv);
+
+        //Stk ADSR bug?
+        if (x->x_noteSustain[x->x_newnote] <= 0.001)
+            x->x_noteSustain[x->x_newnote] = 0.001;
+
+        x->x_noteSize[x->x_newnote] = x->x_noteAttack[x->x_newnote] +
+            x->x_noteDecay[x->x_newnote] + x->x_noteRelease[x->x_newnote];
+    }
+}
+
+// turn oneshot mode on/off. in oneshot mode, the internal granular voice
+// allocation method goes away
+// so the munger will be silent, except when it receives "note" messages
+static void munger_oneshot(t_disis_munger *x, t_symbol *s, int argc,
+    t_atom *argv)
+{
+    int temp;
+
+    if (argc)
+    {
+        temp = (int)atom_getintarg(0, argc, argv);
+        x->x_oneshot = temp;
+        if (x->x_verbose > 1)
+            post("disis_munger~ %s: setting oneshot: %d",
+                x->x_munger_name->s_name, temp);
+    }
+}
+
+static void munger_clearbuffer(t_disis_munger *x)
+{
+    if (x->x_arraylength)
+    {
+        x->x_arrayname = NULL;
+        x->x_arrayname = NULL;
+        x->x_arraylength = 0;
+        x->x_arrayvec = NULL;
+        if (x->x_verbose > 1)
+            post("disis_munger~ %s: external buffer deleted.",
+                x->x_munger_name->s_name);
+    }
+}
+
+static void munger_setbuffer(t_disis_munger *x, t_symbol *s, int argc,
+    t_atom *argv)
+{
+    if (argc == 0)
+    {
+        // argument list is empty
+        // clear existing buffer
+        if (x->x_arraylength) munger_clearbuffer(x);
+    }
+    else if (argc == 1 && argv->a_type == A_SYMBOL)
+    {
+        // one symbol given as argument
+        // clear existing buffer
+        if (x->x_arraylength) munger_clearbuffer(x);
+       	// save buffer munger_name
+       	x->x_arrayname = atom_getsymbolarg(0, argc, argv);
+        /* If our name is NULL then just clear out and return... */
+        if (!x->x_arrayname)
+        {
+            munger_clearbuffer(x);
+            return;
+        }
+       	// make new reference to system buffer object
+        /* make a new reference to the array */
+        t_garray *g = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class);
+        if (!g)
+        {
+            if (*s->s_name) pd_error(x, "disis_munger~: %s: no such array",
+                x->x_arrayname->s_name);
+        }
+        else if (!garray_getfloatwords(g, &x->x_arraylength, &x->x_arrayvec))
+        {
+            pd_error(x, "%s: bad template for disis_munger~'s array",
+                x->x_arrayname->s_name);
+        }
+        else
+        {
+            if (x->x_verbose > 1)
+                post("disis_munger~ %s: successfully associated with "
+                     "the %s array.", x->x_munger_name->s_name,
+                      x->x_arrayname->s_name);
+            x->x_l_chan = 0;
+            garray_usedindsp(g);
+        }
+
+    }
+    else
+    {
+        // invalid argument list, leave buffer as is but issue error message
+        // to console
+       	if (x->x_verbose > 0)
+            post("disis_munger~ %s: error: message argument must be a string.",
+                x->x_munger_name->s_name);
+        if (x->x_arraylength) munger_clearbuffer(x);
+    }
+}
+
+static void munger_setverbose(t_disis_munger *x, t_symbol *s, int argc,
+    t_atom *argv)
+{
+    int temp;
+
+    if (argc)
+    {
+        temp = (int)atom_getintarg(0, argc, argv);
+        if (temp < 0) temp = 0;
+        if (temp > 3) temp = 3;
+        x->x_verbose = temp;
+        post("disis_munger~ %s: setting verbose: %d",
+            x->x_munger_name->s_name, temp);
+        if (x->x_verbose < 3)
+        {
+            x->x_graincounter = 0;
+            x->x_countsamples = 0;
+        }
+    }
+}
+
+//grain funcs
+static t_float munger_envelope(t_disis_munger *x, int whichone, t_float sample)
+{
+    long done = x->x_gvoiceDone[whichone];
+    long tail = x->x_gvoiceSize[whichone] - x->x_gvoiceDone[whichone];
+
+    if (done < x->x_gvoiceRamp[whichone])
+        sample *= (done * x->x_gvoiceOneOverRamp[whichone]);
+    else if (tail < x->x_gvoiceRamp[whichone])
+        sample *= (tail * x->x_gvoiceOneOverRamp[whichone]);
+
+    return sample;
+}
+
+//tries to find an available voice; return -1 if no voices available
+static int munger_findVoice(t_disis_munger *x)
+{
+    int i = 0, foundOne = -1;
+    while (foundOne < 0 && i < x->x_voices ) {
+        if (!x->x_gvoiceOn[i])
+            foundOne = i;
+        i++;
+    }
+    return foundOne;
+}
+
+// creates a size for a new grain
+// actual number of samples PLAYED, regardless of pitch
+// might be shorter for higher pitches and long grains,
+// to avoid collisions with recordCurrent
+// size given now in milliseconds!
+static t_float munger_newSize(t_disis_munger *x, int whichOne)
+{
+    float newsize, temp;
+    int pitchChoice, pitchExponent;
+
+    //set grain pitch
+    if (x->x_smoothPitch == 1)
+        x->x_gvoiceSpeed[whichOne] = x->x_gpitch + ((long)RANDOM() - 16384.) *
+            ONE_OVER_HALFRAND * x->x_gpitch_var;
+    else
+    {
+        //temp = (long)RANDOM() * ONE_OVER_MAXRAND * x->x_gpitch_var *
+        //    (float)PITCHTABLESIZE;
+        temp = (long)RANDOM() * ONE_OVER_MAXRAND * x->x_gpitch_var *
+            (float)x->x_scale_len;
+        pitchChoice = (int) temp;
+        if (pitchChoice > PITCHTABLESIZE)
+            pitchChoice = PITCHTABLESIZE;
+        if (pitchChoice < 0)
+            pitchChoice = 0;
+        pitchExponent = (int)x->x_pitchTable[pitchChoice];
+        x->x_gvoiceSpeed[whichOne] = x->x_gpitch *
+            pow(x->x_semitone, pitchExponent);
+    }
+
+    if (x->x_gvoiceSpeed[whichOne] < MINSPEED)
+        x->x_gvoiceSpeed[whichOne] = MINSPEED;
+    newsize = x->x_srate_ms * (x->x_glen + ((long)RANDOM() - 16384.) *
+        ONE_OVER_HALFRAND * x->x_glen_var);
+    if (newsize > x->x_maxsize)
+        newsize = x->x_maxsize;
+    if (newsize * x->x_gvoiceSpeed[whichOne] > x->x_maxsize)
+        newsize = x->x_maxsize / x->x_gvoiceSpeed[whichOne];
+    if (newsize < x->x_minsize)
+        newsize = x->x_minsize;
+    return newsize;
+}
+
+// creates a new (RANDOM()) start position for a new grain,
+// returns beginning start sample
+// sets up size and direction
+// max grain size is BUFLENGTH / 3, to avoid recording into grains
+// while they are playing
+static t_float munger_newSetup(t_disis_munger* x, int whichVoice)
+{
+    t_float newPosition;
+    int i, tmpdiscretepan;
+
+    x->x_gvoiceSize[whichVoice] = (long)munger_newSize(x, whichVoice);
+    x->x_gvoiceDirection[whichVoice] = munger_newDirection(x);
+    if (x->x_num_channels == 2)
+    {
+        x->x_gvoiceLPan[whichVoice] = ((long)(RANDOM()) - 16384.) *
+            ONE_OVER_MAXRAND * x->x_gpan_spread + 0.5;
+        x->x_gvoiceRPan[whichVoice] = 1. - x->x_gvoiceLPan[whichVoice];
+        //make equal power panning....
+        x->x_gvoiceLPan[whichVoice] = powf(x->x_gvoiceLPan[whichVoice], 0.5);
+        x->x_gvoiceRPan[whichVoice] = powf(x->x_gvoiceRPan[whichVoice], 0.5);
+    }
+    else if (x->x_discretepan)
+    {
+        tmpdiscretepan = (int)((long)(RANDOM()) *
+            ONE_OVER_MAXRAND * ((float)x->x_num_channels + 0.99));
+        for (i = 0; i < x->x_num_channels; i++)
+        {
+            if (i == tmpdiscretepan)
+                x->x_gvoiceSpat[whichVoice][i] = x->x_channelGain[i] +
+                    ((long)(RANDOM()) - 16384.) *
+                    ONE_OVER_HALFRAND * x->x_channelGainSpread[i];
+            else x->x_gvoiceSpat[whichVoice][i] = 0.;
+        }
+    }
+    else
+    {
+        for (i = 0; i < x->x_num_channels; i++)
+            x->x_gvoiceSpat[whichVoice][i] = x->x_channelGain[i] +
+                ((long)(RANDOM()) - 16384.) * ONE_OVER_HALFRAND *
+                x->x_channelGainSpread[i];
+    }
+    x->x_gvoiceOn[whichVoice] = 1;
+    x->x_gvoiceDone[whichVoice] = 0;
+    x->x_gvoiceGain[whichVoice] = x->x_gain + ((long)(RANDOM()) - 16384.) *
+        ONE_OVER_HALFRAND * x->x_randgain;
+    x->x_gvoiceADSRon[whichVoice] = 0;
+
+    if (x->x_gvoiceSize[whichVoice] < 2. * x->x_rampLength)
+    {
+        x->x_gvoiceRamp[whichVoice] = .5 * x->x_gvoiceSize[whichVoice];
+        if (x->x_gvoiceRamp[whichVoice] <= 0.)
+        {
+            x->x_gvoiceRamp[whichVoice] = 1.;
+        }
+        x->x_gvoiceOneOverRamp[whichVoice] = 1. / x->x_gvoiceRamp[whichVoice];
+    }
+    else
+    {
+        x->x_gvoiceRamp[whichVoice] = x->x_rampLength;
+        if (x->x_gvoiceRamp[whichVoice] <= 0.)
+        {
+            x->x_gvoiceRamp[whichVoice] = 1.;
+        }
+        x->x_gvoiceOneOverRamp[whichVoice] = 1. / x->x_gvoiceRamp[whichVoice];
+    }
+
+    /*** set start point; tricky, cause of moving buffer,
+         variable playback rates, backwards/forwards, etc.... ***/
+
+    if (!x->x_arraylength)
+    {
+	// 1. RANDOM() positioning and moving buffer (default)
+	if (x->x_position == -1. && x->x_recordOn == 1)
+        {
+            if (x->x_gvoiceDirection[whichVoice] == 1) // going forward
+            {
+                if (x->x_gvoiceSpeed[whichVoice] > 1.)
+                {
+                    newPosition = x->x_recordCurrent - x->x_onethirdBufsize -
+                        (long)RANDOM() * ONE_OVER_MAXRAND * x->x_onethirdBufsize;
+                }
+                else
+                {
+                    newPosition = x->x_recordCurrent - (long)RANDOM() *
+                        ONE_OVER_MAXRAND * x->x_onethirdBufsize; //was 2/3rds
+                }
+            }
+            else //going backwards
+            {
+                newPosition = x->x_recordCurrent - (long)RANDOM() *
+                    ONE_OVER_MAXRAND * x->x_onethirdBufsize;
+            }
+	}
+
+        // 2. fixed positioning and moving buffer
+        else if (x->x_position >= 0. && x->x_recordOn == 1)
+        {
+            if (x->x_gvoiceDirection[whichVoice] == 1) // going forward
+            {
+                if (x->x_gvoiceSpeed[whichVoice] > 1.)
+                {
+                    //newPosition = x->x_recordCurrent -
+                    //    x->x_onethirdBufsize - x->x_position *
+                    //    x->x_onethirdBufsize;
+                    //this will follow more closely...
+                    newPosition = x->x_recordCurrent -
+                        x->x_gvoiceSize[whichVoice] *
+                        x->x_gvoiceSpeed[whichVoice] -
+                        x->x_position * x->x_onethirdBufsize;
+                }
+                else
+                {
+                    newPosition = x->x_recordCurrent - x->x_position *
+                        x->x_onethirdBufsize; //was 2/3rds
+                }
+            }
+            else //going backwards
+            {
+                newPosition = x->x_recordCurrent - x->x_position *
+                    x->x_onethirdBufsize;
+            }
+        }
+
+        // 3. RANDOM() positioning and fixed buffer
+        else if (x->x_position == -1. && x->x_recordOn == 0)
+        {
+            if (x->x_gvoiceDirection[whichVoice] == 1) // going forward
+            {
+                newPosition = x->x_recordCurrent - x->x_onethirdBufsize -
+                    (long)RANDOM() * ONE_OVER_MAXRAND * x->x_onethirdBufsize;
+            }
+            else //going backwards
+            {
+                newPosition = x->x_recordCurrent - (long)RANDOM() *
+                    ONE_OVER_MAXRAND * x->x_onethirdBufsize;
+            }
+	}
+
+        // 4. fixed positioning and fixed buffer
+        else if (x->x_position >= 0. && x->x_recordOn == 0)
+        {
+            if (x->x_gvoiceDirection[whichVoice] == 1) // going forward
+            {
+                newPosition = x->x_recordCurrent - x->x_onethirdBufsize -
+                    x->x_position * x->x_onethirdBufsize;
+            }
+            else //going backwards
+            {
+                newPosition = x->x_recordCurrent - x->x_position *
+                    x->x_onethirdBufsize;
+            }
+        }
+    }
+    else
+    {
+        if (x->x_position == -1.)
+        {
+            newPosition = (float)(RANDOM() * ONE_OVER_MAXRAND *
+                (float)(x->x_arraylength));
+        }
+        else if (x->x_position >= 0.)
+            newPosition = x->x_position * (float)x->x_arraylength;
+    }
+    return newPosition;
+}
+
+static void munger_clear(t_disis_munger *x)
+{
+    long i, len = (long)x->x_initbuflen;
+    for (i = 0; i < len; i++)
+        x->x_recordBuf[i] = 0;
+}
+
+static void munger_setramp(t_disis_munger *x, t_floatarg f)
+{
+    x->x_doHanning = 0;
+    x->x_rampLength = f <= 0. ? 1. : f;
+    if (x->x_verbose > 1)
+        post("disis_munger~ %s: setting ramp to: %f ms",
+            x->x_munger_name->s_name,
+            (x->x_rampLength * x->x_one_over_srate_ms));
+}
+
+static void munger_scale(t_disis_munger *x, t_symbol *s, int argc, t_atom *argv)
+{
+    int i,j;
+    if (x->x_verbose > 1)
+        post("disis_munger~ %s: loading scale from input list",
+            x->x_munger_name->s_name);
+    x->x_smoothPitch = 0;
+
+    for (i = 0; i < PITCHTABLESIZE; i++)
+        x->x_pitchTable[i] = 0.;
+    if (argc > PITCHTABLESIZE)
+        argc = PITCHTABLESIZE;
+    for (i = 0; i < argc; i++)
+    {
+        x->x_pitchTable[i] = atom_getfloatarg(i, argc, argv);
+    }
+    x->x_scale_len = argc;
+
+    i = 0;
+    //wrap input list through all of pitchTable
+    for (j = argc; j < PITCHTABLESIZE; j++) {
+        x->x_pitchTable[j] = x->x_pitchTable[i++];
+        if (i >= argc) i = 0;
+    }
+}
+
+static void munger_bufsize(t_disis_munger *x, t_symbol *s, int argc,
+    t_atom *argv)
+{
+        t_float temp;
+        if (argc)
+        {
+            temp = x->x_srate * atom_getfloatarg(0, argc, argv);
+            if (temp < 3. * (float)MINSIZE)
+            {
+                temp = 3. * (float)MINSIZE;
+                if (x->x_verbose > 0)
+                    post("disis_munger~ %s error: delaylength too small!",
+                        x->x_munger_name->s_name);
+            }
+            if (temp > x->x_initbuflen)
+            {
+                temp = x->x_initbuflen;
+                if (x->x_verbose > 0)
+                    post("disis_munger~ %s error: delaylength too large!",
+                        x->x_munger_name->s_name);
+            }
+            x->x_maxsize = temp / 3.;
+            x->x_twothirdBufsize = x->x_maxsize * 2.;
+            x->x_onethirdBufsize = x->x_maxsize;
+            if (x->x_verbose > 1)
+                post("disis_munger~ %s: setting delaylength to: %f seconds",
+                    x->x_munger_name->s_name, temp / x->x_srate);
+        }
+}
+
+static void munger_bufsize_ms(t_disis_munger *x, t_symbol *s, int argc,
+    t_atom *argv)
+{
+    t_float temp;
+    if (argc)
+    {
+        temp = x->x_srate_ms * atom_getfloatarg(0, argc, argv);
+        if (temp < 3. * (float)MINSIZE)
+        {
+            temp = 3. * (float)MINSIZE;
+            if (x->x_verbose > 0)
+                post("disis_munger~ %s error: delaylength_ms too small!",
+                    x->x_munger_name->s_name);
+        }
+        if (temp > x->x_initbuflen)
+        {
+            temp = x->x_initbuflen;
+            if (x->x_verbose > 0)
+                post("disis_munger~ %s error: delaylength_ms too large!",
+                    x->x_munger_name->s_name);
+        }
+        x->x_maxsize = temp / 3.;
+        x->x_twothirdBufsize = x->x_maxsize * 2.;
+        x->x_onethirdBufsize = x->x_maxsize;
+        if (x->x_verbose > 1)
+            post("disis_munger~ %s: setting delaylength to: %d milliseconds",
+                x->x_munger_name->s_name, (long)(temp / x->x_srate_ms));
+    }
+}
+
+static void munger_setminsize(t_disis_munger *x, t_symbol *s, int argc,
+    t_atom *argv)
+{
+    t_float temp;
+
+    if (argc)
+    {
+        temp = x->x_srate_ms * atom_getfloatarg(0, argc, argv);
+        if (temp < (float)MINSIZE)
+        {
+            temp = (float)MINSIZE;
+            if (x->x_verbose > 0)
+                post("disis_munger~ %s error: minsize too small!",
+                    x->x_munger_name->s_name);
+        }
+        if (temp >= x->x_initbuflen)
+        {
+            temp = (float)MINSIZE;
+            if (x->x_verbose > 0)
+                post("disis_munger~ %s error: minsize too large!",
+                    x->x_munger_name->s_name);
+        }
+        x->x_minsize = temp;
+        if (x->x_verbose > 1)
+            post("disis_munger~ %s: setting min grain size to: %f ms",
+                x->x_munger_name->s_name, (x->x_minsize / x->x_srate_ms));
+    }
+}
+
+static void munger_discretepan(t_disis_munger *x, t_symbol *s, int argc,
+    t_atom *argv)
+{
+    int temp;
+
+    if (argc)
+    {
+        temp = (int)atom_getintarg(0, argc, argv);
+        if (temp < 0)
+        {
+            if (x->x_verbose > 0)
+                post("disis_munger~ %s error: discretepan can be only 0 or 1!",
+                    x->x_munger_name->s_name);
+            temp = 0;
+        }
+        if (temp > 1)
+        {
+            if (x->x_verbose > 0)
+                post("disis_munger~ %s error: error: discretepan can be only 0 "
+                     "or 1!", x->x_munger_name->s_name);
+            temp = 1;
+        }
+        x->x_discretepan = temp;
+    }
+}
+
+static void munger_setvoices(t_disis_munger *x, t_symbol *s, int argc,
+    t_atom *argv)
+{
+    int temp;
+
+    if (argc)
+    {
+        temp = atom_getintarg(0, argc, argv);
+        if (temp < 0)
+        {
+            if (x->x_verbose > 0)
+                post("disis_munger~ %s error: voices has to be between "
+                     "0 and maxvoices (currently %d)!",
+                    x->x_munger_name->s_name, x->x_maxvoices);
+            temp = 0;
+        }
+        if (temp > x->x_maxvoices)
+        {
+            if (x->x_verbose > 0)
+            {
+                post("disis_munger~ %s error: voices has to be between "
+                     "0 and maxvoices (currently %d)!",
+                    x->x_munger_name->s_name, x->x_maxvoices);
+            }
+            temp = x->x_maxvoices;
+        }
+        if (x->x_verbose > 1)
+            post("disis_munger~ %s: setting voices to: %d ",
+                x->x_munger_name->s_name, x->x_voices);
+        x->x_voices = temp;
+    }
+}
+
+static void munger_maxvoices(t_disis_munger *x, t_symbol *s, int argc,
+    t_atom *argv)
+{
+    int temp;
+
+    if (argc)
+    {
+        temp = (int)atom_getintarg(0, argc, argv);
+        if (temp < 0)
+        {
+            if (x->x_verbose > 0)
+                post("disis_munger~ %s error: maxvoices cannot be less than 0!",
+                    x->x_munger_name->s_name);
+            temp = 0;
+        }
+        if (temp > x->x_numvoices) temp = x->x_numvoices;
+        if (x->x_verbose > 1)
+            post("disis_munger~ %s: setting max voices to: %d ",
+                x->x_munger_name->s_name, x->x_maxvoices);
+        x->x_maxvoices = temp;
+    }
+}
+
+static void munger_setpower(t_disis_munger *x, t_symbol *s, int argc,
+    t_atom *argv)
+{
+    if (argc)
+    {
+        x->x_power = (int)atom_getintarg(0, argc, argv);
+        post("disis_munger~ %s: setting power: %d",
+            x->x_munger_name->s_name, x->x_power);
+    }
+}
+
+static void munger_record(t_disis_munger *x, t_symbol *s, int argc,
+    t_atom *argv)
+{
+    int temp;
+
+    if (argc)
+    {
+        temp = (int)atom_getintarg(0, argc, argv);
+        if (!temp)
+        {
+            x->x_recordRampVal = RECORDRAMP;
+            x->x_rec_ramping = -1;
+        }
+        else
+        {
+            x->x_recordOn = 1;
+            x->x_recordRampVal = 0;
+            x->x_rec_ramping = 1;
+        }
+        if (x->x_verbose > 1)
+            post("disis_munger~ %s: setting record: %d",
+                x->x_munger_name->s_name, temp);
+    }
+}
+
+static void munger_ambidirectional(t_disis_munger *x, t_symbol *s, int argc,
+    t_atom *argv)
+{
+    if (argc)
+    {
+        x->x_ambi = atom_getfloatarg(0, argc, argv);
+        if (x->x_verbose > 1)
+            post("disis_munger~ %s: setting ambidirectional: %d",
+                x->x_munger_name->s_name, x->x_ambi);
+    }
+}
+
+static void munger_gain(t_disis_munger *x, t_symbol *s, int argc,
+    t_atom *argv)
+{
+    if (argc)
+    {
+        x->x_gain = atom_getfloatarg(0, argc, argv);
+        if (x->x_verbose > 1)
+            post("disis_munger~ %s: setting gain to: %f ",
+                x->x_munger_name->s_name, x->x_gain);
+    }
+}
+
+static void munger_setposition(t_disis_munger *x, t_symbol *s, int argc,
+    t_atom *argv)
+{
+    float temp;
+
+    if (argc)
+    {
+        temp = atom_getfloatarg(0, argc, argv);
+        if (temp > 1.) temp = 1.;
+        if (temp < 0.) temp = -1.;
+        if (x->x_verbose > 1)
+            post("disis_munger~ %s: setting position to: %f ",
+                x->x_munger_name->s_name, temp);
+        x->x_position = temp;
+    }
+}
+
+static void munger_randgain(t_disis_munger *x, t_symbol *s, int argc,
+    t_atom *argv)
+{
+    if (argc)
+    {
+        x->x_randgain = atom_getfloatarg(0, argc, argv);
+        if (x->x_verbose > 1)
+            post("disis_munger~ %s: setting rand_gain to: %f ",
+                x->x_munger_name->s_name, x->x_randgain);
+    }
+}
+
+static void munger_sethanning(t_disis_munger *x)
+{
+    x->x_doHanning = 1;
+    if (x->x_verbose > 1)
+        post("disis_munger~ %s: hanning window is busted",
+            x->x_munger_name->s_name);
+}
+
+static void munger_tempered(t_disis_munger *x)
+{
+    int i;
+    if (x->x_verbose > 1)
+        post("disis_munger~ %s: doing tempered scale",
+            x->x_munger_name->s_name);
+    x->x_smoothPitch = 0;
+    x->x_scale_len = 100;
+    for (i=0; i < x->x_scale_len - 1; i += 2)
+    {
+        x->x_pitchTable[i] = 0.5 * i;
+        x->x_pitchTable[i+1] = -0.5 * i;
+    }
+    x->x_scale_len = PITCHTABLESIZE;
+}
+
+static void munger_smooth(t_disis_munger *x)
+{
+    x->x_smoothPitch = 1;
+    if (x->x_verbose > 1)
+        post("disis_munger~ %s: doing smooth scale", x->x_munger_name->s_name);
+}
+
+static void munger_poststate(t_disis_munger *x)
+{
+    post (">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
+    post ("***CURRENT disis_munger~ %s PARAMETER VALUES***:",
+         x->x_munger_name->s_name);
+    post ("all times in milliseconds");
+    post ("version: %d.%d.%d", (int)MUNGER_MAJOR, (int)MUNGER_MINOR, (int)MUNGER_REV);
+    post ("grain spacing = %f", x->x_grate);
+    post ("grain spacing variation = %f", x->x_grate_var);
+    post ("grain length = %f", x->x_glen);
+    post ("grain length variation = %f", x->x_glen_var);
+    post ("grain transposition multiplier = %f", x->x_gpitch);
+    post ("grain transposition multiplier variation = %f", x->x_gpitch_var);
+    post ("panning spread = %f", x->x_gpan_spread);
+    post ("grain gain = %f", x->x_gain);
+    post ("grain gain variation = %f", x->x_randgain);
+    post ("playback position (-1 = RANDOM()) = %f", x->x_position);
+    post ("grain playback direction (0 = both) = %d", x->x_ambi);
+    post ("buffer length = %f", x->x_buflen * x->x_one_over_srate_ms);
+    post ("max grain size = %f", x->x_maxsize * x->x_one_over_srate_ms);
+    post ("min grain size = %f", x->x_minsize * x->x_one_over_srate_ms);
+    post ("max number of voices = %ld", x->x_maxvoices);
+    post ("current number of voices = %d", x->x_voices);
+    post ("grain envelope (ramp) length = %f",
+        x->x_rampLength * x->x_one_over_srate_ms);
+    post ("recording? = %d", x->x_recordOn);
+    post ("power = %d", x->x_power);
+    post ("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
+}
+
+//buffer funcs
+static void munger_recordSamp(t_disis_munger *x, t_float sample)
+{
+    if (x->x_recordCurrent >= x->x_buflen) x->x_recordCurrent = 0;
+
+    if (x->x_recordOn)
+    {
+        if (x->x_rec_ramping == 0)
+            x->x_recordBuf[x->x_recordCurrent++] = sample; //add sample
+        else //ramp up or down if turning on/off recording
+        {
+            x->x_recordBuf[x->x_recordCurrent++] =
+                sample * RECORDRAMP_INV * (float)x->x_recordRampVal;
+            x->x_recordRampVal += x->x_rec_ramping;
+            if (x->x_recordRampVal <= 0)
+            {
+                x->x_rec_ramping = 0;
+                x->x_recordOn = 0;
+            }
+            if (x->x_recordRampVal >= RECORDRAMP) x->x_rec_ramping = 0;
+        }
+    }
+}
+
+static t_float munger_getSamp(t_disis_munger *x, double where)
+{
+    double alpha, om_alpha, output;
+    long first;
+
+    while (where < 0.) where += x->x_buflen;
+    while (where >= x->x_buflen) where -= x->x_buflen;
+
+    first = (long)where;
+
+    alpha = where - first;
+    om_alpha = 1. - alpha;
+
+    output = x->x_recordBuf[first++] * om_alpha;
+    if (first <  x->x_buflen)
+    {
+        output += x->x_recordBuf[first] * alpha;
+    }
+    else
+    {
+        output += x->x_recordBuf[0] * alpha;
+    }
+    return (float)output;
+}
+
+static t_float munger_getExternalSamp(t_disis_munger *x, double where)
+{
+    double alpha, om_alpha, output;
+    long first;
+
+    t_float *tab;
+    double frames, sampNum, nc;
+
+    if (!x->x_arraylength)
+    {
+        post("disis_munger~ %s: error: external buffer mysteriously AWOL, "
+             "reverting to internal buffer...", x->x_munger_name->s_name);
+        return 0.;
+    }
+
+    tab = (t_float *)x->x_arrayvec;
+    frames = (double)x->x_arraylength;
+    /* Hm... isn't this always 1 for a garray? Setting it to that for now... */
+    nc = (double)1; //== buffer~ framesize...
+
+    if (where < 0.) where = 0.;
+    else if (where >= frames) where = 0.;
+
+    sampNum = where * nc;
+
+    first = (long)sampNum;
+
+    alpha = sampNum - first;
+    om_alpha = 1. - alpha;
+
+    output = tab[first] * om_alpha;
+    first += (long)nc;
+    output += tab[first] * alpha;
+
+    return (t_float)output;
+}
+
+static t_int *munger_perform(t_int *w)
+{
+    /* Let's do it this way:
+       (0: our function pointer)
+       (1: our pd)
+       2: insig
+       3: n
+       The outsigs will be pointed to by x->x_out
+    */
+
+    t_disis_munger *x = (t_disis_munger *)(w[1]);
+
+// Hm... shouldn't we be using t_sample here as well as in x_out?
+    t_float samp;
+    int newvoice, i, j, n, sample_number;
+
+    n = (int)(w[3]);
+    /* ins1 holds the signal vector ofthe first inlet, index 0 */
+    t_sample *ins1 = (t_sample *)(w[2]);
+
+    /* pointer for incrementing the outlet samps */
+    t_float **out = x->x_out;
+    if (x->x_gpan_spread > 1.) x->x_gpan_spread = 1.;
+    if (x->x_gpan_spread < 0.) x->x_gpan_spread = 0.;
+
+    if (!x->x_power)
+    {
+        for (i = 0; i < x->x_num_channels; i++)
+            for (j = 0; j < x->x_num_channels; j++)
+                out[i][j] = 0.;
+    }
+    else
+    {
+        for (sample_number = 0; sample_number < n; sample_number++)
+        {
+            if (x->x_verbose > 2)
+            {
+                x->x_countsamples++;
+                if (x->x_countsamples >= ((int)x->x_srate - 1))
+                {
+                    post("disis_munger~ %s: outputting %d grains per second",
+                        x->x_munger_name->s_name, x->x_graincounter);
+                    x->x_graincounter = 0;
+                    x->x_countsamples = 0;
+                }
+            }
+            for (i = 0; i < x->x_num_channels; i++) x->x_outsamp[i] = 0.;
+            //record a sample
+            munger_recordSamp(x, *ins1++);
+
+            //grab a note if requested; works in oneshot mode or otherwise
+            if (x->x_oneshot)
+            {
+                while (x->x_newnote > 0)
+                {
+                    newvoice = munger_findVoice(x);
+                    if (newvoice >= 0)
+                    {
+                        x->x_gvoiceCurrent[newvoice] =
+                            munger_newNote(x, newvoice, x->x_newnote);
+                    }
+                    x->x_newnote--;
+                }
+            }
+            else
+            {
+                /* find a voice if it's time (high resolution).
+                   ignore if in "oneshot" mode */
+                if (x->x_time++ >= (long)x->x_gimme)
+                {
+                    x->x_time = 0;
+                    newvoice = munger_findVoice(x);
+                    if (newvoice >= 0)
+                    {
+                        x->x_gvoiceCurrent[newvoice] =
+                            munger_newSetup(x, newvoice);
+                    }
+                    x->x_tempgrate = x->x_grate + ((long)RANDOM() - 16384.) *
+                        ONE_OVER_HALFRAND * x->x_grate_var;
+                    /* grate is actually time-distance between grains */
+                    x->x_gimme = x->x_srate_ms * x->x_tempgrate;
+                }
+            }
+            x->x_time++;
+            //mix 'em, pan 'em
+            for (i = 0; i < x->x_maxvoices; i++)
+            {
+                if (x->x_gvoiceOn[i])
+                {
+                    //get a sample, envelope it
+                    if (x->x_arraylength)
+                        samp = munger_getExternalSamp(x, x->x_gvoiceCurrent[i]);
+                    else
+                        samp = munger_getSamp(x, x->x_gvoiceCurrent[i]);
+                    if (!x->x_gvoiceADSRon[i])
+                        samp = munger_envelope(x, i, samp) * x->x_gvoiceGain[i];
+                    else
+                        samp = samp * stk_ADSR_tick(&x->x_gvoiceADSR[i]) *
+                            x->x_gvoiceGain[i]; //ADSR_ADRtick->computeSample()
+                    //pan it
+                    if (x->x_num_channels == 2)
+                    {
+                        x->x_outsamp[0] += samp * x->x_gvoiceLPan[i];
+                        x->x_outsamp[1] += samp * x->x_gvoiceRPan[i];
+                    }
+                    else // multichannel subroutine
+                    {
+                        for (j = 0; j < x->x_num_channels; j++)
+                        {
+                            x->x_outsamp[j] += samp * x->x_gvoiceSpat[i][j];
+                        }
+                    }
+
+                    //see if grain is done after jumping to next sample point
+                    x->x_gvoiceCurrent[i] += (double)x->x_gvoiceDirection[i] *
+                        (double)x->x_gvoiceSpeed[i];
+                    if (!x->x_gvoiceADSRon[i])
+                    {
+                        if (x->x_gvoiceDone[i] >= x->x_gvoiceSize[i] ||
+                            ++x->x_gvoiceDone[i] >= x->x_gvoiceSize[i])
+                        {
+                            x->x_gvoiceOn[i] = 0;
+                        }
+                    }
+                    else
+                    {
+                        if (stk_ADSR_getState(&x->x_gvoiceADSR[i]) == SUSTAIN)
+                        {
+                            stk_ADSR_keyOff(&x->x_gvoiceADSR[i]);
+                        }
+                        if (++x->x_gvoiceDone[i] >= x->x_gvoiceSize[i] ||
+                            stk_ADSR_getState(&x->x_gvoiceADSR[i]) == IDLE)
+                        {
+                            x->x_gvoiceOn[i] = 0;
+                        }
+                        if (!x->x_gvoiceOn[i])
+                            x->x_graincounter++;
+                    }
+                }
+            }
+            for (i = 0; i < x->x_num_channels; i++)
+            {
+                out[i][sample_number] = x->x_outsamp[i];
+            }
+        }
+    }
+    return (w+4);
+}
+
+static void munger_dsp(t_disis_munger *x, t_signal **sp)
+{
+    t_float old_srate;
+
+    // Go ahead and set the array based on the array name.
+    pd_vmess(&x->x_obj.te_pd, gensym("buffer"), "s", x->x_arrayname);
+
+    old_srate = x->x_srate;
+    x->x_srate = sys_getsr();
+    if (x->x_srate != old_srate)
+    {
+        x->x_one_over_srate = 1. / x->x_srate;
+        x->x_srate_ms = x->x_srate / 1000;
+        x->x_one_over_srate_ms = 1. / x->x_srate_ms;
+    }
+    /* Let's do it this way:
+       (0: our function pointer)
+       (1: our pd)
+       2: insig
+       3: n
+       The outsigs will be pointed to by x->x_out
+    */
+    int i;
+    for (i = 0; i < x->x_num_channels; i++)
+    {
+        x->x_out[i] = (t_float *)(sp[i + 1]->s_vec);
+    }
+    dsp_add(munger_perform, 3, x, sp[0]->s_vec, sp[0]->s_n);
+}
+
+void disis_munger_tilde_setup(void)
+{
+    disis_munger_class = class_new(gensym("disis_munger~"),
+        (t_newmethod)munger_new, (t_method)munger_free,
+        sizeof(t_disis_munger),
+        CLASS_DEFAULT, A_GIMME, 0);
+    CLASS_MAINSIGNALIN(disis_munger_class, t_disis_munger, x_f);
+    class_addmethod(disis_munger_class, (t_method)munger_dsp,
+        gensym("dsp"), A_CANT, 0);
+    class_addmethod(disis_munger_class, (t_method)munger_setverbose,
+        gensym("verbose"), A_GIMME, 0);
+    class_addmethod(disis_munger_class, (t_method)munger_setramp,
+        gensym("ramptime"), A_DEFFLOAT, 0);
+    class_addmethod(disis_munger_class, (t_method)munger_scale,
+        gensym("scale"), A_GIMME, 0);
+    class_addmethod(disis_munger_class, (t_method)munger_bufsize,
+        gensym("delaylength"), A_GIMME, 0);
+    class_addmethod(disis_munger_class, (t_method)munger_bufsize_ms,
+        gensym("delaylength_ms"), A_GIMME, 0);
+    class_addmethod(disis_munger_class, (t_method)munger_setminsize,
+        gensym("minsize"), A_GIMME, 0);
+    class_addmethod(disis_munger_class, (t_method)munger_setpower,
+        gensym("power"), A_GIMME, 0);
+    class_addmethod(disis_munger_class, (t_method)munger_record,
+        gensym("record"), A_GIMME, 0);
+    class_addmethod(disis_munger_class, (t_method)munger_ambidirectional,
+        gensym("ambidirectional"), A_GIMME, 0);
+    class_addmethod(disis_munger_class, (t_method)munger_smooth,
+        gensym("smooth"), A_GIMME, 0);
+    class_addmethod(disis_munger_class, (t_method)munger_tempered,
+        gensym("tempered"), 0);
+    class_addmethod(disis_munger_class, (t_method)munger_sethanning,
+        gensym("hanning"), 0);
+    class_addmethod(disis_munger_class, (t_method)munger_randgain,
+        gensym("rand_gain"), A_GIMME, 0);
+    class_addmethod(disis_munger_class, (t_method)munger_setposition,
+        gensym("position"), A_GIMME, 0);
+    class_addmethod(disis_munger_class, (t_method)munger_gain,
+        gensym("gain"), A_GIMME, 0);
+    class_addmethod(disis_munger_class, (t_method)munger_setvoices,
+        gensym("voices"), A_GIMME, 0);
+    class_addmethod(disis_munger_class, (t_method)munger_maxvoices,
+        gensym("maxvoices"), A_GIMME, 0);
+    class_addmethod(disis_munger_class, (t_method)munger_clear,
+        gensym("clear"), 0);
+    class_addmethod(disis_munger_class, (t_method)munger_poststate,
+        gensym("state"), 0);
+    class_addmethod(disis_munger_class, (t_method)munger_setbuffer,
+        gensym("buffer"), A_GIMME, 0);
+    class_addmethod(disis_munger_class, (t_method)munger_spat,
+        gensym("spatialize"), A_GIMME, 0);
+    class_addmethod(disis_munger_class, (t_method)munger_note,
+        gensym("note"), A_GIMME, 0);
+    class_addmethod(disis_munger_class, (t_method)munger_oneshot,
+        gensym("oneshot"), A_GIMME, 0);
+    class_addmethod(disis_munger_class, (t_method)munger_discretepan,
+        gensym("discretepan"), A_GIMME, 0);
+}
diff --git a/externals/disis/disis_munger~-help.pd b/externals/disis/disis_munger~-help.pd
new file mode 100644
index 0000000000000000000000000000000000000000..440e39b6b22adc591061bc78ca87d0529847a759
--- /dev/null
+++ b/externals/disis/disis_munger~-help.pd
@@ -0,0 +1,719 @@
+#N canvas 149 44 1056 661 10;
+#X floatatom -8 598 0 0 100 0 - - -;
+#N canvas 331 136 786 621 output 0;
+#X obj 455 510 t b;
+#X obj 455 450 f;
+#X obj 455 390 inlet;
+#X obj 455 540 f;
+#X msg 566 532 0;
+#X msg 455 420 bang;
+#X obj 455 480 moses 1;
+#X obj 566 502 t b f;
+#X obj 535 460 moses 1;
+#X obj 107 121 dbtorms;
+#X obj 535 430 r master-lvl;
+#X obj 107 27 r master-lvl;
+#X obj 455 570 s master-lvl;
+#X obj 95 227 inlet~;
+#X obj 250 258 inlet;
+#X obj 268 283 s master-lvl;
+#X msg 119 57 set \$1;
+#X obj 119 87 outlet;
+#X msg 250 309 \; pd dsp 1;
+#X obj 107 181 line~;
+#X obj 96 257 *~;
+#X obj 107 151 pack 0 50;
+#X text 23 205 audio in;
+#X text 2 313 out both channels;
+#X text 273 182 Level input. Send to master-lvl and start DSP (we infer
+that if you're changing the level you want to hear the network.) If
+you start DSP when it's already running there's no effect.;
+#X text 59 542 here is the previous nonzero master-lvl -->;
+#X text 98 451 recall previous value of master-lvl -->;
+#X text 239 482 test if less than 1 -->;
+#X text 203 510 if true convert to bang -->;
+#X text 218 351 Mute control. If the master level is zero \, restore
+to the last nonzero one \, otherwise zero it.;
+#X text 182 86 <-- update the number box to show new level;
+#X text 178 120 <-- convert from dB to linear units;
+#X text 196 150 <-- make a smooth ramp to avoid clicks or zipper noise
+;
+#X text 333 318 <-- automatically start DSP;
+#X obj 36 228 inlet~;
+#X obj 36 258 *~;
+#X obj 64 290 dac~;
+#X obj 35 346 send~ left;
+#X obj 97 346 send~ right;
+#X connect 0 0 3 0;
+#X connect 1 0 6 0;
+#X connect 2 0 5 0;
+#X connect 3 0 12 0;
+#X connect 4 0 12 0;
+#X connect 5 0 1 0;
+#X connect 6 0 0 0;
+#X connect 6 1 7 0;
+#X connect 7 0 4 0;
+#X connect 8 1 3 1;
+#X connect 9 0 21 0;
+#X connect 10 0 1 1;
+#X connect 10 0 8 0;
+#X connect 11 0 9 0;
+#X connect 11 0 16 0;
+#X connect 13 0 20 0;
+#X connect 14 0 15 0;
+#X connect 14 0 18 0;
+#X connect 16 0 17 0;
+#X connect 19 0 20 1;
+#X connect 19 0 35 1;
+#X connect 20 0 36 1;
+#X connect 20 0 38 0;
+#X connect 21 0 19 0;
+#X connect 34 0 35 0;
+#X connect 35 0 36 0;
+#X connect 35 0 37 0;
+#X restore -18 620 pd output;
+#X msg 17 598 mute;
+#X text -44 18 stereo granulator...;
+#X text -44 33 munger~ takes a signal input;
+#X text -46 43 and granulates it \, allowing for;
+#X text -46 53 different transposition and;
+#X text 615 6 the 'voices' message tells the munger how many grains
+to;
+#X text 613 26 cpu intensive. you can smoothly sweep this parameter.
+;
+#X text -46 62 granular sampling effects.;
+#X text 613 35 'maxvoices' sets an upper limit to this \, and will
+have some;
+#X text 616 45 impact on performance if set really high (20 by default.)
+;
+#X text 615 79 'ramptime' sets the length (in ms) of the ramping envelope
+;
+#X text 613 89 on each grain. if the grain is smaller than the ramptime
+\,;
+#X text 613 99 the ramptime will be scaled to half the grain size.
+;
+#X text 613 121 turn the munger on and off \, to save CPU. (1) by default.
+;
+#X text 611 131 (NOTE: this was responsible for a bug in the previous
+;
+#X text 614 140 versions of munger which resulted in frustratingly
+silent;
+#X text 614 149 mungers. fixed now \, I believe.);
+#X text 614 172 constrain how far back in time the munger looks for
+grains.;
+#X text 612 182 the smaller this is \, the smaller the largest grain
+can be.;
+#X text 612 192 the numnger's argument sets the maximum delay length
+;
+#X text 613 201 possible ( and the default value for delaylength.)
+this is a;
+#X text 614 211 super cool parameter to mess with.;
+#X text 614 231 allows grains to play backwards and forwards (0) \,
+just;
+#X text 612 241 forward (1) \, or just backwards (-1). (0) by default.
+;
+#X text 614 265 sets the minimum allowable grainsize. useful when;
+#X text 612 275 randomizing with the 'grain size variation' input.
+;
+#X text 614 306 turn recording on and off. turning off freezes the
+buffer;
+#X text 612 316 on (1) by default.;
+#X text 614 338 set the playback position within the buffer (between
+0 and;
+#X text 615 348 1.) -1 = randomized position (which is the default.)
+It is;
+#X text 613 358 possible to get some interesting stretching effect
+by;
+#X text 612 368 scrubbing through this with 'record' on \, and some
+good;
+#X text 613 377 transposition effects with 'record' off.;
+#X text 613 397 set the baseline gain for grains (1 by default) \,
+and set a;
+#X text 611 407 randomization range around that baseline (0 by default.)
+;
+#X text 613 429 apply pitch sieves to the grains. control how deeply
+into;
+#X text 611 438 these sieves to go with the 'grain pitch variation'
+input;
+#X text 611 448 (below.) floats work too. set to 'smooth' (no sieve)
+by;
+#X text 611 457 default.;
+#X text 482 554 posts the values of user controlled variables to the
+;
+#X text 482 564 console;
+#X text 480 579 impolitely clears the internal sample buffer.;
+#X text 13 498 grain;
+#X text 0 507 separation;
+#X text 65 509 variation;
+#X text 128 499 grain;
+#X text 128 508 size;
+#X text 248 500 grain;
+#X text 249 509 pitch;
+#X text 297 509 variation;
+#X text 298 491 grain;
+#X text 297 500 pitch;
+#X text 360 500 stereo;
+#X text 360 508 spread;
+#X text 63 493 grain;
+#X text 65 502 rate;
+#X obj 182 27 loadbang;
+#X obj 182 48 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1
+;
+#X obj 182 66 metro 250;
+#X obj 182 86 counter 0 15;
+#N canvas 0 0 450 300 (subpatch) 0;
+#X array mycoll 16 float 1 black black;
+#A 0 57 45 57 57 45 57 57 47 55 47 59 60 60 57 57 57;
+#X coords 0 72 15 40 100 70 1;
+#X restore 78 102 graph;
+#X obj 182 107 tabread mycoll;
+#X obj 181 129 sel 0;
+#X obj 181 153 mtof;
+#X obj 181 178 * 2;
+#X msg 206 200 20;
+#X obj 181 222 line~;
+#X obj 181 245 osc~ 200;
+#X text 426 8 send some messages...;
+#X msg 451 45 voices \$1;
+#X msg 436 102 ramptime \$1;
+#X obj 439 122 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1
+1;
+#X msg 439 140 power \$1;
+#X msg 441 239 ambidirectional \$1;
+#X msg 441 268 minsize 5;
+#X obj 443 292 tgl 15 1 empty empty empty 0 -6 0 8 -262144 -1 -1 1
+1;
+#X msg 443 310 record \$1;
+#X msg 444 358 position \$1;
+#X msg 446 400 gain \$1;
+#X msg 446 419 rand_gain \$1;
+#X msg 446 446 smooth;
+#X msg 446 466 tempered;
+#X msg 446 486 scale 0 4 7 -2 12 15;
+#X msg 446 506 scale 0 4 4 4 7 7 11 11 14 18 -12 -12 -12;
+#X msg 446 559 state;
+#X msg 446 579 clear;
+#X obj -54 526 r msgs;
+#X obj 403 507 s msgs;
+#X obj 400 163 s msgs;
+#X msg 83 296 1;
+#X msg 88 315 2;
+#X msg 94 334 3;
+#X text 36 255 select a sound source;
+#X text 37 291 oscil;
+#X text 28 301 sequence;
+#X text 34 319 sample;
+#N canvas 0 0 473 362 choose 0;
+#X obj 78 50 inlet;
+#X obj 94 93 sel 1 2 3;
+#X msg 108 122 1 0 0;
+#X msg 114 143 0 1 0;
+#X msg 121 164 0 0 1;
+#X obj 138 188 unpack 0 0 0;
+#X obj 240 52 inlet~;
+#X obj 297 52 inlet~;
+#X obj 354 52 inlet~;
+#X obj 240 223 *~ 0;
+#X obj 303 221 *~ 0;
+#X obj 373 225 *~ 0;
+#X obj 346 257 +~;
+#X obj 280 289 +~;
+#X obj 287 331 outlet~;
+#X floatatom 121 223 5 0 0 0 - - -, f 5;
+#X floatatom 156 221 5 0 0 0 - - -, f 5;
+#X floatatom 190 221 5 0 0 0 - - -, f 5;
+#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 2 0 5 0;
+#X connect 3 0 5 0;
+#X connect 4 0 5 0;
+#X connect 5 0 9 1;
+#X connect 5 0 15 0;
+#X connect 5 1 10 1;
+#X connect 5 1 16 0;
+#X connect 5 2 11 1;
+#X connect 5 2 17 0;
+#X connect 6 0 9 0;
+#X connect 7 0 10 0;
+#X connect 8 0 11 0;
+#X connect 9 0 13 0;
+#X connect 10 0 12 0;
+#X connect 11 0 12 1;
+#X connect 12 0 13 1;
+#X connect 13 0 14 0;
+#X restore 82 370 pd choose;
+#X obj 249 144 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 249 162 openpanel;
+#X obj 249 201 soundfiler;
+#N canvas 0 0 450 300 (subpatch) 0;
+#X array mysample 674138 float 0 black black;
+#X coords 0 1 674137 -1 100 70 1;
+#X restore 277 80 graph;
+#X obj 147 335 adc~;
+#X text 52 340 adc;
+#X msg 249 181 read -resize \$1 mysample;
+#X floatatom 248 259 12 0 0 0 - - -, f 12;
+#X obj 248 340 phasor~;
+#X floatatom 248 221 20 0 0 0 - - -, f 20;
+#X obj 248 296 f;
+#X obj 248 277 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 248 319 * 1;
+#X text 311 207 length in samples;
+#X obj 83 274 loadbang;
+#X obj 303 340 snapshot~;
+#X floatatom 303 363 5 0 0 0 - - -, f 5;
+#X obj 303 316 metro 20;
+#X obj 303 294 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0
+1;
+#X obj 247 385 tabread4~ mysample;
+#X text 192 500 grain;
+#X text 184 509 size var;
+#X obj 436 85 nbx 5 14 0 1e+37 0 1 empty empty empty 0 -6 0 10 -262144
+-1 -1 1000 256 0;
+#X obj 451 27 nbx 5 14 0 500 0 1 empty empty empty 0 -6 0 10 -262144
+-1 -1 40 256 0;
+#X obj 445 168 nbx 5 14 0 1e+37 0 1 empty empty empty 0 -6 0 10 -262144
+-1 -1 3000 256 0;
+#X obj 444 219 nbx 5 14 -1 1 0 1 empty empty empty 0 -6 0 10 -262144
+-1 -1 0 256 0;
+#X obj 444 335 nbx 5 14 -1 1 0 1 empty empty empty 0 -6 0 10 -262144
+-1 -1 1 256 0;
+#X obj 446 376 nbx 5 14 0 1e+37 0 1 empty empty empty 0 -6 0 10 -262144
+-1 -1 1 256 0;
+#X obj 509 400 nbx 5 14 0 32767 0 1 empty empty empty 0 -6 0 10 -262144
+-1 -1 0 256 0;
+#X obj 353 527 nbx 5 14 0 10 0 1 empty empty empty 0 -6 0 10 -262144
+-1 -1 1 256 0;
+#X obj 296 527 nbx 5 14 0 100 0 1 empty empty empty 0 -6 0 10 -262144
+-1 -1 1 256 0;
+#X obj 240 527 nbx 5 14 0 1e+37 0 1 empty empty empty 0 -6 0 10 -262144
+-1 -1 1 256 0;
+#X obj 183 527 nbx 5 14 0 1e+37 0 1 empty empty empty 0 -6 0 10 -262144
+-1 -1 24 256 0;
+#X obj 126 527 nbx 5 14 0 1e+37 0 1 empty empty empty 0 -6 0 10 -262144
+-1 -1 24 256 0;
+#X obj 68 527 nbx 5 14 0 1e+37 0 1 empty empty empty 0 -6 0 10 -262144
+-1 -1 5 256 0;
+#X obj 11 527 nbx 5 14 0 1e+37 0 1 empty empty empty 0 -6 0 10 -262144
+-1 -1 2 256 0;
+#X msg 446 526 scale 0 -2 2 -4 4 -6 6 -8 8 -10 10 -12 12 -14 14 -16
+16 -18 18 -20 20;
+#X obj 562 31 loadbang;
+#X msg 581 98 1;
+#X obj 183 483 loadbang;
+#X obj 899 528 vu 15 120 empty empty -1 -8 0 8 -66577 -1 1 0;
+#X obj 898 488 env~ 16384;
+#X obj 815 528 vu 15 120 empty empty -1 -8 0 8 -66577 -1 1 0;
+#X obj 814 488 env~ 16384;
+#X obj 814 507 - 99;
+#X obj 898 507 - 99;
+#X obj 814 469 receive~ left;
+#X obj 899 469 receive~ right;
+#X msg 382 45 verbose \$1;
+#X obj 382 28 nbx 5 14 0 3 0 1 empty empty empty 0 -8 0 10 -262144
+-1 -1 2 256 0;
+#X text 240 1 pd console verbosity;
+#X text 240 12 0 - none;
+#X msg 439 195 delaylength_ms \$1;
+#X text 241 21 1 - critical(default);
+#X msg 172 458 oneshot \$1;
+#X obj 172 440 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0
+1;
+#X msg 69 458 buffer mysample;
+#X obj 11 353 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0
+1;
+#X obj 4 273 nbx 5 14 -1e+37 1e+37 0 0 empty empty empty 0 -8 0 10
+-262144 -1 -1 0 256 0;
+#N canvas 419 193 490 272 optional_arguments 0;
+#X text 75 41 and allocates memory \, so be careful with large values.
+;
+#X text 72 51 (3000ms by default.) this also constrains the maximum
+;
+#X text 74 60 grain size \, to 1/3rd the maximum delay time.;
+#X text 51 12 optional arguments:;
+#X text 64 32 1 sets the maximum delay time (in ms);
+#X text 62 91 3 either optional max voices (default 50) or name;
+#X text 71 100 (optional). If more than one disis_munger~ object is
+used;
+#X text 74 110 in the same patch \, this enables easier tracking of
+the;
+#X text 73 120 PD console output.;
+#X text 59 135 4 if optional max voices was set as third argument;
+#X text 71 145 this argument is used for the name instead. Alternately
+\,;
+#X text 71 154 last argument can be also used for extending the visual
+;
+#X text 72 164 width of the object by typing _____. This can be also
+;
+#X text 71 173 used as the 3rd argument in which case all arguments
+that;
+#X text 70 183 follow are ignored.;
+#X text 67 217 IMPORTANT! In order to be able to name any instance
+\, you;
+#X text 67 228 must provide arguments first 3 arguments. Old 1-argument
+;
+#X text 67 240 format is provided for backwards compatibilitiy purposes.
+;
+#X text 63 76 2 sets number of output channels 2-64 (2 by default)
+;
+#X restore 123 621 pd optional_arguments;
+#X obj 206 596 send~ four;
+#X obj 255 576 send~ five;
+#X obj 275 596 send~ six;
+#X obj 324 576 send~ seven;
+#X obj 180 576 send~ three;
+#X obj 338 596 send~ eight;
+#N canvas 2 50 607 390 8chVU 0;
+#X obj 235 244 vu 15 120 empty empty -1 -8 0 8 -66577 -1 1 0;
+#X obj 234 204 env~ 16384;
+#X obj 234 223 - 99;
+#X obj 164 244 vu 15 120 empty empty -1 -8 0 8 -66577 -1 1 0;
+#X obj 163 204 env~ 16384;
+#X obj 163 223 - 99;
+#X obj 93 244 vu 15 120 empty empty -1 -8 0 8 -66577 -1 1 0;
+#X obj 92 204 env~ 16384;
+#X obj 92 223 - 99;
+#X obj 22 244 vu 15 120 empty empty -1 -8 0 8 -66577 -1 1 0;
+#X obj 21 204 env~ 16384;
+#X obj 21 223 - 99;
+#X obj 21 140 receive~ left;
+#X obj 517 244 vu 15 120 empty empty -1 -8 0 8 -66577 -1 1 0;
+#X obj 516 204 env~ 16384;
+#X obj 516 223 - 99;
+#X obj 446 244 vu 15 120 empty empty -1 -8 0 8 -66577 -1 1 0;
+#X obj 445 204 env~ 16384;
+#X obj 445 223 - 99;
+#X obj 375 244 vu 15 120 empty empty -1 -8 0 8 -66577 -1 1 0;
+#X obj 374 204 env~ 16384;
+#X obj 374 223 - 99;
+#X obj 304 244 vu 15 120 empty empty -1 -8 0 8 -66577 -1 1 0;
+#X obj 303 204 env~ 16384;
+#X obj 303 223 - 99;
+#X obj 92 140 receive~ right;
+#X obj 163 140 receive~ three;
+#X obj 234 140 receive~ four;
+#X obj 303 140 receive~ five;
+#X obj 374 140 receive~ six;
+#X obj 444 140 receive~ seven;
+#X obj 516 140 receive~ eight;
+#X obj 239 54 dbtorms;
+#X obj 239 5 r master-lvl;
+#X msg 250 30 set \$1;
+#X obj 239 114 line~;
+#X obj 239 84 pack 0 50;
+#X obj 374 171 *~;
+#X obj 164 171 *~;
+#X obj 235 171 *~;
+#X obj 445 171 *~;
+#X obj 516 171 *~;
+#X obj 302 171 *~;
+#X connect 1 0 2 0;
+#X connect 2 0 0 0;
+#X connect 2 0 0 1;
+#X connect 4 0 5 0;
+#X connect 5 0 3 0;
+#X connect 5 0 3 1;
+#X connect 7 0 8 0;
+#X connect 8 0 6 0;
+#X connect 8 0 6 1;
+#X connect 10 0 11 0;
+#X connect 11 0 9 0;
+#X connect 11 0 9 1;
+#X connect 12 0 10 0;
+#X connect 14 0 15 0;
+#X connect 15 0 13 0;
+#X connect 15 0 13 1;
+#X connect 17 0 18 0;
+#X connect 18 0 16 0;
+#X connect 18 0 16 1;
+#X connect 20 0 21 0;
+#X connect 21 0 19 0;
+#X connect 21 0 19 1;
+#X connect 23 0 24 0;
+#X connect 24 0 22 0;
+#X connect 24 0 22 1;
+#X connect 25 0 7 0;
+#X connect 26 0 38 0;
+#X connect 27 0 39 0;
+#X connect 28 0 42 0;
+#X connect 29 0 37 0;
+#X connect 30 0 40 0;
+#X connect 31 0 41 0;
+#X connect 32 0 36 0;
+#X connect 33 0 32 0;
+#X connect 33 0 34 0;
+#X connect 35 0 38 1;
+#X connect 35 0 39 1;
+#X connect 35 0 42 1;
+#X connect 35 0 37 1;
+#X connect 35 0 40 1;
+#X connect 35 0 41 1;
+#X connect 36 0 35 0;
+#X connect 37 0 20 0;
+#X connect 38 0 4 0;
+#X connect 39 0 1 0;
+#X connect 40 0 17 0;
+#X connect 41 0 14 0;
+#X connect 42 0 23 0;
+#X restore 263 621 pd 8chVU;
+#X msg 446 599 spatialize 0.1 0.5 0.1 0.5 0.1 0.5 0.1 0.5 0.1 0.5 0.1
+0.5 0.1 0.5 0.1 0.5;
+#X msg 275 436 discretepan \$1;
+#X text 275 450 multichannel only option;
+#X text 274 460 toggles whether every grain;
+#X text 274 469 can be only on one channel;
+#X text 275 478 at any given time.;
+#X obj 275 419 nbx 5 14 0 1 0 0 empty empty empty 0 -8 0 10 -262144
+-1 -1 0 256 0;
+#X obj 11 371 metro 20;
+#X msg -29 474 buffer;
+#X text -50 458 use internal buffer;
+#X text -29 448 revert to or;
+#X msg 391 65 maxvoices 500;
+#X text 240 30 2 - all;
+#X text 240 39 3 - grains/sec;
+#X text 445 627 spatialize multichannel grains (gain + rand_gain pairs/ch)
+;
+#X text 445 636 IMPORTANT! no sound will come out from multichannel
+object;
+#X text 445 644 until this option is passed through to it;
+#X msg 74 408 note 1 1 0.5 500 500 0.9 1000 -1;
+#X text 613 16 allow simultaneously (set to 15 here.) the more \, the
+more;
+#X text 617 55 munger by default has hardwired max of 50 which can
+be;
+#X text 460 65 <- click this one...;
+#X text 617 64 altered by using 3rd creation argument up to 1000;
+#X text -48 178 original munger~;
+#X text -47 187 by Dan Trueman \,;
+#X text -46 81 disis_munger~ by;
+#X text -47 91 Ivica Ico Bukvic;
+#X text -47 101 and Ji-Sun Kim;
+#X text -46 110 with help from;
+#X text -47 120 Thomas Grill and;
+#X text -46 130 Dan Trueman;
+#X text -46 139 Virginia Tech;
+#X text -46 149 DISIS;
+#X text -46 157 disis.music.vt.edu;
+#X text -47 197 Computer Music;
+#X text -47 206 Center \, Columbia;
+#X text -47 214 University;
+#X text -44 4 disis_munger~;
+#X obj 247 363 *~ 88200;
+#X obj 339 259 samplerate~;
+#X obj 248 239 expr ($f2/$f1);
+#X obj 339 239 loadbang;
+#X floatatom 56 598 0 0 100 0 - - -;
+#N canvas 331 136 786 621 output 0;
+#X obj 455 510 t b;
+#X obj 455 450 f;
+#X obj 455 390 inlet;
+#X obj 455 540 f;
+#X msg 566 532 0;
+#X msg 455 420 bang;
+#X obj 455 480 moses 1;
+#X obj 566 502 t b f;
+#X obj 535 460 moses 1;
+#X obj 107 121 dbtorms;
+#X obj 95 227 inlet~;
+#X obj 250 258 inlet;
+#X msg 119 57 set \$1;
+#X obj 119 87 outlet;
+#X msg 250 309 \; pd dsp 1;
+#X obj 107 181 line~;
+#X obj 96 257 *~;
+#X obj 107 151 pack 0 50;
+#X text 23 205 audio in;
+#X text 2 313 out both channels;
+#X text 273 182 Level input. Send to master-lvl and start DSP (we infer
+that if you're changing the level you want to hear the network.) If
+you start DSP when it's already running there's no effect.;
+#X text 59 542 here is the previous nonzero master-lvl -->;
+#X text 98 451 recall previous value of master-lvl -->;
+#X text 239 482 test if less than 1 -->;
+#X text 203 510 if true convert to bang -->;
+#X text 218 351 Mute control. If the master level is zero \, restore
+to the last nonzero one \, otherwise zero it.;
+#X text 182 86 <-- update the number box to show new level;
+#X text 178 120 <-- convert from dB to linear units;
+#X text 196 150 <-- make a smooth ramp to avoid clicks or zipper noise
+;
+#X text 333 318 <-- automatically start DSP;
+#X obj 36 228 inlet~;
+#X obj 36 258 *~;
+#X obj 64 290 dac~;
+#X obj 35 346 send~ left;
+#X obj 97 346 send~ right;
+#X obj 107 27 r master-lvl-dry;
+#X obj 268 283 s master-lvl-dry;
+#X obj 535 430 r master-lvl-dry;
+#X obj 455 570 s master-lvl-dry;
+#X connect 0 0 3 0;
+#X connect 1 0 6 0;
+#X connect 2 0 5 0;
+#X connect 3 0 38 0;
+#X connect 4 0 38 0;
+#X connect 5 0 1 0;
+#X connect 6 0 0 0;
+#X connect 6 1 7 0;
+#X connect 7 0 4 0;
+#X connect 8 1 3 1;
+#X connect 9 0 17 0;
+#X connect 10 0 16 0;
+#X connect 11 0 14 0;
+#X connect 11 0 36 0;
+#X connect 12 0 13 0;
+#X connect 15 0 16 1;
+#X connect 15 0 31 1;
+#X connect 16 0 32 1;
+#X connect 16 0 34 0;
+#X connect 17 0 15 0;
+#X connect 30 0 31 0;
+#X connect 31 0 32 0;
+#X connect 31 0 33 0;
+#X connect 35 0 9 0;
+#X connect 35 0 12 0;
+#X connect 37 0 1 1;
+#X connect 37 0 8 0;
+#X restore 46 620 pd output;
+#X msg 81 598 mute;
+#X text 2 634 WET;
+#X text 63 634 DRY;
+#X obj -18 549 disis_munger~ 3000 8 500 default, f 62;
+#X connect 0 0 1 2;
+#X connect 1 0 0 0;
+#X connect 2 0 1 3;
+#X connect 58 0 59 0;
+#X connect 59 0 60 0;
+#X connect 60 0 61 0;
+#X connect 61 0 63 0;
+#X connect 63 0 64 0;
+#X connect 64 1 65 0;
+#X connect 65 0 66 0;
+#X connect 66 0 67 0;
+#X connect 66 0 68 0;
+#X connect 67 0 68 1;
+#X connect 68 0 69 0;
+#X connect 69 0 98 1;
+#X connect 71 0 90 0;
+#X connect 72 0 90 0;
+#X connect 73 0 74 0;
+#X connect 74 0 90 0;
+#X connect 75 0 90 0;
+#X connect 76 0 90 0;
+#X connect 77 0 78 0;
+#X connect 78 0 90 0;
+#X connect 79 0 90 0;
+#X connect 80 0 89 0;
+#X connect 81 0 89 0;
+#X connect 82 0 89 0;
+#X connect 83 0 89 0;
+#X connect 84 0 89 0;
+#X connect 85 0 89 0;
+#X connect 86 0 89 0;
+#X connect 87 0 89 0;
+#X connect 88 0 212 0;
+#X connect 91 0 98 0;
+#X connect 92 0 98 0;
+#X connect 93 0 98 0;
+#X connect 98 0 208 0;
+#X connect 98 0 208 1;
+#X connect 98 0 212 0;
+#X connect 99 0 100 0;
+#X connect 100 0 105 0;
+#X connect 101 0 108 0;
+#X connect 103 0 98 3;
+#X connect 105 0 101 0;
+#X connect 106 0 109 1;
+#X connect 106 0 110 0;
+#X connect 106 0 107 1;
+#X connect 107 0 203 0;
+#X connect 108 0 203 1;
+#X connect 108 0 205 0;
+#X connect 109 0 111 0;
+#X connect 110 0 109 0;
+#X connect 111 0 107 0;
+#X connect 113 0 91 0;
+#X connect 114 0 115 0;
+#X connect 116 0 114 0;
+#X connect 117 0 116 0;
+#X connect 118 0 98 2;
+#X connect 118 0 114 0;
+#X connect 121 0 72 0;
+#X connect 122 0 71 0;
+#X connect 123 0 151 0;
+#X connect 124 0 75 0;
+#X connect 125 0 79 0;
+#X connect 126 0 80 0;
+#X connect 127 0 81 0;
+#X connect 128 0 212 7;
+#X connect 129 0 212 6;
+#X connect 130 0 212 5;
+#X connect 131 0 212 4;
+#X connect 132 0 212 3;
+#X connect 133 0 212 2;
+#X connect 134 0 212 1;
+#X connect 135 0 89 0;
+#X connect 136 0 122 0;
+#X connect 136 0 121 0;
+#X connect 136 0 137 0;
+#X connect 136 0 123 0;
+#X connect 136 0 124 0;
+#X connect 136 0 125 0;
+#X connect 136 0 126 0;
+#X connect 136 0 127 0;
+#X connect 136 0 148 0;
+#X connect 136 0 166 0;
+#X connect 136 0 84 0;
+#X connect 136 0 76 0;
+#X connect 137 0 73 0;
+#X connect 137 0 77 0;
+#X connect 138 0 128 0;
+#X connect 138 0 129 0;
+#X connect 138 0 130 0;
+#X connect 138 0 131 0;
+#X connect 138 0 132 0;
+#X connect 138 0 133 0;
+#X connect 138 0 134 0;
+#X connect 140 0 144 0;
+#X connect 142 0 143 0;
+#X connect 143 0 141 0;
+#X connect 143 0 141 1;
+#X connect 144 0 139 0;
+#X connect 144 0 139 1;
+#X connect 145 0 142 0;
+#X connect 146 0 140 0;
+#X connect 147 0 90 0;
+#X connect 148 0 147 0;
+#X connect 151 0 90 0;
+#X connect 153 0 212 0;
+#X connect 154 0 153 0;
+#X connect 155 0 212 0;
+#X connect 156 0 173 0;
+#X connect 157 0 173 1;
+#X connect 166 0 89 0;
+#X connect 167 0 89 0;
+#X connect 172 0 167 0;
+#X connect 173 0 183 0;
+#X connect 174 0 212 0;
+#X connect 177 0 90 0;
+#X connect 183 0 212 0;
+#X connect 203 0 118 0;
+#X connect 204 0 205 1;
+#X connect 205 0 106 0;
+#X connect 206 0 204 0;
+#X connect 207 0 208 2;
+#X connect 208 0 207 0;
+#X connect 209 0 208 3;
+#X connect 212 0 1 0;
+#X connect 212 1 1 1;
+#X connect 212 2 163 0;
+#X connect 212 3 159 0;
+#X connect 212 4 160 0;
+#X connect 212 5 161 0;
+#X connect 212 6 162 0;
+#X connect 212 7 164 0;
diff --git a/externals/disis/makefile b/externals/disis/makefile
index d051162ee5a12262573850dbc51371c4b51ee26c..aa1bf9f47309e0d49324cff2c3f4acac3b9359da 100755
--- a/externals/disis/makefile
+++ b/externals/disis/makefile
@@ -3,6 +3,7 @@
 lib.name = disis
 
 class.sources = disis_phasor~.c
+disis_munger~.class.sources = disis_munger.c ADSR.c
 define forLinux
     class.sources += disis_netsend.c disis_netreceive.c
     disis_wiimote.class.sources = disis_wiimote.c
@@ -12,7 +13,7 @@ define forDarwin
     class.sources += disis_netsend.c disis_netreceive.c
 endef
 
-datafiles = disis_phasor~-help.pd disis_netsend-help.pd disis_netreceive-help.pd disis_wiimote-help.pd disis_wiimote_legacy.pd README patch_name-help.pd patch_name.pd disis-meta.pd
+datafiles = disis_munger~-help.pd disis_phasor~-help.pd disis_netsend-help.pd disis_netreceive-help.pd disis_wiimote-help.pd disis_wiimote_legacy.pd README patch_name-help.pd patch_name.pd disis-meta.pd
 
 # IMPORTANT! disis_wiimote requires a custom L2Ork version of cwiid library
 # For the time being we statically link to a L2Ork version of cwiid library
diff --git a/externals/pd-lua b/externals/pd-lua
new file mode 160000
index 0000000000000000000000000000000000000000..4816ca85fd1ed52d97acfd4e5a41b0b5ab11b029
--- /dev/null
+++ b/externals/pd-lua
@@ -0,0 +1 @@
+Subproject commit 4816ca85fd1ed52d97acfd4e5a41b0b5ab11b029
diff --git a/l2ork_addons/tar_em_up.sh b/l2ork_addons/tar_em_up.sh
index 87033e4829920382fa6ef78c6ae200036360026c..b8857396b8b2585781c419ddc4f934b0c62a442b 100755
--- a/l2ork_addons/tar_em_up.sh
+++ b/l2ork_addons/tar_em_up.sh
@@ -2,48 +2,66 @@
 # super-simplistic installer for l2ork things by Ivica Ico Bukvic <ico@vt.edu>
 # for info on L2Ork visit http://l2ork.music.vt.edu
 
+cleanup() {
+    # maybe we'd want to do some actual cleanup here
+    test $2 -ne 0 && echo "$0: $1: command failed with exit code $2, exiting now." && echo "$0: $1: $BASH_COMMAND"
+    exit $2
+}
+
+trap 'cleanup $LINENO $?' ERR
+
 if [ $# -eq 0 ] # should check for no arguments
 then
 	echo
 	echo "   Usage: ./tar_em_up.sh -option1 -option2 ..."
 	echo "   Options:"
-	echo "     -a    l2ork addon to the dev package"
-	echo "     -b    build a deb (incremental, all platforms)"
-	echo "     -B    build a deb (complete recompile)"
+	echo "     -b    build a Debian package (incremental)"
+	echo "     -B    build a Debian package (complete recompile)"
 	echo "     -c    core Pd source tarball"
-	echo "     -e    everything"
-	echo "     -f    full installer (incremental)"
-	echo "     -F    full installer (complete recompile)"
+	echo "     -f    full tarball installer (incremental)"
+	echo "     -F    full tarball installer (complete recompile)"
+	echo "     -k    keep previous build products"
+	echo "     -l    do a light build (only essential externals)"
 	echo "     -n    skip package creation (-bB, -fF)"
-	echo "     -R    build a Raspberry Pi deb (complete recompile)"
 	echo "     -r    build a Raspberry Pi deb (incremental)"
-	echo "     -w    install custom version of cwiid system-wide"
+	echo "     -R    build a Raspberry Pi deb (complete recompile)"
+	echo "     -t    auto-detect target (incremental)"
+	echo "     -T    auto-detect target (complete recompile)"
 	echo "     -X    build an OSX installer (dmg)"
 	echo "     -z    build a Windows installer (incremental)"
 	echo "     -Z    build a Windows installer (complete recompile)"
 	echo
-	echo "   For custom install locations do the following before"
-	echo "   running this script:"
+	echo "   The incremental options bypass Gem compilation. This saves"
+	echo "   (lots of) time, but the generated package will lack Gem"
+	echo "   unless it has already been built previously. NOTE: Building"
+	echo "   Gem is NOT supported on OSX right now."
+	echo
+	echo "   The -k (keep) option doesn't clean before compilation,"
+	echo "   preserving the build products from a previous run. This"
+	echo "   also saves time if the script has been run previously."
+	echo "   Not using this option forces a full recompile."
+	echo
+	echo "   For custom install locations and staged installations"
+	echo "   set the inst_dir environment variable as follows:"
 	echo
 	echo "           export inst_dir=/some/custom/location"
 	echo
 	exit 1
 fi
 
-addon=0
 deb=0
 core=0
 full=0
-sys_cwiid=0
 rpi=0
 pkg=1
 inno=0
 dmg=0
+any=0
+clean=1
+light=0
 
-while getopts ":abBcdefFnRruwXzZ" Option
+while getopts ":bBcfFklnRrTtXzZ" Option
 do case $Option in
-		a)		addon=1;;
-
 		b)		deb=1
 				inst_dir=${inst_dir:-/usr};;
 
@@ -52,14 +70,14 @@ do case $Option in
 
 		c)		core=1;;
 
-		e)		addon=1
-				core=1
-				full=1;;
-
 		f)		full=1;;
 
 		F)		full=2;;
 
+		k)		clean=0;;
+
+		l)		light=1;;
+
 		n)		pkg=0;;
 
 		R)		deb=2
@@ -70,8 +88,9 @@ do case $Option in
 				inst_dir=/usr
 				rpi=1;;
 
-		w)		sys_cwiid=1
-				;;
+		t)		any=1;;
+
+		T)		any=2;;
 
 		X)		dmg=1
 				inst_dir=/usr;;
@@ -88,6 +107,13 @@ done
 
 inst_dir=${inst_dir:-/usr/local}
 
+# configure a light build if requested
+if [ $light -gt 0 ]; then
+    export LIGHT=yes
+else
+    export LIGHT=
+fi
+
 export TAR_EM_UP_PREFIX=$inst_dir
 
 # Get the OS we're running under, normalized to names that can be used
@@ -96,14 +122,46 @@ export TAR_EM_UP_PREFIX=$inst_dir
 os=`uname | tr '[:upper:]' '[:lower:]'`
 if [[ $os == *"mingw32"* ]]; then
 	os=win
-fi
-if [[ $os == "darwin" ]]; then
+elif [[ $os == "darwin" ]]; then
 	os=osx
 fi
 
+# Auto-detect the platform and pick an appropriate build target.
+if [ $any -gt 0 ]; then
+	if [[ $os == "osx" ]]; then
+		dmg=1
+	elif [[ $os == "win" ]]; then
+		inno=$any
+	else
+		deb=$any
+		inst_dir=${inst_dir:-/usr}
+	fi
+fi
+
+# Make sure that we don't try to build a tarball on Mac or Windows (that's
+# part of packages/linux_make and hence only works on Linux), build a regular
+# package for the platform instead.
+if [ $full -gt 0 ]; then
+	if [[ $os == "osx" ]]; then
+		dmg=1
+		echo "Warning: tarball installer not supported on Mac, building a dmg installer instead."
+	elif [[ $os == "win" ]]; then
+		inno=$full
+		echo "Warning: tarball installer not supported on Windows, building a Windows installer instead."
+	fi
+	full=0
+fi
+
+# Automagically disable Debian packaging when the Debian packaging tools are
+# not available.
+if test $deb -gt 0 && test $pkg -gt 0 && ! test -x /usr/bin/dpkg-deb; then
+    pkg=0;
+    echo "Debian toolchain unavailable, Debian packaging disabled"
+fi
+
 # Fetch the nw.js binary if we haven't already. We want to fetch it even
 # for building with no libs, so we do it regardless of the options
-echo nwjs-sdk-v0.16.0-`uname | tr '[:upper:]' '[:lower:]'`
+#echo nwjs-sdk-v0.16.0-`uname | tr '[:upper:]' '[:lower:]'`
 if [ ! -d "../pd/nw/nw" ]; then
 	if [ `getconf LONG_BIT` -eq 32 ]; then
 		arch="ia32"
@@ -142,7 +200,7 @@ if [ ! -d "../pd/nw/nw" ]; then
 	nwjs_url=${nwjs_url}/$nwjs_filename
 	echo "Fetching the nwjs binary from"
 	echo "$nwjs_url"
-        wget -nv $nwjs_url || exit 1
+        wget -nv $nwjs_url
 	if [[ $os == "win" || $os == "osx" ]]; then
 		unzip $nwjs_filename
 	else
@@ -178,6 +236,8 @@ then
 	echo "core Pd..."
 	rm -f ../Pd-l2ork-`date +%Y%m%d`.tar.bz2 2> /dev/null
 	cd pd/src/
+	# make sure that Pd is configured before trying to package it
+	test -f config.h || (aclocal && autoconf && make -C ../../packages pd)
 	make clean
 	cd ../../
 	tar -jcf ./Pd-l2ork-`date +%Y%m%d`.tar.bz2 pd
@@ -188,38 +248,35 @@ then
 	echo "Pd-L2Ork full installer... IMPORTANT! To ensure you have the most up-to-date submodules, this process requires internet connection to pull sources from various repositories..."
 
 	if [ -d .git ]; then
-		# check if Gem submodule is empty, and if so do first init
-		if [ "$(ls -A Gem)" ]; then
-			git submodule update
-			#git submodule foreach git pull origin master
-		else
-			# init all submodules (only necessary the first time)
-			git submodule init
-			git submodule update
-			#git submodule foreach git pull origin master
-		fi
+		git submodule update --init
 	fi
 
 
 	if [ $full -eq 2 -o $deb -eq 2 -o $inno -eq 2 -o $dmg -eq 2 ]
 	then
-	#	echo "Since we are doing a complete recompile we are assuming we will need to install l2ork version of the cwiid library. You will need to remove any existing cwiid libraries manually as they will clash with this one. L2Ork version is fully backwards compatible while also offering unique features like full extension support including the passthrough mode. YOU SHOULD REMOVE EXISTING CWIID LIBRARIES PRIOR TO RUNNING THIS INSTALL... You will also have to enter sudo password to install these... Press any key to continue or CTRL+C to cancel install..."
-	#	read dummy
+		# We bypass -k when doing a full build for the first time, so
+		# that things are set up properly in preparation of the build.
+		if [ ! -f Gem/configure ]; then clean=1; fi
+		if [ $clean -eq 0 ]; then
+		cd externals
+		else
 		# clean files that may remain stuck even after doing global make clean (if any)
+		test $os == "osx" && make -C packages/darwin_app clean || true
 		cd externals/miXed
-		make clean
+		make clean || true # this may fail on 1st attempt
 		cd ../
-		make gem_clean
+		make gem_clean || true # this may fail on 1st attempt
 		cd ../Gem/src/
-		make distclean
+		make distclean || true # this may fail on 1st attempt
 		rm -rf ./.libs
 		rm -rf ./*/.libs
 		cd ../
-		make distclean
-		rm gemglutwindow.pd_linux
-		rm Gem.pd_linux
+		make distclean || true # this may fail on 1st attempt
+		rm -f gemglutwindow.pd_linux
+		rm -f Gem.pd_linux
 		aclocal
 		./autogen.sh
+		fi
 		export INCREMENTAL=""
 	else
 		cd Gem/
@@ -235,21 +292,25 @@ then
 	fi
 	if [ $full -gt 1 -o $deb -eq 2 -o $inno -eq 2 -o $dmg -eq 2 ]
 	then
-		make distclean
+		test $clean -ne 0 && make distclean || true
+		# Run `make git_version` *now* so that we already have
+		# s_stuff.h when we copy it below. XXXNOTE AG: The build seems
+		# to work just fine even when skipping all this, so why again
+		# is this needed?
+		test -f ../../pd/src/s_stuff.h || make -C .. git_version
 		cp ../../pd/src/g_all_guis.h ../../externals/build/include
 		cp ../../pd/src/g_canvas.h ../../externals/build/include
 		cp ../../pd/src/m_imp.h ../../externals/build/include
 		cp ../../pd/src/m_pd.h ../../externals/build/include
 		cp ../../pd/src/s_stuff.h ../../externals/build/include
-		cp ../../pd/src/t_tk.h ../../externals/build/include
-		cp ../../pd/src/g_all_guis.h ../../externals/build/include								
+		cp ../../pd/src/g_all_guis.h ../../externals/build/include
 		rm -rf build/
 	fi
 	if [ $rpi -eq 0 ]
 	then
 		echo "installing desktop version..."
-		cp -f debian/control.desktop debian/control
-		cp -f ../../l2ork_addons/flext/config-lnx-pd-gcc.txt.intel ../../externals/grill/trunk/flext/buildsys/config-lnx-pd-gcc.txt
+		test -f debian/control.desktop && cp -f debian/control.desktop debian/control
+		test -f ../../l2ork_addons/flext/config-lnx-pd-gcc.txt.intel && cp -f ../../l2ork_addons/flext/config-lnx-pd-gcc.txt.intel ../../externals/grill/trunk/flext/buildsys/config-lnx-pd-gcc.txt
 	else
 		echo "installing raspbian version..."
 		cp -f debian/control.raspbian debian/control
@@ -259,24 +320,24 @@ then
 	if [[ $os == "win" ]]; then
 		echo "Making Windows package..."
 		echo `pwd`
-		make install && make package
+		make install INCREMENTAL=$INCREMENTAL LIGHT=$LIGHT && make package
 	elif [[ $os == "osx" ]]; then
 		echo "Making OSX package (dmg)..."
 		echo `pwd`
 		make install && make package
 	else
+		# create images folder
+		mkdir -p ../../packages/linux_make/build$inst_dir/lib/pd-l2ork/extra/images
 		make install prefix=$inst_dir
 	fi
 	echo "copying pd-l2ork-specific externals..."
-	# create images folder
-	mkdir -p ../../packages/linux_make/build$inst_dir/lib/pd-l2ork/extra/images
 	# patch_name
 	# spectdelay
 	if [[ $os == "win" ]]; then
 		cd ../../l2ork_addons
 	elif [[ $os == "osx" ]]; then
 		cd ../../l2ork_addons
-	else
+	elif [ $light -eq 0 ]; then
 		cd ../../l2ork_addons/spectdelay/spectdelay~
 		./linux-install.sh
 		cp -f spectdelay~.pd_linux ../../../packages/linux_make/build$inst_dir/lib/pd-l2ork/extra
@@ -284,9 +345,11 @@ then
 		cp -f array* ../../../packages/linux_make/build$inst_dir/lib/pd-l2ork/extra
 		# return to l2ork_addons folder
 		cd ../../
+	else
+		cd ../../l2ork_addons
 	fi
 	# install raspberry pi externals (if applicable)
-	if [ $inno -eq 0 -a $dmg -eq 0 ]; then
+	if [ $inno -eq 0 -a $dmg -eq 0 -a $light -eq 0 ]; then
 		cd raspberry_pi
 		./makeall.sh
 		cp -f disis_gpio/disis_gpio.pd_linux ../../packages/linux_make/build$inst_dir/lib/pd-l2ork/extra
@@ -324,6 +387,7 @@ then
 		fi
 		elif [ $deb -gt 0 ]; then
 			make debstage prefix=$inst_dir
+			echo "Debian packaging skipped, build results can be found in packages/linux_make/build/."
 		fi
 		cd ../../
 	# move OSX dmg installer
@@ -334,14 +398,6 @@ then
 	fi
 fi
 
-if [ $addon -eq 1 ]
-then
-	echo "l2ork addons..."
-	rm -f ../l2ork_addons-`uname -m`-`date +%Y%m%d`.tar.bz2 2> /dev/null
-	#cp -rf /usr/local/lib/pd/* l2ork_addons/externals/
-	tar -jcf ../l2ork_addons-`uname -m`-`date +%Y%m%d`.tar.bz2 l2ork_addons
-fi
-
 cd l2ork_addons/
 
 echo "done."
diff --git a/packages/Makefile b/packages/Makefile
index f5c1f8c09b4b722fc579a73de66379500dda3d6d..d99f98331e9e7af826788c4032e7c160d8337285 100644
--- a/packages/Makefile
+++ b/packages/Makefile
@@ -193,7 +193,9 @@ devel_install: pd_devel_install
 #------------------------------------------------------------------------------
 # abstractions_install
 abstractions_install:
+ifneq ($(LIGHT),yes)
 	$(MAKE) -C $(abstractions_src) $(DEST_PATHS) install
+endif
 
 #------------------------------------------------------------------------------
 # extensions_install
@@ -204,7 +206,7 @@ extensions_install:
 #------------------------------------------------------------------------------
 # externals_install
 externals_install: 
-	$(MAKE) -C $(externals_src) $(DEST_PATHS) install
+	$(MAKE) -C $(externals_src) $(DEST_PATHS) install INCREMENTAL=$(INCREMENTAL) LIGHT=$(LIGHT)
 
 
 #------------------------------------------------------------------------------
@@ -373,12 +375,15 @@ doc_format:
 # AG: The set_version target is broken since it modifies m_pd.h in-place
 # during the build, which is a bad thing to do to files which are supposed to
 # be kept in a source code repository. Instead, we create s_stuff.h from
-# s_stuff.h.in, where the latter is kept in the repo and the former gets created
-# from the latter by substituting PD_BUILD_VERSION.
+# s_stuff.h.in, where the latter is kept in the repo and the former gets
+# created from the latter by substituting PD_BUILD_VERSION. NOTE: This may
+# fail if we're building in a static tarball snapshop of the repo, in which
+# case we assume that a pre-generated s_stuff.h is supplied.
 
 git_version: $(pd_src)/src/s_stuff.h.in
-	cd $(pd_src)/src/ && \
-	sed 's|^\(#define PD_BUILD_VERSION "\).*"|\1$(PD_BUILD_VERSION)"|' s_stuff.h.in > s_stuff.h
+	@test -d $(cvs_root_dir)/.git && cd $(pd_src)/src/ && \
+	sed 's|^\(#define PD_BUILD_VERSION "\).*"|\1$(PD_BUILD_VERSION)"|' s_stuff.h.in > s_stuff.h.new && \
+	(test -f s_stuff.h && diff -q s_stuff.h s_stuff.h.new > /dev/null && rm -f s_stuff.h.new && echo s_stuff.h unchanged || (rm -f s_stuff.h && mv s_stuff.h.new s_stuff.h)) || test -f $(pd_src)/src/s_stuff.h
 
 set_version:
 # change Pd's version number to reflect the extended build
@@ -419,9 +424,11 @@ clean: abstractions_clean doc_clean externals_clean pd_clean
 
 distclean: cruft_clean
 	$(MAKE) -C $(abstractions_src) distclean
-	$(MAKE) -C $(extensions_src) distclean
+	-$(MAKE) -C $(extensions_src) distclean
 	$(MAKE) -C $(externals_src) distclean
-	-$(MAKE) -C $(pd_src) distclean
+# Make sure that we don't remove the precious s_stuff.h file if we're building
+# outside of the repo.
+	-test -d $(cvs_root_dir)/.git && $(MAKE) -C $(pd_src) distclean || $(MAKE) -C $(pd_src) clean
 
 test_locations:
 	@echo "PD_VERSION: $(PD_VERSION)"
diff --git a/packages/darwin_app/Makefile b/packages/darwin_app/Makefile
index 86823d29e1d649ec59b47b812e969206c47b6599..631b88f72e84cdeb2ebf284d9e5e45aa96d0e3d4 100644
--- a/packages/darwin_app/Makefile
+++ b/packages/darwin_app/Makefile
@@ -155,6 +155,11 @@ readme_install:
 
 
 #------------------------------------------------------------------------------#
+ifeq ($(LIGHT),yes)
+default = light
+else
+default = default
+endif
 darwin_app_core: darwin_app_wrapper
 	$(MAKE) -C $(packages_src) $(DEST_PATHS) \
 		PD_CONFIGURE_FLAGS="--enable-jack=no --disable-fat" \
@@ -164,7 +169,7 @@ darwin_app_core: darwin_app_wrapper
 		ln -s bin Scripts
 # support for Info Panel Plugins mgmt
 	cd "$(PD_APP_CONTENTS)" && ln -s Resources/app.nw/extra Plugins
-	install -p -m0644 org.puredata.pd-l2ork.default.plist "$(PD_APP_CONTENTS)/Resources/"
+	install -p -m0644 org.puredata.pd-l2ork.$(default).plist "$(PD_APP_CONTENTS)/Resources/org.puredata.pd-l2ork.default.plist"
 # since Pd-vanilla on Mac OS X doesn't have an 'include/pd' folder,
 # Pd-extended will mimic Pd-vanilla's include/pd until Pd-vanilla gets one
 	ln -s pd-l2ork "$(PD_APP_CONTENTS)/Resources/app.nw/include/pd"
@@ -181,6 +186,7 @@ package: dmg
 
 VOLUME_NAME = Pd-l2ork
 dmg:
+	rm -f build.dmg
 	hdiutil create -format UDRW -fs HFS+ -srcfolder "$(BUILD_BASE)" \
 		-volname $(VOLUME_NAME) build.dmg
 # detach one with the same name first
@@ -209,6 +215,7 @@ dmg:
 		DESTDIR="/Volumes/$(VOLUME_NAME)/*.app/Contents/Resources" doc_format
 	chmod -R a-w /Volumes/$(VOLUME_NAME)/*.app/Contents/Resources
 	hdiutil detach `mount | grep $(VOLUME_NAME) | cut -d ' ' -f 1`
+	rm -f "$(PACKAGE_NAME).dmg"
 	hdiutil convert -format UDZO -o "$(PACKAGE_NAME).dmg" build.dmg
 	rm -f build.dmg
 # install license
diff --git a/packages/darwin_app/org.puredata.pd-l2ork.default.plist b/packages/darwin_app/org.puredata.pd-l2ork.default.plist
index 90c294358fe77df945743503b56ca8a1ca44b4e6..d9c49f88ada8e39ebffce67005a819770b808d5e 100644
--- a/packages/darwin_app/org.puredata.pd-l2ork.default.plist
+++ b/packages/darwin_app/org.puredata.pd-l2ork.default.plist
@@ -76,8 +76,10 @@
 	<string>disis</string>
 	<key>loadlib35</key>
 	<string>lyonpotpourri</string>
+	<key>loadlib36</key>
+	<string>pdlua</string>
 	<key>nloadlib</key>
-	<string>35</string>
+	<string>36</string>
 	<key>path1</key>
 	<string>/System/Library/Fonts</string>
 	<key>path2</key>
diff --git a/packages/darwin_app/org.puredata.pd-l2ork.light.plist b/packages/darwin_app/org.puredata.pd-l2ork.light.plist
new file mode 100644
index 0000000000000000000000000000000000000000..3844a60a0d825c980f8e55b6e1a4a1f647d631dc
--- /dev/null
+++ b/packages/darwin_app/org.puredata.pd-l2ork.light.plist
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>defeatrt</key>
+	<string>0</string>
+	<key>flags</key>
+	<string>-helppath ~/Library/Pd-l2ork -helppath /Library/Pd-l2ork</string>
+	<key>loadlib1</key>
+	<string>libdir</string>
+	<key>loadlib2</key>
+	<string>pddp</string>
+	<key>nloadlib</key>
+	<string>2</string>
+	<key>path1</key>
+	<string>/System/Library/Fonts</string>
+	<key>path2</key>
+	<string>/Library/Fonts</string>
+	<key>path3</key>
+	<string>~/Library/Fonts</string>
+	<key>path4</key>
+	<string>/usr/X11R6/lib/X11/fonts/TTF</string>
+	<key>path5</key>
+	<string>/System/Library/Frameworks/JavaVM.framework/Versions/1.5.0/Home/lib/fonts</string>
+	<key>npath</key>
+	<string>5</string>
+</dict>
+
+</plist>
+
diff --git a/packages/linux_make/Makefile b/packages/linux_make/Makefile
index e19036680c8c3a3060326ae41d7b32be703571cc..0f712cfa3301efafc6545577587b85dbd1aa6d06 100644
--- a/packages/linux_make/Makefile
+++ b/packages/linux_make/Makefile
@@ -72,6 +72,12 @@ install:
 
 PACKAGE_NAME = pd-l2ork-$(PD_VERSION)-`uname -m`
 
+ifeq ($(LIGHT),yes)
+default = light
+else
+default = default
+endif
+
 package: $(PACKAGE_TYPE)
 
 
@@ -83,10 +89,12 @@ tarbz2: installer_settings installer_makefile installer_readme
 
 # Any special staging for the "Burrito Supreme" installer goes here.
 debstage: $(bindir)
+ifneq ($(LIGHT),yes)
 # add K12 mode
 	cp -rf ../../l2ork_addons/K12/ $(DESTDIR)$(libpddir)/extra/
 # add arduino library
 	cp -rf ../../externals/hardware/arduino $(DESTDIR)$(libpddir)/extra/
+endif
 # free desktop menu, mime, and icon support
 # perhaps the icons should go in /usr/share/pixmaps like 'scribus'
 	install -d $(DESTDIR)/usr/share/icons/hicolor/128x128/apps
@@ -131,7 +139,7 @@ debstage: $(bindir)
 	install -d $(DESTDIR)/etc/pd-l2ork
 	ln -s -f $(libpddir)/default.settings \
 		$(DESTDIR)/etc/pd-l2ork/default.settings
-	install -p $(packages_src)/linux_make/default.settings $(DESTDIR)$(libpddir)
+	install -p $(packages_src)/linux_make/$(default).settings $(DESTDIR)$(libpddir)/default.settings
 # app window icon
 	#install -p $(packages_src)/linux_make/pd-l2ork.gif $(DESTDIR)$(libpddir)
 # emacs mode for .pd files
@@ -141,7 +149,9 @@ debstage: $(bindir)
 # Pd-related scripts
 	#install -p $(scripts_src)/pd-diff $(DESTDIR)$(bindir)
 
+ifeq ($(PACKAGE_TYPE),deb)
 deb: DEB_BUILD_ARCH := $(shell dpkg-architecture -qDEB_BUILD_ARCH)
+endif
 deb: DEB_PD_VERSION := $(shell echo $(PD_VERSION) | sed 's|\(.*\)-l2ork-\(.*\)|\1-\2|')
 deb: debstage
 # delete these since they are provided by the 'puredata-utils' and 'cyclist' package
@@ -185,7 +195,7 @@ installer_readme:
 		$(INSTALLER_README_FILE)
 
 installer_settings:
-	install -p $(packages_src)/linux_make/default.settings $(DESTDIR)$(libpddir)
+	install -p $(packages_src)/linux_make/$(default).settings $(DESTDIR)$(libpddir)/default.settings
 	# app window icon
 	# install -p $(packages_src)/linux_make/pd-l2ork.gif $(DESTDIR)$(libpddir)
 #	install -d $(DESTDIR)/usr/share/icons/hicolor/128x128/apps
diff --git a/packages/linux_make/default.settings b/packages/linux_make/default.settings
index 74d6891ad87b16165a660cce850d58523b1670c9..f5077065b559e8d2d435b2d8b968cdfa26fc1a8f 100644
--- a/packages/linux_make/default.settings
+++ b/packages/linux_make/default.settings
@@ -35,7 +35,8 @@ loadlib31: iem_anything
 loadlib32: ekext
 loadlib33: disis
 loadlib34: lyonpotpourri
-nloadlib: 34
+loadlib35: pdlua
+nloadlib: 35
 path1: /var/lib/defoma/x-ttcidfont-conf.d/dirs/TrueType
 path2: ~/pd-l2ork-externals
 path3: ~/L2Ork/PD/Abstractions
@@ -72,4 +73,5 @@ path33: /usr/lib/pd-l2ork/extra/flext
 path34: /usr/lib/pd-l2ork/extra/rjlib
 path35: /usr/lib/pd-l2ork/extra/disis
 path36: /usr/lib/pd-l2ork/extra/lyonpotpourri
-npath: 36
+path37: /usr/lib/pd-l2ork/extra/pdlua
+npath: 37
diff --git a/packages/linux_make/light.settings b/packages/linux_make/light.settings
new file mode 100644
index 0000000000000000000000000000000000000000..26c84749d09b7b4e0382238f5135a055add7ae06
--- /dev/null
+++ b/packages/linux_make/light.settings
@@ -0,0 +1,9 @@
+standardpath: 1
+verbose: 0
+defeatrt: 0
+loadlib1: libdir
+loadlib2: pddp
+nloadlib: 2
+path1: ~/pd-l2ork-externals
+path2: /usr/lib/pd-l2ork/extra/pddp
+npath: 2
diff --git a/packages/win32_inno/Makefile b/packages/win32_inno/Makefile
index 3d93c56815150b4537cb416d261644e5e9e62af5..348cc1a353d06656490e980151c0e26b884ee10c 100755
--- a/packages/win32_inno/Makefile
+++ b/packages/win32_inno/Makefile
@@ -27,7 +27,11 @@ DEST_PATHS = BUILDLAYOUT_DIR=$(BUILDLAYOUT_DIR) \
 				OPT_CFLAGS="$(OPT_CFLAGS)" \
 				UNAME=$(UNAME)
 
+ifeq ($(LIGHT),yes)
+PD_INNO_SETUP = pd-inno-light.iss
+else
 PD_INNO_SETUP = pd-inno.iss
+endif
 
 package:  $(PD_INNO_SETUP)
 ## this pops up the GUI app
@@ -43,8 +47,9 @@ endif
 	@echo "win32_inno install succeeded!"
 
 git_version: $(pd_src)/src/s_stuff.h.in
-	cd $(pd_src)/src/ && \
-	sed 's|^\(#define PD_BUILD_VERSION "\).*"|\1$(PD_BUILD_VERSION)"|' s_stuff.h.in > s_stuff.h
+	@cd $(pd_src)/src/ && \
+	sed 's|^\(#define PD_BUILD_VERSION "\).*"|\1$(PD_BUILD_VERSION)"|' s_stuff.h.in > s_stuff.h.new && \
+	(test -f s_stuff.h && diff -q s_stuff.h s_stuff.h.new > /dev/null && rm -f s_stuff.h.new && echo s_stuff.h unchanged || (rm -f s_stuff.h && mv s_stuff.h.new s_stuff.h))
 
 build_pd: git_version
 	cd $(pd_src)/src && $(MAKE) -f makefile.mingw
@@ -61,9 +66,13 @@ install: pd_install prebuilt_install lib_install exe_install
 
 
 prebuilt_install:
-	$(MAKE) -C $(packages_src) $(DEST_PATHS) extended_install
+	$(MAKE) -C $(packages_src) $(DEST_PATHS) extended_install INCREMENTAL=$(INCREMENTAL) LIGHT=$(LIGHT)
 	$(MAKE) -C $(packages_src) $(DEST_PATHS) doc_format
+ifeq ($(LIGHT),yes)
+	install -p pd-settings-light.reg $(DESTDIR)$(prefix)/pd-settings.reg
+else
 	install -p pd-settings.reg $(DESTDIR)$(prefix)
+endif
 
 #==============================================================================#
 #
@@ -94,6 +103,7 @@ lib_install:
 	install -p $(bin_src)/libvorbisenc-2.dll  $(DESTDIR)$(bindir)/
 	install -p $(bin_src)/libvorbisfile-3.dll  $(DESTDIR)$(bindir)/
 	install -p $(bin_src)/libmp3lame-0.dll  $(DESTDIR)$(bindir)/
+ifneq ($(LIGHT),yes)
 	# I think these two are needed for zexy/matchbox and zexy/regex
 	install -p $(bin_src)/libsystre-0.dll $(DESTDIR)$(bindir)/
 	install -p $(bin_src)/libtre-5.dll $(DESTDIR)$(bindir)/
@@ -126,6 +136,7 @@ lib_install:
 	-install -p $(DESTDIR)/extra/Gem/gem_model*.dll $(DESTDIR)$(bindir)/
 	-install -p $(DESTDIR)/extra/Gem/gem_record*.dll $(DESTDIR)$(bindir)/
 	-install -p $(DESTDIR)/extra/Gem/gem_video*.dll $(DESTDIR)$(bindir)/
+endif
 # these stay with pd.exe
 # if these are installed, include them in the build root
 	-install -p $(system32)/msvcp71.dll   $(DESTDIR)$(bindir)
@@ -134,12 +145,14 @@ lib_install:
 	install -p $(bin_src)/libwinpthread-1.dll $(DESTDIR)$(bindir)
 	install -p $(bin_src)/libgcc_s_dw2-1.dll $(DESTDIR)$(bindir)
 	install -p $(bin_src)/libstdc++-6.dll $(DESTDIR)$(bindir)
+ifneq ($(LIGHT),yes)
 # lyonpotpourri compiles its own shared lib. On Windows it needs to be
 # in the path of the pd executable in order to get loaded. (There's probably
 # also a way to add the external lib's path but I don't know how to do that.)
 	install -p $(DESTDIR)/extra/lyonpotpourri/liblyonpotpourri.dll $(DESTDIR)$(bindir)
 # fftease also uses a shared lib...
 	install -p $(DESTDIR)/extra/fftease/libfftease.dll $(DESTDIR)$(bindir)
+endif
 
 
 exe_install:
@@ -152,6 +165,9 @@ $(PD_INNO_SETUP): $(PD_INNO_SETUP).in
 		sed 's/PD_VERSION/$(PD_VERSION)/g' | \
 		sed 's/PD_BUILD_VERSION/$(PD_BUILD_VERSION)/g' > \
 		$(PD_INNO_SETUP)
+# in incremental builds the lib directory may not exist, in that case we need
+# to edit the setup file to prevent an inno-setup error
+	test -d $(DESTDIR)$(libdir) || sed -i -e 's/^Source: build\\lib/;Source: build\\lib/' $(PD_INNO_SETUP)
 #	start $(PD_INNO_SETUP)
 
 
diff --git a/packages/win32_inno/pd-inno-light.iss.in b/packages/win32_inno/pd-inno-light.iss.in
new file mode 100644
index 0000000000000000000000000000000000000000..b31855b5309a0a5ba55e0e4d055feda90115d31d
--- /dev/null
+++ b/packages/win32_inno/pd-inno-light.iss.in
@@ -0,0 +1,792 @@
+;
+;
+; This file is a template with packages/win32_inno/Makefile turns
+; into a proper .iss ISTool/Inno Setup file.  <hans@at.or.at>
+;
+;
+
+[Setup]
+AppName=Purr Data
+AppVerName=Purr Data PD_VERSION
+AppPublisher=purrdata.net
+AppPublisherURL=http://purrdata.net
+AppSupportURL=http://puredata.org/community/lists/
+AppUpdatesURL=http://puredata.org/downloads/
+DefaultDirName={pf}\Purr Data
+DefaultGroupName=Purr Data
+LicenseFile=..\gpl-3.0.txt
+DisableWelcomePage=no
+UninstallDisplayIcon={app}\lib\pdPatch_catGraphics.ico
+
+Compression=lzma/ultra
+ChangesAssociations=true
+OutputBaseFilename=Purr Data PD_VERSION
+AppCopyright=GNU GPL
+WizardImageFile=big_cat.bmp
+WizardImageStretch=no
+WizardSmallImageFile=small_cat.bmp
+[Tasks]
+; NOTE: The following entry contains English phrases ("Create a desktop icon" and "Additional icons"). You are free to translate them into another language if required.
+Name: desktopicon; Description: Create a &desktop icon; GroupDescription: Additional icons:; Flags: unchecked
+; NOTE: The following entry contains English phrases ("Create a Quick Launch icon" and "Additional icons"). You are free to translate them into another language if required.
+Name: quicklaunchicon; Description: Create a &Quick Launch icon; GroupDescription: Additional icons:; Flags: unchecked
+Name: fileassociations; Description: Reset File Associations
+Name: libs; Description: Reset Libraries and Paths
+
+[INI]
+Filename: {app}\pd.url; Section: InternetShortcut; Key: URL; String: http://purrdata.net
+Filename: {app}\asio4all.url; Section: InternetShortcut; Key: URL; String: http://asio4all.com
+Filename: {app}\puredata.url; Section: InternetShortcut; Key: URL; String: http://en.flossmanuals.net/puredata
+Filename: {app}\techniques.url; Section: InternetShortcut; Key: URL; String: http://crca.ucsd.edu/~msp/techniques.htm
+Filename: {app}\pd-tutorial.url; Section: InternetShortcut; Key: URL; String: http://www.pd-tutorial.com/
+
+[Icons]
+Name: {group}\Purr-Data; Filename: {app}\bin\pd.exe; IconFilename: {app}\lib\pd.ico; IconIndex: 0; WorkingDir: {app}
+Name: {group}\puredata.org; Filename: {app}\pd.url
+Name: {group}\ASIO4ALL; Filename: {app}\asio4all.url
+Name: {group}\Uninstall Purr-Data; Filename: {uninstallexe}
+Name: {userdesktop}\Purr-Data; Filename: {app}\bin\pd.exe; Tasks: desktopicon; IconFilename: {app}\lib\pd.ico; IconIndex: 0; WorkingDir: {app}
+Name: {userappdata}\Microsoft\Internet Explorer\Quick Launch\Purr-Data; Filename: {app}\bin\pd.exe; Tasks: quicklaunchicon; WorkingDir: {app}; IconFilename: {app}\lib\pd.ico; IconIndex: 0
+Name: {group}\Documentation\Pd Manual; Filename: {app}\doc\1.manual\index.htm
+Name: {group}\Documentation\Pd Drums Tutorial; Filename: {app}\doc\tutorials\footils\pddrums\pddrums.html
+Name: {group}\Documentation\Pure Data FLOSSmanual; Filename: {app}\puredata.url
+Name: {group}\Documentation\Programming Electronic Music in Pd; Filename: {app}\pd-tutorial.url
+Name: {group}\Documentation\Theory and Techniques of Electronic Music; Filename: {app}\techniques.url
+
+
+[Run]
+; NOTE: The following entry contains an English phrase ("Launch"). You are free to translate it into another language if required.
+;Filename: {app}\bin\pd.exe; Description: Launch Purr-Data; Flags: nowait postinstall skipifsilent
+; failed attempt at getting this url to open after the install is complete
+;Filename: rundll32 url.dll,FileProtocolHandler http://asio4all.com; Description: open ASIO4ALL website; Flags: nowait postinstall skipifsilent
+
+[UninstallDelete]
+Type: files; Name: {app}\pd.url
+Type: files; Name: {app}\asio4all.url
+Type: files; Name: {app}\puredata.url
+Type: files; Name: {app}\pd-tutorial.url
+Type: files; Name: {app}\techniques.url
+
+[Registry]
+Root: HKCR; SubKey: Purr.Data; ValueType: dword; ValueName: EditFlags; ValueData: $00000000; Flags: noerror uninsdeletekey; Tasks: fileassociations; Permissions: users-modify
+Root: HKCR; SubKey: Purr.Data; ValueType: dword; ValueName: BrowserFlags; ValueData: $00000008; Flags: uninsdeletekey noerror; Tasks: fileassociations
+Root: HKCR; SubKey: Purr.Data; ValueType: string; ValueData: Purr Data; Flags: uninsdeletekey noerror; Tasks: fileassociations
+Root: HKCR; SubKey: Purr.Data\DefaultIcon; ValueType: string; ValueData: {app}\lib\pdpatch.ico,0; Flags: createvalueifdoesntexist noerror; Tasks: fileassociations
+Root: HKCR; SubKey: Purr.Data\shell; ValueType: string; ValueData: open; Flags: noerror uninsdeletekey; Tasks: fileassociations
+Root: HKCR; SubKey: Purr.Data\shell\open\command; ValueType: string; ValueData: """{app}\bin\pd.exe"" -listdev ""%1"""; Flags: uninsdeletekey noerror; Tasks: fileassociations
+Root: HKCR; SubKey: .pd; ValueType: string; ValueData: Purr.Data; Flags: noerror uninsdeletekey; Tasks: fileassociations
+Root: HKCR; SubKey: .pd; ValueType: string; ValueName: Content Type; ValueData: text/plain; Flags: noerror uninsdeletekey; Tasks: fileassociations
+;
+; STARTHERE: add pd-inno_registry after this comment:
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: string; ValueName: flags; ValueData: ; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: string; ValueName: flags; ValueData: ; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: string; ValueName: loadlib1; ValueData: libdir; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: string; ValueName: loadlib1; ValueData: libdir; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: string; ValueName: loadlib2; ValueData: pddp; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: string; ValueName: loadlib2; ValueData: pddp; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: string; ValueName: nloadlib; ValueData: 2; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: string; ValueName: nloadlib; ValueData: 2; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib3; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib3; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib4; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib4; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib5; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib5; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib6; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib6; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib7; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib7; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib8; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib8; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib9; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib9; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib10; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib10; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib11; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib11; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib12; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib12; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib13; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib13; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib14; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib14; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib15; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib15; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib16; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib16; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib17; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib17; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib18; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib18; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib19; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib19; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib20; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib20; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib21; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib21; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib22; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib22; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib23; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib23; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib24; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib24; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib25; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib25; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib26; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib26; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib27; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib27; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib28; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib28; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib29; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib29; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib30; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib30; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib31; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib31; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib32; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib32; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib33; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib33; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib34; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib34; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib35; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib35; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib36; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib36; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib37; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib37; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib38; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib38; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib39; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib39; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib40; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib40; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib41; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib41; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib42; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib42; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib43; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib43; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib44; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib44; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib45; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib45; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib46; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib46; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib47; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib47; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib48; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib48; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib49; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib49; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib50; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib50; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib51; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib51; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib52; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib52; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib53; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib53; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib54; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib54; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib55; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib55; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib56; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib56; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib57; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib57; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib58; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib58; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib59; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib59; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib60; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib60; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib61; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib61; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib62; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib62; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib63; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib63; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib64; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib64; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib65; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib65; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib66; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib66; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib67; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib67; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib68; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib68; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib69; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib69; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib70; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib70; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib71; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib71; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib72; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib72; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib73; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib73; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib74; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib74; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib75; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib75; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib76; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib76; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib77; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib77; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib78; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib78; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib79; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib79; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib80; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib80; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib81; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib81; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib82; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib82; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib83; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib83; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib84; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib84; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib85; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib85; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib86; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib86; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib87; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib87; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib88; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib88; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib89; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib89; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib90; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib90; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib91; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib91; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib92; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib92; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib93; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib93; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib94; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib94; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib95; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib95; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib96; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib96; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib97; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib97; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib98; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib98; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib99; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib99; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib100; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib100; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: expandsz; ValueName: path1; ValueData: %SystemRoot%/Fonts; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: expandsz; ValueName: path1; ValueData: %SystemRoot%/Fonts; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path2; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path2; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path3; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path3; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path4; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path4; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path5; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path5; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path6; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path6; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path7; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path7; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path8; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path8; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path9; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path9; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path10; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path10; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path11; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path11; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path12; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path12; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path13; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path13; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path14; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path14; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path15; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path15; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path16; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path16; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path17; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path17; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path18; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path18; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path19; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path19; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path20; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path20; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path21; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path21; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path22; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path22; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path23; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path23; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path24; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path24; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path25; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path25; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path26; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path26; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path27; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path27; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path28; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path28; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path29; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path29; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path30; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path30; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path31; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path31; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path32; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path32; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path33; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path33; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path34; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path34; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path35; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path35; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path36; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path36; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path37; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path37; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path38; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path38; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path39; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path39; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path40; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path40; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path41; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path41; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path42; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path42; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path43; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path43; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path44; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path44; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path45; Tasks: libs; Flags: uninsdeletekey
+Root: HKCu; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path45; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path46; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path46; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path47; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path47; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path48; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path48; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path49; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path49; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path50; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path50; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path51; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path51; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path52; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path52; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path53; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path53; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path54; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path54; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path55; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path55; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path56; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path56; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path57; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path57; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path58; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path58; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path59; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path59; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path60; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path60; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path61; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path61; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path62; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path62; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path63; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path63; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path64; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path64; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path65; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path65; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path66; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path66; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path67; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path67; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path68; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path68; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path69; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path69; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path70; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path70; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path71; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path71; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path72; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path72; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path73; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path73; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path74; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path74; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path75; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path75; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path76; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path76; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path77; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path77; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path78; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path78; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path79; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path79; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path80; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path80; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path81; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path81; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path82; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path82; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path83; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path83; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path84; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path84; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path85; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path85; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path86; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path86; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path87; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path87; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path88; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path88; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path89; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path89; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path90; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path90; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path91; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path91; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path92; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path92; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path93; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path93; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path94; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path94; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path95; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path95; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path96; Tasks: libs; Flags: uninsdeletekey
+Root: HKCu; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path96; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path97; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path97; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path98; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path98; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path99; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path99; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path100; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path100; Tasks: libs; Flags: uninsdeletekey
+
+; ENDHERE: add pd-inno_registry before this comment:
+
+[_ISTool]
+Use7zip=true
+OutputExeFilename=Output\PACKAGE_NAME.exe
+
+[Files]
+; commented out lines have no files, so they give an error
+; NOTE: Don't use "Flags: ignoreversion" on any shared system files
+;
+;
+;-----------------------------------------------------------------------------
+; packages\win32_inno
+Source: pdpatch.ico; DestDir: {app}\lib
+Source: pdPatch_catGraphics.ico; DestDir: {app}\lib
+Source: pd.ico; DestDir: {app}\lib
+;
+;
+;-----------------------------------------------------------------------------
+; put pdsend and pdreceive in the System dir so that they are in the path
+;
+Source: build\bin\pdsend.exe; DestDir: {sys}; Flags: confirmoverwrite promptifolder
+Source: build\bin\pdreceive.exe; DestDir: {sys}; Flags: confirmoverwrite promptifolder
+; add Cyclone's cyclist.exe if it is present
+#ifexist "build\bin\cyclist.exe"
+Source: build\bin\cyclist.exe; DestDir: {sys}; Flags: confirmoverwrite promptifolder
+#endif
+;
+;
+;-----------------------------------------------------------------------------
+; MinGW Files
+; these are some helpful utilities from MinGW
+;
+; start.exe - like Mac OS X's 'open' command, allows you to open files and
+; URLs from the command line
+;Source: C:\msys\1.0\bin\start.exe; DestDir: {sys}; Flags: confirmoverwrite
+;
+;
+;-----------------------------------------------------------------------------
+; DejaVu Sans Mono Font Files
+; the files needed for the Pd-0.39.2-extended default font
+;Source: C:\WINDOWS\Fonts\DejaVuSans.ttf; DestDir: {fonts}; Flags: onlyifdoesntexist uninsneveruninstall; FontInstall: DejaVu Sans
+;Source: C:\WINDOWS\Fonts\DejaVuSans-Bold.ttf; DestDir: {fonts}; Flags: onlyifdoesntexist uninsneveruninstall; FontInstall: DejaVu Sans Bold
+;Source: C:\WINDOWS\Fonts\DejaVuSans-BoldOblique.ttf; DestDir: {fonts}; Flags: onlyifdoesntexist uninsneveruninstall; FontInstall: DejaVu Sans Bold Oblique
+;Source: C:\WINDOWS\Fonts\DejaVuSansMono.ttf; DestDir: {fonts}; Flags: onlyifdoesntexist uninsneveruninstall; FontInstall: DejaVu Sans Mono
+;Source: C:\WINDOWS\Fonts\DejaVuSansMono-Bold.ttf; DestDir: {fonts}; Flags: onlyifdoesntexist uninsneveruninstall; FontInstall: DejaVu Sans Mono Bold
+;Source: C:\WINDOWS\Fonts\DejaVuSansMono-BoldOblique.ttf; DestDir: {fonts}; Flags: onlyifdoesntexist uninsneveruninstall; FontInstall: DejaVu Sans Mono Bold Oblique
+;Source: C:\WINDOWS\Fonts\DejaVuSansMono-Oblique.ttf; DestDir: {fonts}; Flags: onlyifdoesntexist uninsneveruninstall; FontInstall: DejaVu Sans Mono Oblique
+;Source: C:\WINDOWS\Fonts\DejaVuSans-Oblique.ttf; DestDir: {fonts}; Flags: onlyifdoesntexist uninsneveruninstall; FontInstall: DejaVu Sans Oblique
+;Source: C:\WINDOWS\Fonts\DejaVuSerif.ttf; DestDir: {fonts}; Flags: onlyifdoesntexist uninsneveruninstall; FontInstall: DejaVu Serif
+;Source: C:\WINDOWS\Fonts\DejaVuSerif-Bold.ttf; DestDir: {fonts}; Flags: onlyifdoesntexist uninsneveruninstall; FontInstall: DejaVu Serif Bold
+; Inconsolata font
+;Source: C:\WINDOWS\Fonts\Inconsolata.otf; DestDir: {fonts}; Flags: onlyifdoesntexist uninsneveruninstall; FontInstall: Inconsolata
+;
+;
+;-----------------------------------------------------------------------------
+; build system files
+;
+;Source: build\doc\manuals\Pd\Welcome.html; DestDir: {app}; Flags: isreadme; Tasks:
+Source: build\doc\manuals\Pd\ReadMe.html; DestDir: {app}; Flags: isreadme
+;Source: build\doc\manuals\Pd\License.html; DestDir: {app}; Flags: isreadme
+;Source: build\doc\manuals\Pd\Pd-LICENSE.txt; DestDir: {app}; Flags: isreadme
+Source: build\pd-settings.reg; DestDir: {app}; Flags: ignoreversion
+Source: build\bin\*.*; DestDir: {app}\bin; Flags: ignoreversion confirmoverwrite recursesubdirs uninsremovereadonly
+Source: build\doc\*.*; DestDir: {app}\doc; Flags: ignoreversion confirmoverwrite recursesubdirs uninsremovereadonly; Attribs: readonly
+Source: build\extra\*.*; DestDir: {app}\extra; Flags: ignoreversion recursesubdirs uninsremovereadonly promptifolder; Attribs: readonly
+Source: build\include\*.*; DestDir: {app}\include; Flags: ignoreversion confirmoverwrite recursesubdirs uninsremovereadonly
+Source: build\lib\*.*; DestDir: {app}\lib; Flags: ignoreversion recursesubdirs
+;
+; DLLs
+;
+Source: build\bin\lib*.dll; DestDir: {sys}; Flags: restartreplace confirmoverwrite sharedfile
+#ifexist "build\msvcp71.dll"
+Source: build\msvcp71.dll; DestDir: {sys}; Flags: restartreplace uninsneveruninstall sharedfile
+#endif
+#ifexist "build\msvcr71.dll"
+Source: build\msvcr71.dll; DestDir: {sys}; Flags: restartreplace uninsneveruninstall sharedfile
+#endif
+;; build stuff is not included now
+;Source: build\portaudio\*.*; DestDir: {app}\portaudio; Flags: ignoreversion recursesubdirs
+;Source: build\src\*.*; DestDir: {app}\src; Flags: ignoreversion recursesubdirs
+;Source: build\tcl\*.*; DestDir: {app}\tcl; Flags: ignoreversion recursesubdirs
+
+[Code]
+function NextButtonClick(CurPageID: Integer): Boolean;
+var
+  ResultCode: Integer;
+begin
+  case CurPageID of
+    wpReady:
+      begin
+		if(FileExists(ExpandConstant('{app}\unins000.exe')) AND FileExists(ExpandConstant('{app}\bin\pd.exe'))) then begin
+			if MsgBox('Found a previous Version of Pure Data at ' + ExpandConstant('{app} ') + #13#13 'Do you want to uninstall it first? (recommended)', mbConfirmation, MB_YESNO) = idYes then begin
+			if not Exec(ExpandConstant('{app}\unins000.exe'), '', '', SW_SHOWNORMAL, ewWaitUntilTerminated, ResultCode) then
+            MsgBox('NextButtonClick:' #13#13 'The uninstall file could not be executed. ' + SysErrorMessage(ResultCode) + '.', mbError, MB_OK);
+			end;
+		end;
+        BringToFrontAndRestore();
+        MsgBox('NextButtonClick:' #13#13 'The normal installation will now start.', mbInformation, MB_OK);
+      end;
+  end;
+
+  Result := True;
+end;
+
diff --git a/packages/win32_inno/pd-inno.iss.in b/packages/win32_inno/pd-inno.iss.in
index 6b6733c04e14c2bea8ae2eee5f2b636b31567eab..420111fca98d489f0b11defff03c00b2b7baf8ab 100755
--- a/packages/win32_inno/pd-inno.iss.in
+++ b/packages/win32_inno/pd-inno.iss.in
@@ -1,82 +1,83 @@
-;
-;
-; This file is a template with packages/win32_inno/Makefile turns
-; into a proper .iss ISTool/Inno Setup file.  <hans@at.or.at>
-;
-;
-
-[Setup]
-AppName=Purr Data
-AppVerName=Purr Data PD_VERSION
-AppPublisher=purrdata.net
-AppPublisherURL=http://purrdata.net
-AppSupportURL=http://puredata.org/community/lists/
-AppUpdatesURL=http://puredata.org/downloads/
-DefaultDirName={pf}\Purr Data
-DefaultGroupName=Purr Data
-LicenseFile=..\gpl-3.0.txt
-DisableWelcomePage=no
-
-Compression=lzma/ultra
-ChangesAssociations=true
-OutputBaseFilename=Purr Data PD_VERSION
-AppCopyright=GNU GPL
-WizardImageFile=big_cat.bmp
-WizardImageStretch=no
-WizardSmallImageFile=small_cat.bmp
-[Tasks]
-; NOTE: The following entry contains English phrases ("Create a desktop icon" and "Additional icons"). You are free to translate them into another language if required.
-Name: desktopicon; Description: Create a &desktop icon; GroupDescription: Additional icons:; Flags: unchecked
-; NOTE: The following entry contains English phrases ("Create a Quick Launch icon" and "Additional icons"). You are free to translate them into another language if required.
-Name: quicklaunchicon; Description: Create a &Quick Launch icon; GroupDescription: Additional icons:; Flags: unchecked
-Name: fileassociations; Description: Reset File Associations
-Name: libs; Description: Reset Libraries and Paths
-
-[INI]
-Filename: {app}\pd.url; Section: InternetShortcut; Key: URL; String: http://purrdata.net
-Filename: {app}\asio4all.url; Section: InternetShortcut; Key: URL; String: http://asio4all.com
-Filename: {app}\puredata.url; Section: InternetShortcut; Key: URL; String: http://en.flossmanuals.net/puredata
-Filename: {app}\techniques.url; Section: InternetShortcut; Key: URL; String: http://crca.ucsd.edu/~msp/techniques.htm
-Filename: {app}\pd-tutorial.url; Section: InternetShortcut; Key: URL; String: http://www.pd-tutorial.com/
-
-[Icons]
-Name: {group}\Purr-Data; Filename: {app}\bin\pd.exe; IconFilename: {app}\lib\pd.ico; IconIndex: 0; WorkingDir: {app}
-Name: {group}\puredata.org; Filename: {app}\pd.url
-Name: {group}\ASIO4ALL; Filename: {app}\asio4all.url
-Name: {group}\Uninstall Purr-Data; Filename: {uninstallexe}
-Name: {userdesktop}\Purr-Data; Filename: {app}\bin\pd.exe; Tasks: desktopicon; IconFilename: {app}\lib\pd.ico; IconIndex: 0; WorkingDir: {app}
-Name: {userappdata}\Microsoft\Internet Explorer\Quick Launch\Purr-Data; Filename: {app}\bin\pd.exe; Tasks: quicklaunchicon; WorkingDir: {app}; IconFilename: {app}\lib\pd.ico; IconIndex: 0
-Name: {group}\Documentation\Pd Manual; Filename: {app}\doc\1.manual\index.htm
-Name: {group}\Documentation\Pd Drums Tutorial; Filename: {app}\doc\tutorials\footils\pddrums\pddrums.html
-Name: {group}\Documentation\Pure Data FLOSSmanual; Filename: {app}\puredata.url
-Name: {group}\Documentation\Programming Electronic Music in Pd; Filename: {app}\pd-tutorial.url
-Name: {group}\Documentation\Theory and Techniques of Electronic Music; Filename: {app}\techniques.url
-
-
-[Run]
-; NOTE: The following entry contains an English phrase ("Launch"). You are free to translate it into another language if required.
-;Filename: {app}\bin\pd.exe; Description: Launch Purr-Data; Flags: nowait postinstall skipifsilent
+;
+;
+; This file is a template with packages/win32_inno/Makefile turns
+; into a proper .iss ISTool/Inno Setup file.  <hans@at.or.at>
+;
+;
+
+[Setup]
+AppName=Purr Data
+AppVerName=Purr Data PD_VERSION
+AppPublisher=purrdata.net
+AppPublisherURL=http://purrdata.net
+AppSupportURL=http://puredata.org/community/lists/
+AppUpdatesURL=http://puredata.org/downloads/
+DefaultDirName={pf}\Purr Data
+DefaultGroupName=Purr Data
+LicenseFile=..\gpl-3.0.txt
+DisableWelcomePage=no
+UninstallDisplayIcon={app}\lib\pdPatch_catGraphics.ico
+
+Compression=lzma/ultra
+ChangesAssociations=true
+OutputBaseFilename=Purr Data PD_VERSION
+AppCopyright=GNU GPL
+WizardImageFile=big_cat.bmp
+WizardImageStretch=no
+WizardSmallImageFile=small_cat.bmp
+[Tasks]
+; NOTE: The following entry contains English phrases ("Create a desktop icon" and "Additional icons"). You are free to translate them into another language if required.
+Name: desktopicon; Description: Create a &desktop icon; GroupDescription: Additional icons:; Flags: unchecked
+; NOTE: The following entry contains English phrases ("Create a Quick Launch icon" and "Additional icons"). You are free to translate them into another language if required.
+Name: quicklaunchicon; Description: Create a &Quick Launch icon; GroupDescription: Additional icons:; Flags: unchecked
+Name: fileassociations; Description: Reset File Associations
+Name: libs; Description: Reset Libraries and Paths
+
+[INI]
+Filename: {app}\pd.url; Section: InternetShortcut; Key: URL; String: http://purrdata.net
+Filename: {app}\asio4all.url; Section: InternetShortcut; Key: URL; String: http://asio4all.com
+Filename: {app}\puredata.url; Section: InternetShortcut; Key: URL; String: http://en.flossmanuals.net/puredata
+Filename: {app}\techniques.url; Section: InternetShortcut; Key: URL; String: http://crca.ucsd.edu/~msp/techniques.htm
+Filename: {app}\pd-tutorial.url; Section: InternetShortcut; Key: URL; String: http://www.pd-tutorial.com/
+
+[Icons]
+Name: {group}\Purr-Data; Filename: {app}\bin\pd.exe; IconFilename: {app}\lib\pd.ico; IconIndex: 0; WorkingDir: {app}
+Name: {group}\puredata.org; Filename: {app}\pd.url
+Name: {group}\ASIO4ALL; Filename: {app}\asio4all.url
+Name: {group}\Uninstall Purr-Data; Filename: {uninstallexe}
+Name: {userdesktop}\Purr-Data; Filename: {app}\bin\pd.exe; Tasks: desktopicon; IconFilename: {app}\lib\pd.ico; IconIndex: 0; WorkingDir: {app}
+Name: {userappdata}\Microsoft\Internet Explorer\Quick Launch\Purr-Data; Filename: {app}\bin\pd.exe; Tasks: quicklaunchicon; WorkingDir: {app}; IconFilename: {app}\lib\pd.ico; IconIndex: 0
+Name: {group}\Documentation\Pd Manual; Filename: {app}\doc\1.manual\index.htm
+Name: {group}\Documentation\Pd Drums Tutorial; Filename: {app}\doc\tutorials\footils\pddrums\pddrums.html
+Name: {group}\Documentation\Pure Data FLOSSmanual; Filename: {app}\puredata.url
+Name: {group}\Documentation\Programming Electronic Music in Pd; Filename: {app}\pd-tutorial.url
+Name: {group}\Documentation\Theory and Techniques of Electronic Music; Filename: {app}\techniques.url
+
+
+[Run]
+; NOTE: The following entry contains an English phrase ("Launch"). You are free to translate it into another language if required.
+;Filename: {app}\bin\pd.exe; Description: Launch Purr-Data; Flags: nowait postinstall skipifsilent
 ; failed attempt at getting this url to open after the install is complete
-;Filename: rundll32 url.dll,FileProtocolHandler http://asio4all.com; Description: open ASIO4ALL website; Flags: nowait postinstall skipifsilent
-
-[UninstallDelete]
-Type: files; Name: {app}\pd.url
-Type: files; Name: {app}\asio4all.url
-Type: files; Name: {app}\puredata.url
-Type: files; Name: {app}\pd-tutorial.url
-Type: files; Name: {app}\techniques.url
-
-[Registry]
-Root: HKCR; SubKey: Purr.Data; ValueType: dword; ValueName: EditFlags; ValueData: $00000000; Flags: noerror uninsdeletekey; Tasks: fileassociations; Permissions: users-modify
-Root: HKCR; SubKey: Purr.Data; ValueType: dword; ValueName: BrowserFlags; ValueData: $00000008; Flags: uninsdeletekey noerror; Tasks: fileassociations
-Root: HKCR; SubKey: Purr.Data; ValueType: string; ValueData: Purr Data; Flags: uninsdeletekey noerror; Tasks: fileassociations
-Root: HKCR; SubKey: Purr.Data\DefaultIcon; ValueType: string; ValueData: {app}\lib\pdpatch.ico,0; Flags: createvalueifdoesntexist noerror; Tasks: fileassociations
-Root: HKCR; SubKey: Purr.Data\shell; ValueType: string; ValueData: open; Flags: noerror uninsdeletekey; Tasks: fileassociations
-Root: HKCR; SubKey: Purr.Data\shell\open\command; ValueType: string; ValueData: """{app}\bin\pd.exe"" -listdev ""%1"""; Flags: uninsdeletekey noerror; Tasks: fileassociations
-Root: HKCR; SubKey: .pd; ValueType: string; ValueData: Purr.Data; Flags: noerror uninsdeletekey; Tasks: fileassociations
-Root: HKCR; SubKey: .pd; ValueType: string; ValueName: Content Type; ValueData: text/plain; Flags: noerror uninsdeletekey; Tasks: fileassociations
-;
-; STARTHERE: add pd-inno_registry after this comment:
+;Filename: rundll32 url.dll,FileProtocolHandler http://asio4all.com; Description: open ASIO4ALL website; Flags: nowait postinstall skipifsilent
+
+[UninstallDelete]
+Type: files; Name: {app}\pd.url
+Type: files; Name: {app}\asio4all.url
+Type: files; Name: {app}\puredata.url
+Type: files; Name: {app}\pd-tutorial.url
+Type: files; Name: {app}\techniques.url
+
+[Registry]
+Root: HKCR; SubKey: Purr.Data; ValueType: dword; ValueName: EditFlags; ValueData: $00000000; Flags: noerror uninsdeletekey; Tasks: fileassociations; Permissions: users-modify
+Root: HKCR; SubKey: Purr.Data; ValueType: dword; ValueName: BrowserFlags; ValueData: $00000008; Flags: uninsdeletekey noerror; Tasks: fileassociations
+Root: HKCR; SubKey: Purr.Data; ValueType: string; ValueData: Purr Data; Flags: uninsdeletekey noerror; Tasks: fileassociations
+Root: HKCR; SubKey: Purr.Data\DefaultIcon; ValueType: string; ValueData: {app}\lib\pdpatch.ico,0; Flags: createvalueifdoesntexist noerror; Tasks: fileassociations
+Root: HKCR; SubKey: Purr.Data\shell; ValueType: string; ValueData: open; Flags: noerror uninsdeletekey; Tasks: fileassociations
+Root: HKCR; SubKey: Purr.Data\shell\open\command; ValueType: string; ValueData: """{app}\bin\pd.exe"" -listdev ""%1"""; Flags: uninsdeletekey noerror; Tasks: fileassociations
+Root: HKCR; SubKey: .pd; ValueType: string; ValueData: Purr.Data; Flags: noerror uninsdeletekey; Tasks: fileassociations
+Root: HKCR; SubKey: .pd; ValueType: string; ValueName: Content Type; ValueData: text/plain; Flags: noerror uninsdeletekey; Tasks: fileassociations
+;
+; STARTHERE: add pd-inno_registry after this comment:
 
 Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: string; ValueName: flags; ValueData: ; Tasks: libs; Flags: uninsdeletekey
 Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: string; ValueName: flags; ValueData: ; Tasks: libs; Flags: uninsdeletekey
@@ -183,8 +184,11 @@ Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: string; ValueName: loadlib33;
 Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: string; ValueName: loadlib34; ValueData: lyonpotpourri; Tasks: libs; Flags: uninsdeletekey
 Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: string; ValueName: loadlib34; ValueData: lyonpotpourri; Tasks: libs; Flags: uninsdeletekey
 
-Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: string; ValueName: nloadlib; ValueData: 34; Tasks: libs; Flags: uninsdeletekey
-Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: string; ValueName: nloadlib; ValueData: 34; Tasks: libs; Flags: uninsdeletekey
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: string; ValueName: loadlib35; ValueData: pdlua; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: string; ValueName: loadlib35; ValueData: pdlua; Tasks: libs; Flags: uninsdeletekey
+
+Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: string; ValueName: nloadlib; ValueData: 35; Tasks: libs; Flags: uninsdeletekey
+Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: string; ValueName: nloadlib; ValueData: 35; Tasks: libs; Flags: uninsdeletekey
 
 Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib36; Tasks: libs; Flags: uninsdeletekey
 Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: loadlib36; Tasks: libs; Flags: uninsdeletekey
@@ -681,107 +685,108 @@ Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path99; Task
 Root: HKLM; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path100; Tasks: libs; Flags: uninsdeletekey
 Root: HKCU; SubKey: SOFTWARE\Purr-Data; ValueType: none; ValueName: path100; Tasks: libs; Flags: uninsdeletekey
 
-; ENDHERE: add pd-inno_registry before this comment:
-
-[_ISTool]
-Use7zip=true
-OutputExeFilename=Output\PACKAGE_NAME.exe
-
-[Files]
-; commented out lines have no files, so they give an error
-; NOTE: Don't use "Flags: ignoreversion" on any shared system files
-;
-;
-;-----------------------------------------------------------------------------
-; packages\win32_inno
-Source: pdpatch.ico; DestDir: {app}\lib
-Source: pd.ico; DestDir: {app}\lib
-;
-;
-;-----------------------------------------------------------------------------
-; put pdsend and pdreceive in the System dir so that they are in the path
-;
-Source: build\bin\pdsend.exe; DestDir: {sys}; Flags: confirmoverwrite promptifolder
-Source: build\bin\pdreceive.exe; DestDir: {sys}; Flags: confirmoverwrite promptifolder
-; add Cyclone's cyclist.exe if it is present
-#ifexist "build\bin\cyclist.exe"
-Source: build\bin\cyclist.exe; DestDir: {sys}; Flags: confirmoverwrite promptifolder
-#endif
-;
-;
-;-----------------------------------------------------------------------------
-; MinGW Files
-; these are some helpful utilities from MinGW
-;
-; start.exe - like Mac OS X's 'open' command, allows you to open files and
-; URLs from the command line
-;Source: C:\msys\1.0\bin\start.exe; DestDir: {sys}; Flags: confirmoverwrite
-;
-;
-;-----------------------------------------------------------------------------
-; DejaVu Sans Mono Font Files
-; the files needed for the Pd-0.39.2-extended default font
-;Source: C:\WINDOWS\Fonts\DejaVuSans.ttf; DestDir: {fonts}; Flags: onlyifdoesntexist uninsneveruninstall; FontInstall: DejaVu Sans
-;Source: C:\WINDOWS\Fonts\DejaVuSans-Bold.ttf; DestDir: {fonts}; Flags: onlyifdoesntexist uninsneveruninstall; FontInstall: DejaVu Sans Bold
-;Source: C:\WINDOWS\Fonts\DejaVuSans-BoldOblique.ttf; DestDir: {fonts}; Flags: onlyifdoesntexist uninsneveruninstall; FontInstall: DejaVu Sans Bold Oblique
-;Source: C:\WINDOWS\Fonts\DejaVuSansMono.ttf; DestDir: {fonts}; Flags: onlyifdoesntexist uninsneveruninstall; FontInstall: DejaVu Sans Mono
-;Source: C:\WINDOWS\Fonts\DejaVuSansMono-Bold.ttf; DestDir: {fonts}; Flags: onlyifdoesntexist uninsneveruninstall; FontInstall: DejaVu Sans Mono Bold
-;Source: C:\WINDOWS\Fonts\DejaVuSansMono-BoldOblique.ttf; DestDir: {fonts}; Flags: onlyifdoesntexist uninsneveruninstall; FontInstall: DejaVu Sans Mono Bold Oblique
-;Source: C:\WINDOWS\Fonts\DejaVuSansMono-Oblique.ttf; DestDir: {fonts}; Flags: onlyifdoesntexist uninsneveruninstall; FontInstall: DejaVu Sans Mono Oblique
-;Source: C:\WINDOWS\Fonts\DejaVuSans-Oblique.ttf; DestDir: {fonts}; Flags: onlyifdoesntexist uninsneveruninstall; FontInstall: DejaVu Sans Oblique
-;Source: C:\WINDOWS\Fonts\DejaVuSerif.ttf; DestDir: {fonts}; Flags: onlyifdoesntexist uninsneveruninstall; FontInstall: DejaVu Serif
-;Source: C:\WINDOWS\Fonts\DejaVuSerif-Bold.ttf; DestDir: {fonts}; Flags: onlyifdoesntexist uninsneveruninstall; FontInstall: DejaVu Serif Bold
+; ENDHERE: add pd-inno_registry before this comment:
+
+[_ISTool]
+Use7zip=true
+OutputExeFilename=Output\PACKAGE_NAME.exe
+
+[Files]
+; commented out lines have no files, so they give an error
+; NOTE: Don't use "Flags: ignoreversion" on any shared system files
+;
+;
+;-----------------------------------------------------------------------------
+; packages\win32_inno
+Source: pdpatch.ico; DestDir: {app}\lib
+Source: pdPatch_catGraphics.ico; DestDir: {app}\lib
+Source: pd.ico; DestDir: {app}\lib
+;
+;
+;-----------------------------------------------------------------------------
+; put pdsend and pdreceive in the System dir so that they are in the path
+;
+Source: build\bin\pdsend.exe; DestDir: {sys}; Flags: confirmoverwrite promptifolder
+Source: build\bin\pdreceive.exe; DestDir: {sys}; Flags: confirmoverwrite promptifolder
+; add Cyclone's cyclist.exe if it is present
+#ifexist "build\bin\cyclist.exe"
+Source: build\bin\cyclist.exe; DestDir: {sys}; Flags: confirmoverwrite promptifolder
+#endif
+;
+;
+;-----------------------------------------------------------------------------
+; MinGW Files
+; these are some helpful utilities from MinGW
+;
+; start.exe - like Mac OS X's 'open' command, allows you to open files and
+; URLs from the command line
+;Source: C:\msys\1.0\bin\start.exe; DestDir: {sys}; Flags: confirmoverwrite
+;
+;
+;-----------------------------------------------------------------------------
+; DejaVu Sans Mono Font Files
+; the files needed for the Pd-0.39.2-extended default font
+;Source: C:\WINDOWS\Fonts\DejaVuSans.ttf; DestDir: {fonts}; Flags: onlyifdoesntexist uninsneveruninstall; FontInstall: DejaVu Sans
+;Source: C:\WINDOWS\Fonts\DejaVuSans-Bold.ttf; DestDir: {fonts}; Flags: onlyifdoesntexist uninsneveruninstall; FontInstall: DejaVu Sans Bold
+;Source: C:\WINDOWS\Fonts\DejaVuSans-BoldOblique.ttf; DestDir: {fonts}; Flags: onlyifdoesntexist uninsneveruninstall; FontInstall: DejaVu Sans Bold Oblique
+;Source: C:\WINDOWS\Fonts\DejaVuSansMono.ttf; DestDir: {fonts}; Flags: onlyifdoesntexist uninsneveruninstall; FontInstall: DejaVu Sans Mono
+;Source: C:\WINDOWS\Fonts\DejaVuSansMono-Bold.ttf; DestDir: {fonts}; Flags: onlyifdoesntexist uninsneveruninstall; FontInstall: DejaVu Sans Mono Bold
+;Source: C:\WINDOWS\Fonts\DejaVuSansMono-BoldOblique.ttf; DestDir: {fonts}; Flags: onlyifdoesntexist uninsneveruninstall; FontInstall: DejaVu Sans Mono Bold Oblique
+;Source: C:\WINDOWS\Fonts\DejaVuSansMono-Oblique.ttf; DestDir: {fonts}; Flags: onlyifdoesntexist uninsneveruninstall; FontInstall: DejaVu Sans Mono Oblique
+;Source: C:\WINDOWS\Fonts\DejaVuSans-Oblique.ttf; DestDir: {fonts}; Flags: onlyifdoesntexist uninsneveruninstall; FontInstall: DejaVu Sans Oblique
+;Source: C:\WINDOWS\Fonts\DejaVuSerif.ttf; DestDir: {fonts}; Flags: onlyifdoesntexist uninsneveruninstall; FontInstall: DejaVu Serif
+;Source: C:\WINDOWS\Fonts\DejaVuSerif-Bold.ttf; DestDir: {fonts}; Flags: onlyifdoesntexist uninsneveruninstall; FontInstall: DejaVu Serif Bold
 ; Inconsolata font
-;Source: C:\WINDOWS\Fonts\Inconsolata.otf; DestDir: {fonts}; Flags: onlyifdoesntexist uninsneveruninstall; FontInstall: Inconsolata
-;
-;
-;-----------------------------------------------------------------------------
-; build system files
-;
-;Source: build\doc\manuals\Pd\Welcome.html; DestDir: {app}; Flags: isreadme; Tasks:
-Source: build\doc\manuals\Pd\ReadMe.html; DestDir: {app}; Flags: isreadme
-;Source: build\doc\manuals\Pd\License.html; DestDir: {app}; Flags: isreadme
-;Source: build\doc\manuals\Pd\Pd-LICENSE.txt; DestDir: {app}; Flags: isreadme
-Source: build\pd-settings.reg; DestDir: {app}; Flags: ignoreversion
-Source: build\bin\*.*; DestDir: {app}\bin; Flags: ignoreversion confirmoverwrite recursesubdirs uninsremovereadonly
-Source: build\doc\*.*; DestDir: {app}\doc; Flags: ignoreversion confirmoverwrite recursesubdirs uninsremovereadonly; Attribs: readonly
-Source: build\extra\*.*; DestDir: {app}\extra; Flags: ignoreversion recursesubdirs uninsremovereadonly promptifolder; Attribs: readonly
-Source: build\include\*.*; DestDir: {app}\include; Flags: ignoreversion confirmoverwrite recursesubdirs uninsremovereadonly
-Source: build\lib\*.*; DestDir: {app}\lib; Flags: ignoreversion recursesubdirs
-;
-; DLLs
-;
-Source: build\bin\lib*.dll; DestDir: {sys}; Flags: restartreplace confirmoverwrite sharedfile
-#ifexist "build\msvcp71.dll"
-Source: build\msvcp71.dll; DestDir: {sys}; Flags: restartreplace uninsneveruninstall sharedfile
-#endif
-#ifexist "build\msvcr71.dll"
-Source: build\msvcr71.dll; DestDir: {sys}; Flags: restartreplace uninsneveruninstall sharedfile
-#endif
-;; build stuff is not included now
-;Source: build\portaudio\*.*; DestDir: {app}\portaudio; Flags: ignoreversion recursesubdirs
-;Source: build\src\*.*; DestDir: {app}\src; Flags: ignoreversion recursesubdirs
-;Source: build\tcl\*.*; DestDir: {app}\tcl; Flags: ignoreversion recursesubdirs
-
-[Code]
-function NextButtonClick(CurPageID: Integer): Boolean;
-var
-  ResultCode: Integer;
-begin
-  case CurPageID of
-    wpReady:
-      begin
-		if(FileExists(ExpandConstant('{app}\unins000.exe')) AND FileExists(ExpandConstant('{app}\bin\pd.exe'))) then begin
-			if MsgBox('Found a previous Version of Pure Data at ' + ExpandConstant('{app} ') + #13#13 'Do you want to uninstall it first? (recommended)', mbConfirmation, MB_YESNO) = idYes then begin
-			if not Exec(ExpandConstant('{app}\unins000.exe'), '', '', SW_SHOWNORMAL, ewWaitUntilTerminated, ResultCode) then
-            MsgBox('NextButtonClick:' #13#13 'The uninstall file could not be executed. ' + SysErrorMessage(ResultCode) + '.', mbError, MB_OK);
-			end;
-		end;
-        BringToFrontAndRestore();
-        MsgBox('NextButtonClick:' #13#13 'The normal installation will now start.', mbInformation, MB_OK);
-      end;
-  end;
-
-  Result := True;
-end;
-
+;Source: C:\WINDOWS\Fonts\Inconsolata.otf; DestDir: {fonts}; Flags: onlyifdoesntexist uninsneveruninstall; FontInstall: Inconsolata
+;
+;
+;-----------------------------------------------------------------------------
+; build system files
+;
+;Source: build\doc\manuals\Pd\Welcome.html; DestDir: {app}; Flags: isreadme; Tasks:
+Source: build\doc\manuals\Pd\ReadMe.html; DestDir: {app}; Flags: isreadme
+;Source: build\doc\manuals\Pd\License.html; DestDir: {app}; Flags: isreadme
+;Source: build\doc\manuals\Pd\Pd-LICENSE.txt; DestDir: {app}; Flags: isreadme
+Source: build\pd-settings.reg; DestDir: {app}; Flags: ignoreversion
+Source: build\bin\*.*; DestDir: {app}\bin; Flags: ignoreversion confirmoverwrite recursesubdirs uninsremovereadonly
+Source: build\doc\*.*; DestDir: {app}\doc; Flags: ignoreversion confirmoverwrite recursesubdirs uninsremovereadonly; Attribs: readonly
+Source: build\extra\*.*; DestDir: {app}\extra; Flags: ignoreversion recursesubdirs uninsremovereadonly promptifolder; Attribs: readonly
+Source: build\include\*.*; DestDir: {app}\include; Flags: ignoreversion confirmoverwrite recursesubdirs uninsremovereadonly
+Source: build\lib\*.*; DestDir: {app}\lib; Flags: ignoreversion recursesubdirs
+;
+; DLLs
+;
+Source: build\bin\lib*.dll; DestDir: {sys}; Flags: restartreplace confirmoverwrite sharedfile
+#ifexist "build\msvcp71.dll"
+Source: build\msvcp71.dll; DestDir: {sys}; Flags: restartreplace uninsneveruninstall sharedfile
+#endif
+#ifexist "build\msvcr71.dll"
+Source: build\msvcr71.dll; DestDir: {sys}; Flags: restartreplace uninsneveruninstall sharedfile
+#endif
+;; build stuff is not included now
+;Source: build\portaudio\*.*; DestDir: {app}\portaudio; Flags: ignoreversion recursesubdirs
+;Source: build\src\*.*; DestDir: {app}\src; Flags: ignoreversion recursesubdirs
+;Source: build\tcl\*.*; DestDir: {app}\tcl; Flags: ignoreversion recursesubdirs
+
+[Code]
+function NextButtonClick(CurPageID: Integer): Boolean;
+var
+  ResultCode: Integer;
+begin
+  case CurPageID of
+    wpReady:
+      begin
+		if(FileExists(ExpandConstant('{app}\unins000.exe')) AND FileExists(ExpandConstant('{app}\bin\pd.exe'))) then begin
+			if MsgBox('Found a previous Version of Pure Data at ' + ExpandConstant('{app} ') + #13#13 'Do you want to uninstall it first? (recommended)', mbConfirmation, MB_YESNO) = idYes then begin
+			if not Exec(ExpandConstant('{app}\unins000.exe'), '', '', SW_SHOWNORMAL, ewWaitUntilTerminated, ResultCode) then
+            MsgBox('NextButtonClick:' #13#13 'The uninstall file could not be executed. ' + SysErrorMessage(ResultCode) + '.', mbError, MB_OK);
+			end;
+		end;
+        BringToFrontAndRestore();
+        MsgBox('NextButtonClick:' #13#13 'The normal installation will now start.', mbInformation, MB_OK);
+      end;
+  end;
+
+  Result := True;
+end;
+
diff --git a/packages/win32_inno/pd-settings-light.reg b/packages/win32_inno/pd-settings-light.reg
new file mode 100644
index 0000000000000000000000000000000000000000..483722c20e0cb14a89f209360c90294b1ae990c0
--- /dev/null
+++ b/packages/win32_inno/pd-settings-light.reg
@@ -0,0 +1,209 @@
+Windows Registry Editor Version 5.00
+
+[HKEY_LOCAL_MACHINE\SOFTWARE\Pd-extended]
+"flags"=""
+"loadlib1"="libdir"
+"loadlib2"="pddp"
+"nloadlib"=2
+; delete any previous loadlib flags
+"loadlib3"=-
+"loadlib4"=-
+"loadlib5"=-
+"loadlib6"=-
+"loadlib7"=-
+"loadlib8"=-
+"loadlib9"=-
+"loadlib10"=-
+"loadlib11"=-
+"loadlib12"=-
+"loadlib13"=-
+"loadlib14"=-
+"loadlib15"=-
+"loadlib16"=-
+"loadlib17"=-
+"loadlib18"=-
+"loadlib19"=-
+"loadlib20"=-
+"loadlib21"=-
+"loadlib22"=-
+"loadlib23"=-
+"loadlib24"=-
+"loadlib25"=-
+"loadlib26"=-
+"loadlib27"=-
+"loadlib28"=-
+"loadlib29"=-
+"loadlib30"=-
+"loadlib31"=-
+"loadlib32"=-
+"loadlib33"=-
+"loadlib34"=-
+"loadlib35"=-
+"loadlib36"=-
+"loadlib37"=-
+"loadlib38"=-
+"loadlib39"=-
+"loadlib40"=-
+"loadlib41"=-
+"loadlib42"=-
+"loadlib43"=-
+"loadlib44"=-
+"loadlib45"=-
+"loadlib46"=-
+"loadlib47"=-
+"loadlib48"=-
+"loadlib49"=-
+"loadlib50"=-
+"loadlib51"=-
+"loadlib52"=-
+"loadlib53"=-
+"loadlib54"=-
+"loadlib55"=-
+"loadlib56"=-
+"loadlib57"=-
+"loadlib58"=-
+"loadlib59"=-
+"loadlib60"=-
+"loadlib61"=-
+"loadlib62"=-
+"loadlib63"=-
+"loadlib64"=-
+"loadlib65"=-
+"loadlib66"=-
+"loadlib67"=-
+"loadlib68"=-
+"loadlib69"=-
+"loadlib70"=-
+"loadlib71"=-
+"loadlib72"=-
+"loadlib73"=-
+"loadlib74"=-
+"loadlib75"=-
+"loadlib76"=-
+"loadlib77"=-
+"loadlib78"=-
+"loadlib79"=-
+"loadlib80"=-
+"loadlib81"=-
+"loadlib82"=-
+"loadlib83"=-
+"loadlib84"=-
+"loadlib85"=-
+"loadlib86"=-
+"loadlib87"=-
+"loadlib88"=-
+"loadlib89"=-
+"loadlib90"=-
+"loadlib91"=-
+"loadlib92"=-
+"loadlib93"=-
+"loadlib94"=-
+"loadlib95"=-
+"loadlib96"=-
+"loadlib97"=-
+"loadlib98"=-
+"loadlib99"=-
+"loadlib100"=-
+"path1"=hex(2):25,00,53,00,79,00,73,00,74,00,65,00,6d,00,52,00,6f,00,6f,00,74,00,25,00,2f,00,46,00,6f,00,6e,00,74,00,73,00,00,00
+"npath"=1
+; delete all existing path flags
+"path2"=-
+"path3"=-
+"path4"=-
+"path5"=-
+"path6"=-
+"path7"=-
+"path8"=-
+"path9"=-
+"path10"=-
+"path11"=-
+"path12"=-
+"path13"=-
+"path14"=-
+"path15"=-
+"path16"=-
+"path17"=-
+"path18"=-
+"path19"=-
+"path20"=-
+"path21"=-
+"path22"=-
+"path23"=-
+"path24"=-
+"path25"=-
+"path26"=-
+"path27"=-
+"path28"=-
+"path29"=-
+"path30"=-
+"path31"=-
+"path32"=-
+"path33"=-
+"path34"=-
+"path35"=-
+"path36"=-
+"path37"=-
+"path38"=-
+"path39"=-
+"path40"=-
+"path41"=-
+"path42"=-
+"path43"=-
+"path44"=-
+"path45"=-
+"path46"=-
+"path47"=-
+"path48"=-
+"path49"=-
+"path50"=-
+"path51"=-
+"path52"=-
+"path53"=-
+"path54"=-
+"path55"=-
+"path56"=-
+"path57"=-
+"path58"=-
+"path59"=-
+"path60"=-
+"path61"=-
+"path62"=-
+"path63"=-
+"path64"=-
+"path65"=-
+"path66"=-
+"path67"=-
+"path68"=-
+"path69"=-
+"path70"=-
+"path71"=-
+"path72"=-
+"path73"=-
+"path74"=-
+"path75"=-
+"path76"=-
+"path77"=-
+"path78"=-
+"path79"=-
+"path80"=-
+"path81"=-
+"path82"=-
+"path83"=-
+"path84"=-
+"path85"=-
+"path86"=-
+"path87"=-
+"path88"=-
+"path89"=-
+"path90"=-
+"path91"=-
+"path92"=-
+"path93"=-
+"path94"=-
+"path95"=-
+"path96"=-
+"path97"=-
+"path98"=-
+"path99"=-
+"path100"=-
+; delete all existing path flags
diff --git a/packages/win32_inno/pdPatch_catGraphics.ico b/packages/win32_inno/pdPatch_catGraphics.ico
new file mode 100644
index 0000000000000000000000000000000000000000..04921c65cfc6b75be80f995e0094112a7cbb42c5
Binary files /dev/null and b/packages/win32_inno/pdPatch_catGraphics.ico differ
diff --git a/pd/nw/dialog_prefs.html b/pd/nw/dialog_prefs.html
index e5b7d77533c670e2ae667a99b1aa02a73a7e29ad..8148d0d5c749a533cc7d968e4e14f0e75c7ff62b 100644
--- a/pd/nw/dialog_prefs.html
+++ b/pd/nw/dialog_prefs.html
@@ -302,6 +302,23 @@
               <input type="checkbox" id="save_zoom" name="save_zoom">
               <span data-i18n="prefs.gui.zoom.save_zoom"></span>
             </label>
+            <br/><br/>
+            <span data-i18n="prefs.gui.browser.browser_title"></span>
+            <br/>
+            <label data-i18n="[title]prefs.gui.browser.browser_doc_tt">
+              <input type="checkbox" id="browser_doc" name="browser_doc">
+              <span data-i18n="prefs.gui.browser.browser_doc"></span>
+            </label>
+            <br/>
+            <label data-i18n="[title]prefs.gui.browser.browser_path_tt">
+              <input type="checkbox" id="browser_path" name="browser_path">
+              <span data-i18n="prefs.gui.browser.browser_path"></span>
+            </label>
+            <br/>
+            <label data-i18n="[title]prefs.gui.browser.browser_init_tt">
+              <input type="checkbox" id="browser_init" name="browser_init">
+              <span data-i18n="prefs.gui.browser.browser_init"></span>
+            </label>
           </div>
         </div>
 
@@ -396,8 +413,8 @@ function get_gui_preset() {
     return document.getElementById("gui_preset").selectedOptions[0].value;
 }
 
-function get_save_zoom() {
-    return +document.getElementById("save_zoom").checked;
+function get_bool_elem(elem) {
+    return +document.getElementById(elem).checked;
 }
 
 // startup config data
@@ -606,9 +623,10 @@ function apply(save_prefs) {
         midi_use_alsa ? get_attr("midi-outdev-names", attrs).length : 0
     );
 
-    // Send the gui prefs (currently just the name of the gui preset and the
-    // status of the save-zoom toggle) to Pd
-    pdgui.pdsend("pd gui-prefs", get_gui_preset(), get_save_zoom());
+    // Send the gui prefs (currently just the name of the gui preset, the
+    // status of the save-zoom toggle and various options related to the help
+    // browser) to Pd
+    pdgui.pdsend("pd gui-prefs", get_gui_preset(), get_bool_elem("save_zoom"), get_bool_elem("browser_doc"), get_bool_elem("browser_path"), get_bool_elem("browser_init"));
 
     // Send the startup config data to Pd
     pdgui.pdsend.apply(null, ["pd path-dialog", startup_use_stdpath, startup_verbose].concat(get_path_array()));
@@ -847,7 +865,7 @@ function midi_prefs_callback(attrs) {
     pdgui.resize_window(pd_object_callback);
 }
 
-function gui_prefs_callback(name, save_zoom) {
+function gui_prefs_callback(name, save_zoom, browser_doc, browser_path, browser_init) {
     var s = document.getElementById("gui_preset"),
         i;
     for (i = 0; i < s.options.length; i++) {
@@ -857,6 +875,9 @@ function gui_prefs_callback(name, save_zoom) {
         }
     }
     document.getElementById("save_zoom").checked = !!save_zoom;
+    document.getElementById("browser_doc").checked = !!browser_doc;
+    document.getElementById("browser_path").checked = !!browser_path;
+    document.getElementById("browser_init").checked = !!browser_init;
 }
 
 // startup settings
diff --git a/pd/nw/dialog_search.html b/pd/nw/dialog_search.html
index 53d8e74abcf449940fe6dd2ab02914886d2a8771..19343356d190fb2ea7a896382bbbd5a90b5177be 100644
--- a/pd/nw/dialog_search.html
+++ b/pd/nw/dialog_search.html
@@ -4,27 +4,18 @@
     <link id="page_style" rel="stylesheet"
           type="text/css" href="css/default.css">
     <title>Pd Search Engine</title>
-    <script type="text/javascript" src="./elasticlunr.js"></script>
     <script type="text/javascript" src="./console_search.js"></script>
     <script>
 "use strict";
 var pdgui = require("./pdgui.js");
 var fs = require("fs");
 var path = require("path");
-var dive = require("./dive.js"); // small module to recursively search dirs
 var l = pdgui.get_local_string;
 
-var index = elasticlunr();
+var index;
 
 pdgui.skin.apply(window);
 
-index.addField("title");
-index.addField("keywords");
-index.addField("description");
-//index.addField("body");
-index.addField("path");
-index.setRef("id");
-
 var filetypes = [".pd", ".txt", ".htm", ".html", ".pdf"];
 
 // Table of Contents to start with
@@ -159,54 +150,6 @@ function translate_form() {
     }
 }
 
-function add_doc_to_index(filename, data) {
-    var title = path.basename(filename, ".pd"),
-        big_line = data.replace("\n", " "),
-        keywords,
-        desc;
-        // We use [\s\S] to match across multiple lines...
-        keywords = big_line
-            .match(/#X text \-?[0-9]+ \-?[0-9]+ KEYWORDS ([\s\S]*?);/i),
-        desc = big_line
-            .match(/#X text \-?[0-9]+ \-?[0-9]+ DESCRIPTION ([\s\S]*?);/i);
-        keywords = keywords && keywords.length > 1 ? keywords[1].trim() : null;
-        desc = desc && desc.length > 1 ? desc[1].trim() : null;
-        // Remove the Pd escapes for commas
-        desc = desc ? desc.replace(" \\,", ",") : null;
-        if (desc) {
-            // format Pd's "comma atoms" as normal commas
-            desc = desc.replace(" \\,", ",");
-        }
-    if (title.slice(-5) === "-help") {
-        title = title.slice(0, -5);
-    }
-    index.addDoc({
-        "id": filename,
-        "title": title,
-        "keywords": keywords,
-        "description": desc
-        //"body": big_line,
-    });
-}
-
-function read_file(err, filename, stat) {
-    if (!err) {
-        if (filename.slice(-3) === ".pd") {
-            fs.readFile(filename, { encoding: "utf8", flag: "r" },
-                function(read_err, data) {
-                    if (!read_err) {
-                        add_doc_to_index(filename, data);
-                    } else {
-                        pdgui.post("err: " + read_err);
-                    }
-                }
-            );
-        }
-    } else {
-        pdgui.post("err: " + err);
-    }
-}
-
 function click_toc(dir) {
     document.getElementById("search_text").value = dir;
     doc_search();
@@ -251,18 +194,13 @@ function display_toc() {
     });
 }
 
-function finish_build() {
+function finish_build(idx) {
+    index = idx;
     document.getElementById("search_text").disabled = false;
     clear_results();
     display_toc();
 }
 
-function build_index() {
-    var doc_path = path.join(pdgui.get_lib_dir(), "doc");
-    pdgui.post("doc path is " + doc_path);
-    dive(doc_path, read_file, finish_build);
-}
-
 function clear_results() {
     document.getElementById("results").innerHTML = "";
 }
@@ -528,7 +466,7 @@ function register_window_id(id, attrs) {
     document.getElementById("search_text").disabled = true;
     document.getElementById("file_browser").setAttribute("nwworkingdir",
         doc_path); // Probably need a doc getter in pdgui
-    build_index();
+    pdgui.build_index(finish_build);
 }
 
 function display_no_results() {
diff --git a/pd/nw/locales/de/translation.json b/pd/nw/locales/de/translation.json
index 6b0ea4e01febdba7a7e0ea4addc83c8668359a81..f382fa17c9889c466db4412024d44700bf72664e 100644
--- a/pd/nw/locales/de/translation.json
+++ b/pd/nw/locales/de/translation.json
@@ -407,6 +407,15 @@
       "zoom": {
         "save_zoom": "Speichern/Laden der Vergrößerung im Patch",
         "save_zoom_tt": "Speichere die aktuelle Vergrößerung mit dem Patch und stelle diese beim Laden des Patches wieder her"
+      },
+      "browser": {
+        "browser_title": "Hilfe-Browser-Einstellungen (WARNUNG: Änderungen können Startup-Zeiten beeinflussen!)",
+        "browser_doc": "Hilfe-Browser durchsucht nur den doc-Ordner",
+        "browser_doc_tt": "Der Hilfe-Browser durchkämmt nur Hilfe-Patches im doc-Ordner nach Suchbegriffen (schneller)",
+        "browser_path": "Hilfe-Browser durchsucht auch den Hilfe-Pfad",
+        "browser_path_tt": "Der Hilfe-Browser durchkämmt auch Hilfe-Patches im benutzerdefinierten Hilfe-Pfad nach Suchbegriffen (langsamer)",
+        "browser_init": "Erstelle den Hilfe-Index beim Programmstart",
+        "browser_init_tt": "Falls aktiviert, erstelle den Index für den Hilfe-Browser bereits beim Programmstart"
       }
     },
     "audio": {
diff --git a/pd/nw/locales/en/translation.json b/pd/nw/locales/en/translation.json
index 2032010d8526513fd8ca91f3dd4843836ed8a4cd..c779742a70f17f466865b89090416169b593fd64 100644
--- a/pd/nw/locales/en/translation.json
+++ b/pd/nw/locales/en/translation.json
@@ -408,6 +408,15 @@
       "zoom": {
         "save_zoom": "save/load zoom level with patch",
         "save_zoom_tt": "Save the current zoom level with the patch and restore it when reloading the patch"
+      },
+      "browser": {
+        "browser_title": "Help browser settings (WARNING: changing these may affect startup times!)",
+        "browser_doc": "help browser only searches the doc folder",
+        "browser_doc_tt": "Only scan help patches in the doc folder for searchable keywords (faster)",
+        "browser_path": "help browser also searches the help path",
+        "browser_path_tt": "Also scan help patches in the user-defined help path for searchable keywords (slower)",
+        "browser_init": "prepare the help index at application start",
+        "browser_init_tt": "If checked, prepare the index for the help browser already when the application starts"
       }
     },
     "audio": {
diff --git a/pd/nw/pdgui.js b/pd/nw/pdgui.js
index 08a1247482e13402eb9dae9da82be652d3526675..7f3bffa474585e25a182bf0d711651e32d1a29f3 100644
--- a/pd/nw/pdgui.js
+++ b/pd/nw/pdgui.js
@@ -2,6 +2,7 @@
 
 var pwd;
 var lib_dir;
+var help_path, browser_doc, browser_path, browser_init;
 var pd_engine_id;
 
 exports.set_pwd = function(pwd_string) {
@@ -26,6 +27,19 @@ exports.set_pd_engine_id = function (id) {
 
 exports.defunkify_windows_path = defunkify_windows_path;
 
+function gui_set_browser_config(doc_flag, path_flag, init_flag, helppath) {
+    // post("gui_set_browser_config: " + helppath.join(":"));
+    browser_doc = doc_flag;
+    browser_path = path_flag;
+    browser_init = init_flag;
+    help_path = helppath;
+    // AG: Start building the keyword index for dialog_search.html. We do this
+    // here so that we can be sure that lib_dir and help_path are known already.
+    // (This may also be deferred until the browser is launched for the first
+    // time, depending on the value of browser_init.)
+    if (browser_init == 1) make_index();
+}
+
 function gui_set_lib_dir(dir) {
     lib_dir = dir;
 }
@@ -60,10 +74,140 @@ exports.set_focused_patchwin = function(cid) {
     last_focused = cid;
 }
 
+// Keyword index (cf. dialog_search.html)
+
+var fs = require("fs");
+var path = require("path");
+var dive = require("./dive.js"); // small module to recursively search dirs
+var elasticlunr = require("./elasticlunr.js"); // lightweight full-text search engine in JavaScript, cf. https://github.com/weixsong/elasticlunr.js/
+
+var index = elasticlunr();
+
+index.addField("title");
+index.addField("keywords");
+index.addField("description");
+//index.addField("body");
+index.addField("path");
+index.setRef("id");
+
+function add_doc_to_index(filename, data) {
+    var title = path.basename(filename, ".pd"),
+        big_line = data.replace("\n", " "),
+        keywords,
+        desc;
+        // We use [\s\S] to match across multiple lines...
+        keywords = big_line
+            .match(/#X text \-?[0-9]+ \-?[0-9]+ KEYWORDS ([\s\S]*?);/i),
+        desc = big_line
+            .match(/#X text \-?[0-9]+ \-?[0-9]+ DESCRIPTION ([\s\S]*?);/i);
+        keywords = keywords && keywords.length > 1 ? keywords[1].trim() : null;
+        desc = desc && desc.length > 1 ? desc[1].trim() : null;
+        // Remove the Pd escapes for commas
+        desc = desc ? desc.replace(" \\,", ",") : null;
+        if (desc) {
+            // format Pd's "comma atoms" as normal commas
+            desc = desc.replace(" \\,", ",");
+        }
+    if (title.slice(-5) === "-help") {
+        title = title.slice(0, -5);
+    }
+    index.addDoc({
+        "id": filename,
+        "title": title,
+        "keywords": keywords,
+        "description": desc
+        //"body": big_line,
+    });
+}
+
+function read_file(err, filename, stat) {
+    if (!err) {
+        if (filename.slice(-3) === ".pd") {
+            // AG: We MUST read the files synchronously here. This might be a
+            // performance issue on some systems, but if we don't do this then
+            // we may open a huge number of files simultaneously, causing the
+            // process to run out of file handles.
+            try {
+                var data = fs.readFileSync(filename, { encoding: "utf8", flag: "r" });
+                add_doc_to_index(filename, data);
+            } catch (read_err) {
+                post("err: " + read_err);
+            }
+        }
+    } else {
+        // AG: Simply ignore missing/unreadable files and directories.
+        // post("err: " + err);
+    }
+}
+
+var index_done = false;
+var index_started = false;
+
+function finish_index() {
+    index_done = true;
+    post("finished building help index");
+}
+
+// AG: pilfered from https://stackoverflow.com/questions/21077670
+function expand_tilde(filepath) {
+    if (filepath[0] === '~') {
+        return path.join(process.env.HOME, filepath.slice(1));
+    }
+    return filepath;
+}
+
+// AG: This is supposed to be executed only once, after lib_dir has been set.
+// Note that dive() traverses lib_dir asynchronously, so we report back in
+// finish_index() when this is done.
+function make_index() {
+    var doc_path = browser_doc?path.join(lib_dir, "doc"):lib_dir;
+    var i = 0;
+    var l = help_path.length;
+    function make_index_cont() {
+        if (i < l) {
+            var doc_path = help_path[i++];
+            // AG: These paths might not exist, ignore them in this case. Also
+            // note that we need to expand ~ here.
+            var full_path = expand_tilde(doc_path);
+            fs.lstat(full_path, function(err, stat) {
+                if (!err) {
+                    post("building help index in " + doc_path);
+                    dive(full_path, read_file, make_index_cont);
+                } else {
+                    make_index_cont();
+                }
+            });
+        } else {
+            finish_index();
+        }
+    }
+    index_started = true;
+    post("building help index in " + doc_path);
+    dive(doc_path, read_file, browser_path?make_index_cont:finish_index);
+}
+
+// AG: This is called from dialog_search.html with a callback that expects to
+// receive the finished index as its sole argument. We also build the index
+// here if needed, using make_index, then simply wait until make_index
+// finishes and finally invoke the callback on the resulting index.
+function build_index(cb) {
+    function build_index_worker() {
+        if (index_done == true) {
+            cb(index);
+        } else {
+            setTimeout(build_index_worker, 500);
+        }
+    }
+    if (index_started == false) {
+        make_index();
+    }
+    build_index_worker();
+}
+
+exports.build_index = build_index;
+
 // Modules
 
-var fs = require("fs");     // for fs.existsSync
-var path = require("path"); // for path.dirname path.extname path.join
 var cp = require("child_process"); // for starting core Pd from GUI in OSX
 
 var parse_svg_path = require("./parse-svg-path.js");
@@ -4964,9 +5108,9 @@ function gui_midi_properties(gfxstub, sys_indevs, sys_outdevs,
     }
 }
 
-function gui_gui_properties(dummy, name, save_zoom) {
+function gui_gui_properties(dummy, name, save_zoom, browser_doc, browser_path, browser_init) {
     if (dialogwin["prefs"] !== null) {
-        dialogwin["prefs"].window.gui_prefs_callback(name, save_zoom);
+        dialogwin["prefs"].window.gui_prefs_callback(name, save_zoom, browser_doc, browser_path, browser_init);
     }
 }
 
diff --git a/pd/src/d_fftroutine.c b/pd/src/d_fftroutine.c
index 0222a0c006ac522e93e1334f4ea5e59cf13eab86..5c841f24a97f698c78a07879ea3743c6b05169bb 100644
--- a/pd/src/d_fftroutine.c
+++ b/pd/src/d_fftroutine.c
@@ -486,7 +486,7 @@ void load_registers(FFT_NET *fft_net, SAMPLE *buf, int buf_form,
 {
          int      *load_index = fft_net->load_index;
          SAMPLE *window;
-         int index, i = 0, n = fft_net->n;
+         int index, i = 0;
 
          if      (trnsfrm_dir==FORWARD)   window = fft_net->window;
          else if (trnsfrm_dir==INVERSE)   window = fft_net->inv_window;
@@ -617,7 +617,7 @@ void store_registers(FFT_NET    *fft_net, SAMPLE *buf, int buf_form,
 
 {
          int        i;
-         SAMPLE     real, imag, mag, phase;
+         SAMPLE     real, imag;
          int        n;
 
          i = 0;
@@ -992,7 +992,7 @@ void short_to_float(short *short_buf, float *float_buf, int n)
 void pd_fft(t_float *buf, int npoints, int inverse)
 {
   double renorm;
-  SAMPLE *fp, *fp2;
+  SAMPLE *fp;
   int i;
   renorm = (inverse ? npoints : 1.);
   cfft((inverse ? INVERSE : FORWARD), npoints, RECTANGULAR, 
diff --git a/pd/src/d_math.c b/pd/src/d_math.c
index 7b385c8bf9df003de5c2e03661ee70c289d9d4ba..c58eb31886026f3a2d0b0e018fcf53708bee3314 100644
--- a/pd/src/d_math.c
+++ b/pd/src/d_math.c
@@ -361,7 +361,7 @@ static t_int *ftom_tilde_perform(t_int *w)
 {
     t_sample *in = *(t_sample **)(w+1), *out = *(t_sample **)(w+2);
     t_int n = *(t_int *)(w+3);
-    for (; n--; *in++, out++)
+    for (; n--; in++, out++)
     {
         t_sample f = *in;
         *out = (f > 0 ? 17.3123405046 * log(.12231220585 * f) : -1500);
diff --git a/pd/src/d_soundfile.c b/pd/src/d_soundfile.c
index 85d6c573996e036014feea741717fafcb278dcd4..891c191a9a6430fccf0a97de69026f7a8ef4d2f7 100644
--- a/pd/src/d_soundfile.c
+++ b/pd/src/d_soundfile.c
@@ -231,7 +231,7 @@ int open_soundfile_via_fd(int fd, int headersize,
     int *p_bytespersamp, int *p_bigendian, int *p_nchannels, long *p_bytelimit,
     long skipframes)
 {
-    int format, nchannels, bigendian, bytespersamp, swap, sysrtn;
+    int nchannels, bigendian, bytespersamp, swap, sysrtn;
     long bytelimit = 0x7fffffff;
     errno = 0;
     if (headersize >= 0) /* header detection overridden */
@@ -1633,7 +1633,6 @@ static void *readsf_child_main(void *zz)
         }
         else if (x->x_requestcode == REQUEST_OPEN)
         {
-            char boo[80];
             int sysrtn, wantbytes;
             
                 /* copy file stuff out of the data structure so we can
@@ -1950,7 +1949,7 @@ static t_int *readsf_perform(t_int *w)
     t_sample *fp;
     if (x->x_state == STATE_STREAM)
     {
-        int wantbytes, nchannels, sfchannels = x->x_sfchannels;
+        int wantbytes, sfchannels = x->x_sfchannels;
         pthread_mutex_lock(&x->x_mutex);
         wantbytes = sfchannels * vecsize * bytespersample;
         while (
@@ -2189,14 +2188,10 @@ static void *writesf_child_main(void *zz)
         }
         else if (x->x_requestcode == REQUEST_OPEN)
         {
-            char boo[80];
             int fd, sysrtn, writebytes;
             
                 /* copy file stuff out of the data structure so we can
                 relinquish the mutex while we're in open_soundfile(). */
-            long onsetframes = x->x_onsetframes;
-            long bytelimit = 0x7fffffff;
-            int skipheaderbytes = x->x_skipheaderbytes;
             int bytespersample = x->x_bytespersample;
             int sfchannels = x->x_sfchannels;
             int bigendian = x->x_bigendian;
@@ -2360,7 +2355,6 @@ static void *writesf_child_main(void *zz)
             if (x->x_fd >= 0)
             {
                 int bytesperframe = x->x_bytespersample * x->x_sfchannels;
-                int bigendian = x->x_bigendian;
                 char *filename = x->x_filename;
                 int fd = x->x_fd;
                 int filetype = x->x_filetype;
@@ -2397,7 +2391,8 @@ static void *writesf_child_main(void *zz)
 
 /******** the object proper runs in the calling (parent) thread ****/
 
-static void writesf_tick(t_writesf *x);
+/* Not sure why this is declared here so commenting it out... */
+//static void writesf_tick(t_writesf *x);
 
 static void *writesf_new(t_floatarg fnchannels, t_floatarg fbufsize)
 {
diff --git a/pd/src/d_ugen.c b/pd/src/d_ugen.c
index da6c94aebe29b5cf588294741adb26a934e54067..5e9ea9bba8e739eabf337754ce83016bbedcfdc8 100644
--- a/pd/src/d_ugen.c
+++ b/pd/src/d_ugen.c
@@ -365,7 +365,7 @@ static t_signal *signal_freeborrowed;
     /* call this when DSP is stopped to free all the signals */
 void signal_cleanup(void)
 {
-    t_signal **svec, *sig, *sig2;
+    t_signal *sig;
     int i;
     while ((sig = pd_this->pd_signals))
     {
@@ -432,9 +432,8 @@ void signal_makereusable(t_signal *sig)
 
 t_signal *signal_new(int n, t_float sr)
 {
-    int logn, n2, vecsize = 0;
+    int logn, vecsize = 0;
     t_signal *ret, **whichlist;
-    t_sample *fp;
     logn = ilog2(n);
     if (n)
     {
@@ -566,8 +565,6 @@ t_signal *signal_newfromcontext(int borrowed)
 
 void ugen_stop(void)
 {
-    t_signal *s;
-    int i;
     if (pd_this->pd_dspchain)
     {
         freebytes(pd_this->pd_dspchain,
@@ -624,7 +621,6 @@ t_dspcontext *ugen_start_graph(int toplevel, t_signal **sp,
     int ninlets, int noutlets)
 {
     t_dspcontext *dc = (t_dspcontext *)getbytes(sizeof(*dc));
-    int parent_vecsize, vecsize;
 
     if (ugen_loud) post("ugen_start_graph...");
 
@@ -729,7 +725,7 @@ static void ugen_doit(t_dspcontext *dc, t_ugenbox *u)
 {
     t_sigoutlet *uout;
     t_siginlet *uin;
-    t_sigoutconnect *oc, *oc2;
+    t_sigoutconnect *oc;
     t_class *class = pd_class(&u->u_obj->ob_pd);
     int i, n;
         /* suppress creating new signals for the outputs of signal
@@ -882,7 +878,7 @@ static void ugen_doit(t_dspcontext *dc, t_ugenbox *u)
 
 void ugen_done_graph(t_dspcontext *dc)
 {
-    t_ugenbox *u, *u2;
+    t_ugenbox *u;
     t_sigoutlet *uout;
     t_siginlet *uin;
     t_sigoutconnect *oc, *oc2;
@@ -891,7 +887,7 @@ void ugen_done_graph(t_dspcontext *dc)
     t_dspcontext *parent_context = dc->dc_parentcontext;
     t_float parent_srate;
     int parent_vecsize;
-    int period, frequency, phase, vecsize, calcsize;
+    int period, frequency, vecsize, calcsize;
     t_float srate;
     int chainblockbegin;    /* DSP chain onset before block prolog code */
     int chainblockend;      /* and after block epilog code */
@@ -958,7 +954,6 @@ void ugen_done_graph(t_dspcontext *dc)
             (parent_vecsize * realoverlap * upsample);
         frequency = (parent_vecsize * realoverlap * upsample)/
             (vecsize * downsample);
-        phase = blk->x_phase;
         srate = parent_srate * realoverlap * upsample / downsample;
         if (period < 1) period = 1;
         if (frequency < 1) frequency = 1;
@@ -978,7 +973,6 @@ void ugen_done_graph(t_dspcontext *dc)
         calcsize = (parent_context ? parent_context->dc_calcsize : vecsize);
         downsample = upsample = 1;
         period = frequency = 1;
-        phase = 0;
         if (!parent_context) reblock = 1;
         switched = 0;
     }
@@ -1031,7 +1025,7 @@ void ugen_done_graph(t_dspcontext *dc)
 
         if (pd_class(zz) == vinlet_class)
             vinlet_dspprolog((struct _vinlet *)zz,
-                dc->dc_iosigs, vecsize, calcsize, dsp_phase, period, frequency,
+                insigs, vecsize, calcsize, dsp_phase, period, frequency,
                     downsample, upsample, reblock, switched);
         else if (pd_class(zz) == voutlet_class)
             voutlet_dspprolog((struct _voutlet *)zz,
diff --git a/pd/src/g_clone.c b/pd/src/g_clone.c
index 7ef9cd49f1aea7531bb8553af21447930a388012..ade8cddd5e9f789e103030608076bee555969e27 100644
--- a/pd/src/g_clone.c
+++ b/pd/src/g_clone.c
@@ -125,7 +125,7 @@ static void clone_in_set(t_in *x, t_floatarg f)
 
 static void clone_in_all(t_in *x, t_symbol *s, int argc, t_atom *argv)
 {
-    int phasewas = x->i_owner->x_phase, i;
+    int i;
     for (i = 0; i < x->i_owner->x_n; i++)
     {
         x->i_owner->x_phase = i;
@@ -145,7 +145,7 @@ static void clone_in_vis(t_in *x, t_floatarg fn, t_floatarg vis)
 
 static void clone_out_anything(t_out *x, t_symbol *s, int argc, t_atom *argv)
 {
-    t_atom *outv, *ap;
+    t_atom *outv;
     int first =
         1 + (s != &s_list && s != &s_float && s != &s_symbol && s != &s_bang),
             outc = argc + first;
diff --git a/pd/src/import.c b/pd/src/import.c
index 039dce878b1909b550028799a79832141d2f12a1..f04bf5facb418686b3376b7485c0386be0cd23d9 100644
--- a/pd/src/import.c
+++ b/pd/src/import.c
@@ -122,7 +122,6 @@ static void import_rewind(t_import* x)
 static void *import_new(t_symbol *s, int argc, t_atom *argv)
 {
     t_import *x = (t_import *)pd_new(import_class);
-    t_symbol *currentdir;
 
     x->x_data_outlet = outlet_new(&x->x_obj, &s_symbol);
     x->x_status_outlet = outlet_new(&x->x_obj, 0);
diff --git a/pd/src/m_binbuf.c b/pd/src/m_binbuf.c
index db7cbff15ac67ba864cc9cfaf6fea4b8141990b0..1b96e33d3ac05fecf798498b3277e80ce47a104c 100644
--- a/pd/src/m_binbuf.c
+++ b/pd/src/m_binbuf.c
@@ -687,7 +687,6 @@ void binbuf_eval(t_binbuf *x, t_pd *target, int argc, t_atom *argv)
     t_atom *at = x->b_vec;
     int ac = x->b_n;
     int nargs, maxnargs = 0;
-    int at_arg = 0;
 
     //first we need to check if the list of arguments has $@
     //fprintf(stderr,"=========\nbinbuf_eval argc:%d ac:%d\n", argc, (int)ac);
diff --git a/pd/src/m_class.c b/pd/src/m_class.c
index 00e8287826cf69f9973016b8a2830808928994da..a9ed52ad9c48003b6d2f5d8aba198242f5288041 100644
--- a/pd/src/m_class.c
+++ b/pd/src/m_class.c
@@ -601,16 +601,6 @@ t_symbol *gensym(const char *s)
     return(dogensym(s, 0));
 }
 
-static t_symbol *addfileextent(t_symbol *s)
-{
-    char namebuf[FILENAME_MAX], *str = s->s_name;
-    int ln = strlen(str);
-    if (!strcmp(str + ln - 3, ".pd")) return (s);
-    strcpy(namebuf, str);
-    strcpy(namebuf+ln, ".pd");
-    return (gensym(namebuf));
-}
-
 #define MAXOBJDEPTH 1000
 static int tryingalready;
 
diff --git a/pd/src/m_glob.c b/pd/src/m_glob.c
index 1f2b49bbff9a19718e87201fc7ea5aae765cf760..42e135d0de56f110f0356e33382bfd4b5916d787 100644
--- a/pd/src/m_glob.c
+++ b/pd/src/m_glob.c
@@ -75,18 +75,21 @@ static void glob_perf(t_pd *dummy, float f)
     sys_perf = (f != 0);
 }
 
-extern int sys_zoom;
+extern int sys_zoom, sys_browser_doc, sys_browser_path, sys_browser_init;
 extern t_symbol *sys_gui_preset;
-static void glob_gui_prefs(t_pd *dummy, t_symbol *s, float f)
+static void glob_gui_prefs(t_pd *dummy, t_symbol *s, float f, float f2, float f3, float f4)
 {
     sys_gui_preset = s;
     sys_zoom = !!(int)f;
+    sys_browser_doc = !!(int)f2;
+    sys_browser_path = !!(int)f3;
+    sys_browser_init = !!(int)f4;
 }
 
-/* just the gui-preset and the save-zoom toggle for now */
+/* just the gui-preset, the save-zoom toggle and various help browser options for now */
 static void glob_gui_properties(t_pd *dummy)
 {
-    gui_vmess("gui_gui_properties", "xsi", 0, sys_gui_preset->s_name, sys_zoom);
+    gui_vmess("gui_gui_properties", "xsiiii", 0, sys_gui_preset->s_name, sys_zoom, sys_browser_doc, sys_browser_path, sys_browser_init);
 }
 
 // ths one lives inside g_editor so that it can access the clipboard
@@ -167,10 +170,12 @@ void glob_init(void)
         gensym("version"), A_FLOAT, 0);
     class_addmethod(glob_pdobject, (t_method)glob_perf,
         gensym("perf"), A_FLOAT, 0);
+    class_addmethod(glob_pdobject, (t_method)glob_compatibility,
+        gensym("compatibility"), A_FLOAT, 0);
     class_addmethod(glob_pdobject, (t_method)glob_clipboard_text,
         gensym("clipboardtext"), A_FLOAT, 0);
     class_addmethod(glob_pdobject, (t_method)glob_gui_prefs,
-        gensym("gui-prefs"), A_SYMBOL, A_FLOAT, 0);
+        gensym("gui-prefs"), A_SYMBOL, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0);
     class_addmethod(glob_pdobject, (t_method)glob_gui_properties,
         gensym("gui-properties"), 0);
     class_addmethod(glob_pdobject, (t_method)glob_recent_files,
diff --git a/pd/src/m_pd.c b/pd/src/m_pd.c
index 0583c213c04eae1e7f5ecedc3836b9f2ccc52c08..04fed7e385918646cc911d1edd74e79e67344f91 100644
--- a/pd/src/m_pd.c
+++ b/pd/src/m_pd.c
@@ -3,6 +3,7 @@
 * WARRANTIES, see the file, "LICENSE.txt," in this distribution.  */
 
 #include <stdlib.h>
+#include <string.h>
 #include "m_pd.h"
 #include "m_imp.h"
 
diff --git a/pd/src/m_pd.h b/pd/src/m_pd.h
index 1c3467410abe59408a82b81e0273c678fd3e1d64..4972e75743e6473947639e9e14b46aab8d6ddd17 100644
--- a/pd/src/m_pd.h
+++ b/pd/src/m_pd.h
@@ -356,6 +356,7 @@ EXTERN void binbuf_restore(t_binbuf *x, int argc, t_atom *argv);
 EXTERN void binbuf_print(t_binbuf *x);
 EXTERN int binbuf_getnatom(t_binbuf *x);
 EXTERN t_atom *binbuf_getvec(t_binbuf *x);
+EXTERN int binbuf_resize(t_binbuf *x, int newsize);
 EXTERN void binbuf_eval(t_binbuf *x, t_pd *target, int argc, t_atom *argv);
 EXTERN int binbuf_read(t_binbuf *b, char *filename, char *dirname,
     int crflag);
diff --git a/pd/src/m_sched.c b/pd/src/m_sched.c
index b47e8a40f113fca6c4ed1637ba5fe5f854f16cf7..55c464c6e6f0f8ceb87c8e74cb174b83e38b53bb 100644
--- a/pd/src/m_sched.c
+++ b/pd/src/m_sched.c
@@ -220,7 +220,7 @@ static int sys_histphase;
 
 int sys_addhist(int phase)
 {
-    int i, j, phasewas = sys_histphase;
+    int j, phasewas = sys_histphase;
     double newtime = sys_getrealtime();
     int msec = (newtime - sys_histtime) * 1000.;
     for (j = NBIN-1; j >= 0; j--)
@@ -259,7 +259,7 @@ static char *(oss_errornames[]) = {
 
 void glob_audiostatus(void)
 {
-    int dev, nresync, nresyncphase, i;
+    int nresync, nresyncphase, i;
     nresync = (oss_nresync >= NRESYNC ? NRESYNC : oss_nresync);
     nresyncphase = oss_resyncphase - 1;
     post("audio I/O error history:");
diff --git a/pd/src/s_audio.c b/pd/src/s_audio.c
index d535928f3a996e83e10d2f585e66dd74312ef97e..6573adbf93153cde605b8a9726fe20472a426960 100644
--- a/pd/src/s_audio.c
+++ b/pd/src/s_audio.c
@@ -221,7 +221,7 @@ void sys_set_audio_settings(int naudioindev, int *audioindev, int nchindev,
     int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev,
     int *choutdev, int rate, int advance, int callback, int blocksize)
 {
-    int i, *ip;
+    int i;
     int defaultchannels = SYS_DEFAULTCH;
     int inchans, outchans, nrealindev, nrealoutdev;
     int realindev[MAXAUDIOINDEV], realoutdev[MAXAUDIOOUTDEV];
@@ -711,7 +711,7 @@ static void sys_listaudiodevs(void )
     /* start an audio settings dialog window */
 void glob_audio_properties(t_pd *dummy, t_floatarg flongform)
 {
-    char buf[1024 + 2 * MAXNDEV*(DEVDESCSIZE+4)];
+    //char buf[1024 + 2 * MAXNDEV*(DEVDESCSIZE+4)];
         /* these are the devices you're using: */
     int naudioindev, audioindev[MAXAUDIOINDEV], chindev[MAXAUDIOINDEV];
     int naudiooutdev, audiooutdev[MAXAUDIOOUTDEV], choutdev[MAXAUDIOOUTDEV];
@@ -774,10 +774,10 @@ void glob_audio_properties(t_pd *dummy, t_floatarg flongform)
     audiooutchan4 = (naudiooutdev > 3 ? choutdev[3] : 0);
 
 //    sprintf(buf,
-//"pdtk_audio_dialog %%s \
-//%d %d %d %d %d %d %d %d \
-//%d %d %d %d %d %d %d %d \
-//%d %d %d %d %d %d\n",
+//"pdtk_audio_dialog %%s "
+//"%d %d %d %d %d %d %d %d "
+//"%d %d %d %d %d %d %d %d "
+//"%d %d %d %d %d %d\n",
 //        audioindev1, audioindev2, audioindev3, audioindev4, 
 //        audioinchan1, audioinchan2, audioinchan3, audioinchan4, 
 //        audiooutdev1, audiooutdev2, audiooutdev3, audiooutdev4,
@@ -834,10 +834,7 @@ extern int pa_foo;
     /* new values from dialog window */
 void glob_audio_dialog(t_pd *dummy, t_symbol *s, int argc, t_atom *argv)
 {
-    int naudioindev, audioindev[MAXAUDIOINDEV], chindev[MAXAUDIOINDEV];
-    int naudiooutdev, audiooutdev[MAXAUDIOOUTDEV], choutdev[MAXAUDIOOUTDEV];
-    int rate, advance, audioon, i, nindev, noutdev;
-    int audioindev1, audioinchan1, audiooutdev1, audiooutchan1;
+    int i, nindev, noutdev;
     int newaudioindev[4], newaudioinchan[4],
         newaudiooutdev[4], newaudiooutchan[4];
         /* the new values the dialog came back with: */
@@ -1145,7 +1142,7 @@ int sys_audiodevnametonumber(int output, const char *name)
 void sys_audiodevnumbertoname(int output, int devno, char *name, int namesize)
 {
     char indevlist[MAXNDEV*DEVDESCSIZE], outdevlist[MAXNDEV*DEVDESCSIZE];
-    int nindevs = 0, noutdevs = 0, i, canmulti, cancallback;
+    int nindevs = 0, noutdevs = 0, canmulti, cancallback;
     if (devno < 0)
     {
         *name = 0;
diff --git a/pd/src/s_audio_alsa.c b/pd/src/s_audio_alsa.c
index 4726d004e3087b2faedd0bbbc332dddda0d286de..cb59b0966f7d29fbdc4773c6be4bb18d79575134 100644
--- a/pd/src/s_audio_alsa.c
+++ b/pd/src/s_audio_alsa.c
@@ -235,12 +235,10 @@ int alsa_open_audio(int naudioindev, int *audioindev, int nchindev,
     int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev,
     int *choutdev, int rate, int blocksize)
 {
-    int err, inchans = 0, outchans = 0, subunitdir;
+    int err, inchans = 0, outchans = 0;
     char devname[512];
-    snd_output_t* out;
     int frag_size = (blocksize ? blocksize : ALSA_DEFFRAGSIZE);
     int nfrags, i, iodev, dev2;
-    int wantinchans, wantoutchans, device;
 
     nfrags = sys_schedadvance * (float)rate / (1e6 * frag_size);
         /* save our belief as to ALSA's buffer size for later */
@@ -393,12 +391,12 @@ void alsa_close_audio(void)
 
 int alsa_send_dacs(void)
 {
+    static double timenow;
 #ifdef DEBUG_ALSA_XFER
     static int xferno = 0;
     static int callno = 0;
+    double timelast = timenow;
 #endif
-    static double timenow;
-    double timelast;
     t_sample *fp1, *fp2;
     int i, j, k, iodev, result, ch; 
     int chansintogo, chansouttogo;
@@ -414,7 +412,6 @@ int alsa_send_dacs(void)
     chansouttogo = sys_outchannels;
     transfersize = DEFDACBLKSIZE;
 
-    timelast = timenow;
     timenow = sys_getrealtime();
 
 #ifdef DEBUG_ALSA_XFER
diff --git a/pd/src/s_audio_oss.c b/pd/src/s_audio_oss.c
index f7f7a1934ab80ec9ee8a23a883c6817b3357411f..c2153ab353b5cb3d77cd435f84a5dd1f833bbeed 100644
--- a/pd/src/s_audio_oss.c
+++ b/pd/src/s_audio_oss.c
@@ -48,9 +48,6 @@ typedef int32_t t_oss_int32;
 #define OSS_XFERSIZE(chans, width) (DEFDACBLKSIZE * (chans) * (width))
 
 /* GLOBALS */
-static int linux_meters;        /* true if we're metering */
-static t_sample linux_inmax;       /* max input amplitude */
-static t_sample linux_outmax;      /* max output amplitude */
 static int linux_fragsize = 0;  /* for block mode; block size (sample frames) */
 extern int audio_blocksize;     /* stolen from s_audio.c */
 /* our device handles */
@@ -77,7 +74,6 @@ t_sample *sys_soundin;
 
     /* OSS-specific private variables */
 static int oss_blockmode = 1;   /* flag to use "blockmode"  */
-static char ossdsp[] = "/dev/dsp%d"; 
 
     /* don't assume we can turn all 31 bits when doing float-to-fix; 
     otherwise some audio drivers (e.g. Midiman/ALSA) wrap around. */
@@ -131,9 +127,8 @@ int oss_reset(int fd) {
 void oss_configure(t_oss_dev *dev, int srate, int dac, int skipblocksize,
     int suggestedblocksize)
 {
-    int orig, param, nblk, fd = dev->d_fd, wantformat;
+    int orig, param, fd = dev->d_fd, wantformat;
     int nchannels = dev->d_nchannels;
-    int advwas = sys_schedadvance;
 
     audio_buf_info ainfo;
 
@@ -272,10 +267,7 @@ int oss_open_audio(int nindev,  int *indev,  int nchin,  int *chin,
     char devname[20];
     int n, i, fd, flags;
     char buf[OSS_MAXSAMPLEWIDTH * DEFDACBLKSIZE * OSS_MAXCHPERDEV];
-    int num_devs = 0;
     int wantmore=0;
-    int spread = 0;
-    audio_buf_info ainfo;
 
     linux_nindevs = linux_noutdevs = 0;
         /* mark devices unopened */
@@ -551,7 +543,7 @@ in audio output and/or input. */
 
 static void oss_doresync( void)
 {
-    int dev, zeroed = 0, wantsize;
+    int dev, zeroed = 0;
     char buf[OSS_MAXSAMPLEWIDTH * DEFDACBLKSIZE * OSS_MAXCHPERDEV];
     audio_buf_info ainfo;
 
@@ -630,11 +622,9 @@ static void oss_doresync( void)
 int oss_send_dacs(void)
 {
     t_sample *fp1, *fp2;
-    long fill;
     int i, j, dev, rtnval = SENDDACS_YES;
     char buf[OSS_MAXSAMPLEWIDTH * DEFDACBLKSIZE * OSS_MAXCHPERDEV];
     t_oss_int16 *sp;
-    t_oss_int32 *lp;
         /* the maximum number of samples we should have in the ADC buffer */
     int idle = 0;
     int thischan;
@@ -675,7 +665,6 @@ int oss_send_dacs(void)
         for (dev = 0;dev < linux_nindevs; dev++) 
             if (linux_adcs[dev].d_space == 0)
         {
-            audio_buf_info ainfo;
             sys_microsleep(2000);
             oss_calcspace();
             if (linux_adcs[dev].d_space != 0) continue;
diff --git a/pd/src/s_file.c b/pd/src/s_file.c
index c12bb98b69cf8b650f151814ba0393f8f0c60db5..30a39d61aa69f99c4db46f78e38ed3450107e309 100644
--- a/pd/src/s_file.c
+++ b/pd/src/s_file.c
@@ -40,7 +40,7 @@
 #define snprintf sprintf_s
 #endif
 
-int sys_defeatrt, sys_zoom;
+int sys_defeatrt, sys_zoom, sys_browser_doc = 1, sys_browser_path, sys_browser_init;
 t_symbol *sys_flags = &s_;
 void sys_doflags( void);
 
@@ -493,6 +493,8 @@ static int check_exists(const char*path)
 }
 #endif
 
+extern void sys_expandpathelems(const char *name, char *result);
+
 void sys_loadpreferences( void)
 {
     int naudioindev, audioindev[MAXAUDIOINDEV], chindev[MAXAUDIOINDEV];
@@ -667,6 +669,12 @@ void sys_loadpreferences( void)
         sscanf(prefbuf, "%d", &sys_defeatrt);
     if (sys_getpreference("savezoom", prefbuf, MAXPDSTRING))
         sscanf(prefbuf, "%d", &sys_zoom);
+    if (sys_getpreference("browser_doc", prefbuf, MAXPDSTRING))
+        sscanf(prefbuf, "%d", &sys_browser_doc);
+    if (sys_getpreference("browser_path", prefbuf, MAXPDSTRING))
+        sscanf(prefbuf, "%d", &sys_browser_path);
+    if (sys_getpreference("browser_init", prefbuf, MAXPDSTRING))
+        sscanf(prefbuf, "%d", &sys_browser_init);
     if (sys_getpreference("guipreset", prefbuf, MAXPDSTRING))
     {
         char preset_buf[MAXPDSTRING];
@@ -806,6 +814,12 @@ void glob_savepreferences(t_pd *dummy)
     sys_putpreference("defeatrt", buf1);
     sprintf(buf1, "%d", sys_zoom);
     sys_putpreference("savezoom", buf1);
+    sprintf(buf1, "%d", sys_browser_doc);
+    sys_putpreference("browser_doc", buf1);
+    sprintf(buf1, "%d", sys_browser_path);
+    sys_putpreference("browser_path", buf1);
+    sprintf(buf1, "%d", sys_browser_init);
+    sys_putpreference("browser_init", buf1);
     sys_putpreference("guipreset", sys_gui_preset->s_name);
     sys_putpreference("flags", 
         (sys_flags ? sys_flags->s_name : ""));
diff --git a/pd/src/s_main.c b/pd/src/s_main.c
index cbfae74ed97149bf9e619985e66262d29dd07c63..42a2e59f12136c820c5b2391aff20594fd7ad59d 100644
--- a/pd/src/s_main.c
+++ b/pd/src/s_main.c
@@ -284,10 +284,14 @@ void glob_forward_files_from_secondary_instance(void)
     gui_end_vmess();
 }
 
+extern void glob_recent_files(t_pd *dummy);
+extern int sys_browser_doc, sys_browser_path, sys_browser_init;
+
 /* this is called from main() in s_entry.c */
 int sys_main(int argc, char **argv)
 {
     int i, noprefs;
+    t_namelist *nl;
     sys_externalschedlib = 0;
     sys_extraflags = 0;
     sys_gui_preset = gensym("default");
@@ -323,6 +327,17 @@ int sys_main(int argc, char **argv)
     gui_vmess("gui_set_gui_preset", "s", sys_gui_preset->s_name);
         /* send the recent files list */
     glob_recent_files(0);
+        /* AG: send the browser config; this must come *after* gui_set_lib_dir
+           so that the lib_dir is available when help indexing starts */
+    gui_start_vmess("gui_set_browser_config", "iii",
+                    sys_browser_doc, sys_browser_path, sys_browser_init);
+    gui_start_array();
+    for (nl = sys_helppath; nl; nl = nl->nl_next)
+    {
+        gui_s(nl->nl_string);
+    }
+    gui_end_array();
+    gui_end_vmess();
 
     if (sys_externalschedlib)
         return (sys_run_scheduler(sys_externalschedlibname,
diff --git a/pd/src/s_midi.c b/pd/src/s_midi.c
index 289d702433ff094b913db0415de5f2dfcb29d55a..51ffb91dffd002ffe7ecdac55ba68250a5726053 100644
--- a/pd/src/s_midi.c
+++ b/pd/src/s_midi.c
@@ -703,7 +703,7 @@ extern t_class *glob_pdobject;
     /* start a midi settings dialog window */
 void glob_midi_properties(t_pd *dummy, t_floatarg flongform)
 {
-    char buf[1024 + 2 * MAXNDEV*(DEVDESCSIZE+4)];
+    //char buf[1024 + 2 * MAXNDEV*(DEVDESCSIZE+4)];
         /* these are the devices you're using: */
     int nindev, midiindev[MAXMIDIINDEV];
     int noutdev, midioutdev[MAXMIDIOUTDEV];
@@ -780,9 +780,9 @@ void glob_midi_properties(t_pd *dummy, t_floatarg flongform)
     if (sys_midiapi == API_ALSA)
     {
 //    sprintf(buf,
-//"pdtk_alsa_midi_dialog %%s \
-//%d %d %d %d %d %d %d %d \
-//%d 1\n",
+//"pdtk_alsa_midi_dialog %%s "
+//"%d %d %d %d %d %d %d %d "
+//"%d 1\n",
 //        midiindev1, midiindev2, midiindev3, midiindev4, 
 //        midioutdev1, midioutdev2, midioutdev3, midioutdev4,
 //        (flongform != 0));
@@ -795,9 +795,9 @@ void glob_midi_properties(t_pd *dummy, t_floatarg flongform)
     gui_end_array();
     gui_end_vmess();
 //    sprintf(buf,
-//"pdtk_midi_dialog %%s \
-//%d %d %d %d %d %d %d %d \
-//%d\n",
+//"pdtk_midi_dialog %%s "
+//"%d %d %d %d %d %d %d %d "
+//"%d\n",
 //        midiindev1, midiindev2, midiindev3, midiindev4, 
 //        midioutdev1, midioutdev2, midioutdev3, midioutdev4,
 //        (flongform != 0));
@@ -928,7 +928,7 @@ int sys_mididevnametonumber(int output, const char *name)
 void sys_mididevnumbertoname(int output, int devno, char *name, int namesize)
 {
     char indevlist[MAXNDEV*DEVDESCSIZE], outdevlist[MAXNDEV*DEVDESCSIZE];
-    int nindevs = 0, noutdevs = 0, i;
+    int nindevs = 0, noutdevs = 0;
     if (devno < 0)
     {
         *name = 0;
diff --git a/pd/src/s_midi_alsa.c b/pd/src/s_midi_alsa.c
index bcffa7d3dbf5df04743ab2525151e52f8a74258d..2267eece20ce418766b778f4dbdb780f3746b286 100644
--- a/pd/src/s_midi_alsa.c
+++ b/pd/src/s_midi_alsa.c
@@ -242,7 +242,6 @@ static int alsa_nmidiindevs, alsa_nmidioutdevs, alsa_initted;
 
 void midi_alsa_init(void)     
 {
-    int i;
     if (alsa_initted)
         return;
     alsa_initted = 1;
diff --git a/pd/src/s_path.c b/pd/src/s_path.c
index a4b108cff4898947a525714ba5f38b8008105f8b..152bd4149381744f0f39e5f93950c89025bb0fe2 100644
--- a/pd/src/s_path.c
+++ b/pd/src/s_path.c
@@ -513,7 +513,7 @@ FILE *sys_fopen(const char *filename, const char *mode)
 #include <stdarg.h>
 int sys_open(const char *path, int oflag, ...)
 {
-    int i, fd;
+    int fd;
     char pathbuf[MAXPDSTRING];
     sys_bashfilename(path, pathbuf);
     if (oflag & O_CREAT)
@@ -770,26 +770,20 @@ t_symbol *sys_decodedialog(t_symbol *s)
     /* start a search path dialog window */
 void glob_start_path_dialog(t_pd *dummy)
 {
-    char buf[MAXPDSTRING];
-    int i;
     t_namelist *nl;
 
-    //sys_gui("global pd_path; set pd_path {}\n");
     gui_start_vmess("gui_path_properties", "xii",
         dummy,
         sys_usestdpath,
         sys_verbose
     );
     gui_start_array();
-    for (nl = sys_searchpath, i = 0; nl; nl = nl->nl_next, i++)
+    for (nl = sys_searchpath; nl; nl = nl->nl_next)
     {
-        //sys_vgui("lappend pd_path {%s}\n", nl->nl_string);
         gui_s(nl->nl_string);
     }
     gui_end_array();
     gui_end_vmess();
-    //sprintf(buf, "pdtk_path_dialog %%s %d %d\n", sys_usestdpath, sys_verbose);
-    //gfxstub_new(&glob_pdobject, (void *)glob_start_path_dialog, buf);
 }
 
     /* new values from dialog window */
@@ -811,27 +805,20 @@ void glob_path_dialog(t_pd *dummy, t_symbol *s, int argc, t_atom *argv)
     /* start a startup dialog window */
 void glob_start_startup_dialog(t_pd *dummy)
 {
-    char buf[MAXPDSTRING];
-    int i;
     t_namelist *nl;
 
-    //sys_gui("global pd_startup; set pd_startup {}\n");
     gui_start_vmess("gui_lib_properties", "xis",
         dummy,
         sys_defeatrt,
         sys_flags->s_name
     );
     gui_start_array();
-    for (nl = sys_externlist, i = 0; nl; nl = nl->nl_next, i++)
+    for (nl = sys_externlist; nl; nl = nl->nl_next)
     {
-        //sys_vgui("lappend pd_startup {%s}\n", nl->nl_string);
         gui_s(nl->nl_string);
     }
     gui_end_array();
     gui_end_vmess();
-    //sprintf(buf, "pdtk_startup_dialog %%s %d \"%s\"\n", sys_defeatrt,
-    //    sys_flags->s_name);
-    //gfxstub_new(&glob_pdobject, (void *)glob_start_startup_dialog, buf);
 }
 
     /* new values from dialog window */
diff --git a/pd/src/s_print.c b/pd/src/s_print.c
index 715df30c5b303217b4ec0fb81ec93035fe6c6fff..f9600704c324172118624e1c07d00b5e6938cb3e 100644
--- a/pd/src/s_print.c
+++ b/pd/src/s_print.c
@@ -89,7 +89,6 @@ static void dologpost(const void *object, const int level, const char *s)
     }
     else
     {
-        char obuf[MAXPDSTRING];
         //sys_vgui("::pdwindow::logpost {%s} %d {%s}\n", 
                  //strnpointerid(obuf, object, MAXPDSTRING), 
                  //level, strnescape(upbuf, s, MAXPDSTRING));
@@ -133,8 +132,6 @@ void logpost(const void *object, const int level, const char *fmt, ...)
 {
     char buf[MAXPDSTRING];
     va_list ap;
-    t_int arg[8];
-    int i;
     va_start(ap, fmt);
     vsnprintf(buf, MAXPDSTRING-1, fmt, ap);
     va_end(ap);
diff --git a/pd/src/x_arithmetic.c b/pd/src/x_arithmetic.c
index 1f6600178393d41321e4d1a48a2fe36fb00aa8f7..94f1a5be95f422f721099587f90399bc864c2157 100644
--- a/pd/src/x_arithmetic.c
+++ b/pd/src/x_arithmetic.c
@@ -758,7 +758,6 @@ void x_arithmetic_setup(void)
 {
     t_symbol *binop1_sym = gensym("operators");
     t_symbol *binop23_sym = gensym("otherbinops");
-    t_symbol *math_sym = gensym("math");
 
     binop1_plus_class = class_new(gensym("+"), (t_newmethod)binop1_plus_new, 0,
         sizeof(t_binop), 0, A_DEFFLOAT, 0);
diff --git a/pd/src/x_array.c b/pd/src/x_array.c
index 27c6d1b02141cb626a9c214899317bb082a8064a..67471549dee81f54c40c34301c77b346941328c4 100644
--- a/pd/src/x_array.c
+++ b/pd/src/x_array.c
@@ -533,10 +533,8 @@ static int array_rangeop_getrange(t_array_rangeop *x,
 {
     t_glist *glist;
     t_array *a = array_client_getbuf(&x->x_tc, &glist);
-    char *elemp;
-    int stride, fieldonset, arrayonset, nitem, i, type;
+    int stride, fieldonset, arrayonset, nitem, type;
     t_symbol *arraytype;
-    double sum;
     t_template *template;
     if (!a)
         return (0);
@@ -720,8 +718,8 @@ static void array_random_seed(t_array_random *x, t_floatarg f)
 
 static void array_random_bang(t_array_random *x)
 {
-    char *itemp, *firstitem;
-    int stride, nitem, arrayonset, i;
+    char *firstitem;
+    int stride, nitem, arrayonset;
 
     if (!array_rangeop_getrange(&x->x_r, &firstitem, &nitem, &stride,
         &arrayonset))
diff --git a/pd/src/x_connective.c b/pd/src/x_connective.c
index 5aaade46b14354c4d068c730ff920d29108b2d01..2e61671dcb9802030c7657e506a822c148e5c137 100644
--- a/pd/src/x_connective.c
+++ b/pd/src/x_connective.c
@@ -135,6 +135,8 @@ static void pdsymbol_anything(t_pdsymbol *x, t_symbol *s, int ac, t_atom *av)
     empty lists aren't equivalent to "bang"???  Should Pd's message passer
     always check and call the more specific method, or should it be the 
     object's responsibility?  Dunno... */
+    /* Currently this function isn't used... */
+/*
 static void pdsymbol_list(t_pdsymbol *x, t_symbol *s, int ac, t_atom *av)
 {
     if (!ac)
@@ -143,6 +145,7 @@ static void pdsymbol_list(t_pdsymbol *x, t_symbol *s, int ac, t_atom *av)
         pdsymbol_symbol(x, av->a_w.w_symbol);
     else pdsymbol_anything(x, s, ac, av);
 }
+*/
 
 void pdsymbol_setup(void)
 {
diff --git a/pd/src/x_midi.c b/pd/src/x_midi.c
index 4926b223c2e5945b0956b3f0180ff26431e939fd..c827ea7375cbd2a31eb08dfe3484ea5ca41217e7 100644
--- a/pd/src/x_midi.c
+++ b/pd/src/x_midi.c
@@ -945,7 +945,6 @@ static void *stripnote_new(void )
 
 static void stripnote_float(t_stripnote *x, t_float f)
 {
-    t_hang *hang;
     if (!x->x_velo) return;
     outlet_float(x->x_velout, x->x_velo);
     outlet_float(x->x_pitchout, f);
diff --git a/pd/src/x_misc.c b/pd/src/x_misc.c
index e468fe31eba04bb9e9398937f7a037180360858b..a0ccae4ccd8a01ca7b1671575454a3072b58755c 100644
--- a/pd/src/x_misc.c
+++ b/pd/src/x_misc.c
@@ -420,7 +420,7 @@ typedef struct _oscparse
 static t_symbol *grabstring(int argc, t_atom *argv, int *ip, int slash)
 {
     char buf[MAXPDSTRING];
-    int first, nchar;
+    int nchar;
     if (slash)
         while (*ip < argc && argv[*ip].a_w.w_float == '/')
             (*ip)++;
@@ -681,7 +681,7 @@ static void oscformat_list(t_oscformat *x, t_symbol *s, int argc, t_atom *argv)
             msgindex += ROUNDUPTO4(strlen(argv[j].a_w.w_symbol->s_name) + 1);
         else if (typecode == 'b')
         {
-            int blobsize = 0x7fffffff, blobindex;
+            int blobsize = 0x7fffffff;
                 /* check if we have a nonnegative size field */
             if (argv[j].a_type == A_FLOAT &&
                 (int)(argv[j].a_w.w_float) >= 0)
diff --git a/pd/src/x_net.c b/pd/src/x_net.c
index ed7aa2ec0bc57d53e14ecf582fbce1415ae22439..e81ce245041e3fab868093bcfe770b1ec73674a9 100644
--- a/pd/src/x_net.c
+++ b/pd/src/x_net.c
@@ -122,7 +122,6 @@ static void netsend_readbin(t_netsend *x, int fd)
 
 static void netsend_doit(void *z, t_binbuf *b)
 {
-    t_atom messbuf[1024];
     t_netsend *x = (t_netsend *)z;
     int msg, natom = binbuf_getnatom(b);
     t_atom *at = binbuf_getvec(b);
diff --git a/pd/src/x_text.c b/pd/src/x_text.c
index d61ef6ab5af13e3829eb99c8cf9094a2afa5c011..f8e1a9b3fdab096dde5125b32348190e1eb11b80 100644
--- a/pd/src/x_text.c
+++ b/pd/src/x_text.c
@@ -246,7 +246,7 @@ static int text_nthline(int n, t_atom *vec, int line, int *startp, int *endp)
     {
         if (cnt == line)
         {
-            int j = i, outc, k;
+            int j = i;
             while (j < n && vec[j].a_type != A_SEMI &&
                 vec[j].a_type != A_COMMA)
                     j++;
@@ -343,7 +343,6 @@ static void text_define_frompointer(t_text_define *x, t_gpointer *gp,
         gp, s, "text_frompointer");
     if (b)
     {
-        t_gstub *gs = gp->gp_stub;
         binbuf_clear(x->x_textbuf.b_binbuf);
         binbuf_add(x->x_textbuf.b_binbuf, binbuf_getnatom(b), binbuf_getvec(b));
     }
@@ -914,8 +913,6 @@ static void *text_tolist_new(t_symbol *s, int argc, t_atom *argv)
 static void text_tolist_bang(t_text_tolist *x)
 {
     t_binbuf *b = text_client_getbuf(x), *b2;
-    int n, i, cnt = 0;
-    t_atom *vec;
     if (!b)
        return;
     b2 = binbuf_new();
@@ -1036,10 +1033,9 @@ static void text_search_list(t_text_search *x,
     t_symbol *s, int argc, t_atom *argv)
 {
     t_binbuf *b = text_client_getbuf(&x->x_tc);
-    int i, j, n, lineno, bestline = -1, beststart=-1, bestn, thisstart, thisn,
+    int i, n, lineno, bestline = -1, beststart=-1, thisstart,
         nkeys = x->x_nkeys, failed = 0;
     t_atom *vec;
-    t_key *kp = x->x_keyvec;
     if (!b)
        return;
     if (argc < nkeys)
@@ -1191,10 +1187,10 @@ static void text_search_list(t_text_search *x,
                 }
                 goto nomatch;   /* a tie - keep the old one */
             replace:
-                bestline = lineno, beststart = thisstart, bestn = thisn;
+                bestline = lineno, beststart = thisstart;
             }
                 /* no previous match so we're best */
-            else bestline = lineno, beststart = thisstart, bestn = thisn;
+            else bestline = lineno, beststart = thisstart;
         nomatch:
             lineno++;
             thisstart = i+1;
@@ -1302,7 +1298,7 @@ static void *text_sequence_new(t_symbol *s, int argc, t_atom *argv)
 
 static void text_sequence_doit(t_text_sequence *x, int argc, t_atom *argv)
 {
-    t_binbuf *b = text_client_getbuf(&x->x_tc), *b2;
+    t_binbuf *b = text_client_getbuf(&x->x_tc);
     int n, i, onset, nfield, wait, eatsemi = 1, gotcomma = 0;
     t_atom *vec, *outvec, *ap;
     if (!b)
@@ -1505,7 +1501,7 @@ static void text_sequence_step(t_text_sequence *x)
 
 static void text_sequence_line(t_text_sequence *x, t_floatarg f)
 {
-    t_binbuf *b = text_client_getbuf(&x->x_tc), *b2;
+    t_binbuf *b = text_client_getbuf(&x->x_tc);
     int n, start, end;
     t_atom *vec;
     if (!b)
@@ -1856,7 +1852,7 @@ static void *textfile_new( void)
 static void textfile_bang(t_qlist *x)
 {
     int argc = binbuf_getnatom(x->x_binbuf),
-        count, onset = x->x_onset, onset2;
+        onset = x->x_onset, onset2;
     t_atom *argv = binbuf_getvec(x->x_binbuf);
     t_atom *ap = argv + onset, *ap2;
     while (onset < argc &&