[SCM] pd-iemguts/master: Imported Upstream version 0.2

umlaeute at users.alioth.debian.org umlaeute at users.alioth.debian.org
Tue Jan 19 19:54:51 UTC 2016


The following commit has been merged in the master branch:
commit 5e0e8bc84b8a3afb051449bc1d613ee03b0079ee
Author: IOhannes m zmölnig <zmoelnig at umlautQ.umlaeute.mur.at>
Date:   Tue Jan 19 20:29:24 2016 +0100

    Imported Upstream version 0.2

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..59fd5d1
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,8 @@
+# git ls-files --others --exclude-from=.git/info/exclude
+# Lines that start with '#' are comments.
+# For a project mostly in C, the following would be a good set of
+# exclude patterns (uncomment them if you want to use them):
+*.[oa]
+*~
+*.pd_*
+*.dll
diff --git a/Makefile b/Makefile
index 24fe3b2..54302e9 100644
--- a/Makefile
+++ b/Makefile
@@ -1,473 +1,32 @@
-## Pd library template version 1.0.12
-# For instructions on how to use this template, see:
-#  http://puredata.info/docs/developer/MakefileTemplate
-LIBRARY_NAME = iemguts
+#!/usr/bin/make -f
+# Makefile for pure data externals in lib creb.
+# Needs Makefile.pdlibbuilder to work (https://github.com/pure-data/pd-lib-builder)
 
-# add your .c source files, one object per file, to the SOURCES
-# variable, help files will be included automatically, and for GUI
-# objects, the matching .tcl file too
-SOURCES = \
-  autoabstraction.c \
-  canvasargs.c \
-  canvasconnections.c \
-  canvasdelete.c \
-  canvasdollarzero.c \
-  canvaserror.c \
-  canvasindex.c \
-  canvasname.c \
-  canvasobjectposition.c \
-  canvasposition.c \
-  canvasselect.c \
-  classtest.c \
-  oreceive.c \
-  propertybang.c \
-  receivecanvas.c \
-  savebangs.c \
-  sendcanvas.c \
-  try.c
+lib.name = iemguts
 
-HELPPATCHES =  \
-  help/autoabstraction-help.pd \
-  help/canvasargs-help.pd \
-  help/canvasconnections-help.pd \
-  help/canvasdelete-help.pd \
-  help/canvasdollarzero-help.pd \
-  help/canvaserror-help.pd \
-  help/canvasindex-help.pd \
-  help/canvasname-help.pd \
-  help/canvasobjectposition-help.pd \
-  help/canvasposition-help.pd \
-  help/canvasselect-help.pd \
-  help/classtest-help.pd \
-  help/oreceive-help.pd \
-  help/propertybang-help.pd \
-  help/receivecanvas-help.pd \
-  help/savebangs-help.pd \
-  help/sendcanvas-help.pd \
-  help/try-help.pd
+# special file that does not provide a class
+lib.setup.sources = 
 
-# list all pd objects (i.e. myobject.pd) files here, and their helpfiles will
-# be included automatically
-PDOBJECTS = 
+# all other C and C++ files in subdirs are source files per class
+# (alternatively, enumerate them by hand)
+class.sources = $(filter-out $(lib.setup.sources),$(wildcard src/*.c))
 
-# example patches and related files, in the 'examples' subfolder
-EXAMPLES = \
-  03.persistent_properties.pd \
-  04.moving_in_gem.pd \
-  05.flies.pd \
-  06.interacting_sound.pd \
-  disconnectme.pd \
-  fly.pd \
-  FM~.pd \
-  gemmover.pd \
-  gopcanvas.pd \
-  mover.pd \
-  randomoffset.pd \
-  randomwalk.pd \
-  sink~.pd \
-  valX~.pd \
-  valY~.pd \
-  versioning.pd
+datafiles = \
+$(wildcard help/*-help.pd) \
+LICENSE.txt \
+README.txt \
+iemguts-meta.pd
 
+datadirs =  examples
 
-# manuals and related files, in the 'manual' subfolder
-MANUAL = 
+cflags = -DVERSION=$(lib.version)
 
-# if you want to include any other files in the source and binary tarballs,
-# list them here.  This can be anything from header files, test patches,
-# documentation, etc.  README.txt and LICENSE.txt are required and therefore
-# automatically included
-EXTRA_DIST = 
+################################################################################
+### pdlibbuilder ###############################################################
+################################################################################
 
-VPATH=src
-
-#------------------------------------------------------------------------------#
-#
-# things you might need to edit if you are using other C libraries
-#
-#------------------------------------------------------------------------------#
-
-ALL_CFLAGS = -I"$(PD_INCLUDE)"
-ALL_LDFLAGS =  
-SHARED_LDFLAGS =
-ALL_LIBS = 
-
-
-#------------------------------------------------------------------------------#
-#
-# you shouldn't need to edit anything below here, if we did it right :)
-#
-#------------------------------------------------------------------------------#
-
-# these can be set from outside without (usually) breaking the build
-CFLAGS = -Wall -Wno-unused -W -g
-LDFLAGS =
-LIBS =
-
-# get library version from meta file
-LIBRARY_VERSION = $(shell sed -n 's|^\#X text [0-9][0-9]* [0-9][0-9]* VERSION \(.*\);|\1|p' $(LIBRARY_NAME)-meta.pd)
-
-ALL_CFLAGS += -DPD -DVERSION='"$(LIBRARY_VERSION)"'
-
-PD_INCLUDE = $(PD_PATH)/include/pd
-# where to install the library, overridden below depending on platform
-prefix = /usr/local
-libdir = $(prefix)/lib
-pkglibdir = $(libdir)/pd-externals
-objectsdir = $(pkglibdir)
-
-INSTALL = install
-INSTALL_PROGRAM = $(INSTALL) -p -m 644
-INSTALL_DATA = $(INSTALL) -p -m 644
-INSTALL_DIR     = $(INSTALL) -p -m 755 -d
-
-ALLSOURCES_tmp = $(SOURCES) $(SOURCES_android) $(SOURCES_cygwin) $(SOURCES_macosx) \
-	         $(SOURCES_iphoneos) $(SOURCES_linux) $(SOURCES_windows)
-ALLSOURCES:=$(ALLSOURCES_tmp:%=src/%)
-
-
-DISTDIR=$(LIBRARY_NAME)-$(LIBRARY_VERSION)
-ORIGDIR=pd-$(LIBRARY_NAME:~=)_$(LIBRARY_VERSION)
-
-UNAME := $(shell uname -s)
-ifeq ($(UNAME),Darwin)
-  CPU := $(shell uname -p)
-  ifeq ($(CPU),arm) # iPhone/iPod Touch
-    SOURCES += $(SOURCES_iphoneos)
-    EXTENSION = pd_darwin
-    SHARED_EXTENSION = dylib
-    OS = iphoneos
-    PD_PATH = /Applications/Pd-extended.app/Contents/Resources
-    IPHONE_BASE=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin
-    CC=$(IPHONE_BASE)/gcc
-    CPP=$(IPHONE_BASE)/cpp
-    CXX=$(IPHONE_BASE)/g++
-    ISYSROOT = -isysroot /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.0.sdk
-    IPHONE_CFLAGS = -miphoneos-version-min=3.0 $(ISYSROOT) -arch armv6
-    OPT_CFLAGS = -fast -funroll-loops -fomit-frame-pointer
-    ALL_CFLAGS := $(IPHONE_CFLAGS) $(ALL_CFLAGS)
-    ALL_LDFLAGS += -arch armv6 -bundle -undefined dynamic_lookup $(ISYSROOT)
-    SHARED_LDFLAGS += -arch armv6 -dynamiclib -undefined dynamic_lookup $(ISYSROOT)
-    ALL_LIBS += -lc $(LIBS_iphoneos)
-    STRIP = strip -x
-    DISTBINDIR=$(DISTDIR)-$(OS)
-  else # Mac OS X
-    SOURCES += $(SOURCES_macosx)
-    EXTENSION = pd_darwin
-    SHARED_EXTENSION = dylib
-    OS = macosx
-    PD_PATH = /Applications/Pd-extended.app/Contents/Resources
-    OPT_CFLAGS = -ftree-vectorize -ftree-vectorizer-verbose=2 -fast
-# build universal 32-bit on 10.4 and 32/64 on newer
-    ifeq ($(shell uname -r | sed 's|\([0-9][0-9]*\)\.[0-9][0-9]*\.[0-9][0-9]*|\1|'), 8)
-      FAT_FLAGS = -arch ppc -arch i386 -mmacosx-version-min=10.4
-    else
-      FAT_FLAGS = -arch ppc -arch i386 -arch x86_64 -mmacosx-version-min=10.4
-      SOURCES += $(SOURCES_iphoneos)
-    endif
-    ALL_CFLAGS += $(FAT_FLAGS) -fPIC -I/sw/include
-    # if the 'pd' binary exists, check the linking against it to aid with stripping
-    BUNDLE_LOADER = $(shell test ! -e $(PD_PATH)/bin/pd || echo -bundle_loader $(PD_PATH)/bin/pd)
-    ALL_LDFLAGS += $(FAT_FLAGS) -bundle $(BUNDLE_LOADER) -undefined dynamic_lookup -L/sw/lib
-    SHARED_LDFLAGS += $(FAT_FLAGS) -dynamiclib -undefined dynamic_lookup \
-	-install_name @loader_path/$(SHARED_LIB) -compatibility_version 1 -current_version 1.0
-    ALL_LIBS += -lc $(LIBS_macosx)
-    STRIP = strip -x
-    DISTBINDIR=$(DISTDIR)-$(OS)
-# install into ~/Library/Pd on Mac OS X since /usr/local isn't used much
-    pkglibdir=$(HOME)/Library/Pd
-  endif
-endif
-# Tho Android uses Linux, we use this fake uname to provide an easy way to
-# setup all this things needed to cross-compile for Android using the NDK
-ifeq ($(UNAME),ANDROID)
-  CPU := arm
-  SOURCES += $(SOURCES_android)
-  EXTENSION = pd_linux
-  SHARED_EXTENSION = so
-  OS = android
-  PD_PATH = /usr
-  NDK_BASE := /usr/local/android-ndk
-  NDK_PLATFORM_VERSION := 5
-  NDK_SYSROOT=$(NDK_BASE)/platforms/android-$(NDK_PLATFORM_VERSION)/arch-arm
-  NDK_UNAME := $(shell uname -s | tr '[A-Z]' '[a-z]')
-  NDK_TOOLCHAIN_BASE=$(NDK_BASE)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/$(NDK_UNAME)-x86
-  CC := $(NDK_TOOLCHAIN_BASE)/bin/arm-linux-androideabi-gcc --sysroot=$(NDK_SYSROOT)
-  OPT_CFLAGS = -O6 -funroll-loops -fomit-frame-pointer
-  CFLAGS += 
-  LDFLAGS += -rdynamic -shared
-  SHARED_LDFLAGS += -Wl,-soname,$(SHARED_LIB) -shared
-  LIBS += -lc $(LIBS_android)
-  STRIP := $(NDK_TOOLCHAIN_BASE)/bin/arm-linux-androideabi-strip \
-	--strip-unneeded -R .note -R .comment
-  DISTBINDIR=$(DISTDIR)-$(OS)-$(shell uname -m)
-endif
-ifeq ($(UNAME),Linux)
-  CPU := $(shell uname -m)
-  SOURCES += $(SOURCES_linux)
-  EXTENSION = pd_linux
-  SHARED_EXTENSION = so
-  OS = linux
-  PD_PATH = /usr
-  OPT_CFLAGS = -O6 -funroll-loops -fomit-frame-pointer
-  ALL_CFLAGS += -fPIC
-  ALL_LDFLAGS += -rdynamic -shared -fPIC -Wl,-rpath,"\$$ORIGIN",--enable-new-dtags
-  SHARED_LDFLAGS += -Wl,-soname,$(SHARED_LIB) -shared
-  ALL_LIBS += -lc $(LIBS_linux)
-  STRIP = strip --strip-unneeded -R .note -R .comment
-  DISTBINDIR=$(DISTDIR)-$(OS)-$(shell uname -m)
-endif
-ifeq ($(UNAME),GNU)
-  # GNU/Hurd, should work like GNU/Linux for basically all externals
-  CPU := $(shell uname -m)
-  SOURCES += $(SOURCES_linux)
-  EXTENSION = pd_linux
-  SHARED_EXTENSION = so
-  OS = linux
-  PD_PATH = /usr
-  OPT_CFLAGS = -O6 -funroll-loops -fomit-frame-pointer
-  ALL_CFLAGS += -fPIC
-  ALL_LDFLAGS += -rdynamic -shared -fPIC -Wl,-rpath,"\$$ORIGIN",--enable-new-dtags
-  SHARED_LDFLAGS += -shared -Wl,-soname,$(SHARED_LIB)
-  ALL_LIBS += -lc $(LIBS_linux)
-  STRIP = strip --strip-unneeded -R .note -R .comment
-  DISTBINDIR=$(DISTDIR)-$(OS)-$(shell uname -m)
-endif
-ifeq ($(UNAME),GNU/kFreeBSD)
-  # Debian GNU/kFreeBSD, should work like GNU/Linux for basically all externals
-  CPU := $(shell uname -m)
-  SOURCES += $(SOURCES_linux)
-  EXTENSION = pd_linux
-  SHARED_EXTENSION = so
-  OS = linux
-  PD_PATH = /usr
-  OPT_CFLAGS = -O6 -funroll-loops -fomit-frame-pointer
-  ALL_CFLAGS += -fPIC
-  ALL_LDFLAGS += -rdynamic -shared -fPIC -Wl,-rpath,"\$$ORIGIN",--enable-new-dtags
-  SHARED_LDFLAGS += -shared -Wl,-soname,$(SHARED_LIB)
-  ALL_LIBS += -lc $(LIBS_linux)
-  STRIP = strip --strip-unneeded -R .note -R .comment
-  DISTBINDIR=$(DISTDIR)-$(OS)-$(shell uname -m)
-endif
-ifeq (CYGWIN,$(findstring CYGWIN,$(UNAME)))
-  CPU := $(shell uname -m)
-  SOURCES += $(SOURCES_cygwin)
-  EXTENSION = dll
-  SHARED_EXTENSION = dll
-  OS = cygwin
-  PD_PATH = $(shell cygpath $$PROGRAMFILES)/pd
-  OPT_CFLAGS = -O6 -funroll-loops -fomit-frame-pointer
-  ALL_CFLAGS += 
-  ALL_LDFLAGS += -rdynamic -shared -L"$(PD_PATH)/src" -L"$(PD_PATH)/bin"
-  SHARED_LDFLAGS += -shared -Wl,-soname,$(SHARED_LIB)
-  ALL_LIBS += -lc -lpd $(LIBS_cygwin)
-  STRIP = strip --strip-unneeded -R .note -R .comment
-  DISTBINDIR=$(DISTDIR)-$(OS)
-endif
-ifeq (MINGW,$(findstring MINGW,$(UNAME)))
-  CPU := $(shell uname -m)
-  SOURCES += $(SOURCES_windows)
-  EXTENSION = dll
-  SHARED_EXTENSION = dll
-  OS = windows
-  PD_PATH = $(shell cd "$$PROGRAMFILES/pd" && pwd)
-  # MinGW doesn't seem to include cc so force gcc
-  CC=gcc
-  OPT_CFLAGS = -O3 -funroll-loops -fomit-frame-pointer
-  ALL_CFLAGS += -mms-bitfields
-  ALL_LDFLAGS += -s -shared -Wl,--enable-auto-import -L"$(PD_PATH)/src" -L"$(PD_PATH)/bin" -L"$(PD_PATH)/obj"
-  SHARED_LDFLAGS += -shared
-  ALL_LIBS += -lpd -lwsock32 -lkernel32 -luser32 -lgdi32 $(LIBS_windows)
-  STRIP = strip --strip-unneeded -R .note -R .comment
-  DISTBINDIR=$(DISTDIR)-$(OS)
-endif
-
-# in case somebody manually set the HELPPATCHES above
-HELPPATCHES ?= $(SOURCES:.c=-help.pd) $(PDOBJECTS:.pd=-help.pd)
-
-ALL_CFLAGS := $(ALL_CFLAGS) $(CFLAGS) $(OPT_CFLAGS)
-ALL_LDFLAGS := $(LDFLAGS) $(ALL_LDFLAGS)
-ALL_LIBS := $(LIBS) $(ALL_LIBS)
-
-SHARED_SOURCE ?= $(wildcard lib$(LIBRARY_NAME).c)
-SHARED_HEADER ?= $(shell test ! -e $(LIBRARY_NAME).h || echo $(LIBRARY_NAME).h)
-SHARED_LIB = $(shell test "x$(SHARED_SOURCE)" = "x" || echo lib$(LIBRARY_NAME).$(SHARED_EXTENSION))
-SHARED_TCL_LIB = $(wildcard lib$(LIBRARY_NAME).tcl)
-
-.PHONY = install libdir_install single_install install-doc install-examples install-manual clean distclean dist etags $(LIBRARY_NAME)
-
-all: $(SOURCES:.c=.$(EXTENSION)) $(SHARED_LIB)
-
-%.o: %.c
-	$(CC) $(ALL_CFLAGS) -o $@ -c $<
-
-%.$(EXTENSION): %.o $(SHARED_LIB)
-	$(CC) $(ALL_LDFLAGS) -o $@ $^  $(ALL_LIBS)
-	chmod a-x $@
-
-# this links everything into a single binary file
-$(LIBRARY_NAME): $(SOURCES:.c=.o) $(LIBRARY_NAME).o
-	$(CC) $(ALL_LDFLAGS) -o $@ $^ $(ALL_LIBS)
-	chmod a-x $@
-
-$(SHARED_LIB): $(SHARED_SOURCE:.c=.o)
-	$(CC) $(SHARED_LDFLAGS) -o $@ $^ $(LIBS)
-
-install: libdir_install
-
-# The meta and help files are explicitly installed to make sure they are
-# actually there.  Those files are not optional, then need to be there.
-libdir_install: $(SOURCES:.c=.$(EXTENSION)) $(SHARED_LIB) install-doc install-examples install-manual
-	$(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
-	$(INSTALL_DATA) $(LIBRARY_NAME)-meta.pd \
-		$(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
-	test -z "$(strip $(SOURCES))" || (\
-		$(INSTALL_PROGRAM) $(SOURCES:.c=.$(EXTENSION)) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) && \
-		$(STRIP) $(addprefix $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/,$(SOURCES:.c=.$(EXTENSION))))
-	test -z "$(strip $(SHARED_LIB))" || \
-		$(INSTALL_DATA) $(SHARED_LIB) \
-			$(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
-	test -z "$(strip $(wildcard $(SOURCES:.c=.tcl)))" || \
-		$(INSTALL_DATA) $(wildcard $(SOURCES:.c=.tcl)) \
-			$(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
-	test -z "$(strip $(PDOBJECTS))" || \
-		$(INSTALL_DATA) $(PDOBJECTS) \
-			$(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
-	test -z "$(strip $(SHARED_TCL_LIB))" || \
-		$(INSTALL_DATA) $(SHARED_TCL_LIB) \
-			$(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
-
-# install library linked as single binary
-single_install: $(LIBRARY_NAME) install-doc install-examples install-manual
-	$(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
-	$(INSTALL_PROGRAM) $(LIBRARY_NAME).$(EXTENSION) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
-	$(STRIP) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/$(LIBRARY_NAME).$(EXTENSION)
-
-install-doc:
-	$(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
-	test -z "$(strip $(SOURCES) $(PDOBJECTS))" || \
-		$(INSTALL_DATA) $(HELPPATCHES) \
-			$(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
-	$(INSTALL_DATA) README.txt $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/README.txt
-	$(INSTALL_DATA) LICENSE.txt $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/LICENSE.txt
-
-install-examples:
-	test -z "$(strip $(EXAMPLES))" || \
-		$(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/examples && \
-		for file in $(EXAMPLES); do \
-			$(INSTALL_DATA) examples/$$file $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/examples; \
-		done
-
-install-manual:
-	test -z "$(strip $(MANUAL))" || \
-		$(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/manual && \
-		for file in $(MANUAL); do \
-			$(INSTALL_DATA) manual/$$file $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/manual; \
-		done
-
-
-clean:
-	-rm -f -- $(SOURCES:.c=.o) $(SOURCES_LIB:.c=.o) $(SHARED_SOURCE:.c=.o)
-	-rm -f -- $(SOURCES:.c=.$(EXTENSION))
-	-rm -f -- $(LIBRARY_NAME).o
-	-rm -f -- $(LIBRARY_NAME).$(EXTENSION)
-	-rm -f -- $(SHARED_LIB)
-
-distclean: clean
-	-rm -f -- $(DISTBINDIR).tar.gz
-	-rm -rf -- $(DISTBINDIR)
-	-rm -f -- $(DISTDIR).tar.gz
-	-rm -rf -- $(DISTDIR)
-	-rm -f -- $(ORIGDIR).tar.gz
-	-rm -rf -- $(ORIGDIR)
-
-
-$(DISTBINDIR):
-	$(INSTALL_DIR) $(DISTBINDIR)
-
-libdir: all $(DISTBINDIR)
-	$(INSTALL_DATA) $(LIBRARY_NAME)-meta.pd  $(DISTBINDIR)
-	$(INSTALL_DATA) $(SOURCES) $(SHARED_SOURCE) $(SHARED_HEADER) $(DISTBINDIR)
-	$(INSTALL_DATA) $(HELPPATCHES) $(DISTBINDIR)
-	test -z "$(strip $(EXTRA_DIST))" || \
-		$(INSTALL_DATA) $(EXTRA_DIST)    $(DISTBINDIR)
-#	tar --exclude-vcs -czpf $(DISTBINDIR).tar.gz $(DISTBINDIR)
-
-$(DISTDIR):
-	$(INSTALL_DIR) $(DISTDIR)
-
-$(ORIGDIR):
-	$(INSTALL_DIR) $(ORIGDIR)
-
-dist: $(DISTDIR)
-	$(INSTALL_DATA) Makefile  $(DISTDIR)
-	$(INSTALL_DATA) README.txt $(DISTDIR)
-	$(INSTALL_DATA) LICENSE.txt $(DISTDIR)
-	$(INSTALL_DATA) $(LIBRARY_NAME)-meta.pd  $(DISTDIR)
-	test -z "$(strip $(ALLSOURCES))" || \
-		$(INSTALL_DATA) $(ALLSOURCES)  $(DISTDIR)
-	test -z "$(strip $(wildcard $(ALLSOURCES:.c=.tcl)))" || \
-		$(INSTALL_DATA) $(wildcard $(ALLSOURCES:.c=.tcl))  $(DISTDIR)
-	test -z "$(strip $(SHARED_HEADER))" || \
-		$(INSTALL_DATA) $(SHARED_HEADER)  $(DISTDIR)
-	test -z "$(strip $(SHARED_SOURCE))" || \
-		$(INSTALL_DATA) $(SHARED_SOURCE)  $(DISTDIR)
-	test -z "$(strip $(SHARED_TCL_LIB))" || \
-		$(INSTALL_DATA) $(SHARED_TCL_LIB)  $(DISTDIR)
-	test -z "$(strip $(PDOBJECTS))" || \
-		$(INSTALL_DATA) $(PDOBJECTS)  $(DISTDIR)
-	test -z "$(strip $(HELPPATCHES))" || \
-		$(INSTALL_DATA) $(HELPPATCHES) $(DISTDIR)
-	test -z "$(strip $(EXTRA_DIST))" || \
-		$(INSTALL_DATA) $(EXTRA_DIST)    $(DISTDIR)
-	test -z "$(strip $(EXAMPLES))" || \
-		$(INSTALL_DIR) $(DISTDIR)/examples && \
-		for file in $(EXAMPLES); do \
-			$(INSTALL_DATA) examples/$$file $(DISTDIR)/examples; \
-		done
-	test -z "$(strip $(MANUAL))" || \
-		$(INSTALL_DIR) $(DISTDIR)/manual && \
-		for file in $(MANUAL); do \
-			$(INSTALL_DATA) manual/$$file $(DISTDIR)/manual; \
-		done
-	tar --exclude-vcs -czpf $(DISTDIR).tar.gz $(DISTDIR)
-
-# make a Debian source package
-dpkg-source:
-	debclean
-	make distclean dist
-	mv $(DISTDIR) $(ORIGDIR)
-	tar --exclude-vcs -czpf ../$(ORIGDIR).orig.tar.gz $(ORIGDIR)
-	rm -f -- $(DISTDIR).tar.gz
-	rm -rf -- $(DISTDIR) $(ORIGDIR)
-	cd .. && dpkg-source -b $(LIBRARY_NAME)
-
-etags:
-	etags *.h $(SOURCES) ../../pd/src/*.[ch] /usr/include/*.h /usr/include/*/*.h
-
-showsetup:
-	@echo "CC: $(CC)"
-	@echo "CFLAGS: $(CFLAGS)"
-	@echo "LDFLAGS: $(LDFLAGS)"
-	@echo "LIBS: $(LIBS)"
-	@echo "ALL_CFLAGS: $(ALL_CFLAGS)"
-	@echo "ALL_LDFLAGS: $(ALL_LDFLAGS)"
-	@echo "ALL_LIBS: $(ALL_LIBS)"
-	@echo "PD_INCLUDE: $(PD_INCLUDE)"
-	@echo "PD_PATH: $(PD_PATH)"
-	@echo "objectsdir: $(objectsdir)"
-	@echo "LIBRARY_NAME: $(LIBRARY_NAME)"
-	@echo "LIBRARY_VERSION: $(LIBRARY_VERSION)"
-	@echo "SOURCES: $(SOURCES)"
-	@echo "SHARED_HEADER: $(SHARED_HEADER)"
-	@echo "SHARED_SOURCE: $(SHARED_SOURCE)"
-	@echo "SHARED_LIB: $(SHARED_LIB)"
-	@echo "SHARED_TCL_LIB: $(SHARED_TCL_LIB)"
-	@echo "PDOBJECTS: $(PDOBJECTS)"
-	@echo "ALLSOURCES: $(ALLSOURCES)"
-	@echo "ALLSOURCES TCL: $(wildcard $(ALLSOURCES:.c=.tcl))"
-	@echo "UNAME: $(UNAME)"
-	@echo "CPU: $(CPU)"
-	@echo "pkglibdir: $(pkglibdir)"
-	@echo "DISTDIR: $(DISTDIR)"
-	@echo "ORIGDIR: $(ORIGDIR)"
+# This Makefile is based on the Makefile from pd-lib-builder written by
+# Katja Vetter. You can get it from:
+# https://github.com/pure-data/pd-lib-builder
+PDLIBBUILDER_DIR=pd-lib-builder/
+include $(firstword $(wildcard $(PDLIBBUILDER_DIR)/Makefile.pdlibbuilder Makefile.pdlibbuilder))
diff --git a/Makefile.pdlibbuilder b/Makefile.pdlibbuilder
new file mode 100644
index 0000000..861d9e4
--- /dev/null
+++ b/Makefile.pdlibbuilder
@@ -0,0 +1,1140 @@
+# Makefile.pdlibbuilder version 0.0.1, dated 2015-10-31
+#
+# Helper makefile for Pure Data external libraries.
+# Written by Katja Vetter March-June 2015 for the public domain. No warranties.
+# Inspired by Hans Christoph Steiner's Makefile Template and Stephan Beal's
+# ShakeNMake.
+#
+# GNU make version >= 3.81 required.
+#
+#
+#=== characteristics ===========================================================
+#
+#
+# - defines build settings based on autodetected OS and architecture
+# - defines rules to build Pd class- or lib executables from C or C++ sources
+# - defines rules for libdir installation
+# - defines convenience targets for developer and user
+# - evaluates implicit dependencies for non-clean builds
+#
+#
+#=== basic usage ===============================================================
+#
+#
+# In your Makefile, define your Pd lib name and class files, and include
+# Makefile.pdlibbuilder at the end of the Makefile. Like so:
+#
+#    ________________________________________________________________________
+#
+#     # Makefile for mylib
+#
+#     lib.name = mylib
+#
+#     class.sources = myclass1.c myclass2.c
+#
+#     datafiles = myclass1-help.pd myclass2-help.pd README.txt LICENSE.txt
+#
+#     include Makefile.pdlibbuilder
+#    ________________________________________________________________________
+#
+#
+# For files in class.sources it is assumed that class basename == source file
+# basename. The default target builds all classes as individual executables
+# with Pd's default extension for the platform. For anything more than the
+# most basic usage, continue reading.
+#
+#
+#=== list of Makefile.pdlibbuilder API variables ===============================
+#
+#
+# Variables available for definition in your library Makefile:
+#
+# - lib.name
+# - lib.setup.sources
+# - class.sources
+# - common.sources
+# - shared.sources
+# - <classname>.class.sources
+# - <classname>.class.ldflags
+# - <classname>.class.ldlibs
+# - cflags
+# - ldflags
+# - ldlibs
+# - datafiles
+# - datadirs
+# - makefiles
+# - makefiledirs
+# - externalsdir
+#
+# Variables avaialable for (re)definition via command arguments:
+#
+# - pdbinpath (Windows only)
+# - pdincludepath
+# - DESTDIR
+# - prefix
+# - libdir
+# - pkglibdir
+# - CFLAGS
+# - CC
+# - CXX
+# - INSTALL
+# - INSTALL_PROGRAM
+# - INSTALL_DATA
+# - INSTALL_DIR
+#
+# Variables available for your makefile or as command argument:
+#
+# - objectsdir
+# - make-lib-executable
+# - suppress-wunused
+#
+#
+#=== descriptions of Makefile.pdlibbuilder API variables =======================
+#
+#
+# lib.name:
+# Name of the library directory as it will be installed / distributed. Also the
+# name of the lib executable in the case where all classes are linked into
+# a single binary.
+#
+# lib.setup.sources:
+# Source file(s) (C or C++) which must be compiled only when linking all classes
+# into a single lib binary.
+#
+# class.sources:
+# All sources files (C or C++) for which the condition holds that
+# class name == source file basename.
+#
+# <classname>.class.sources:
+# Source file(s) (C or C++) specific to class <classname>. Use this for
+# multiple-source classes or when class name != source file basename.
+#
+# common.sources:
+# Source file(s) which must be statically linked to each class in the library.
+#
+# shared.sources:
+# Source file(s) (C or C++) to build a shared dynamic link lib, to be linked
+# with all class executables.
+#
+# cflags, ldflags, ldlibs:
+# Define cflags (preprocessor&compiler), ldflags (linker) and ldlibs (dynamic
+# link libs) for the whole library. These flags are added to platform-specific
+# flags defined by Makefile.pdlibbuilder.
+#
+# <classname>.class.ldflags and <classname>.class.ldlibs:
+# Define ldflags resp. ldlibs specific to class <classname>. These flags are
+# added to platform-specific flags defined by Makefile.pdlibbuilder, and flags
+# defined in your Makefile for the whole library. Note: cflags can not be
+# defined per class in the current implementation.
+#
+# datafiles and datadirs:
+# All extra files you want to include in binary distributions of the
+# library: abstractions and help patches, example patches, meta patch, readme
+# and license texts, manuals, sound files, etcetera. Use 'datafiles' for all
+# files that should go into your lib rootdir and 'datadirs' for complete
+# directories you want to copy from source to distribution.
+#
+# externalsdir:
+# Relative path to directory 'externals' in the context of pd-extended SVN, or
+# any other centralized build layout for multiple libraries. Default value
+# is '..', meaning the direct parent. The value is used in search paths for
+# pd core components (header files, and executable in the case of Windows).
+#
+# makefiles and makefiledirs:
+# Extra makefiles or directories with makefiles that should be made in sub-make
+# processes.
+#
+# pdbinpath:
+# For Windows only. Directory where pd.dll can be found for linking.
+#
+# pdincludepath:
+# Directory where Pd API m_pd.h can be found, and other Pd header files.
+#
+# DESTDIR, prefix, libdir:
+# Components of the path for installation as conventionally used on Linux.
+#
+# pkglibdir:
+# Base path for installation of Pd library directories. Default is specified
+# per OS, see section about paths below.
+#
+# objectsdir:
+# Alias of pkglibdir. Can be defined in your makefile to enable project-
+# dependent relative install locations.
+#
+# CFLAGS:
+# Compiler (notably optimization) flags which are defined by
+# Makefile.pdlibbuilder, but may be overriden via command argument.
+#
+# CC and CXX:
+# C and C++ compiler programs as defined in your build environment.
+#
+# INSTALL, INSTALL_PROGRAM, INSTALL_DATA, INSTALL_DIR:
+# Definitions of install program, may be overriden via command argument.
+#
+# make-lib-executable:
+# When this variable is defined 'yes' in your makefile or as command argument,
+# Makefile.pdlibbuilder will try to build all classes into a single library
+# executable (but it will force exit if lib.setup.sources is undefined).
+# If your makefile defines 'make-lib-executable=yes' as the library default,
+# this can still be overriden with 'make-lib-executable=no' as command argument
+# to build individual class executables (the Makefile.pdlibbuilder default.)
+#
+# suppress-wunused:
+# When this variable is defined ('yes' or any other value), -Wunused-variable,
+# -Wunused-parameter, -Wunused-value and -Wunused-function are suppressed,
+# but the other warnings from -Wall are retained.
+#
+#
+#=== paths =====================================================================
+#
+#
+# Source files in directories other than current working directory must be
+# prefixed with their relative path. Do not rely on VPATH or vpath.
+# Object (.o) files are built in the directory of their source files.
+# Executables are built in current working directory.
+#
+# Variable 'pdincludepath' stores the location where m_pd.h was found.
+# Locations where Makefile.pdlibbuilder tries to find it, in order of priority:
+#
+# any OS:   $(externalsdir)../pd/src/
+#
+# Linux:    /usr/include/pdextended/
+#           /usr/include/pd/
+#
+# OSX:      /Applications/Pd-extended.app/Contents/Resources/include/pdextended/
+#           /Applications/Pd.app/Contents/Resources/src/
+#
+# Windows:  %PROGRAMFILES%/pd/include/pdextended/
+#           %PROGRAMFILES%/pd/src/
+#
+# The path for installation of all library components is constructed as:
+#
+# installpath := $(DESTDIR)$(objectsdir)/$(lib.name)
+#
+# Default for 'objectsdir' is defined per platform and follows this convention:
+# https://puredata.info/docs/faq/how-do-i-install-externals-and-help-files
+#
+# Linux:    /usr/local/lib/pd-externals
+# OSX:      ~/Library/Pd
+# Windows:  %APPDATA%/Pd
+#
+# The rationale for not installing to ~/pd-externals by default on Linux
+# is that some people share the home dir between 32 and 64 bit installations.
+#
+#
+#=== targets ===================================================================
+#
+#
+# all: build classes (default) or library blob (if make-lib-executable=true)
+# alldebug: build all with -g option turned on for debug symbols
+# <classname>: force clean build of an individual class
+# <sourcefile>.pre: make preprocessor output file in current working directory
+# <sourcefile>.lst: make asm/source output file in current working directory
+#
+# install: install executables and data files
+# clean: remove build products from source tree
+#
+# help: print help text
+# vars: print makefile variables
+# allvars: print all variables
+# depend: print generated prerequisites
+# coffee: dummy target
+#
+#
+#=== Pd-extended libdir concept ================================================
+#
+#
+# For libdir layout as conceived by Hans-Christoph Steiner, see:
+#
+# https://puredata.info/docs/developer/Libdir
+#
+# Files README.txt, LICENSE.txt and <lib.name>-meta.pd are part of the libdir
+# convention. Help patches for each class and abstraction are supposed to be
+# available. Makefile.pdlibbuilder does not force the presence of these files
+# however. It does not automatically include such files in libdir installations.
+# Data files you want to include in distributions must be defined explicitly in
+# your Makefile.
+#
+#
+#=== Makefile.pdlibbuilder syntax conventions ==================================
+#
+#
+# Makefile.pdlibbuilder variable names are lower case. Default make variables,
+# environment variables, and standard user variables (CC, CXX, CFLAGS, DESTDIR)
+# are upper case. Use target 'allvars' to print all variables and their values.
+#
+# 'Fields' in data variables are separated by dots, like in 'foo.class.sources'.
+# Words in variables expressing a function or command are separated by dashes,
+# like in 'make-lib-executable'.
+#
+#
+#=== useful make options =======================================================
+#
+#
+# Use 'make -d <target>' to print debug details of the make process.
+# Use 'make -p <target>' to print make's database.
+#
+#
+#=== TODO ======================================================================
+#
+#
+# - decide whether to use -static-libgcc or shared dll in MinGW
+# - cygwin support
+# - android support
+# - Windows 64 bit support
+# - figure out how to handle '$' in filenames
+# - add makefile template targets dpkg-source dist libdir distclean tags?
+#
+#
+#=== end of documentation sections =============================================
+#
+#
+################################################################################
+################################################################################
+################################################################################
+
+
+# GNU make version 3.81 (2006) or higher is required because of the following:
+# - function 'info'
+# - variable '.DEFAULT_GOAL'
+
+# force exit when make version is < 3.81
+ifneq ($(firstword $(sort 3.81 $(MAKE_VERSION))), 3.81)
+  $(error GNU make version 3.81 or higher is required)
+endif
+
+# Relative path to externals root dir in multi-lib source tree like
+# pd-extended SVN. Default is parent of current working directory. May be
+# defined differently in including makefile. This variable is used to probe for
+# paths.
+externalsdir ?= ..
+
+# variable you can use to check if Makefile.pdlibbuilder is already included
+Makefile.pdlibbuilder = true
+
+
+################################################################################
+### variables: library name and version ########################################
+################################################################################
+
+
+# strip possibles spaces from lib.name, they mess up calculated file names
+lib.name := $(strip $(lib.name))
+
+# if meta file exists, check library version
+metafile := $(wildcard $(lib.name)-meta.pd)
+
+ifdef metafile
+  lib.version := $(shell sed -n \
+    's|^\#X text [0-9][0-9]* [0-9][0-9]* VERSION \(.*\);|\1|p' \
+    $(metafile))
+endif
+
+
+################################################################################
+### variables: files ###########################################################
+################################################################################
+
+
+#=== sources ===================================================================
+
+
+# (re)define <classname>.class.sources using file names in class.sources
+
+define add-class-source
+$(notdir $(basename $v)).class.sources += $v
+endef
+
+$(foreach v, $(class.sources), $(eval $(add-class-source)))
+
+# derive class names from <classname>.class.sources variables
+sourcevariables := $(filter %.class.sources, $(.VARIABLES))
+classes := $(basename $(basename $(sourcevariables)))
+
+# accumulate all source files specified in makefile
+classes.sources := $(sort $(foreach v, $(sourcevariables), $($v)))
+all.sources := $(classes.sources) $(lib.setup.sources) \
+  $(shared.sources) $(common.sources)
+
+
+#=== object files ==============================================================
+
+
+# construct object filenames from all C and C++ source file names
+classes.objects := $(addsuffix .o, $(basename $(classes.sources)))
+common.objects := $(addsuffix .o, $(basename $(common.sources)))
+shared.objects := $(addsuffix .o, $(basename $(shared.sources)))
+lib.setup.objects := $(addsuffix .o, $(basename $(lib.setup.sources)))
+all.objects = $(classes.objects) $(common.objects) $(shared.objects) \
+  $(lib.setup.objects)
+
+
+#=== executables ===============================================================
+
+
+# use recursive variables here because executable extension is not yet known
+
+# construct class executable names from class names
+classes.executables = $(addsuffix .$(extension), $(classes))
+
+# construct shared lib executable name if shared sources are defined
+ifdef shared.sources
+  shared.lib = lib$(lib.name).$(shared.extension)
+else
+  shared.lib =
+endif
+
+
+################################################################################
+### variables per platform #####################################################
+################################################################################
+
+
+#=== flags per architecture ====================================================
+
+
+# Set architecture-dependent cflags, mainly for Linux. For Mac and Windows,
+# arch.c.flags are overriden below.
+
+machine := $(shell uname -m)
+
+# Raspberry Pi 1st generation
+ifeq ($(machine), armv6l)
+  arch.c.flags = -march=armv6 -mfpu=vfp -mfloat-abi=hard
+endif
+
+# Beagle, Udoo, RPi2 etc.
+ifeq ($(machine), armv7l)
+  arch.c.flags = -march=armv7-a -mfpu=vfpv3 -mfloat-abi=hard
+endif
+
+# Intel 32 bit, build with SSE and SSE2 instructions
+ifeq ($(findstring $(machine), i386 i686), $(machine))
+  arch.c.flags = -march=pentium4 -mfpmath=sse -msse -msse2
+endif
+
+# Intel/AMD 64 bit, build with SSE, SSE2 and SSE3 instructions
+ifeq ($(findstring $(machine), ia64 x86_64), $(machine))
+  arch.c.flags = -march=core2 -mfpmath=sse -msse -msse2 -msse3
+endif
+
+
+#=== operating system ==========================================================
+
+
+# The following systems are defined: Linux, Darwin, Windows. GNU and
+# GNU/kFreeBSD are treated as Linux to get the same options.
+
+uname := $(shell uname)
+
+ifeq ($(findstring $(uname), Linux GNU GNU/kFreeBSD), $(uname))
+  system = Linux
+endif
+
+ifeq ($(uname), Darwin)
+  system = Darwin
+endif
+
+ifeq ($(findstring MINGW, $(uname)), MINGW)
+  system = Windows
+endif
+
+# TODO: Cygwin, Android
+
+
+#=== flags and paths for Linux =================================================
+
+
+ifeq ($(system), Linux)
+  prefix = /usr/local
+  libdir := $(prefix)/lib
+  pkglibdir = $(libdir)/pd-externals
+  pdincludepath := $(firstword $(dir $(wildcard \
+    $(externalsdir)/../pd/src/m_pd.h \
+    /usr/include/pdextended/m_pd.h \
+    /usr/include/pd/m_pd.h)))
+  extension = pd_linux
+  cpp.flags := -DUNIX
+  c.flags := -fpic
+  c.ldflags := -rdynamic -shared -fpic -Wl,-rpath,"\$$ORIGIN",--enable-new-dtags
+  c.ldlibs := -lc -lm
+  cxx.flags := -fpic -fcheck-new
+  cxx.ldflags := -rdynamic -shared -fpic -Wl,-rpath,"\$$ORIGIN",--enable-new-dtags
+  cxx.ldlibs := -lc -lm -lstdc++
+  shared.extension = so
+  shared.ldflags := -rdynamic -fpic -shared -Wl,-soname,$(shared.lib)
+  stripflags = --strip-unneeded -R .note -R .comment
+endif
+
+
+#=== flags and paths for Darwin ================================================
+
+
+# On OSX we try to build fat binaries by default. It is assumed that OSX i386
+# can build for ppc and OSX x86_64 can't. TODO: try to refine this condition.
+# LLVM-clang doesn't support -fcheck-new, therefore this flag is omitted for
+# OSX x86_64.
+
+ifeq ($(system), Darwin)
+  pkglibdir = $(HOME)/Library/Pd
+  pdincludepath := $(firstword $(dir $(wildcard \
+    $(externalsdir)/../pd/src/m_pd.h \
+    /Applications/Pd-extended.app/Contents/Resources/include/pdextended/m_pd.h \
+    /Applications/Pd.app/Contents/Resources/src/m_pd.h)))
+  extension = pd_darwin
+  cpp.flags := -DUNIX -DMACOSX -I /sw/include
+  c.flags :=
+  c.ldflags := -undefined suppress -flat_namespace -bundle
+  c.ldlibs := -lc
+  cxx.ldflags := -undefined suppress -flat_namespace -bundle
+  cxx.ldlibs := -lc
+  shared.extension = dylib
+  shared.ldflags = -dynamiclib -undefined dynamic_lookup \
+    -install_name @loader_path/$(shared.lib) \
+    -compatibility_version 1 -current_version 1.0
+  stripflags = -x
+  ifeq ($(machine), i386)
+    cxx.flags := -fcheck-new
+    arch.c.flags := -arch ppc -arch i386 -arch x86_64 -mmacosx-version-min=10.4
+    arch.ld.flags := -arch ppc -arch i386 -arch x86_64 -mmacosx-version-min=10.4
+  endif
+  ifeq ($(machine), x86_64)
+    arch.c.flags := -arch i386 -arch x86_64 -mmacosx-version-min=10.5
+    arch.ld.flags := -arch i386 -arch x86_64 -mmacosx-version-min=10.5
+  endif
+endif
+
+
+#=== flags and paths for Windows ===============================================
+
+
+# Standard paths on Windows contain spaces, and GNU make functions treat such
+# paths as lists, with unintended effects. Therefore we must use shell function
+# ls instead of make's wildcard, and probe for each standard path individually.
+# Using double quotes around paths with spaces is obligatory. Since some path
+# variables are assembled or re-expanded later, great care must be taken to put
+# quotes at appropriate points throughout the makefile. Thanks, Bill.
+
+# paths for 32-bit executables on 64-bit Windows aren't yet defined here (TODO)
+ifeq ($(system), Windows)
+  pkglibdir := $(APPDATA)/Pd
+  pdbinpath := $(wildcard $(externalsdir)/../pd/bin/)
+  pdincludepath := $(wildcard $(externalsdir)/../pd/src/)
+  ifndef pdbinpath
+    pdbinpath := $(shell ls -d "$(PROGRAMFILES)/pd/bin/")
+  endif
+  ifndef pdincludepath
+    pdincludepath := $(shell ls -d "$(PROGRAMFILES)/pd/include/pdextended/")
+  endif
+  ifndef pdincludepath
+    pdincludepath := $(shell ls -d "$(PROGRAMFILES)/pd/src/")
+  endif
+endif
+
+# On Windows we build 32 bit by default to match Pd(-extended) binary
+# distributions. This may change in the future.
+# TODO: decide whether -mms-bitfields should be specified.
+ifeq ($(system), Windows)
+  extension = dll
+  CC = gcc
+  CXX = g++
+  arch.c.flags := -march=pentium4 -msse -msse2 -mfpmath=sse
+  cpp.flags := -DMSW -DNT
+  c.flags :=
+  c.ldflags := -static-libgcc -shared \
+    -Wl,--enable-auto-import "$(pdbinpath)pd.dll"
+  c.ldlibs :=
+  cxx.flags := -fcheck-new
+  cxx.ldflags := -static-libstdc++ -shared \
+    -Wl,--enable-auto-import "$(pdbinpath)pd.dll"
+  cxx.ldlibs :=
+  shared.extension = dll
+  shared.ldflags := -static-libgcc -shared "$(pdbinpath)pd.dll"
+  stripflags = --strip-unneeded -R .note -R .comment
+endif
+
+
+#=== paths =====================================================================
+
+
+# Default pkglibdir is specified above per operating system. It is aliased as
+# 'objectsdir' to retain compatibility with pd-extended template. Assignment
+# operator '?=' is used to enable a project-relative path definition in the
+# including makefile.
+objectsdir ?= $(pkglibdir)
+
+# base path where all components of the lib will be installed by default
+installpath := $(DESTDIR)$(objectsdir)/$(lib.name)
+
+# check if pdincludepath contains spaces (as is often the case on Windows)
+# if so, store the path so we can later do checks with it
+pdincludepathwithspaces := $(if $(word 2, $(pdincludepath)), $(pdincludepath))
+
+
+#=== accumulated build flags ===================================================
+
+
+# From GNU make docs: 'Users expect to be able to specify CFLAGS freely
+# themselves.' So we use CFLAGS to define options which  are not strictly
+# required for compilation: optimizations, architecture specifications, and
+# warnings. CFLAGS can be safely overriden using a make command argument.
+# Variables cflags, ldflags and ldlibs may be defined in including makefile.
+
+optimization.flags = -O3 -ffast-math -funroll-loops -fomit-frame-pointer
+warn.flags = -Wall -Wextra -Wshadow -Winline -Wstrict-aliasing
+
+# suppress -Wunused-variable & Co if you don't want to clutter a build log
+ifdef suppress-wunused
+  warn.flags += $(addprefix -Wno-unused-, function parameter value variable)
+endif
+
+CFLAGS = $(warn.flags) $(optimization.flags) $(arch.c.flags)
+
+# preprocessor flags
+cpp.flags += -DPD -I "$(pdincludepath)" $(CPPFLAGS)
+
+# architecture specifications for linker are overridable by LDFLAGS
+LDFLAGS := $(arch.ld.flags)
+
+# now add the same ld flags to shared dynamic lib
+shared.ldflags := $(shared.ldflags) $(LDFLAGS)
+
+# accumulated flags for C compiler / linker
+c.flags := $(cpp.flags) $(c.flags) $(cflags) $(CFLAGS)
+c.ldflags := $(c.ldflags) $(ldflags) $(LDFLAGS)
+c.ldlibs := $(c.ldlibs) $(ldlibs)
+
+# accumulated flags for C++ compiler / linker
+cxx.flags := $(cpp.flags) $(cxx.flags) $(cflags) $(CFLAGS)
+cxx.ldflags := $(cxx.ldflags) $(ldflags) $(LDFLAGS)
+cxx.ldlibs := $(cxx.ldlibs) $(ldlibs)
+
+
+################################################################################
+### variables: tools ###########################################################
+################################################################################
+
+
+# aliases so we can later define 'compile-$1' and set 'c' or 'cxx' as argument
+compile-c := $(CC)
+compile-cxx := $(CXX)
+
+
+################################################################################
+### checks #####################################################################
+################################################################################
+
+
+# At this point most variables are defined. Now do some checks and info's
+# before rules begin.
+
+# 'forward declaration' of default target, needed to do checks
+all:
+
+# To avoid unpredictable results, make sure the default target is not redefined
+# by including makefile.
+ifneq ($(.DEFAULT_GOAL), all)
+  $(error Default target must be 'all'.)
+endif
+
+# find out which target(s) will be made
+ifdef MAKECMDGOALS
+  goals := $(MAKECMDGOALS)
+else
+  goals := all
+endif
+
+# check if m_pd.h is found and print info about it
+$(if $(shell ls "$(pdincludepath)m_pd.h"), \
+  $(info ++++ info: using Pd API $(pdincludepath)m_pd.h), \
+  $(warning Where is your m_pd.h? Do 'make help' for info.))
+
+# print target info
+$(info ++++ info: making target $(goals) $(if $(lib.name),in lib $(lib.name)))
+
+# when installing, print installpath info
+$(if $(filter install install-lib, $(goals)), $(info ++++ info: \
+  installpath is '$(installpath)'))
+
+
+#=== define executables ========================================================
+
+
+# By default we build class executables, and optionally a shared dynamic link
+# lib. When make-lib-executable=yes we build all classes into a single lib
+# executable, on the condition that variable lib.setup.sources is defined.
+
+ifeq ($(make-lib-executable),yes)
+  $(if $(lib.setup.sources), ,\
+    $(error Can not build library blob because lib.setup.sources is undefined))
+  executables := $(lib.name).$(extension)
+else
+  executables := $(classes.executables) $(shared.lib)
+endif
+
+
+################################################################################
+### rules: special targets #####################################################
+################################################################################
+
+
+# Disable built-in rules. If some target can't be built with the specified
+# rules, it should not be built at all.
+MAKEFLAGS += --no-builtin-rules
+
+.PRECIOUS:
+.SUFFIXES:
+.PHONY: all build-classes build-lib $(classes) $(makefiledirs) $(makefiles)\
+        install install-executables install-datafiles install-datadirs \
+        force clean vars allvars depend help
+
+
+################################################################################
+### rules: build targets #######################################################
+################################################################################
+
+
+# target all builds class executables plus optional shared lib
+# or alternatively a single lib executable when make-lib-executable=true
+all: $(executables)
+	$(info ++++ info: $(if $(executables),executables in $(lib.name) completed))
+
+# build all with -g option turned on for debug symbols
+alldebug: c.flags += -g
+alldebug: cxx.flags += -g
+alldebug: all
+
+
+#=== class executable ==========================================================
+
+
+# recipe for linking objects in class executable
+# argument $1 = compiler type (c or cxx)
+# argument $2 = class basename
+define link-class
+  $(compile-$1) \
+  $($1.ldflags) $($2.class.ldflags) \
+  -o $2.$(extension) \
+  $(addsuffix .o, $(basename $($2.class.sources))) \
+  $(addsuffix .o, $(basename $(common.sources))) \
+  $($1.ldlibs) $($2.class.ldlibs) $(shared.lib)
+endef
+
+# general rule for linking object files in class executable
+%.$(extension): $(shared.lib)
+	$(info ++++ info: linking objects in $@ for lib $(lib.name))
+	$(if $(filter %.cc %.cpp, $($*.class.sources)), \
+        $(call link-class,cxx,$*), \
+        $(call link-class,c,$*))
+
+
+#=== library blob ==============================================================
+
+
+# build all classes into single executable
+build-lib: $(lib.name).$(extension)
+	$(info ++++ info: library blob $(lib.name).$(extension) completed)
+
+# recipe for linking objects in lib executable
+# argument $1 = compiler type (c or cxx)
+define link-lib
+  $(compile-$1) \
+  $($1.ldflags) $(lib.ldflags) \
+  -o $(lib.name).$(extension) $(all.objects) \
+  $($1.ldlibs) $(lib.ldlibs)
+endef
+
+# rule for linking objects in lib executable
+# declared conditionally to avoid name clashes
+ifeq ($(make-lib-executable),yes)
+$(lib.name).$(extension): $(all.objects)
+	$(if $(filter %.cc %.cpp, $(all.sources)), \
+        $(call link-lib,cxx), \
+        $(call link-lib,c))
+endif
+
+
+#=== shared dynamic lib ========================================================
+
+
+# recipe for linking objects in shared executable
+# argument $1 = compiler type (c or cxx)
+define link-shared
+  $(compile-$1) \
+  $(shared.ldflags) \
+  -o lib$(lib.name).$(shared.extension) $(shared.objects) \
+  $($1.ldlibs) $(shared.ldlibs)
+endef
+
+# rule for linking objects in shared executable
+# build recipe is in macro 'link-shared'
+lib$(lib.name).$(shared.extension): $(shared.objects)
+	$(info ++++ info: linking objects in shared lib $@)
+	$(if $(filter %.cc %.cpp, $(shared.sources)), \
+        $(call link-shared,cxx), \
+        $(call link-shared,c))
+
+
+#=== object files ==============================================================
+
+
+# recipe to make .o file from source
+# argument $1 is compiler type (c or cxx)
+define make-object-file
+  $(info ++++ info: making $@ in lib $(lib.name))
+  $(compile-$1) \
+  $($1.flags) \
+  -o $@ -c $<
+endef
+
+# Three rules to create .o files. These are double colon 'terminal' rules,
+# meaning they are the last in a rules chain.
+
+%.o:: %.c
+	$(call make-object-file,c)
+
+%.o:: %.cc
+	$(call make-object-file,cxx)
+
+%.o:: %.cpp
+	$(call make-object-file,cxx)
+
+
+#=== explicit prerequisites for class executables ==============================
+
+
+# For class executables, prerequisite rules are declared in run time. Target
+# 'depend' prints these rules for debugging purposes.
+
+# declare explicit prerequisites rule like 'class: class.extension'
+# argument $v is class basename
+define declare-class-target
+$v: $v.$(extension)
+endef
+
+# declare explicit prerequisites rule like 'class.extension: object1.o object2.o'
+# argument $v is class basename
+define declare-class-executable-target
+$v.$(extension): $(addsuffix .o, $(basename $($v.class.sources))) \
+  $(addsuffix .o, $(basename $(common.sources)))
+endef
+
+# evaluate explicit prerequisite rules for all classes
+$(foreach v, $(classes), $(eval $(declare-class-target)))
+$(foreach v, $(classes), $(eval $(declare-class-executable-target)))
+
+
+#=== implicit prerequisites for class executables ==============================
+
+
+# Evaluating implicit prerequisites (header files) with help from the
+# preprocessor is 'expensive' so this is done conditionally and selectively.
+# Note that it is also possible to trigger a build via install targets, in
+# which case implicit prerequisites are not checked.
+
+# When the Pd include path contains spaces it will mess up the implicit
+# prerequisites rules so we do not evaluate them in that case.
+
+ifndef pdincludepathwithspaces
+  must-build-everything := $(filter all default lib, $(goals))
+  must-build-class := $(filter $(classes), $(goals))
+  must-build-sources := $(foreach v, $(must-build-class), $($v.class.sources))
+endif
+
+# declare implicit prerequisites rule like 'object.o: header1.h header2.h ...'
+# argument $1 is input source file(s)
+define declare-object-target
+$(filter %.o: %.h, $(shell $(CPP) $(c.flags) -MM $1)) $(MAKEFILE_LIST)
+endef
+
+# evaluate implicit prerequisite rules when rebuilding everything
+ifdef must-build-everything
+  $(if $(wildcard $(all.objects)), \
+  $(info ++++ info: evaluating implicit prerequisites in lib $(lib.name).....) \
+  $(foreach v, $(all.sources), $(eval $(call declare-object-target, $v))))
+endif
+
+# evaluate implicit prerequisite rules when selectively building classes
+ifdef must-build-class
+  $(foreach v, $(must-build-sources), \
+  $(eval $(call declare-object-target, $v)))
+  $(foreach v, $(shared.sources), \
+  $(eval $(call declare-object-target, $v)))
+endif
+
+
+################################################################################
+### rules: preprocessor and assembly files #####################################
+################################################################################
+
+
+# Preprocessor and assembly output files for bug tracing etc. They are not part
+# of the build processes for executables. By default these files are created in
+# the current working directory. Dependency tracking is not performed, the build
+# is forced instead to make sure it's up to date.
+
+force:
+
+
+#=== preprocessor file =========================================================
+
+
+# make preprocessor output file with extension .pre
+# argument $1 = compiler type (c or cxx)
+define make-preprocessor-file
+  $(info ++++ info: making preprocessor output file $(notdir $*.pre) \
+  in current working directory)
+  $(compile-$1) -E $< $(c.flags) $($1.flags) -o $(notdir $*.pre)
+endef
+
+%.pre:: %.c force
+	$(call make-preprocessor-file,c)
+
+%.pre:: %.cc force
+	$(call make-preprocessor-file,cxx)
+
+%.pre:: %.cpp force
+	$(call make-preprocessor-file,cxx)
+
+
+#=== assembly file =============================================================
+
+
+# make C / assembly interleaved output file with extension .lst
+# argument $1 = compiler type (c or cxx)
+define make-assembly-file
+  $(info ++++ info: making assembly output file $(notdir $*.lst) \
+  in current working directory)
+  $(compile-$1) \
+  -c -Wa,-a,-ad -fverbose-asm \
+  $($1.flags) \
+  $< > $(notdir $*.lst)
+endef
+
+%.lst:: %.c force
+	$(call make-assembly-file,c)
+
+%.lst:: %.cc force
+	$(call make-assembly-file,cxx)
+
+%.lst:: %.cpp force
+	$(call make-assembly-file,cxx)
+
+
+################################################################################
+### rules: installation targets ################################################
+################################################################################
+
+
+# Install targets depend on successful exit status of target all because nothing
+# must be installed in case of a build error.
+
+
+# -p = preserve time stamps
+# -m = set permission mode (as in chmod)
+# -d = create all components of specified directories
+INSTALL = install
+INSTALL_PROGRAM := $(INSTALL) -p -m 644
+INSTALL_DATA := $(INSTALL) -p -m 644
+INSTALL_DIR := $(INSTALL) -m 755 -d
+
+# strip spaces from file names
+executables := $(strip $(executables))
+datafiles := $(strip $(datafiles))
+datadirs := $(strip $(datadirs))
+
+# Do not make any install sub-target with empty variable definition because the
+# install program would exit with an error.
+install: $(if $(executables), install-executables)
+install: $(if $(datafiles), install-datafiles)
+install: $(if $(datadirs), install-datadirs)
+
+install-executables: all
+	$(INSTALL_DIR) -v "$(installpath)"
+	$(INSTALL_PROGRAM) $(executables) "$(installpath)"
+	$(info ++++ info: executables of lib $(lib.name) installed \
+        from $(CURDIR) to $(installpath))
+
+install-datafiles: all
+	$(INSTALL_DIR) -v "$(installpath)"
+	$(INSTALL_DATA) $(datafiles) "$(installpath)"
+	$(info ++++ info: data files of lib $(lib.name) installed \
+        from $(CURDIR) to $(installpath))
+
+install-datadirs: all
+	$(foreach v, $(datadirs), $(INSTALL_DIR) "$(installpath)/$v";)
+	$(foreach v, $(datadirs), \
+        $(INSTALL_DATA) $(wildcard $v/*) "$(installpath)/$v";)
+	$(info ++++ info: data directories of lib $(lib.name) installed \
+        from $(CURDIR) to $(installpath))
+
+
+################################################################################
+### rules: distribution targets ################################################
+################################################################################
+
+
+# TODO
+# These targets are implemented in Makefile Template, but I have to figure out
+# how to do it under the not-so-strict conditions of Makefile.pdlibbuilder.
+
+# make source package
+dist:
+	@echo "target dist not yet implemented"
+
+# make Debian source package
+dpkg-source:
+	@echo "target dpkg-source not yet implemented"
+
+$(ORIGDIR):
+
+$(DISTDIR):
+
+
+################################################################################
+### rules: clean targets #######################################################
+################################################################################
+
+
+# delete build products from build tree
+clean:
+	rm -f $(all.objects)
+	rm -f $(classes.executables) $(lib.name).$(extension) $(shared.lib)
+	rm -f *.pre *.lst
+
+# remove distribution directories and tarballs from build tree
+distclean: clean
+	@echo "target distclean not yet implemented"
+
+
+################################################################################
+### rules: submake targets #####################################################
+################################################################################
+
+
+# Iterate over sub-makefiles or makefiles in other directories.
+
+# When 'continue-make=yes' is set, sub-makes will report 'true' to the parent
+# process regardless of their real exit status. This prevents the parent make
+# from being aborted by a sub-make error. Useful when you want to quickly find
+# out which sub-makes from a large set will succeed.
+ifeq ($(continue-make),yes)
+  continue = || true
+endif
+
+# These targets will trigger sub-make processes for entries in 'makefiledirs'
+# and 'makefiles'.
+all alldebug install clean distclean dist dkpg-source: \
+        $(makefiledirs) $(makefiles)
+
+# this expands to identical rules for each entry in 'makefiledirs'
+$(makefiledirs):
+	$(MAKE) --directory=$@ $(MAKECMDGOALS) $(continue)
+
+# this expands to identical rules for each entry in 'makefiles'
+$(makefiles):
+	$(MAKE) --directory=$(dir $@) --makefile=$(notdir $@) $(MAKECMDGOALS) $(continue)
+
+
+################################################################################
+### rules: convenience targets #################################################
+################################################################################
+
+
+#=== show variables ============================================================
+
+
+# Several 'function' macro's cause errors when expanded within a rule or without
+# proper arguments. Variables which are set with the define directive are only
+# shown by name for that reason.
+functions = \
+add-class-source \
+declare-class-target \
+declare-class-executable-target \
+declare-object-target \
+link-class \
+link-lib \
+link-shared \
+make-object-file \
+make-preprocessor-file \
+make-assembly-file
+
+
+# show variables from makefiles
+vars:
+	$(info ++++ info: showing makefile variables:)
+	$(foreach v,\
+        $(sort $(filter-out $(functions) functions, $(.VARIABLES))),\
+        $(if $(filter file, $(origin $v)),\
+        $(info variable $v = $($v))))
+	$(foreach v, $(functions), $(info 'function' name: $v))
+	@echo
+
+# show all variables
+allvars:
+	$(info ++++ info: showing default, automatic and makefile variables:)
+	$(foreach v, \
+        $(sort $(filter-out $(functions) functions, $(.VARIABLES))), \
+        $(info variable ($(origin $v)) $v = $($v)))
+	$(foreach v, $(functions), $(info 'function' name: $v))
+	@echo
+
+
+#=== show dependencies =========================================================
+
+
+# show generated prerequisites rules
+depend:
+	$(info ++++ info: generated prerequisite rules)
+	$(foreach v, $(classes), $(info $(declare-class-target)))
+	$(foreach v, $(classes), $(info $(declare-class-executable-target)))
+	$(foreach v, $(all.sources), $(info $(call declare-object-target, $v)))
+	@echo
+
+
+#=== show help text ============================================================
+
+
+# brief info about targets and paths
+
+mpdh := $(shell ls "$(pdincludepath)m_pd.h")
+mpdh := $(if $(mpdh), $(mpdh),  m_pd.h not found. Is Pd(-extended) installed?)
+
+
+help:
+	@echo
+	@echo "  Main targets:"
+	@echo "    all:     build executables (default target)"
+	@echo "    install: install all components of the library"
+	@echo "    vars:    print makefile variables for troubleshooting"
+	@echo "    allvars: print all variables for troubleshooting"
+	@echo "    help:    print this help text"
+	@echo
+	@echo "  Pd API m_pd.h:"
+	@echo "    $(shell ls "$(pdincludepath)m_pd.h")"
+	@echo "  You may specify your preferred include path as argument to"
+	@echo "  the make command, like 'pdincludepath=path/to/pd/src'."
+	@echo
+	@echo "  Path for installation of your libdir(s):"
+	@echo "    $(objectsdir)"
+	@echo "  Alternatively you may specify your path for installation as argument"
+	@echo "  to the make command, like 'objectsdir=path/to/pd-externals'."
+	@echo "  For detailed info read the doc sections in Makefile.pdlibbuilder."
+	@echo
+
+
+#=== dummy target ==============================================================
+
+
+coffee:
+	@echo "Makefile.pdlibbuilder: Can not make coffee. Sorry."
+
+
+################################################################################
+### end of rules sections ######################################################
+################################################################################
+
+
+# for syntax highlighting in vim and github
+# vim: set filetype=make:
+
diff --git a/README.txt b/README.txt
index 79cc75f..047d95b 100644
--- a/README.txt
+++ b/README.txt
@@ -5,41 +5,42 @@
 whatsit::
 ---------
 IEMguts is an extension-library (aka: external, plugin) for 
-miller.s.puckette's realtime computer-music environment "Pure data"; 
-it is of no use without Pure data
+miller.s.puckette's realtime computer-music environment "Pure Data"; 
+it is of no use without Pure Data!
 
-IEMguts is a collection of objects that deal with the infrastructure to build 
-better abstractions.
+IEMguts is a collection of low level objects that deal with the infrastructure
+to build better abstractions.
 they might be of no use on their own...
 
 
 danger::
 --------
 IEMguts often deal with non-official internals of Pure data.
-These internals might change in future versions of Pd, rendering IEMguts unuseable.
-Always make sure that you are using IEMguts with the same version as it was compiled with!
-Else you might experience non-functional, crashing or exploding intestines.
+these internals might change in future versions of Pd, rendering IEMguts
+unusable.
+always make sure that you are using IEMguts with the same version of Pd as it
+was compiled with! else you might experience non-functional, crashing or
+exploding intestines.
 
 installation::
 --------------
-#1> cd src/
 #2> make
 #3> make install
 
 note: IEMguts depends on some internal headers of Pd.
 therefore you might have to specify the full path to your Pd-sources
-using the PDROOT environment variable.
-something like
-#2> PDROOT=/home/me/src/pd-0.41-2/ make
-should do the trick
-(PDROOT should point to a directory wherein there is a src/-subdirectory
-containing the sources of the Pd you are running)
+using the 'pdincludepath' make-variable should do the trick.
+something like:
+#2> make pdincludepath=/home/me/src/pd-0.47-0/src
+should do the trick.
+(if you happen to need to the path to the Pd-binaries as well, you
+can additionally use the 'pdbinpath' variable.)
 
 license::
 ---------
-this software is released under the GNU General Public License v2 or later
+this software is released under the GNU General Public License v2 or later.
 you can find the full text of this license in the GnuGPL.txt file that must
-be shipped with this software
+be shipped with this software.
 
 authors::
 ---------
@@ -49,4 +50,3 @@ copyleft 2007- by
 	Institute of Electronic Music and Acoustics,
 	University of Music and Dramatic Arts, Graz, Austria
 
-
diff --git a/help/canvasdelete-help.pd b/help/canvasdelete-help.pd
index b7d9108..91a6ea1 100644
--- a/help/canvasdelete-help.pd
+++ b/help/canvasdelete-help.pd
@@ -1,7 +1,7 @@
-#N canvas 0 16 526 374 10;
+#N canvas 548 244 526 374 10;
 #X obj 45 14 canvasdelete;
-#N canvas 0 103 634 353 canvas 0;
-#N canvas 543 15 194 274 \$0.sandbox 0;
+#N canvas 4 99 634 353 canvas 0;
+#N canvas 543 50 194 274 \$0.sandbox 0;
 #X obj 20 140 t a a;
 #X msg 20 110 Bitte entferne mich!;
 #X obj 20 80 f 20;
@@ -35,23 +35,23 @@ optional argument;
 #X obj 41 145 canvasdelete 1;
 #X text 148 145 will delete the containing canvas (parent-depth:1)
 ;
-#N canvas 0 0 450 300 \$0.examples 0;
+#N canvas 4 49 450 300 \$0.examples 0;
 #X msg 20 100 bang;
 #X obj 20 130 canvasdelete;
 #X text 60 100 this will only delete the [canvasdelete] object itself
 ;
 #X msg 20 200 bang;
-#N canvas 0 0 450 300 1002.parent-deletion 0;
+#N canvas 4 49 450 300 1003.parent-deletion 0;
 #X obj 20 20 inlet;
 #X obj 20 50 delay 1000;
 #X obj 20 80 canvasdelete 1;
 #X connect 0 0 1 0;
 #X connect 1 0 2 0;
-#X restore 20 230 pd 1002.parent-deletion;
+#X restore 20 230 pd 1003.parent-deletion;
 #X text 60 200 the containing [canvasdelete 1] will delete the entire
 subpatch after 1 second;
 #X msg 20 20 click here to regenerate this patch;
-#X obj 20 40 s 1002.init;
+#X obj 20 40 s 1003.init;
 #X connect 0 0 1 0;
 #X connect 3 0 4 0;
 #X connect 6 0 7 0;
@@ -59,7 +59,7 @@ subpatch after 1 second;
 #X text 40 212 two examples on how to use this:;
 #X text 43 249 for advanced lovers of dynamic patching:;
 #N canvas 41 71 418 300 \$0.init 0;
-#N canvas 53 36 735 315 dynamic 0;
+#N canvas 53 50 735 315 dynamic 0;
 #X obj 56 73 r \$0.init;
 #X obj 56 97 t b;
 #X obj 56 119 del;
@@ -74,7 +74,7 @@ subpatch after 1 second;
 #X obj 502 163 del 2000;
 #X text 509 54 autoclose;
 #X text 83 122 protect against self-deletion (might crash);
-#N canvas 0 0 450 300 canvas.messages 0;
+#N canvas 0 50 450 300 canvas.messages 0;
 #X msg 29 168 clear \, obj 20 140 t a a \, msg 20 110 Bitte entferne
 mich! \, obj 20 80 f 20;
 #X obj 29 208 s pd-\$0.sandbox;
@@ -82,10 +82,10 @@ mich! \, obj 20 80 f 20;
 #X connect 0 0 1 0;
 #X connect 2 0 0 0;
 #X restore 85 251 pd canvas.messages;
-#N canvas 0 0 450 300 examples 0;
+#N canvas 0 50 450 300 examples 0;
 #X obj 89 254 s pd-\$0.examples;
 #X msg 149 214 clear;
-#N canvas 0 0 781 300 withmakesubpatch 0;
+#N canvas 0 50 781 300 withmakesubpatch 0;
 #X obj 91 10 inlet;
 #X obj 88 292 outlet;
 #X obj 91 32 t b;
@@ -116,7 +116,7 @@ obj 20 80 canvasdelete 1 \, connect 0 0 1 0 \, connect 1 0 2 0;
 #X connect 11 0 1 0;
 #X restore 109 157 pd withmakesubpatch;
 #X obj 89 89 t b;
-#N canvas 0 0 450 300 nosubpatch 0;
+#N canvas 0 50 450 300 nosubpatch 0;
 #X obj 111 19 inlet;
 #X obj 126 219 outlet;
 #X msg 21 118 msg 20 100 bang \, obj 20 130 canvasdelete \, text 60
@@ -126,7 +126,7 @@ obj 20 80 canvasdelete 1 \, connect 0 0 1 0 \, connect 1 0 2 0;
 #X connect 2 0 1 0;
 #X restore 129 133 pd nosubpatch;
 #X obj 89 109 t b b b b;
-#N canvas 0 0 671 300 initializer 0;
+#N canvas 0 50 671 300 initializer 0;
 #X obj 73 19 inlet;
 #X obj 73 252 outlet;
 #X obj 73 41 t b;
@@ -169,3 +169,17 @@ obj 20 80 canvasdelete 1 \, connect 0 0 1 0 \, connect 1 0 2 0;
 #X text 182 397 secret init stuff;
 #X text 42 311 (c) 2010 IOhannes m zmoelnig \, Roman Haefeli;
 #X text 77 334 this is part of iemguts;
+#X text 48 281 shut down a top-level patch:;
+#N canvas 4 49 685 353 close 0;
+#X obj 109 285 canvasdelete 2;
+#X msg 109 266 bang;
+#X text 31 69 you can also close the top-level patch (which was opened
+via File->Open rather than instantiated as an abstraction).;
+#X msg 108 150 bang;
+#X obj 108 170 canvasdelete 3;
+#X text 229 273 parent-depth:2 is the top-level patch;
+#X text 217 157 parent-depth:3 does not exist (one level too above
+top-level patch) - so this won't do anything;
+#X connect 1 0 0 0;
+#X connect 3 0 4 0;
+#X restore 271 282 pd close top-level patch;
diff --git a/help/closebang-help.pd b/help/closebang-help.pd
new file mode 100644
index 0000000..8a4c7a1
--- /dev/null
+++ b/help/closebang-help.pd
@@ -0,0 +1,9 @@
+#N canvas 612 413 505 298 10;
+#X obj 28 38 closebang;
+#X text 108 39 emits a bang when an abstraction is deleted.;
+#X text 41 126 [closebang] notifies you when an abstraction is about
+to be deleted \, so you can:;
+#X text 52 162 - cleanup ressources;
+#X text 52 177 - keep track of instances (PUSH);
+#X text 52 193 - say goodbye;
+#X text 24 240 note: [closebang] requires Pd>=0.47;
diff --git a/help/findbrokenobjects-help.pd b/help/findbrokenobjects-help.pd
new file mode 100644
index 0000000..5fc7e9a
--- /dev/null
+++ b/help/findbrokenobjects-help.pd
@@ -0,0 +1,55 @@
+#N canvas 255 179 867 556 10;
+#X obj 57 19 findbrokenobjects;
+#X obj 59 494 /dev/device;
+#X obj 170 493 color 1;
+#X text 202 18 finds broken objects;
+#N canvas 321 143 706 395 subpatch 0;
+#X msg 37 129 bang;
+#X msg 309 129 bang;
+#X obj 309 153 findbrokenobjects 0;
+#X obj 37 153 findbrokenobjects;
+#X text 33 73 without args \, it finds ALL broken objects in the running
+Pd-instance, f 23;
+#X msg 511 129 bang;
+#X obj 511 153 findbrokenobjects 1;
+#X text 507 56 an argument specifies the search root. '1' will search
+the parent canvas and its children, f 23;
+#X text 304 56 an argument specifies the search root. '0' will only
+search in this canvas and its children, f 23;
+#X obj 375 289 /////////////;
+#X text 201 290 another unknown object:;
+#X obj 511 175 print borked-in-parent;
+#X obj 309 175 print borked-here;
+#X obj 37 175 print all;
+#X connect 0 0 3 0;
+#X connect 1 0 2 0;
+#X connect 2 0 12 0;
+#X connect 3 0 13 0;
+#X connect 5 0 6 0;
+#X connect 6 0 11 0;
+#X restore 102 292 pd subpatch;
+#X text 33 254 if you don't give an argument \, the entire Pd-instance
+is searched., f 66;
+#X msg 44 353 verbose 1 \, bang;
+#X obj 44 375 findbrokenobjects;
+#X text 31 205 arguments: you can pass a number (int>=0) as argument
+to [findbrokenobjects] to limit the search to a given root-canvas and
+it's children. '0' is the canvas the [findbrokenobjects] object lives
+in \, '1' is it's parent-canvas and so on., f 80;
+#X text 198 293 <- open to see rooted-search in action;
+#X text 245 493 <- a few broken objects...;
+#X text 185 363 when "verbose" is turned on \, the objects are also
+printed to the console where you can <Ctrl>-<Click> them;
+#X msg 54 67 bang;
+#X obj 54 133 print not-found;
+#X obj 54 111 route not-found not-created;
+#X text 180 129 objects that are broken because Pd doesn't know how
+to create them;
+#X obj 147 167 print not-created;
+#X text 281 165 objects that failed to create for other reasons;
+#X obj 54 89 findbrokenobjects;
+#X connect 6 0 7 0;
+#X connect 12 0 18 0;
+#X connect 14 0 13 0;
+#X connect 14 1 16 0;
+#X connect 18 0 14 0;
diff --git a/help/ib_demux.pd b/help/ib_demux.pd
new file mode 100644
index 0000000..30b0706
--- /dev/null
+++ b/help/ib_demux.pd
@@ -0,0 +1,141 @@
+#N canvas 299 382 555 300 10;
+#X obj 182 96 inlet;
+#X obj 303 96 inlet index;
+#X obj 182 126 send;
+#X obj 231 96 initbang;
+#N canvas 635 253 727 361 guts 0;
+#X obj 66 309 sendcanvas 1;
+#N canvas 852 153 450 491 cleanup 0;
+#X obj 113 166 inlet;
+#X obj 113 187 canvasindex 1;
+#X obj 201 231 t f b;
+#X obj 201 253 until;
+#X obj 123 435 canvasdelete;
+#X msg 201 351 delete \$1;
+#X obj 201 373 outlet;
+#X obj 244 184 r \$0-skipobjects;
+#X obj 201 286 i 5;
+#X obj 244 206 t f f;
+#X obj 201 209 - 5;
+#X text 15 62 this uses [canvasindex] to get the number of objects
+in the grandparent-patch (the first-level patch of [ib_demux]).;
+#X text 32 24 cleanup unwanted objects.;
+#X text 15 95 \$0-skipobjects is the number (N) of objects that should
+be kept (the fixed objects are created first \, so they occupy the
+IDs 0..N. everything after N is a dynamically created object which
+we want to remove \, so we can create anew).;
+#X connect 0 0 1 0;
+#X connect 1 1 10 0;
+#X connect 2 0 3 0;
+#X connect 3 0 8 0;
+#X connect 5 0 6 0;
+#X connect 7 0 9 0;
+#X connect 8 0 5 0;
+#X connect 9 0 10 1;
+#X connect 9 1 8 1;
+#X connect 10 0 2 0;
+#X restore 183 241 pd cleanup;
+#X msg 164 95 bang;
+#N canvas 568 189 677 449 creator 0;
+#X obj 63 89 inlet;
+#X obj 62 379 outlet;
+#X obj 179 231 r \$0-skipobjects;
+#X obj 87 280 + 50;
+#X obj 142 254 +;
+#X obj 142 276 t f f;
+#X obj 174 299 + 1;
+#X obj 63 111 t f b;
+#X obj 63 133 until;
+#X obj 63 155 i;
+#X obj 63 177 t f f;
+#X obj 94 154 + 1;
+#X msg 108 135 0;
+#X obj 142 231 * 2;
+#X obj 62 203 t f f f b;
+#X obj 87 258 * 70;
+#X msg 62 357 obj \$2 200 r \$5-\$1 \, obj \$2 230 outlet #\$1 \, connect
+\$3 0 \$4 0;
+#X obj 62 319 pack 0 0 0 0 \$0;
+#X text 63 20 this creates N output structures (a [send \$0-#] and
+an [outlet] object which are connected).;
+#X text 70 50 for connecting them up \, we need to know their patch-IDs
+\, which we can calculate if we know the number of (fixed) objects
+in the patch (given via \$0-skipobjects);
+#X text 274 266 #1: index;
+#X text 274 281 #2: x-position;
+#X text 274 296 #3: canvas-ID of [send];
+#X text 274 311 #4: canvas-ID of [outlet];
+#X text 274 326 #5: \$0 (pre-expanded);
+#X connect 0 0 7 0;
+#X connect 2 0 4 1;
+#X connect 3 0 17 1;
+#X connect 4 0 5 0;
+#X connect 5 0 17 2;
+#X connect 5 1 6 0;
+#X connect 6 0 17 3;
+#X connect 7 0 8 0;
+#X connect 7 1 12 0;
+#X connect 8 0 9 0;
+#X connect 9 0 10 0;
+#X connect 10 0 14 0;
+#X connect 10 1 11 0;
+#X connect 11 0 9 1;
+#X connect 12 0 9 1;
+#X connect 13 0 4 0;
+#X connect 14 0 17 0;
+#X connect 14 1 15 0;
+#X connect 14 2 13 0;
+#X connect 15 0 3 0;
+#X connect 16 0 1 0;
+#X connect 17 0 16 0;
+#X restore 66 244 pd creator;
+#X obj 66 141 i \$1;
+#X obj 66 207 t f;
+#X msg 66 185 2;
+#X obj 67 163 moses 1;
+#X obj 66 97 inlet;
+#X obj 520 209 max 0;
+#X obj 520 231 pack 0 \$0;
+#X msg 520 253 symbol \$2-\$1;
+#X obj 520 275 outlet;
+#X obj 520 155 inlet;
+#X obj 66 279 t a a;
+#X obj 301 190 s \$0-skipobjects;
+#X obj 66 119 t b b b b;
+#X obj 520 187 i \$2;
+#X msg 183 220 bang;
+#X msg 301 168 7;
+#X text 100 40 [pd cleanup] removes unwanted objects;
+#X text 101 57 [pd creator] creates a number of send/outlet pairs and
+connects them.;
+#X text 59 17 here's the fun part:;
+#X connect 1 0 14 0;
+#X connect 2 0 16 0;
+#X connect 3 0 14 0;
+#X connect 4 0 7 0;
+#X connect 5 0 3 0;
+#X connect 6 0 5 0;
+#X connect 7 0 6 0;
+#X connect 7 1 5 0;
+#X connect 8 0 16 0;
+#X connect 9 0 10 0;
+#X connect 10 0 11 0;
+#X connect 11 0 12 0;
+#X connect 13 0 17 0;
+#X connect 14 0 0 0;
+#X connect 16 0 4 0;
+#X connect 16 1 18 0;
+#X connect 16 2 19 0;
+#X connect 16 3 17 0;
+#X connect 17 0 9 0;
+#X connect 18 0 1 0;
+#X connect 19 0 15 0;
+#X restore 231 126 pd guts;
+#X text 85 165 vv- below this line \, everything is created dynamically
+-vv;
+#X text 38 30 [ib_demux] is an abstraction implementation of a demultiplexer
+\, it uses [initbang] to create a dynamic number of outlets.;
+#X connect 0 0 2 0;
+#X connect 1 0 4 1;
+#X connect 3 0 4 0;
+#X connect 4 0 2 1;
diff --git a/help/initbang-help.pd b/help/initbang-help.pd
new file mode 100644
index 0000000..a27dcf1
--- /dev/null
+++ b/help/initbang-help.pd
@@ -0,0 +1,40 @@
+#N canvas 541 256 656 407 10;
+#X obj 24 47 initbang;
+#X text 100 41 emits a bang right after the abstraction got loaded
+(and *before* the parent patch continues to load);
+#X floatatom 64 206 5 0 0 0 - - -, f 5;
+#X obj 124 207 hradio 15 1 0 2 empty empty empty 0 -8 0 10 -262144
+-1 -1 1;
+#X obj 403 199 hradio 15 1 0 4 empty empty empty 0 -8 0 10 -262144
+-1 -1 0;
+#X obj 308 277 print B1;
+#X obj 308 299 print B2;
+#X obj 373 277 print B3;
+#X obj 373 299 print B4;
+#X floatatom 64 263 5 0 0 0 - - -, f 5;
+#X floatatom 124 263 5 0 0 0 - - -, f 5;
+#X text 59 327 note: [initbang] will *not* trigger in [subpatches]
+;
+#X text 76 88 this makes it possible to create abstractions with variable
+iolets (something that is not possible with [loadbang]).;
+#X obj 308 225 ib_demux 4 1;
+#X obj 64 241 ib_demux 2;
+#X floatatom 308 177 5 0 0 0 - - -, f 5;
+#X msg 308 199 foo bar \$1;
+#X text 40 134 [ib_demux] is an abstraction. the number of outlets is
+given as the 1st argument! (2nd argument is the initially selected
+outlet);
+#X text 59 348 note2: if you are running an older version of Pd \,
+the [ib_demux] objects might not have outlets due to [initbang] not
+working properly.;
+#X connect 2 0 14 0;
+#X connect 3 0 14 1;
+#X connect 4 0 13 1;
+#X connect 13 0 5 0;
+#X connect 13 1 6 0;
+#X connect 13 2 7 0;
+#X connect 13 3 8 0;
+#X connect 14 0 9 0;
+#X connect 14 1 10 0;
+#X connect 15 0 16 0;
+#X connect 16 0 13 0;
diff --git a/iemguts-meta.pd b/iemguts-meta.pd
index 26f98f8..e24dc70 100644
--- a/iemguts-meta.pd
+++ b/iemguts-meta.pd
@@ -2,5 +2,5 @@
 #N canvas 25 49 420 300 META 1;
 #X text 13 41 NAME iemguts;
 #X text 10 25 AUTHOR forum::für::umläute;
-#X text 10 10 VERSION 0.1;
+#X text 10 10 VERSION 0.2;
 #X restore 10 10 pd META;
diff --git a/src/autoabstraction.c b/src/autoabstraction.c
index 9eec17d..56e7ae1 100644
--- a/src/autoabstraction.c
+++ b/src/autoabstraction.c
@@ -1,7 +1,11 @@
-/* Copyright (c) 2008 IOhannes m zmölnig @ IEM
+/* Copyright (c) 2008 IOhannes m zmölnig @ IEM
  * For information on usage and redistribution, and for a DISCLAIMER OF ALL
  * WARRANTIES, see the file, "LICENSE.txt," that comes with Pd.  
- */
+ ******************************************************
+ *
+ * license: GNU General Public License v.2 (or later)
+ *
+ ******************************************************/
 
 /*
  * this code adds an external "loader" to Miller S. Puckette's "pure data",
@@ -23,7 +27,7 @@
 # define MSW
 #endif
 
-#include "m_pd.h"
+#include "iemguts.h"
 
 
 typedef struct _autoabstraction
@@ -34,15 +38,12 @@ static t_class *autoabstraction_class;
 
 static int s_state=0;
 
-static char *version = "$Revision: 0.1 $";
-
 /* this is the name of the filename that get's loaded as a default template for new abstractions */
 static char*s_templatefilename="autoabstraction.template";
 /* if the loading above fails, we resort to a simple default abstraction that automatically opens up */
 /* LATER: make the font-size the same as the one used by Pd */
 static char*s_templatestring="#N canvas 0 0 450 300 10; #X vis 1;";
 
-
 #if (PD_MINOR_VERSION >= 40)
 # define AUTOABSTRACTION_ENABLED 1
 #endif
@@ -103,14 +104,14 @@ static int autoabstraction_loader(t_canvas *canvas, char *classname)
   int fd=0;
   char dirbuf[MAXPDSTRING], *nameptr;
 
-  if((fd=canvas_open(canvas, classname, ".pd", dirbuf, &nameptr, MAXPDSTRING, 0)) >= 0 ||
-     (fd=canvas_open(canvas, classname, ".pat", dirbuf, &nameptr, MAXPDSTRING, 0)) >= 0)
+  if((fd=canvas_open(canvas, classname, ".pd", dirbuf, &nameptr, MAXPDSTRING, 0)) >= 0)
     {
       /* oops, there's already an abstraction of the given <classname> */
       close(fd);
       return(0);
     }
 
+  /* none! we create one, so Pd can later find it... */
   autoabstraction_createpatch(canvas, classname);
 
   /* we always fail, because we want Pd to do the real opening of abstractions */
@@ -160,15 +161,12 @@ static void*autoabstraction_new(t_symbol *s, int argc, t_atom *argv)
 void autoabstraction_setup(void)
 {
   /* relies on t.grill's loader functionality, fully added in 0.40 */
-  post("automatic abstraction creator %s",version);  
-  post("\twritten by IOhannes m zmoelnig, IEM <zmoelnig at iem.at>");
-  post("\tcompiled on "__DATE__" at "__TIME__ " ");
-  post("\tcompiled against Pd version %d.%d.%d.%s", PD_MAJOR_VERSION, PD_MINOR_VERSION, PD_BUGFIX_VERSION, PD_TEST_VERSION);
+  iemguts_boilerplate("automatic abstraction creator", 0);
 #ifdef AUTOABSTRACTION_ENABLED
   autoabstraction_initialize();
   sys_register_loader(autoabstraction_loader);
 #else
-  error("to function, this needs to be compiled against Pd 0.40 or higher,\n");
+  error("autoabstraction needs to be compiled against Pd 0.40 or higher,\n");
   error("\tor a version that has sys_register_loader()");
 #endif
 
diff --git a/src/canvasargs.c b/src/canvasargs.c
index a3c733f..190570d 100644
--- a/src/canvasargs.c
+++ b/src/canvasargs.c
@@ -2,15 +2,15 @@
  *
  * canvasargs - implementation file
  *
- * copyleft (c) IOhannes m zm-bölnig-A
+ * copyleft (c) IOhannes m zmölnig
  *
- *   2007:forum::f-bür::umläute:2007-A
+ *   2007:forum::für::umläute:2007
  *
  *   institute of electronic music and acoustics (iem)
  *
  ******************************************************
  *
- * license: GNU General Public License v.2
+ * license: GNU General Public License v.2 (or later)
  *
  ******************************************************/
 
@@ -31,7 +31,7 @@
  * nice, eh?
  */
 
-#include "m_pd.h"
+#include "iemguts.h"
 #include "g_canvas.h"
 
 
@@ -49,11 +49,10 @@ typedef struct _canvasargs
 
 static void canvasargs_list(t_canvasargs *x, t_symbol*s, int argc, t_atom*argv)
 {
-  t_canvas*c=x->x_canvas;
   t_binbuf*b=0;
   t_atom name[1];
 
-  if(!x->x_canvas) return;
+  if(!x || !x->x_canvas) return;
   b=x->x_canvas->gl_obj.te_binbuf;
 
   if(!b)return;
@@ -112,6 +111,7 @@ static void *canvasargs_new(t_floatarg f)
 
 void canvasargs_setup(void)
 {
+  iemguts_boilerplate("[canvasargs]", 0);
   canvasargs_class = class_new(gensym("canvasargs"), (t_newmethod)canvasargs_new,
                                (t_method)canvasargs_free, sizeof(t_canvasargs), 0, A_DEFFLOAT, 0);
   class_addlist(canvasargs_class, (t_method)canvasargs_list);
diff --git a/src/canvasconnections.c b/src/canvasconnections.c
index 2d29e79..d2338fd 100644
--- a/src/canvasconnections.c
+++ b/src/canvasconnections.c
@@ -3,15 +3,15 @@
  *
  * canvasconnections - implementation file
  *
- * copyleft (c) IOhannes m zmölnig
+ * copyleft (c) IOhannes m zmölnig
  *
- *   2008:forum::für::umläute:2008
+ *   2008:forum::für::umläute:2008
  *
  *   institute of electronic music and acoustics (iem)
  *
  ******************************************************
  *
- * license: GNU General Public License v.2
+ * license: GNU General Public License v.2 (or later)
  *
  ******************************************************/
 
@@ -23,7 +23,7 @@
  * e.g. [canvasconnections 1] will query the parent of the containing canvas
  */
 
-#include "m_pd.h"
+#include "iemguts.h"
 #include "g_canvas.h"
 #include "m_imp.h"
 #include <string.h>
@@ -114,7 +114,6 @@ static int query_inletconnections(t_canvasconnections *x, t_intvec***outobj, t_i
   t_intvec**invecs=NULL;
   t_intvec**inwhich=NULL;
   int ninlets=0;
-  int nin=0;
  
   t_gobj*y;
 
@@ -208,7 +207,6 @@ static void canvasconnections_queryinlets(t_canvasconnections *x)
 static void canvasconnections_inlet(t_canvasconnections *x, t_floatarg f)
 {
   int inlet=f;
-  t_atom at;
   t_intvec**invecs=0;
   int ninlets=query_inletconnections(x, &invecs, 0); 
 
@@ -325,7 +323,6 @@ static void canvasconnections_outconnect(t_canvasconnections *x, t_floatarg f)
     t_outconnect*conn=obj_starttraverseoutlet(x->x_object, &out, outlet);
     t_object*dest=0;
     t_inlet*in=0;
-    int count=0;
     int id=glist_getindex(x->x_parent, (t_gobj*)x->x_object);
 
     conn=obj_starttraverseoutlet(x->x_object, &out, outlet);
@@ -349,7 +346,6 @@ static void canvasconnections_outconnect(t_canvasconnections *x, t_floatarg f)
 static void canvasconnections_outlet(t_canvasconnections *x, t_floatarg f)
 {
   int outlet=f;
-  t_atom*at=NULL;
   int noutlets=0;
 
   if(0==x->x_object || 0==x->x_parent)
@@ -476,6 +472,7 @@ static void *canvasconnections_new(t_floatarg f)
 
 void canvasconnections_setup(void)
 {
+  iemguts_boilerplate("[canvasconnections]", 0);
   canvasconnections_class = class_new(gensym("canvasconnections"), 
                                       (t_newmethod)canvasconnections_new, (t_method)canvasconnections_free, 
                                       sizeof(t_canvasconnections), 0, 
diff --git a/src/canvasdelete.c b/src/canvasdelete.c
index 843af6b..9e9f934 100644
--- a/src/canvasdelete.c
+++ b/src/canvasdelete.c
@@ -3,24 +3,24 @@
  *
  * canvasdelete - implementation file
  *
- * copyleft (c) IOhannes m zmölnig
+ * copyleft (c) IOhannes m zmölnig
  *
- *   2007:forum::für::umläute:2007
+ *   2007:forum::für::umläute:2007
  *
  *   institute of electronic music and acoustics (iem)
  *
  ******************************************************
  *
- * license: GNU General Public License v.2
+ * license: GNU General Public License v.2 (or later)
  *
  ******************************************************/
 
 
-/* 
+/*
  * this object deletes itself (or the specified parent canvas) when banged
  */
 
-#include "m_pd.h"
+#include "iemguts.h"
 
 #include "g_canvas.h"
 
@@ -43,22 +43,25 @@ static void canvasdelete_doit(t_canvasdelete *x)
   clock_free(x->x_clock);
   x->x_clock=NULL;
 
-  glist_delete(x->x_glist, x->x_gobj);
+  if(x->x_glist)
+    glist_delete(x->x_glist, x->x_gobj);
+  else {
+    t_atom ap[1];
+    SETFLOAT(ap, 1);
+    typedmess(x->x_gobj, gensym("menuclose"), 1, ap);
+  }
+
 
   canvas_resume_dsp(dspstate);
 }
 
 static void canvasdelete_bang(t_canvasdelete *x)
 {
-  int x1=0, y1=0, width=0, height=0;
-  t_atom alist[2];
-
   if(x->x_clock) {
     pd_error(x, "deletion already scheduled");
     return;
   }
-
-  if(NULL==x->x_glist || NULL==x->x_gobj)return;
+  if(NULL==x->x_gobj)return;
 
   x->x_clock=clock_new(x, (t_method)canvasdelete_doit);
   clock_delay(x->x_clock, 0);
@@ -71,7 +74,7 @@ static void *canvasdelete_new(t_floatarg f)
   t_canvas *canvas=(t_canvas*)glist_getcanvas(glist);
   t_gobj*obj=(t_gobj*)x;
   int depth=(int)f;
-  
+
   if(depth<0)depth=0;
 
   while(depth && canvas) {
@@ -80,9 +83,12 @@ static void *canvasdelete_new(t_floatarg f)
     depth--;
   }
 
-  x->x_glist = canvas;
-  x->x_gobj=obj;
-  
+  x->x_glist = x->x_gobj = NULL;
+  if (!depth) {
+    x->x_glist = canvas;
+    x->x_gobj=obj;
+  }
+
   x->x_clock=NULL;
 
   return (x);
@@ -97,8 +103,9 @@ static void canvasdelete_canvasmethods(void);
 
 void canvasdelete_setup(void)
 {
-  canvasdelete_class = class_new(gensym("canvasdelete"), 
-                                 (t_newmethod)canvasdelete_new, (t_method)canvasdelete_free, 
+  iemguts_boilerplate("[canvasdelete] - delete message for the canvas", 0);
+  canvasdelete_class = class_new(gensym("canvasdelete"),
+                                 (t_newmethod)canvasdelete_new, (t_method)canvasdelete_free,
                                  sizeof(t_canvasdelete), 0,
                                  A_DEFFLOAT, 0);
   class_addbang(canvasdelete_class, (t_method)canvasdelete_bang);
@@ -110,7 +117,7 @@ void canvasdelete_setup(void)
 /* 'delete' message for the canvas */
 static int canvas_delete_docb(t_glist*glist, int index) {
   /* this will crash Pd if the object to be deleted is on the stack
-   * workarounds: 
+   * workarounds:
    *   - use a clock (see above)
    *   - finally fix this in Pd
    */
@@ -157,6 +164,5 @@ static void canvasdelete_canvasmethods(void) {
     verbose(0, "adding 'delete' method to canvas");
     class_addmethod(canvas_class, (t_method)canvas_delete_cb, gensym("delete"), A_GIMME, 0);
   }
-
 }
 
diff --git a/src/canvasdollarzero.c b/src/canvasdollarzero.c
index 6a43eb9..5d9d7e4 100644
--- a/src/canvasdollarzero.c
+++ b/src/canvasdollarzero.c
@@ -1,10 +1,25 @@
-/* For information on usage and redistribution, and for a DISCLAIMER OF ALL
-* WARRANTIES, see the file, "LICENSE.txt," in this distribution.
 
-based on iemlib2 written by Thomas Musil, Copyright (c) IEM KUG Graz Austria 2000 - 2006 */
+/******************************************************
+ *
+ * canvasdollarzero - implementation file
+ *
+ *
+ * copyleft (c) IOhannes m zmölnig
+ *
+ *   2007:forum::für::umläute:2007
+ *
+ *   institute of electronic music and acoustics (iem)
+ *
+ * based on iemlib2 
+ *   copyright (c) 2000-2006 Thomas Musil, IEM, KUG, Graz/Austria
+ *
+ ******************************************************
+ *
+ * license: GNU General Public License v.2 (or later)
+ *
+ ******************************************************/
 
-
-#include "m_pd.h"
+#include "iemguts.h"
 #include "g_canvas.h"
 
 
@@ -50,6 +65,7 @@ static void *canvasdollarzero_new(t_floatarg f)
 
 void canvasdollarzero_setup(void)
 {
+  iemguts_boilerplate("[canvasdollarzero]", 0);
   canvasdollarzero_class = class_new(gensym("canvasdollarzero"), 
                                      (t_newmethod)canvasdollarzero_new, 0, 
                                      sizeof(t_canvasdollarzero), 0, 
diff --git a/src/canvaserror.c b/src/canvaserror.c
index 29a8004..5c38f46 100644
--- a/src/canvaserror.c
+++ b/src/canvaserror.c
@@ -3,15 +3,15 @@
  *
  * canvaserror - implementation file
  *
- * copyleft (c) IOhannes m zm-bölnig-A
+ * copyleft (c) IOhannes m zmölnig
  *
- *   2007:forum::f-bür::umläute:2007-A
+ *   2007:forum::für::umläute:2007
  *
  *   institute of electronic music and acoustics (iem)
  *
  ******************************************************
  *
- * license: GNU General Public License v.2
+ * license: GNU General Public License v.2 (or later)
  *
  ******************************************************/
 
@@ -32,7 +32,7 @@
  * nice, eh?
  */
 
-#include "m_pd.h"
+#include "iemguts.h"
 #include "g_canvas.h"
 
 
@@ -100,6 +100,7 @@ static void *canvaserror_new(t_floatarg f)
 
 void canvaserror_setup(void)
 {
+  iemguts_boilerplate("[canvaserror]", 0);
   canvaserror_class = class_new(gensym("canvaserror"), (t_newmethod)canvaserror_new,
                                (t_method)canvaserror_free, sizeof(t_canvaserror), 0, A_DEFFLOAT, 0);
   class_addanything(canvaserror_class, (t_method)canvaserror_any);
diff --git a/src/canvasindex.c b/src/canvasindex.c
index 6633c1b..9fa0668 100644
--- a/src/canvasindex.c
+++ b/src/canvasindex.c
@@ -3,15 +3,15 @@
  *
  * canvasindex - implementation file
  *
- * copyleft (c) IOhannes m zmölnig
+ * copyleft (c) IOhannes m zmölnig
  *
- *   2007:forum::für::umläute:2007
+ *   2007:forum::für::umläute:2007
  *
  *   institute of electronic music and acoustics (iem)
  *
  ******************************************************
  *
- * license: GNU General Public License v.2
+ * license: GNU General Public License v.2 (or later)
  *
  ******************************************************/
 
@@ -27,7 +27,7 @@
  * abstraction that holds this object
  */
 
-#include "m_pd.h"
+#include "iemguts.h"
 #include "m_imp.h"
 #include "g_canvas.h"
 
@@ -150,6 +150,7 @@ static void *canvasindex_new(t_floatarg f)
 
 void canvasindex_setup(void)
 {
+  iemguts_boilerplate("[canvasindex]", 0);
   canvasindex_class = class_new(gensym("canvasindex"), 
                                 (t_newmethod)canvasindex_new, (t_method)canvasindex_free, 
                                 sizeof(t_canvasindex), 0, 
diff --git a/src/canvasname.c b/src/canvasname.c
index 8bcbf6a..bf7cc14 100644
--- a/src/canvasname.c
+++ b/src/canvasname.c
@@ -3,15 +3,15 @@
  *
  * canvasname - implementation file
  *
- * copyleft (c) IOhannes m zm-bölnig-A
+ * copyleft (c) IOhannes m zmölnig
  *
- *   2007:forum::f-bür::umläute:2007-A
+ *   2007:forum::für::umläute:2007
  *
  *   institute of electronic music and acoustics (iem)
  *
  ******************************************************
  *
- * license: GNU General Public License v.2
+ * license: GNU General Public License v.2 (or later)
  *
  ******************************************************/
 
@@ -32,7 +32,7 @@
  * nice, eh?
  */
 
-#include "m_pd.h"
+#include "iemguts.h"
 #include "g_canvas.h"
 
 
@@ -132,6 +132,7 @@ static void *canvasname_new(t_floatarg f)
 
 void canvasname_setup(void)
 {
+  iemguts_boilerplate("[canvasname]", 0);
   canvasname_class = class_new(gensym("canvasname"), (t_newmethod)canvasname_new,
                                (t_method)canvasname_free, sizeof(t_canvasname), 0, A_DEFFLOAT, 0);
   class_addsymbol(canvasname_class, (t_method)canvasname_symbol);
diff --git a/src/canvasobjectposition.c b/src/canvasobjectposition.c
index a8b2ded..b7798a3 100644
--- a/src/canvasobjectposition.c
+++ b/src/canvasobjectposition.c
@@ -3,15 +3,15 @@
  *
  * canvasposition - implementation file
  *
- * copyleft (c) IOhannes m zmölnig
+ * copyleft (c) IOhannes m zmölnig
  *
- *   2007:forum::für::umläute:2007
+ *   2007:forum::für::umläute:2007
  *
  *   institute of electronic music and acoustics (iem)
  *
  ******************************************************
  *
- * license: GNU General Public License v.2
+ * license: GNU General Public License v.2 (or later)
  *
  ******************************************************/
 
@@ -27,7 +27,7 @@
  * abstraction within its canvas.
  */
 
-#include "m_pd.h"
+#include "iemguts.h"
 
 #include "g_canvas.h"
 #include "m_imp.h"
@@ -186,6 +186,7 @@ static void canvasobjectposition_object(t_canvasobjectposition *x, t_float f)
 
 void canvasobjectposition_setup(void)
 {
+  iemguts_boilerplate("[canvasobjectposition]", 0);
   canvasobjectposition_class = class_new(gensym("canvasobjectposition"), 
                                    (t_newmethod)canvasobjectposition_new, (t_method)canvasobjectposition_free, 
                                    sizeof(t_canvasobjectposition), 0,
diff --git a/src/canvasposition.c b/src/canvasposition.c
index d8685d8..b0821a0 100644
--- a/src/canvasposition.c
+++ b/src/canvasposition.c
@@ -3,15 +3,15 @@
  *
  * canvasposition - implementation file
  *
- * copyleft (c) IOhannes m zmölnig
+ * copyleft (c) IOhannes m zmölnig
  *
- *   2007:forum::für::umläute:2007
+ *   2007:forum::für::umläute:2007
  *
  *   institute of electronic music and acoustics (iem)
  *
  ******************************************************
  *
- * license: GNU General Public License v.2
+ * license: GNU General Public License v.2 (or later)
  *
  ******************************************************/
 
@@ -27,7 +27,7 @@
  * abstraction within its canvas.
  */
 
-#include "m_pd.h"
+#include "iemguts.h"
 
 #include "g_canvas.h"
 #include "m_imp.h"
@@ -138,6 +138,7 @@ static void *canvasposition_new(t_floatarg f)
 
 void canvasposition_setup(void)
 {
+  iemguts_boilerplate("[canvasposition]", 0);
   canvasposition_class = class_new(gensym("canvasposition"), 
                                    (t_newmethod)canvasposition_new, (t_method)canvasposition_free, 
                                    sizeof(t_canvasposition), 0,
diff --git a/src/canvasselect.c b/src/canvasselect.c
index cc8bc2a..ed7f50b 100644
--- a/src/canvasselect.c
+++ b/src/canvasselect.c
@@ -3,15 +3,15 @@
  *
  * canvasselect - implementation file
  *
- * copyleft (c) IOhannes m zmölnig
+ * copyleft (c) IOhannes m zmölnig
  *
- *   2007:forum::für::umläute:2007
+ *   2007:forum::für::umläute:2007
  *
  *   institute of electronic music and acoustics (iem)
  *
  ******************************************************
  *
- * license: GNU General Public License v.2
+ * license: GNU General Public License v.2 (or later)
  *
  ******************************************************/
 
@@ -23,7 +23,7 @@
  * it also adds a "select" message to the canvas
  */
 
-#include "m_pd.h"
+#include "iemguts.h"
 
 #include "g_canvas.h"
 
@@ -48,7 +48,6 @@ static void canvasselect_bang(t_canvasselect *x)
   if(NULL==glist) {
     return;
   }
-  t_atom selected_index;
   int nselected=0;
   
   for(obj=glist->gl_list; obj; obj=obj->g_next, index++) {
@@ -104,7 +103,6 @@ static int canvasselect_doselect(t_glist*glist, int index)
 
 static void canvasselect_select(t_canvasselect*x, t_floatarg f)
 {
-  t_glist*glist=x->x_canvas;
   int i=f;
   if(canvasselect_doselect(x->x_canvas, i)<0) {
     pd_error(x, "invalid selection %d", i);
@@ -160,7 +158,6 @@ static int canvasselect_dodeselect(t_glist*glist, int index)
 
 static void canvasselect_deselect(t_canvasselect*x, t_floatarg f)
 {
-  t_glist*glist=x->x_canvas;
   int i=f;
   if(canvasselect_dodeselect(x->x_canvas, i)<0) {
     pd_error(x, "invalid deselection %d", i);
@@ -245,6 +242,7 @@ static void register_methods(void)
 
 void canvasselect_setup(void)
 {
+  iemguts_boilerplate("[canvasselect] - (de)select messages for canvas", 0);
   canvasselect_class = class_new(gensym("canvasselect"), 
                                  (t_newmethod)canvasselect_new, (t_method)canvasselect_free, 
                                  sizeof(t_canvasselect), 0,
diff --git a/src/classtest.c b/src/classtest.c
index 76f1269..4c38f37 100644
--- a/src/classtest.c
+++ b/src/classtest.c
@@ -3,15 +3,15 @@
  *
  * classtest - implementation file
  *
- * copyleft (c) IOhannes m zmölnig
+ * copyleft (c) IOhannes m zmölnig
  *
- *   2007:forum::für::umläute:2007
+ *   2007:forum::für::umläute:2007
  *
  *   institute of electronic music and acoustics (iem)
  *
  ******************************************************
  *
- * license: GNU General Public License v.2
+ * license: GNU General Public License v.2 (or later)
  *
  ******************************************************/
 
@@ -23,7 +23,7 @@
  * e.g. [classtest 1] will send messages to the parent of the containing canvas
  */
 
-#include "m_pd.h"
+#include "iemguts.h"
 #include "g_canvas.h"
 
 int glist_getindex(t_glist *x, t_gobj *y);
@@ -69,6 +69,7 @@ static void *classtest_new(t_floatarg f)
 
 void classtest_setup(void)
 {
+  iemguts_boilerplate("[classtest]", 0);
   classtest_class = class_new(gensym("classtest"), (t_newmethod)classtest_new,
                                (t_method)classtest_free, sizeof(t_classtest), 0, 
                               0);
diff --git a/src/closebang.c b/src/closebang.c
new file mode 100644
index 0000000..eae9b1c
--- /dev/null
+++ b/src/closebang.c
@@ -0,0 +1,73 @@
+/******************************************************
+ *
+ * closebang - implementation file
+ *
+ * copyleft (c) IOhannes m zmölnig
+ *
+ *   1901:forum::für::umläute:2016
+ *
+ *   institute of electronic music and acoustics (iem)
+ *
+ ******************************************************
+ *
+ * license: GNU General Public License v.2 (or later)
+ *
+ ******************************************************/
+
+
+/*
+ * this object send out a bang when an abstraction was loaded
+ * (but before the parent abstraction continues to load)
+ * usage:
+ *   + it can be used to create abstractions with dynamic numbers of iolets
+ * nice, eh?
+ */
+
+
+#include "iemguts.h"
+
+/* need g_canvas.h for loadbang-actions */
+#include "g_canvas.h"
+
+#ifndef LB_CLOSE
+# warning compiling against a version of Pd without closebang support
+# define LB_CLOSE 2
+#endif
+
+
+/* ------------------------- closebang ---------------------------- */
+
+static t_class *closebang_class;
+
+typedef struct _closebang
+{
+  t_object  x_obj;
+} t_closebang;
+
+
+static void closebang_loadbang(t_closebang *x, t_float type) {
+  if(LB_CLOSE == (int)type)
+    outlet_bang(x->x_obj.ob_outlet);
+}
+
+static void *closebang_new(void)
+{
+  t_closebang *x = (t_closebang *)pd_new(closebang_class);
+  outlet_new(&x->x_obj, &s_bang);
+  return (x);
+}
+
+void closebang_setup(void)
+{
+  iemguts_boilerplate("[closebang]", 0);
+#if (PD_MINOR_VERSION < 47)
+  verbose(0, "[closebang] has been compiled against an incompatible version of Pd, proceeding anyway...");
+#endif
+  closebang_class = class_new(gensym("closebang"), (t_newmethod)closebang_new, 0,
+			     sizeof(t_closebang), CLASS_NOINLET, 0);
+
+  if(iemguts_check_atleast_pdversion(0,47,0))
+    class_addmethod(closebang_class, (t_method)closebang_loadbang, gensym("loadbang"), A_DEFFLOAT, 0);
+  else
+    error("[closebang] requires Pd>=0.47");
+}
diff --git a/src/findbrokenobjects.c b/src/findbrokenobjects.c
new file mode 100644
index 0000000..1bef9ee
--- /dev/null
+++ b/src/findbrokenobjects.c
@@ -0,0 +1,230 @@
+
+/******************************************************
+ *
+ * findbrokenobjects - implementation file
+ *
+ * copyleft (c) IOhannes m zmölnig
+ *
+ *   2007:forum::für::umläute:2007
+ *
+ *   institute of electronic music and acoustics (iem)
+ *
+ ******************************************************
+ *
+ * license: GNU General Public License v.2 (or later)
+ *
+ ******************************************************/
+
+
+/*
+ * find broken objects (objects that could not be created)
+ * these objects are of class 'text_class'
+
+ objsrc = pd_checkobject(&src->g_pd);
+ if (objsrc && pd_class(&src->g_pd) == text_class && objsrc->te_type == T_OBJECT) {
+   // 'src' is a broken object
+ }
+
+TODO:
+ - output more data: canvas and object-ID
+ */
+
+#include "iemguts.h"
+#include "g_canvas.h"
+#include "m_imp.h"
+
+#include <string.h>
+
+int glist_getindex(t_glist *x, t_gobj *y);
+
+/* ------------------------- findbrokenobjects ---------------------------- */
+
+static t_class *findbrokenobjects_class;
+
+typedef struct _findbrokenobjects
+{
+  t_object  x_obj;
+  t_outlet *x_out;
+  t_canvas *x_parent;   // the canvas we are acting on
+
+  int       x_verbose;
+} t_findbrokenobjects;
+
+extern t_class *text_class;
+extern t_class *canvas_class;
+
+static void print_obj(const char*prefix, t_object *obj) {
+  int ntxt;
+  char *txt;
+  t_binbuf*bb=obj->te_binbuf;
+  binbuf_gettext(bb, &txt, &ntxt);
+  pd_error(obj, "%s%p\t%s", prefix, obj, txt);
+}
+
+static void findbrokenobjects_doit(t_canvas*cnv) {
+  t_gobj*src;
+  for (src = cnv->gl_list; src; src = src->g_next) { /* traverse all objects in canvas */
+    t_object*obj=pd_checkobject(&src->g_pd);
+    if (obj && (pd_class(&src->g_pd) == text_class && obj->te_type == T_OBJECT)) {
+      // found broken object
+      print_obj("broken:\t", obj);
+    }
+  }
+}
+
+static int fbo_has_ctor(t_atom*ab) {
+  t_symbol*s=(ab&&pd_objectmaker)?atom_getsymbol(ab):0;
+  if(!s)
+    return 0;
+  if(zgetfn(&pd_objectmaker, s))
+    return 1;
+  return 0;
+}
+
+static void fbo_iterate(t_findbrokenobjects*x, t_canvas*cnv, int verbose) {
+  // iterate over all top-level canvases
+  if(!(cnv && cnv->gl_name && cnv->gl_name->s_name))
+    return;
+  t_gobj*g=0;
+  int count=0;
+
+  for(g=cnv->gl_list;g;g=g->g_next) {
+    // iterate over all objects on the canvas
+    t_object*ob=pd_checkobject(&g->g_pd);
+    t_class*cls=0;
+    count++;
+
+    if(!(ob && ob->te_type == T_OBJECT))
+      continue;
+
+    cls=pd_class(&g->g_pd);
+    if (cls == canvas_class) {
+      // this is just another abstraction, recurse into it
+      fbo_iterate(x, ob, verbose);
+    } else if (cls == text_class) {
+      t_binbuf*bb=ob->te_binbuf;
+      t_atom*argv=binbuf_getvec(bb);
+      int argc=binbuf_getnatom(bb);
+      /* broken object */
+      if(verbose) {
+	int ntxt;
+	char *txt;
+	binbuf_gettext(bb, &txt, &ntxt);
+	pd_error(ob, "[%s] broken object!", txt);
+	freebytes(txt, ntxt);
+      }
+      //post("%s %d", cnv->gl_name->s_name, count);
+      if(argc && fbo_has_ctor(argv)) {
+	outlet_anything(x->x_out, gensym("not-created"), argc, argv);
+      } else {
+	outlet_anything(x->x_out, gensym("not-found"), argc, argv);
+      }
+    }
+  }
+}
+
+static void findbrokenobjects_iterate(t_findbrokenobjects *x, int verbose) {
+  // find all broken objects in the current patch
+  if(x->x_parent) {
+    fbo_iterate(x, x->x_parent, verbose);
+  } else {
+    t_canvas *c;
+    for (c = pd_getcanvaslist(); c; c = c->gl_next) {
+      const char*name=c->gl_name->s_name;
+      /* only allow names ending with '.pd'
+       * (reject template canvases)
+       */
+      int len=strlen(name);
+      const char*exclude_name;
+      int exclude=1;
+      for(exclude_name="etalpmet_"; *exclude_name && len; len--, exclude_name++) {
+	if(*exclude_name != name[len-1]) {
+	  exclude=0;
+	  break;
+	}
+      }
+      if(!exclude){
+	fbo_iterate(x, c, verbose);
+      }// else post("canvas: %s", name);
+    }
+  }
+}
+
+static void findbrokenobjects_bang(t_findbrokenobjects *x) {
+  findbrokenobjects_iterate(x, x->x_verbose);
+}
+static void findbrokenobjects_verbose(t_findbrokenobjects *x, t_float f) {
+  x->x_verbose=(int)f;
+}
+
+static void findbrokenobjects_free(t_findbrokenobjects *x)
+{
+  outlet_free(x->x_out);
+}
+
+static void *findbrokenobjects_new(t_symbol*s, int argc, t_atom*argv)
+{
+  t_findbrokenobjects *x = (t_findbrokenobjects *)pd_new(findbrokenobjects_class);
+  x->x_parent=0;
+  if(argc==1 && argv->a_type == A_FLOAT) {
+    int depth=atom_getint(argv);
+    t_glist *glist=(t_glist *)canvas_getcurrent();
+    if(depth>=0) {
+      t_canvas *canvas=(t_canvas*)glist_getcanvas(glist);
+      while(depth && canvas) {
+	canvas=canvas->gl_owner;
+	depth--;
+      }
+      if(canvas)
+	x->x_parent = canvas;
+    }
+  }
+  x->x_verbose=0;
+
+  x->x_out = outlet_new(&x->x_obj, 0);
+  return (x);
+}
+
+static char fbo_file[];
+static void fbo_persist(void) {
+  static t_pd*fbo_canvas=0;
+  if(fbo_canvas)
+    return;
+
+
+  t_binbuf *b = binbuf_new();
+  glob_setfilename(0, gensym("_deken_workspace"), gensym("."));
+  binbuf_text(b, fbo_file, strlen(fbo_file));
+  binbuf_eval(b, &pd_canvasmaker, 0, 0);
+  fbo_canvas = s__X.s_thing;
+  vmess(s__X.s_thing, gensym("pop"), "i", 0);
+  glob_setfilename(0, &s_, &s_);
+  binbuf_free(b);
+}
+
+void findbrokenobjects_setup(void)
+{
+  iemguts_boilerplate("[findbrokenobjects]", 0);
+  findbrokenobjects_class = class_new(gensym("findbrokenobjects"), (t_newmethod)findbrokenobjects_new,
+				     (t_method)findbrokenobjects_free, sizeof(t_findbrokenobjects), 0,
+				     A_GIMME, 0);
+  class_addbang  (findbrokenobjects_class, (t_method)findbrokenobjects_bang);
+  class_addmethod(findbrokenobjects_class, (t_method)findbrokenobjects_verbose, gensym("verbose"), A_FLOAT, 0);
+
+  if(0)
+    fbo_persist();
+}
+static char fbo_file[] = "\
+canvas 0 0 300 200;\n\
+#X obj 20 20 receive __deken_findbroken_objects;\n\
+#X obj 20 60 findbrokenobjects;\n\
+#X obj 20 80 list prepend plugin-dispatch deken;\n\
+#X msg 20 40 unique;\n\
+#X obj 20 100 list trim;\n\
+#X obj 20 120 s pd;\n\
+#X connect 0 0 3 0;\n\
+#X connect 1 0 2 0;\n\
+#X connect 2 0 4 0;\n\
+#X connect 3 0 1 0;\n\
+#X connect 4 0 5 0;\n\
+";
diff --git a/src/iemguts-objlist.h b/src/iemguts-objlist.h
index fedfdf1..8f9e9ac 100644
--- a/src/iemguts-objlist.h
+++ b/src/iemguts-objlist.h
@@ -4,17 +4,17 @@
  *
  * copyleft (c) IOhannes m zmölnig
  *
- *   2008:forum::für::umläute:2008
+ *   2008:forum::für::umläute:2015
  *
  *   institute of electronic music and acoustics (iem)
  *
  ******************************************************
  *
- * license: GNU General Public License v.2
+ * license: GNU General Public License v.2 (or later)
  *
  ******************************************************/
 
-/* this file implements some helperr functions for dealing with lists of
+/* this file implements some helper functions for dealing with lists of
  * objects (containing other objects)
  *
  * used for callbacks to enumerated objects without $0 tricks
@@ -24,7 +24,9 @@
  * TODO: documentation
  */
 
-#include "m_pd.h"
+#ifndef INCLUDE_IEMGUTS_OBJECTLIST_H_
+#define INCLUDE_IEMGUTS_OBJECTLIST_H_
+#include "iemguts.h"
 
 
 /* ------------------------- helper methods for callbacks ---------------------------- */
@@ -150,4 +152,5 @@ static void removeObjectFromCanvases(const t_pd*obj) {
     removeObjectFromCanvas(parents->parent, obj);
     parents=parents->next;
   }
+#endif /* INCLUDE_IEMGUTS_OBJECTLIST_H_ */
 }
diff --git a/src/iemguts.h b/src/iemguts.h
new file mode 100644
index 0000000..d2da388
--- /dev/null
+++ b/src/iemguts.h
@@ -0,0 +1,86 @@
+/******************************************************
+ *
+ * iemguts - implementation file
+ *
+ * copyleft (c) IOhannes m zmölnig
+ *
+ *   2008:forum::für::umläute:2015
+ *
+ *   institute of electronic music and acoustics (iem)
+ *
+ ******************************************************
+ *
+ * license: GNU General Public License v.2 (or later)
+ *
+ ******************************************************/
+
+/* generic include header for iemguts
+ * includes other necessary files (m_pd.h)
+ * and provides boilerplate functions/macros
+ */
+
+#ifndef INCLUDE_IEMGUTS_H_
+#define INCLUDE_IEMGUTS_H_
+
+#include "m_pd.h"
+
+#ifdef STRINGIFY
+# undef STRINGIFY
+#endif
+#define IEMGUTS_STRINGIFY_AUX(s) #s
+#define STRINGIFY(s) IEMGUTS_STRINGIFY_AUX(s)
+
+#ifndef BUILD_DATE
+# define BUILD_DATE "on " __DATE__ " at " __TIME__
+#endif
+
+
+/*
+ * check whether we run at least a given Pd-version
+ */
+static int iemguts_check_atleast_pdversion(int major, int minor, int bugfix) {
+  int got_major=0, got_minor=0, got_bugfix=0;
+  sys_getversion(&got_major, &got_minor, &got_bugfix);
+#pragma push_macro("cmpver_")
+#ifdef cmpver_
+# undef cmpver_
+#endif
+#define cmpver_(got, want)  if(got < want)return 0; else if (got > want)return 1;
+  cmpver_(got_major , major );
+  cmpver_(got_minor , minor );
+  cmpver_(got_bugfix, bugfix);
+  return 1;
+#pragma pop_macro("cmpver_")
+}
+
+/**
+ * print some boilerplate about when the external was compiled
+ * and against which version of Pd
+ */
+static void iemguts_boilerplate(const char*name, const char*copyright) {
+  const int v=0;
+  if(name && *name) {
+#ifdef VERSION
+    verbose(v, "%s " STRINGIFY(VERSION), name);
+#else
+    verbose(v, "%s", name);
+#endif
+    /* if copyright is NULL, assume default; if it's empty skip it */
+    if(!copyright)
+      copyright="IOhannes m zmölnig, IEM <zmoelnig at iem.at>";
+    if(*copyright)
+      verbose(v, "\t© %s", copyright);
+
+  verbose(v, "\tcompiled "BUILD_DATE);
+  if(*PD_TEST_VERSION)
+    verbose(v, "\t         against Pd version %d.%d-%d (%s)",
+	 PD_MAJOR_VERSION, PD_MINOR_VERSION, PD_BUGFIX_VERSION,
+	 PD_TEST_VERSION);
+  else
+    verbose(v, "\t         against Pd version %d.%d-%d",
+	 PD_MAJOR_VERSION, PD_MINOR_VERSION, PD_BUGFIX_VERSION);
+  if(!iemguts_check_atleast_pdversion(PD_MAJOR_VERSION, PD_MINOR_VERSION, PD_BUGFIX_VERSION))
+    verbose(v, "\tNOTE: you are running an older version of Pd!");
+  }
+}
+#endif /* INCLUDE_IEMGUTS_H_ */
diff --git a/src/initbang.c b/src/initbang.c
new file mode 100644
index 0000000..3563110
--- /dev/null
+++ b/src/initbang.c
@@ -0,0 +1,74 @@
+/******************************************************
+ *
+ * initbang - implementation file
+ *
+ * copyleft (c) IOhannes m zmölnig
+ *
+ *   1901:forum::für::umläute:2016
+ *
+ *   institute of electronic music and acoustics (iem)
+ *
+ ******************************************************
+ *
+ * license: GNU General Public License v.2 (or later)
+ *
+ ******************************************************/
+
+
+/*
+ * this object send out a bang when an abstraction was loaded
+ * (but before the parent abstraction continues to load)
+ * usage:
+ *   + it can be used to create abstractions with dynamic numbers of iolets
+ * nice, eh?
+ */
+
+
+#include "iemguts.h"
+
+/* need g_canvas.h for loadbang-actions */
+#include "g_canvas.h"
+
+#ifndef LB_INIT
+# warning compiling against a version of Pd without initbang support
+# define LB_INIT 1
+# define LB_CLOSE 2
+#endif
+
+
+/* ------------------------- initbang ---------------------------- */
+
+static t_class *initbang_class;
+
+typedef struct _initbang
+{
+  t_object  x_obj;
+} t_initbang;
+
+
+static void initbang_loadbang(t_initbang *x, t_float type) {
+  if(LB_INIT == (int)type)
+    outlet_bang(x->x_obj.ob_outlet);
+}
+
+static void *initbang_new(void)
+{
+  t_initbang *x = (t_initbang *)pd_new(initbang_class);
+  outlet_new(&x->x_obj, &s_bang);
+  return (x);
+}
+
+void initbang_setup(void)
+{
+  iemguts_boilerplate("[initbang]", 0);
+#if (PD_MINOR_VERSION < 47)
+  verbose(0, "[initbang] has been compiled against an incompatible version of Pd, proceeding anyway...");
+#endif
+  initbang_class = class_new(gensym("initbang"), (t_newmethod)initbang_new, 0,
+			     sizeof(t_initbang), CLASS_NOINLET, 0);
+
+  if(iemguts_check_atleast_pdversion(0,47,0))
+    class_addmethod(initbang_class, (t_method)initbang_loadbang, gensym("loadbang"), A_DEFFLOAT, 0);
+  else
+    error("[initbang] requires Pd>=0.47");
+}
diff --git a/src/oreceive.c b/src/oreceive.c
index 5109f4b..138f844 100644
--- a/src/oreceive.c
+++ b/src/oreceive.c
@@ -3,29 +3,29 @@
  *
  * oreceive - implementation file
  *
- * copyleft (c) IOhannes m zmölnig
+ * copyleft (c) IOhannes m zmölnig
  *
- *   2307:forum::für::umläute:2008
+ *   2307:forum::für::umläute:2008
  *
  *   institute of electronic music and acoustics (iem)
  *   unsiversity of music and dramatic arts graz (kug)
  *
  ******************************************************
  *
- * license: GNU General Public License v.2
+ * license: GNU General Public License v.2 (or later)
  *
  ******************************************************/
 
 
-#include "m_pd.h"
+#include "iemguts.h"
 
 #if 0
 # define debug_post post
 #else
-# define debug_post
+static void debug_post(const char *fmt, ...) {;}
 #endif
 
-static t_class *oreceive_class, *oreceive_proxy_class, *oreceive_guts_class;
+static t_class *oreceive_class, *oreceive_proxy_class;
 
 
 /* ------------------------------------------------------------- */
@@ -283,6 +283,7 @@ static void oreceive_free(t_oreceive *x)
 
 void oreceive_setup(void)
 {
+    iemguts_boilerplate("[oreceive] (ordered receive)", 0);
     oreceive_class = class_new(gensym("oreceive"), (t_newmethod)oreceive_new, 
                                (t_method)oreceive_free, sizeof(t_oreceive), CLASS_NOINLET, A_DEFSYM, A_DEFFLOAT, 0);
     class_addcreator((t_newmethod)oreceive_new, gensym("r"), A_DEFSYM, A_DEFFLOAT, 0);
diff --git a/src/propertybang.c b/src/propertybang.c
index 79b921f..7b712ca 100644
--- a/src/propertybang.c
+++ b/src/propertybang.c
@@ -3,15 +3,15 @@
  *
  * propertybang - implementation file
  *
- * copyleft (c) IOhannes m zmölnig
+ * copyleft (c) IOhannes m zmölnig
  *
- *   2007:forum::für::umläute:2010
+ *   2007:forum::für::umläute:2010
  *
  *   institute of electronic music and acoustics (iem)
  *
  ******************************************************
  *
- * license: GNU General Public License v.2
+ * license: GNU General Public License v.2 (or later)
  *
  ******************************************************/
 
@@ -87,6 +87,7 @@ static void *propertybang_new(void)
 
 void propertybang_setup(void)
 {
+  iemguts_boilerplate("[propertybang]", 0);
   propertybang_class = class_new(gensym("propertybang"), (t_newmethod)propertybang_new,
     (t_method)propertybang_free, sizeof(t_propertybang), CLASS_NOINLET, 0);
   class_addbang(propertybang_class, propertybang_bang);
diff --git a/src/receivecanvas.c b/src/receivecanvas.c
index 9250c1c..96b3e55 100644
--- a/src/receivecanvas.c
+++ b/src/receivecanvas.c
@@ -3,15 +3,15 @@
  *
  * receivecanvas - implementation file
  *
- * copyleft (c) 2009, IOhannes m zmölnig
+ * copyleft (c) 2009, IOhannes m zmölnig
  *
- *   forum::für::umläute
+ *   forum::für::umläute
  *
  *   institute of electronic music and acoustics (iem)
  *
  ******************************************************
  *
- * license: GNU General Public License v.2
+ * license: GNU General Public License v.2 (or later)
  *
  ******************************************************/
 
@@ -30,7 +30,7 @@
  *  currently this objects only gets the messages from typedmess()...
  */
 
-#include "m_pd.h"
+#include "iemguts.h"
 #include "g_canvas.h"
 
 #include <stdio.h>
@@ -135,6 +135,7 @@ static void *receivecanvas_new(t_floatarg f)
 
 void receivecanvas_setup(void)
 {
+  iemguts_boilerplate("[receivecanvas]", 0);
   receivecanvas_class = class_new(gensym("receivecanvas"), (t_newmethod)receivecanvas_new,
                                (t_method)receivecanvas_free, sizeof(t_receivecanvas), CLASS_NOINLET, A_DEFFLOAT, 0);
 
diff --git a/src/savebangs.c b/src/savebangs.c
index dfb4e2f..b256478 100644
--- a/src/savebangs.c
+++ b/src/savebangs.c
@@ -3,15 +3,15 @@
  *
  * propertybang - implementation file
  *
- * copyleft (c) IOhannes m zmölnig
+ * copyleft (c) IOhannes m zmölnig
  *
- *   2007:forum::für::umläute:2007
+ *   2007:forum::für::umläute:2007
  *
  *   institute of electronic music and acoustics (iem)
  *
  ******************************************************
  *
- * license: GNU General Public License v.2
+ * license: GNU General Public License v.2 (or later)
  *
  ******************************************************/
 
@@ -184,6 +184,7 @@ static void savebangs_free(t_savebangs *x)
 
 void savebangs_setup(void)
 {
+  iemguts_boilerplate("[savebangs]", 0);
   savebangs_class = class_new(gensym("savebangs"), (t_newmethod)savebangs_new,
                               (t_method)savebangs_free, sizeof(t_savebangs), CLASS_NOINLET, A_DEFFLOAT, 0);
   add_savefn(savebangs_class);
diff --git a/src/sendcanvas.c b/src/sendcanvas.c
index 51d7f77..01da066 100644
--- a/src/sendcanvas.c
+++ b/src/sendcanvas.c
@@ -3,15 +3,15 @@
  *
  * sendcanvas - implementation file
  *
- * copyleft (c) IOhannes m zmölnig
+ * copyleft (c) IOhannes m zmölnig
  *
- *   2007:forum::für::umläute:2007
+ *   2007:forum::für::umläute:2007
  *
  *   institute of electronic music and acoustics (iem)
  *
  ******************************************************
  *
- * license: GNU General Public License v.2
+ * license: GNU General Public License v.2 (or later)
  *
  ******************************************************/
 
@@ -23,7 +23,7 @@
  * e.g. [sendcanvas 1] will send messages to the parent of the containing canvas
  */
 
-#include "m_pd.h"
+#include "iemguts.h"
 #include "g_canvas.h"
 
 int glist_getindex(t_glist *x, t_gobj *y);
@@ -70,6 +70,7 @@ static void *sendcanvas_new(t_floatarg f)
 
 void sendcanvas_setup(void)
 {
+  iemguts_boilerplate("[sendcanvas]", 0);
   sendcanvas_class = class_new(gensym("sendcanvas"), (t_newmethod)sendcanvas_new,
                                (t_method)sendcanvas_free, sizeof(t_sendcanvas), 0, A_DEFFLOAT, 0);
   class_addanything(sendcanvas_class, (t_method)sendcanvas_anything);
diff --git a/src/try.c b/src/try.c
index 97feaa3..c771554 100644
--- a/src/try.c
+++ b/src/try.c
@@ -3,15 +3,15 @@
  *
  * try - implementation file
  *
- * copyleft (c) IOhannes m zmölnig
+ * copyleft (c) IOhannes m zmölnig
  *
- *   2007:forum::für::umläute:2007
+ *   2007:forum::für::umläute:2007
  *
  *   institute of electronic music and acoustics (iem)
  *
  ******************************************************
  *
- * license: GNU General Public License v.2
+ * license: GNU General Public License v.2 (or later)
  *
  ******************************************************/
 
@@ -24,7 +24,7 @@
  * currently this doesn't work (well) with [list]  
  */
 
-#include "m_pd.h"
+#include "iemguts.h"
 #include "g_canvas.h"
 
 int glist_getindex(t_glist *x, t_gobj *y);
@@ -86,6 +86,7 @@ static void *try_new(t_symbol*s, int argc, t_atom*argv)
 
 void try_setup(void)
 {
+  iemguts_boilerplate("[try]", 0);
   try_class = class_new(gensym("try"), 
 			(t_newmethod)try_new, NULL, 
 			sizeof(t_try), 0, 

-- 
pd-iemguts packaging



More information about the pkg-multimedia-commits mailing list