From 3e9603e37c943634a8d711b1989d5787a1b6534d Mon Sep 17 00:00:00 2001 From: Jonathan Wilkes <jon.w.wilkes@gmail.com> Date: Fri, 26 Aug 2016 16:52:06 -0400 Subject: [PATCH] update mrpeach from Sourceforge svn --- externals/mrpeach/LICENSE.txt | 16 + externals/mrpeach/Makefile | 460 ++++++- externals/mrpeach/README.txt | 29 + externals/mrpeach/binfile/binfile-help.pd | 147 +-- externals/mrpeach/binfile/binfile.c | 47 +- externals/mrpeach/cmos/LICENSE.txt | 16 + externals/mrpeach/cmos/Makefile | 461 +++++++ externals/mrpeach/cmos/README.txt | 6 + externals/mrpeach/cmos/cd4000.c | 6 +- externals/mrpeach/cmos/cd4001.c | 4 +- externals/mrpeach/cmos/cd4002.c | 8 +- externals/mrpeach/cmos/cd4008.c | 18 +- externals/mrpeach/cmos/cd4011.c | 4 +- externals/mrpeach/cmos/cd4012.c | 8 +- externals/mrpeach/cmos/cd4013.c | 2 +- externals/mrpeach/cmos/cd4014.c | 24 +- externals/mrpeach/cmos/cd4015.c | 8 +- externals/mrpeach/cmos/cd4017.c | 4 +- externals/mrpeach/cmos/cd40193.c | 18 +- externals/mrpeach/cmos/cd4023.c | 6 +- externals/mrpeach/cmos/cd4024.c | 8 +- externals/mrpeach/cmos/cd4025.c | 6 +- externals/mrpeach/cmos/cd4027.c | 2 +- externals/mrpeach/cmos/cd4070.c | 4 +- externals/mrpeach/cmos/cd4071.c | 4 +- externals/mrpeach/cmos/cd4072.c | 8 +- externals/mrpeach/cmos/cd4073.c | 6 +- externals/mrpeach/cmos/cd4075.c | 6 +- externals/mrpeach/cmos/cd4076.c | 28 +- externals/mrpeach/cmos/cd4081.c | 4 +- externals/mrpeach/cmos/cd4082.c | 8 +- externals/mrpeach/cmos/cd4094.c | 12 +- externals/mrpeach/cmos/cd4516.c | 20 +- externals/mrpeach/cmos/cmos-meta.pd | 6 + externals/mrpeach/midifile/midifile.c | 147 ++- externals/mrpeach/mrpeach-meta.pd | 6 + externals/mrpeach/net/tcpclient.c | 31 +- externals/mrpeach/net/tcpsend.c | 11 +- externals/mrpeach/net/tcpserver-help.pd | 94 +- externals/mrpeach/net/tcpserver.c | 784 +++++++----- externals/mrpeach/net/udpreceive~-help.pd | 106 +- externals/mrpeach/net/udpreceive~.c | 8 +- externals/mrpeach/net/udpsend.c | 11 +- externals/mrpeach/net/udpsend~-help.pd | 2 +- externals/mrpeach/net/udpsend~.c | 2 +- externals/mrpeach/net/udpsndrcv-help.pd | 73 ++ externals/mrpeach/net/udpsndrcv.c | 398 ++++++ externals/mrpeach/op~/op~.c | 2 +- externals/mrpeach/osc/osc-meta.pd | 2 +- externals/mrpeach/osc/packOSC-help.pd | 72 +- externals/mrpeach/osc/packOSC.c | 304 +++-- externals/mrpeach/osc/packingOSC.h | 10 +- externals/mrpeach/osc/routeOSC-help.pd | 168 ++- externals/mrpeach/osc/routeOSC.c | 66 +- externals/mrpeach/osc/unpackOSC.c | 226 ++-- externals/mrpeach/rcosc~/rcosc~.c | 2 +- externals/mrpeach/rc~/rc~.c | 2 +- externals/mrpeach/rojo~/rojo~.c | 2 +- .../mrpeach/runningmean/runningmean-help.pd | 40 +- externals/mrpeach/runningmean/runningmean.c | 28 +- externals/mrpeach/serializer/b2f-help.pd | 14 + externals/mrpeach/serializer/b2f.c | 88 ++ externals/mrpeach/serializer/f2b-help.pd | 28 + externals/mrpeach/serializer/f2b.c | 63 + externals/mrpeach/slipdec/slipdec.c | 22 +- externals/mrpeach/slipenc/slipenc.c | 4 +- externals/mrpeach/sqosc~/sqosc~.c | 2 +- externals/mrpeach/str/str.c | 15 +- externals/mrpeach/tabfind/tabfind.c | 4 +- externals/mrpeach/which/which-help.pd | 12 +- externals/mrpeach/which/which.c | 6 +- externals/mrpeach/xbee/bits.pd | 100 ++ externals/mrpeach/xbee/packxbee-example.pd | 132 ++ externals/mrpeach/xbee/packxbee-help.pd | 1097 +++++++++------- externals/mrpeach/xbee/packxbee.c | 328 ++++- externals/mrpeach/xbee/pdxbee.h | 7 + externals/mrpeach/xbee/unpackxbee-help.pd | 330 +++++ externals/mrpeach/xbee/unpackxbee.c | 305 ++++- externals/mrpeach/xbee/xbeeio.pd | 1114 +++++++++++++++++ 79 files changed, 6043 insertions(+), 1639 deletions(-) create mode 100644 externals/mrpeach/LICENSE.txt create mode 100644 externals/mrpeach/README.txt create mode 100644 externals/mrpeach/cmos/LICENSE.txt create mode 100644 externals/mrpeach/cmos/Makefile create mode 100644 externals/mrpeach/cmos/README.txt create mode 100644 externals/mrpeach/cmos/cmos-meta.pd create mode 100644 externals/mrpeach/mrpeach-meta.pd create mode 100644 externals/mrpeach/net/udpsndrcv-help.pd create mode 100644 externals/mrpeach/net/udpsndrcv.c create mode 100644 externals/mrpeach/serializer/b2f-help.pd create mode 100644 externals/mrpeach/serializer/b2f.c create mode 100644 externals/mrpeach/serializer/f2b-help.pd create mode 100644 externals/mrpeach/serializer/f2b.c create mode 100644 externals/mrpeach/xbee/bits.pd create mode 100644 externals/mrpeach/xbee/packxbee-example.pd create mode 100644 externals/mrpeach/xbee/unpackxbee-help.pd create mode 100644 externals/mrpeach/xbee/xbeeio.pd diff --git a/externals/mrpeach/LICENSE.txt b/externals/mrpeach/LICENSE.txt new file mode 100644 index 000000000..d5a39448c --- /dev/null +++ b/externals/mrpeach/LICENSE.txt @@ -0,0 +1,16 @@ + mrpeach - a bag of tricks + Copyright (C) 2006-2015 Martin Peach + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + diff --git a/externals/mrpeach/Makefile b/externals/mrpeach/Makefile index 576ff8781..f17df5cfc 100644 --- a/externals/mrpeach/Makefile +++ b/externals/mrpeach/Makefile @@ -1,17 +1,455 @@ -TARGET := $(shell pwd | sed 's|.*/\(.*\)$$|\1|') -EXTERNALS_ROOT := $(shell pwd | sed 's|^\(/.*externals\).*|\1|') +## based on Pd library template version 1.0.14 +## (with some modifications to allow for sources/helppatches in subdirectories) +LIBRARY_NAME = mrpeach -default: - make -C $(EXTERNALS_ROOT) $(TARGET) +# 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 = \ + f2b.c b2f.c \ + slipdec.c slipenc.c \ + packxbee.c unpackxbee.c \ + binfile.c \ + midifile.c \ + life2x.c \ + op~.c \ + rc~.c \ + rcosc~.c \ + rojo~.c \ + runningmean.c \ + sqosc~.c \ + str.c \ + tab2flist.c \ + tabfind.c \ + flist2tab.c \ + which.c -install: - make -C $(EXTERNALS_ROOT) $(TARGET)_install +## where to find the source files (and help-patches) +VPATH=binfile:flist2tab:life2x:midifile:op~:rc~:rcosc~:rojo~:runningmean:serializer:slipdec:slipenc:sqosc~:str:tab2flist:tabfind:which:xbee + +# list all pd objects (i.e. myobject.pd) files here, and their helpfiles will +# be included automatically +PDOBJECTS = + +# example patches and related files, in the 'examples' subfolder +EXAMPLES = + +# manuals and related files, in the 'manual' subfolder +MANUAL = + +# 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 = pdxbee.h + +# unit tests and related files here, in the 'unittests' subfolder +UNITTESTS = + + + +#------------------------------------------------------------------------------# +# +# 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 -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 := $(SOURCES) $(SOURCES_android) $(SOURCES_cygwin) $(SOURCES_macosx) \ + $(SOURCES_iphoneos) $(SOURCES_linux) $(SOURCES_windows) + +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 + SOURCES += $(SOURCES_iphoneos) +# Starting with Xcode 4.0, the PowerPC compiler is not installed by default + ifeq ($(wildcard /usr/llvm-gcc-4.2/libexec/gcc/powerpc*), ) + FAT_FLAGS = -arch i386 -arch x86_64 -mmacosx-version-min=10.5 + else + FAT_FLAGS = -arch ppc -arch i386 -arch x86_64 -mmacosx-version-min=10.4 + endif + 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) -headerpad_max_install_names -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 = so + SHARED_EXTENSION = so + OS = android + PD_PATH = /usr + NDK_BASE := /opt/android-ndk + NDK_PLATFORM_LEVEL ?= 5 + NDK_ABI=arm + NDK_COMPILER_VERSION = 4.6 + NDK_SYSROOT=$(NDK_BASE)/platforms/android-$(NDK_PLATFORM_LEVEL)/arch-$(NDK_ABI) + NDK_UNAME:=$(shell uname -s | tr '[A-Z]' '[a-z]') + ifeq ($(NDK_ABI),x86) + HOST = i686-linux-android + NDK_TOOLCHAIN = $(NDK_ABI)-$(NDK_COMPILER_VERSION) + else + HOST = $(NDK_ABI)-linux-androideabi + NDK_TOOLCHAIN = $(HOST)-$(NDK_COMPILER_VERSION) + endif + NDK_TOOLCHAIN_BASE=$(NDK_BASE)/toolchains/$(NDK_TOOLCHAIN)/prebuilt/$(NDK_UNAME)-$(NDK_PROCESSOR) + CC := $(NDK_TOOLCHAIN_BASE)/bin/$(HOST)-gcc --sysroot=$(NDK_SYSROOT) + LD := $(NDK_TOOLCHAIN_BASE)/bin/$(HOST)-ld + 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/$(HOST)-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 + SHARED_LDFLAGS += -shared + ALL_LIBS += -L"$(PD_PATH)/src" -L"$(PD_PATH)/bin" -L"$(PD_PATH)/obj" \ + -lpd -lwsock32 -lkernel32 -luser32 -lgdi32 -liberty $(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 ?= $(SHARED_SOURCE:.c=.$(SHARED_EXTENSION)) +SHARED_TCL_LIB = $(wildcard lib$(LIBRARY_NAME).tcl) + +.PHONY = install libdir_install single_install install-objects install-libobject install-doc install-examples install-manual install-unittests 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 lib$(LIBRARY_NAME).o + $(CC) $(ALL_LDFLAGS) -o $(LIBRARY_NAME).$(EXTENSION) $(SOURCES:.c=.o) \ + $(LIBRARY_NAME).o lib$(LIBRARY_NAME).o $(ALL_LIBS) + chmod a-x $(LIBRARY_NAME).$(EXTENSION) + +$(SHARED_LIB): $(SHARED_SOURCE:.c=.o) + $(CC) $(SHARED_LDFLAGS) -o $(SHARED_LIB) $(SHARED_SOURCE:.c=.o) $(ALL_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. +install-objects: $(SOURCES:.c=.$(EXTENSION)) $(SHARED_LIB) $(PDOBJECTS) $(SHARED_TCL_LIB) + $(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) + $(INSTALL_DATA) $(LIBRARY_NAME)-meta.pd \ + $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) + $(INSTALL_DATA) $^ $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) + test -z "$(strip $(wildcard $(SOURCES:.c=.tcl)))" || \ + $(INSTALL_DATA) $(wildcard $(SOURCES:.c=.tcl)) \ + $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) +libdir_install: install-objects install-doc install-examples install-manual install-unittests + +# install library linked as single binary +install-libobject: $(LIBRARY_NAME).$(EXTENSION) + $(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) + $(INSTALL_PROGRAM) $@ $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) + $(STRIP) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/$@ +single_install: install-libobject install-doc install-examples install-manual install-unittests + +install-doc: $(HELPPATCHES) + $(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) + $(INSTALL_DATA) $^ $(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 + +install-unittests: + test -z "$(strip $(UNITTESTS))" || \ + $(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/unittests && \ + for file in $(UNITTESTS); do \ + $(INSTALL_DATA) unittests/$$file $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/unittests; \ + done clean: - make -C $(EXTERNALS_ROOT) $(TARGET)_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: $(ALLSOURCES) $(HELPPATCHES) $(EXTRA_DIST) $(SHARED_HEADER) $(SHARED_SOURCE) $(SHARED_TCL_LIB) $(PDOBJECTS) + $(INSTALL_DIR) $(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 $^)" || \ + $(INSTALL_DATA) $^ $(DISTDIR) + test -z "$(strip $(wildcard $(ALLSOURCES:.c=.tcl)))" || \ + $(INSTALL_DATA) $(wildcard $(ALLSOURCES:.c=.tcl)) $(DISTDIR) + test -z "$(strip $(wildcard $(LIBRARY_NAME).c))" || \ + $(INSTALL_DATA) $(LIBRARY_NAME).c $(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 + test -z "$(strip $(UNITTESTS))" || \ + $(INSTALL_DIR) $(DISTDIR)/unittests && \ + for file in $(UNITTESTS); do \ + $(INSTALL_DATA) unittests/$$file $(DISTDIR)/unittests; \ + 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: TAGS -test_locations: - make -C $(EXTERNALS_ROOT) test_locations +TAGS: $(wildcard $(PD_INCLUDE)/*.h) $(SOURCES) $(SHARED_SOURCE) $(SHARED_HEADER) + etags $(wildcard $(PD_INCLUDE)/*.h) + etags -a *.h $(SOURCES) $(SHARED_SOURCE) $(SHARED_HEADER) + etags -a --language=none --regex="/proc[ \t]+\([^ \t]+\)/\1/" *.tcl -etags: - etags *.[ch] ~/cvs/pure-data/pd/src/*.[ch] /usr/include/*.h /usr/include/sys/*.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)" + @echo "NDK_TOOLCHAIN: $(NDK_TOOLCHAIN)" + @echo "NDK_BASE: $(NDK_BASE)" + @echo "NDK_SYSROOT: $(NDK_SYSROOT)" + @echo "VPATH: $(VPATH)" diff --git a/externals/mrpeach/README.txt b/externals/mrpeach/README.txt new file mode 100644 index 000000000..c4ec7c8b9 --- /dev/null +++ b/externals/mrpeach/README.txt @@ -0,0 +1,29 @@ +mrpeach - bag of tricks +=== + +## serial communication +slipenc, slipdec: SLIP encoder/decoder +f2b, b2f : float32<->bytes converter + +## xbee +communication with the XBee + +## binfile +read raw files (as bytes) + +## midifile +play and record MIDI-files + +## general purpose objects +[life2x] game of life +[op~] signal comparision +[rc~] resistor-capacitor circuit +[rcosc~] resistor-capacitor oscillator +[rojo~] red noise generator +[runningmean] moving average filter +[sqosc~] bandlimited pulse generator +[str] strings +[tabfind] find a number in a table +[flist2tab] write lists of floats into a table +[tab2flist] extract lists of floats from a table +[which] output path to a Pd-object diff --git a/externals/mrpeach/binfile/binfile-help.pd b/externals/mrpeach/binfile/binfile-help.pd index f87e31b4b..3be34e54c 100644 --- a/externals/mrpeach/binfile/binfile-help.pd +++ b/externals/mrpeach/binfile/binfile-help.pd @@ -1,69 +1,65 @@ -#N canvas 1 53 875 617 12; -#X msg 83 78 rewind; -#X obj 195 465 textfile; -#X msg 60 55 bang; -#X msg 129 124 clear; -#X msg 220 215 set 2 4 6 8; +#N canvas 237 152 1080 699 12; +#X msg 103 98 rewind; +#X obj 267 577 textfile; +#X msg 80 75 bang; +#X msg 179 174 clear; +#X msg 282 277 set 2 4 6 8; #X obj 181 -89 binfile; #X text 246 -90 read and write binary files; -#X text 403 330 You can also use this object simply for storing heterogeneous -sequences of bytes.; -#X msg 152 147 add 10 20 255; -#X msg 106 101 read afile.bin; -#X obj 338 353 binfile; -#X text 272 464 to read and write text files; -#X msg 243 238 write afile.bin; -#X text 478 367 This outlet gives a bang when you hit the end of the +#X msg 202 197 add 10 20 255; +#X obj 410 425 binfile; +#X text 344 576 to read and write text files; +#X msg 305 300 write afile.bin; +#X text 534 449 This outlet gives a bang when you hit the end of the sequence.; -#X text 409 427 This outlet gives the bytes in sequence \, or bangs +#X text 481 539 This outlet gives the bytes in sequence \, or bangs if no more bytes.; -#X text 308 213 clear the buffer and then add some bytes; -#X text 174 123 empty the buffer; -#X text 135 78 set the read pointer to the beginnning of the buffer +#X text 370 275 clear the buffer and then add some bytes; +#X text 224 173 empty the buffer; +#X text 155 98 set the read pointer to the beginnning of the buffer ; -#X text 99 55 output one byte from the buffer as a float; -#X text 360 236 write the entire buffer to a file; -#X obj 338 433 print one; -#X obj 15 40 bng 15 250 50 0 empty empty empty 17 7 0 10 -4034 -257985 +#X text 119 75 output one byte from the buffer as a float; +#X text 422 298 write the entire buffer to a file; +#X obj 410 545 print one; +#X obj 35 60 bng 15 250 50 0 empty empty empty 17 7 0 10 -4034 -257985 -1; -#X text 194 447 See also:; -#X obj 37 -13 openpanel; -#X obj 17 -48 bng 15 250 50 0 empty empty read_any_file_into_buffer +#X text 266 559 See also:; +#X obj 57 -13 openpanel; +#X obj 57 -37 bng 15 250 50 0 empty empty read_any_file_into_buffer 17 7 0 10 -4032 -258113 -1; -#X msg 37 32 read \$1; -#X obj 17 292 bng 15 250 50 0 empty empty save_buffer_as_any_file 17 +#X msg 57 52 read \$1; +#X obj 39 354 bng 15 250 50 0 empty empty save_buffer_as_any_file 17 7 0 10 -4032 -258113 -1; -#X msg 335 330 write \$1; -#X obj 338 307 savepanel; -#X msg 175 170 77 128 129 130; +#X msg 397 392 write \$1; +#X obj 400 369 savepanel; +#X msg 237 232 77 128 129 130; #X text 254 -50 The binfile object reads and writes binary files to and from a buffer in memory. You can read a file and output its contents one byte at a time as floats.; -#X text 422 26 To add bytes to the buffer \, first send "clear" to +#X text 442 46 To add bytes to the buffer \, first send "clear" to empty the buffer and then "add" to add bytes. Finally \, "write" will save the entire buffer as a binary file.; -#X floatatom 197 193 5 0 0 0 - - -; -#X text 237 191 add one byte \, same as "add"; -#X text 287 169 add a list of bytes \, same as "add"; +#X floatatom 259 255 5 0 0 0 - - -; +#X text 299 253 add one byte \, same as "add"; +#X text 349 231 add a list of bytes \, same as "add"; #X msg 15 10 info; -#X obj 361 403 print info; -#X obj 410 373 print end; -#X msg 266 261 readat 3; -#X msg 289 284 writeat 3; -#X text 363 284 set the write position; -#X text 333 261 set the read position; -#X text 440 397 This outlet gives a list of current parameters from +#X obj 433 515 print info; +#X obj 466 455 print end; +#X msg 328 323 readat 3; +#X msg 351 346 writeat 3; +#X text 425 346 set the write position; +#X text 395 323 set the read position; +#X text 512 509 This outlet gives a list of current parameters from the info message.; -#X text 255 136 add a list of byte-floats to the buffer at the current +#X text 303 197 add a list of byte-floats to the buffer at the current write offset; -#X text 108 6 output current buffer length and pointer values through +#X text 65 10 output current buffer length and pointer values through the middle outlet.; -#X text 213 101 read a file into the buffer and make it the new buffer +#X text 233 121 read a file into the buffer and make it the new buffer ; -#X obj 384 381 tgl 15 0 empty empty empty 17 7 0 10 -258113 -257985 +#X obj 456 493 tgl 15 0 empty empty empty 17 7 0 10 -258113 -257985 -1 0 1; -#X text 688 468 Martin Peach 2009/10/13; -#N canvas 506 311 494 344 META 0; +#N canvas 507 310 494 344 META 0; #X text 12 175 HELP_PATCH_AUTHORS "pd meta" information added by Jonathan Wilkes for Pd version 0.42.; #X text 12 25 LICENSE GPL v2 or later; @@ -75,27 +71,36 @@ write readat writeat symbol; #X text 12 115 OUTLET_1 list; #X text 12 135 OUTLET_2 bang; #X text 12 155 AUTHOR Martin Peach; -#X restore 812 497 pd META; -#X connect 0 0 10 0; -#X connect 2 0 10 0; -#X connect 3 0 10 0; -#X connect 4 0 10 0; -#X connect 8 0 10 0; -#X connect 9 0 10 0; -#X connect 10 0 20 0; -#X connect 10 1 36 0; -#X connect 10 2 37 0; -#X connect 10 2 46 0; -#X connect 12 0 10 0; -#X connect 21 0 2 0; -#X connect 23 0 25 0; -#X connect 24 0 23 0; -#X connect 25 0 10 0; -#X connect 26 0 28 0; -#X connect 27 0 10 0; -#X connect 28 0 27 0; -#X connect 29 0 10 0; -#X connect 32 0 10 0; -#X connect 35 0 10 0; -#X connect 38 0 10 0; -#X connect 39 0 10 0; +#X restore 882 607 pd META; +#X text 525 363 You can also use this object simply for storing heterogeneous +sequences of bytes.; +#X text 481 404 Optional arguments for filename and length to be read +(same as [read( message; +#X msg 151 146 read test.txt 5; +#X msg 126 121 read test.txt; +#X text 267 145 read the first 5 bytes of a file into the buffer; +#X text 760 580 Martin Peach 2014/01/27; +#X connect 0 0 8 0; +#X connect 2 0 8 0; +#X connect 3 0 8 0; +#X connect 4 0 8 0; +#X connect 7 0 8 0; +#X connect 8 0 18 0; +#X connect 8 1 34 0; +#X connect 8 2 35 0; +#X connect 8 2 44 0; +#X connect 10 0 8 0; +#X connect 19 0 2 0; +#X connect 21 0 23 0; +#X connect 22 0 21 0; +#X connect 23 0 8 0; +#X connect 24 0 26 0; +#X connect 25 0 8 0; +#X connect 26 0 25 0; +#X connect 27 0 8 0; +#X connect 30 0 8 0; +#X connect 33 0 8 0; +#X connect 36 0 8 0; +#X connect 37 0 8 0; +#X connect 48 0 8 0; +#X connect 49 0 8 0; diff --git a/externals/mrpeach/binfile/binfile.c b/externals/mrpeach/binfile/binfile.c index c32c9afe6..09c0a79fc 100644 --- a/externals/mrpeach/binfile/binfile.c +++ b/externals/mrpeach/binfile/binfile.c @@ -1,5 +1,5 @@ /* binfile.c An external for Pure Data that reads and writes binary files -* Copyright (C) 2007 Martin Peach +* Copyright (C) 2007-2014 Martin Peach * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -30,6 +30,13 @@ static t_class *binfile_class; #define ALLOC_BLOCK_SIZE 65536 /* number of bytes to add when resizing buffer */ #define PATH_BUF_SIZE 1024 /* maximumn length of a file path */ +/* support older Pd versions without sys_open(), sys_fopen(), sys_fclose() */ +#if PD_MAJOR_VERSION == 0 && PD_MINOR_VERSION < 44 +#define sys_open open +#define sys_fopen fopen +#define sys_fclose fclose +#endif + typedef struct t_binfile { t_object x_obj; @@ -49,7 +56,7 @@ typedef struct t_binfile static void binfile_rewind (t_binfile *x); static void binfile_free(t_binfile *x); static FILE *binfile_open_path(t_binfile *x, char *path, char *mode); -static void binfile_read(t_binfile *x, t_symbol *path); +static void binfile_read(t_binfile *x, t_symbol *path, t_float max_bytes); static void binfile_write(t_binfile *x, t_symbol *path); static void binfile_bang(t_binfile *x); static void binfile_float(t_binfile *x, t_float val); @@ -74,7 +81,7 @@ void binfile_setup(void) class_addbang(binfile_class, binfile_bang); class_addfloat(binfile_class, binfile_float); class_addlist(binfile_class, binfile_list); - class_addmethod(binfile_class, (t_method)binfile_read, gensym("read"), A_DEFSYMBOL, 0); + class_addmethod(binfile_class, (t_method)binfile_read, gensym("read"), A_DEFSYMBOL, A_DEFFLOAT, 0); class_addmethod(binfile_class, (t_method)binfile_write, gensym("write"), A_DEFSYMBOL, 0); class_addmethod(binfile_class, (t_method)binfile_add, gensym("add"), A_GIMME, 0); class_addmethod(binfile_class, (t_method)binfile_set, gensym("set"), A_GIMME, 0); @@ -99,25 +106,25 @@ static void *binfile_new(t_symbol *s, int argc, t_atom *argv) x->x_fP = NULL; x->x_fPath[0] = '\0'; x->x_our_directory = canvas_getcurrentdir();/* get the current directory to use as the base for relative file paths */ - x->x_buf_length = ALLOC_BLOCK_SIZE; x->x_rd_offset = x->x_wr_offset = x->x_length = 0L; + x->x_buf_length = 0;//ALLOC_BLOCK_SIZE; /* find the first string in the arg list and interpret it as a path to a file */ + /* find the first float in the arg list and interpret it as the size of the buffer */ for (i = 0; i < argc; ++i) { - if (argv[i].a_type == A_SYMBOL) + if (argv[i].a_type == A_FLOAT) { - pathSymbol = atom_getsymbol(&argv[i]); - if (pathSymbol != NULL) - binfile_read(x, pathSymbol); + x->x_buf_length = atom_getfloat(&argv[i]); + break; // take the first number } } - /* find the first float in the arg list and interpret it as the size of the buffer */ for (i = 0; i < argc; ++i) { - if (argv[i].a_type == A_FLOAT) + if (argv[i].a_type == A_SYMBOL) { - x->x_buf_length = atom_getfloat(&argv[i]); - break; + pathSymbol = atom_getsymbol(&argv[i]); + if (pathSymbol != NULL) binfile_read(x, pathSymbol, x->x_buf_length); + break; // only try one path } } if ((x->x_buf = getbytes(x->x_buf_length)) == NULL) @@ -154,7 +161,7 @@ static FILE *binfile_open_path(t_binfile *x, char *path, char *mode) strncpy(tryPath, path, PATH_BUF_SIZE-1); /* copy path into a length-limited buffer */ /* ...if it doesn't work we won't mess up x->fPath */ tryPath[PATH_BUF_SIZE-1] = '\0'; /* just make sure there is a null termination */ - fP = fopen(tryPath, mode); + fP = sys_fopen(tryPath, mode); } if (fP == NULL) { @@ -164,7 +171,7 @@ static FILE *binfile_open_path(t_binfile *x, char *path, char *mode) strncat(tryPath, path, PATH_BUF_SIZE-1); /* append path to a length-limited buffer */ /* ...if it doesn't work we won't mess up x->fPath */ tryPath[PATH_BUF_SIZE-1] = '\0'; /* make sure there is a null termination */ - fP = fopen(tryPath, mode); + fP = sys_fopen(tryPath, mode); } if (fP != NULL) strncpy(x->x_fPath, tryPath, PATH_BUF_SIZE); @@ -183,12 +190,13 @@ static void binfile_write(t_binfile *x, t_symbol *path) bytes_written = fwrite(x->x_buf, 1L, x->x_length, x->x_fP); if (bytes_written != x->x_length) post("binfile: %ld bytes written != %ld", bytes_written, x->x_length); else post("binfile: wrote %ld bytes to %s", bytes_written, path->s_name); - fclose(x->x_fP); + sys_fclose(x->x_fP); x->x_fP = NULL; } -static void binfile_read(t_binfile *x, t_symbol *path) +static void binfile_read(t_binfile *x, t_symbol *path, t_float max_bytes) /* open the file for reading and load it into the buffer, then close it */ +/* if max_bytes > 0 read only max_bytes into the buffer */ { size_t file_length = 0L; size_t bytes_read = 0L; @@ -198,8 +206,9 @@ static void binfile_read(t_binfile *x, t_symbol *path) error("binfile: Unable to open %s for reading", path->s_name); return; } - /* get length of file */ - while (EOF != getc(x->x_fP)) ++file_length; + /* get length of file up to max_bytes */ + if (max_bytes > 0) while ((EOF != getc(x->x_fP))&&(file_length < max_bytes)) ++file_length; + else while (EOF != getc(x->x_fP)) ++file_length; if (file_length == 0L) return; /* get storage for file contents */ @@ -219,7 +228,7 @@ static void binfile_read(t_binfile *x, t_symbol *path) x->x_wr_offset = x->x_buf_length; /* write new data at end of file */ x->x_length = x->x_buf_length; /* file length is same as buffer size 7*/ x->x_rd_offset = 0L; /* read from start of file */ - fclose (x->x_fP); + sys_fclose (x->x_fP); x->x_fP = NULL; if (bytes_read != file_length) post("binfile length %ld not equal to bytes read (%ld)", file_length, bytes_read); else post("binfle: read %ld bytes from %s", bytes_read, path->s_name); diff --git a/externals/mrpeach/cmos/LICENSE.txt b/externals/mrpeach/cmos/LICENSE.txt new file mode 100644 index 000000000..23a8f9c67 --- /dev/null +++ b/externals/mrpeach/cmos/LICENSE.txt @@ -0,0 +1,16 @@ + CMOS digital logic emulation objects for Pure Data + Copyright (C) 2007-2014 Martin Peach + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + diff --git a/externals/mrpeach/cmos/Makefile b/externals/mrpeach/cmos/Makefile new file mode 100644 index 000000000..8e07528eb --- /dev/null +++ b/externals/mrpeach/cmos/Makefile @@ -0,0 +1,461 @@ +## Pd library template version 1.0.14 +# For instructions on how to use this template, see: +# http://puredata.info/docs/developer/MakefileTemplate +LIBRARY_NAME = cmos + +# 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 = \ + cd4000.c cd4008.c cd4013.c cd4017.c cd4024.c cd4070.c cd4073.c \ + cd4081.c cd4516.c cd4001.c cd4011.c cd4014.c cd40193.c cd4025.c \ + cd4071.c cd4075.c cd4082.c cd4002.c cd4012.c cd4015.c cd4023.c \ + cd4027.c cd4072.c cd4076.c cd4094.c + +# list all pd objects (i.e. myobject.pd) files here, and their helpfiles will +# be included automatically +PDOBJECTS = + +# example patches and related files, in the 'examples' subfolder +EXAMPLES = + +# manuals and related files, in the 'manual' subfolder +MANUAL = + +# 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 = + +# unit tests and related files here, in the 'unittests' subfolder +UNITTESTS = + + + +#------------------------------------------------------------------------------# +# +# 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 -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 := $(SOURCES) $(SOURCES_android) $(SOURCES_cygwin) $(SOURCES_macosx) \ + $(SOURCES_iphoneos) $(SOURCES_linux) $(SOURCES_windows) + +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 + SOURCES += $(SOURCES_iphoneos) +# Starting with Xcode 4.0, the PowerPC compiler is not installed by default + ifeq ($(wildcard /usr/llvm-gcc-4.2/libexec/gcc/powerpc*), ) + FAT_FLAGS = -arch i386 -arch x86_64 -mmacosx-version-min=10.5 + else + FAT_FLAGS = -arch ppc -arch i386 -arch x86_64 -mmacosx-version-min=10.4 + endif + 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) -headerpad_max_install_names -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 = so + SHARED_EXTENSION = so + OS = android + PD_PATH = /usr + NDK_BASE := /opt/android-ndk + NDK_PLATFORM_LEVEL ?= 5 + NDK_ABI=arm + NDK_COMPILER_VERSION = 4.6 + NDK_SYSROOT=$(NDK_BASE)/platforms/android-$(NDK_PLATFORM_LEVEL)/arch-$(NDK_ABI) + NDK_UNAME:=$(shell uname -s | tr '[A-Z]' '[a-z]') + ifeq ($(NDK_ABI),x86) + HOST = i686-linux-android + NDK_TOOLCHAIN = $(NDK_ABI)-$(NDK_COMPILER_VERSION) + else + HOST = $(NDK_ABI)-linux-androideabi + NDK_TOOLCHAIN = $(HOST)-$(NDK_COMPILER_VERSION) + endif + NDK_TOOLCHAIN_BASE=$(NDK_BASE)/toolchains/$(NDK_TOOLCHAIN)/prebuilt/$(NDK_UNAME)-$(NDK_PROCESSOR) + CC := $(NDK_TOOLCHAIN_BASE)/bin/$(HOST)-gcc --sysroot=$(NDK_SYSROOT) + LD := $(NDK_TOOLCHAIN_BASE)/bin/$(HOST)-ld + 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/$(HOST)-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 + SHARED_LDFLAGS += -shared + ALL_LIBS += -L"$(PD_PATH)/src" -L"$(PD_PATH)/bin" -L"$(PD_PATH)/obj" \ + -lpd -lwsock32 -lkernel32 -luser32 -lgdi32 -liberty $(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 ?= $(SHARED_SOURCE:.c=.$(SHARED_EXTENSION)) +SHARED_TCL_LIB = $(wildcard lib$(LIBRARY_NAME).tcl) + +.PHONY = install libdir_install single_install install-doc install-examples install-manual install-unittests clean distclean dist etags $(LIBRARY_NAME) + +all: $(SOURCES:.c=.$(EXTENSION)) $(SHARED_LIB) + +%.o: %.c + $(CC) $(ALL_CFLAGS) -o "$*.o" -c "$*.c" + +%.$(EXTENSION): %.o $(SHARED_LIB) + $(CC) $(ALL_LDFLAGS) -o "$*.$(EXTENSION)" "$*.o" $(ALL_LIBS) $(SHARED_LIB) + chmod a-x "$*.$(EXTENSION)" + +# this links everything into a single binary file +$(LIBRARY_NAME): $(SOURCES:.c=.o) $(LIBRARY_NAME).o lib$(LIBRARY_NAME).o + $(CC) $(ALL_LDFLAGS) -o $(LIBRARY_NAME).$(EXTENSION) $(SOURCES:.c=.o) \ + $(LIBRARY_NAME).o lib$(LIBRARY_NAME).o $(ALL_LIBS) + chmod a-x $(LIBRARY_NAME).$(EXTENSION) + +$(SHARED_LIB): $(SHARED_SOURCE:.c=.o) + $(CC) $(SHARED_LDFLAGS) -o $(SHARED_LIB) $(SHARED_SOURCE:.c=.o) $(ALL_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-unittests + $(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-unittests + $(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 + +install-unittests: + test -z "$(strip $(UNITTESTS))" || \ + $(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/unittests && \ + for file in $(UNITTESTS); do \ + $(INSTALL_DATA) unittests/$$file $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/unittests; \ + 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 $(wildcard $(LIBRARY_NAME).c))" || \ + $(INSTALL_DATA) $(LIBRARY_NAME).c $(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 + test -z "$(strip $(UNITTESTS))" || \ + $(INSTALL_DIR) $(DISTDIR)/unittests && \ + for file in $(UNITTESTS); do \ + $(INSTALL_DATA) unittests/$$file $(DISTDIR)/unittests; \ + 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: TAGS + +TAGS: $(wildcard $(PD_INCLUDE)/*.h) $(SOURCES) $(SHARED_SOURCE) $(SHARED_HEADER) + etags $(wildcard $(PD_INCLUDE)/*.h) + etags -a *.h $(SOURCES) $(SHARED_SOURCE) $(SHARED_HEADER) + etags -a --language=none --regex="/proc[ \t]+\([^ \t]+\)/\1/" *.tcl + +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)" + @echo "NDK_TOOLCHAIN: $(NDK_TOOLCHAIN)" + @echo "NDK_BASE: $(NDK_BASE)" + @echo "NDK_SYSROOT: $(NDK_SYSROOT)" diff --git a/externals/mrpeach/cmos/README.txt b/externals/mrpeach/cmos/README.txt new file mode 100644 index 000000000..f56c4a7a9 --- /dev/null +++ b/externals/mrpeach/cmos/README.txt @@ -0,0 +1,6 @@ +CMOS digital logic emulation objects +=== + +This is a collection of small objects that emulate +logic CMOS components. +The emulation assumes idealized components. diff --git a/externals/mrpeach/cmos/cd4000.c b/externals/mrpeach/cmos/cd4000.c index a2a4e457c..f9adeaa1c 100644 --- a/externals/mrpeach/cmos/cd4000.c +++ b/externals/mrpeach/cmos/cd4000.c @@ -5,9 +5,9 @@ typedef struct _cd4000 { t_object x_obj; - t_int x_in1; - t_int x_in2; - t_int x_in3; + int x_in1; + int x_in2; + int x_in3; t_outlet *x_out; t_inlet *x_inlet2;/* Second inlet is 'live' like the first */ t_inlet *x_inlet3;/* Third inlet is 'live' like the first */ diff --git a/externals/mrpeach/cmos/cd4001.c b/externals/mrpeach/cmos/cd4001.c index 0fbbfb9b4..0e6b2b95b 100644 --- a/externals/mrpeach/cmos/cd4001.c +++ b/externals/mrpeach/cmos/cd4001.c @@ -5,8 +5,8 @@ typedef struct _cd4001 { t_object x_obj; - t_int x_in1; - t_int x_in2; + int x_in1; + int x_in2; t_outlet *x_out; t_inlet *x_inlet2;/* Second inlet is 'live' like the first */ } t_cd4001; diff --git a/externals/mrpeach/cmos/cd4002.c b/externals/mrpeach/cmos/cd4002.c index b55769f6b..d54404eae 100644 --- a/externals/mrpeach/cmos/cd4002.c +++ b/externals/mrpeach/cmos/cd4002.c @@ -5,10 +5,10 @@ typedef struct _cd4002 { t_object x_obj; - t_int x_in1; - t_int x_in2; - t_int x_in3; - t_int x_in4; + int x_in1; + int x_in2; + int x_in3; + int x_in4; t_outlet *x_out; t_inlet *x_inlet2;/* extra inlets are 'live' like the first */ t_inlet *x_inlet3; diff --git a/externals/mrpeach/cmos/cd4008.c b/externals/mrpeach/cmos/cd4008.c index 06fbe4711..19100254c 100644 --- a/externals/mrpeach/cmos/cd4008.c +++ b/externals/mrpeach/cmos/cd4008.c @@ -5,15 +5,15 @@ typedef struct _cd4008 { t_object x_obj; - t_int x_A1; - t_int x_A2; - t_int x_A3; - t_int x_A4; - t_int x_B1; - t_int x_B2; - t_int x_B3; - t_int x_B4; - t_int x_CarryIn; + int x_A1; + int x_A2; + int x_A3; + int x_A4; + int x_B1; + int x_B2; + int x_B3; + int x_B4; + int x_CarryIn; t_outlet *x_outS1; t_outlet *x_outS2; t_outlet *x_outS3; diff --git a/externals/mrpeach/cmos/cd4011.c b/externals/mrpeach/cmos/cd4011.c index e04ee14fa..7a00ae5f1 100644 --- a/externals/mrpeach/cmos/cd4011.c +++ b/externals/mrpeach/cmos/cd4011.c @@ -5,8 +5,8 @@ typedef struct _cd4011 { t_object x_obj; - t_int x_in1; - t_int x_in2; + int x_in1; + int x_in2; t_outlet *x_out; t_inlet *x_inlet2;/* Second inlet is 'live' like the first */ } t_cd4011; diff --git a/externals/mrpeach/cmos/cd4012.c b/externals/mrpeach/cmos/cd4012.c index 752d8c15e..1e73483c9 100644 --- a/externals/mrpeach/cmos/cd4012.c +++ b/externals/mrpeach/cmos/cd4012.c @@ -5,10 +5,10 @@ typedef struct _cd4012 { t_object x_obj; - t_int x_in1; - t_int x_in2; - t_int x_in3; - t_int x_in4; + int x_in1; + int x_in2; + int x_in3; + int x_in4; t_outlet *x_out; t_inlet *x_inlet2;/* extra inlets are 'live' like the first */ t_inlet *x_inlet3; diff --git a/externals/mrpeach/cmos/cd4013.c b/externals/mrpeach/cmos/cd4013.c index c92f63535..291d8301d 100644 --- a/externals/mrpeach/cmos/cd4013.c +++ b/externals/mrpeach/cmos/cd4013.c @@ -5,7 +5,7 @@ typedef struct _cd4013 { t_object x_obj; - t_int x_state;/* set = bit0, clock = bit1, reset = bit2 j = bit3 k = bit4 q = bit 5 */ + int x_state;/* set = bit0, clock = bit1, reset = bit2 j = bit3 k = bit4 q = bit 5 */ t_outlet *x_Q; t_outlet *x_notQ; t_inlet *x_set;/* set takes one or zero as acceptable inputs. */ diff --git a/externals/mrpeach/cmos/cd4014.c b/externals/mrpeach/cmos/cd4014.c index 7485f5f3d..b9bf26dd5 100644 --- a/externals/mrpeach/cmos/cd4014.c +++ b/externals/mrpeach/cmos/cd4014.c @@ -5,18 +5,18 @@ typedef struct _cd4014 { t_object x_obj; - t_int x_P1; - t_int x_P2; - t_int x_P3; - t_int x_P4; - t_int x_P5; - t_int x_P6; - t_int x_P7; - t_int x_P8; - t_int x_SerialIn; - t_int x_Clk; - t_int x_Q; - t_int x_ParallelSerial; + int x_P1; + int x_P2; + int x_P3; + int x_P4; + int x_P5; + int x_P6; + int x_P7; + int x_P8; + int x_SerialIn; + int x_Clk; + int x_Q; + int x_ParallelSerial; t_outlet *x_outQ6; t_outlet *x_outQ7; t_outlet *x_outQ8; diff --git a/externals/mrpeach/cmos/cd4015.c b/externals/mrpeach/cmos/cd4015.c index d2f0d686f..511ebf92e 100644 --- a/externals/mrpeach/cmos/cd4015.c +++ b/externals/mrpeach/cmos/cd4015.c @@ -5,10 +5,10 @@ typedef struct _cd4015 { t_object x_obj; - t_int x_D; - t_int x_R; - t_int x_Clk; - t_int x_Q; + int x_D; + int x_R; + int x_Clk; + int x_Q; t_outlet *x_outQ1; t_outlet *x_outQ2; t_outlet *x_outQ3; diff --git a/externals/mrpeach/cmos/cd4017.c b/externals/mrpeach/cmos/cd4017.c index d5bcc9732..59c08ab31 100644 --- a/externals/mrpeach/cmos/cd4017.c +++ b/externals/mrpeach/cmos/cd4017.c @@ -5,8 +5,8 @@ typedef struct _cd4017 { t_object x_obj; - t_int x_state;/* clock_inhibit value in bit 0, clock level in bit 1, reset level in bit 2 */ - t_int x_count; + int x_state;/* clock_inhibit value in bit 0, clock level in bit 1, reset level in bit 2 */ + int x_count; t_outlet *x_0; t_outlet *x_1; t_outlet *x_2; diff --git a/externals/mrpeach/cmos/cd40193.c b/externals/mrpeach/cmos/cd40193.c index 22bdcbc04..8247f4210 100644 --- a/externals/mrpeach/cmos/cd40193.c +++ b/externals/mrpeach/cmos/cd40193.c @@ -11,15 +11,15 @@ typedef struct _cd40193 t_outlet *x_QDOut; t_outlet *x_CarryOut; t_outlet *x_BorrowOut; - t_int x_countUp; - t_int x_countDown; - t_int x_dataA; - t_int x_dataB; - t_int x_dataC; - t_int x_dataD; - t_int x_load; - t_int x_clear; - t_int x_count; + int x_countUp; + int x_countDown; + int x_dataA; + int x_dataB; + int x_dataC; + int x_dataD; + int x_load; + int x_clear; + int x_count; t_inlet *x_CountDownIn;/* All inlets take one or zero as acceptable inputs. */ t_inlet *x_ClearIn; t_inlet *x_LoadIn; diff --git a/externals/mrpeach/cmos/cd4023.c b/externals/mrpeach/cmos/cd4023.c index ff6025571..aef6a3de8 100644 --- a/externals/mrpeach/cmos/cd4023.c +++ b/externals/mrpeach/cmos/cd4023.c @@ -5,9 +5,9 @@ typedef struct _cd4023 { t_object x_obj; - t_int x_in1; - t_int x_in2; - t_int x_in3; + int x_in1; + int x_in2; + int x_in3; t_outlet *x_out; t_inlet *x_inlet2;/* Second inlet is 'live' like the first */ t_inlet *x_inlet3;/* Third inlet is 'live' like the first */ diff --git a/externals/mrpeach/cmos/cd4024.c b/externals/mrpeach/cmos/cd4024.c index 93c3bf419..bf86dd2bc 100644 --- a/externals/mrpeach/cmos/cd4024.c +++ b/externals/mrpeach/cmos/cd4024.c @@ -5,10 +5,10 @@ typedef struct _cd4024 { t_object x_obj; - t_int x_reset; - t_int x_clock; - t_int x_count; - t_int x_updating; + int x_reset; + int x_clock; + int x_count; + int x_updating; t_outlet *x_Q1; t_outlet *x_Q2; t_outlet *x_Q3; diff --git a/externals/mrpeach/cmos/cd4025.c b/externals/mrpeach/cmos/cd4025.c index 5124f14b4..9353e1b6f 100644 --- a/externals/mrpeach/cmos/cd4025.c +++ b/externals/mrpeach/cmos/cd4025.c @@ -5,9 +5,9 @@ typedef struct _cd4025 { t_object x_obj; - t_int x_in1; - t_int x_in2; - t_int x_in3; + int x_in1; + int x_in2; + int x_in3; t_outlet *x_out; t_inlet *x_inlet2;/* Second inlet is 'live' like the first */ t_inlet *x_inlet3;/* Third inlet is 'live' like the first */ diff --git a/externals/mrpeach/cmos/cd4027.c b/externals/mrpeach/cmos/cd4027.c index 69aaf48c5..18058a68c 100644 --- a/externals/mrpeach/cmos/cd4027.c +++ b/externals/mrpeach/cmos/cd4027.c @@ -5,7 +5,7 @@ typedef struct _cd4027 { t_object x_obj; - t_int x_state;/* set = bit0, clock = bit1, reset = bit2 j = bit3 k = bit4 q = bit 5 */ + int x_state;/* set = bit0, clock = bit1, reset = bit2 j = bit3 k = bit4 q = bit 5 */ t_outlet *x_Q; t_outlet *x_notQ; t_inlet *x_set;/* set takes one or zero as acceptable inputs. */ diff --git a/externals/mrpeach/cmos/cd4070.c b/externals/mrpeach/cmos/cd4070.c index ece39b0bb..7c92d67b6 100644 --- a/externals/mrpeach/cmos/cd4070.c +++ b/externals/mrpeach/cmos/cd4070.c @@ -5,8 +5,8 @@ typedef struct _cd4070 { t_object x_obj; - t_int x_in1; - t_int x_in2; + int x_in1; + int x_in2; t_outlet *x_out; t_inlet *x_inlet2;/* Second inlet is 'live' like the first */ } t_cd4070; diff --git a/externals/mrpeach/cmos/cd4071.c b/externals/mrpeach/cmos/cd4071.c index d6f49e78e..9cbfef177 100644 --- a/externals/mrpeach/cmos/cd4071.c +++ b/externals/mrpeach/cmos/cd4071.c @@ -5,8 +5,8 @@ typedef struct _cd4071 { t_object x_obj; - t_int x_in1; - t_int x_in2; + int x_in1; + int x_in2; t_outlet *x_out; t_inlet *x_inlet2;/* Second inlet is 'live' like the first */ } t_cd4071; diff --git a/externals/mrpeach/cmos/cd4072.c b/externals/mrpeach/cmos/cd4072.c index 9ce4b8040..934138a8d 100644 --- a/externals/mrpeach/cmos/cd4072.c +++ b/externals/mrpeach/cmos/cd4072.c @@ -5,10 +5,10 @@ typedef struct _cd4072 { t_object x_obj; - t_int x_in1; - t_int x_in2; - t_int x_in3; - t_int x_in4; + int x_in1; + int x_in2; + int x_in3; + int x_in4; t_outlet *x_out; t_inlet *x_inlet2;/* Second inlet is 'live' like the first */ t_inlet *x_inlet3;/* Third inlet is 'live' like the first */ diff --git a/externals/mrpeach/cmos/cd4073.c b/externals/mrpeach/cmos/cd4073.c index 530444bdd..a8e29c05f 100644 --- a/externals/mrpeach/cmos/cd4073.c +++ b/externals/mrpeach/cmos/cd4073.c @@ -5,9 +5,9 @@ typedef struct _cd4073 { t_object x_obj; - t_int x_in1; - t_int x_in2; - t_int x_in3; + int x_in1; + int x_in2; + int x_in3; t_outlet *x_out; t_inlet *x_inlet2;/* Second inlet is 'live' like the first */ t_inlet *x_inlet3;/* Third inlet is 'live' like the first */ diff --git a/externals/mrpeach/cmos/cd4075.c b/externals/mrpeach/cmos/cd4075.c index 6274f9c2d..47bc3f23a 100644 --- a/externals/mrpeach/cmos/cd4075.c +++ b/externals/mrpeach/cmos/cd4075.c @@ -5,9 +5,9 @@ typedef struct _cd4075 { t_object x_obj; - t_int x_in1; - t_int x_in2; - t_int x_in3; + int x_in1; + int x_in2; + int x_in3; t_outlet *x_out; t_inlet *x_inlet2;/* Second inlet is 'live' like the first */ t_inlet *x_inlet3;/* Third inlet is 'live' like the first */ diff --git a/externals/mrpeach/cmos/cd4076.c b/externals/mrpeach/cmos/cd4076.c index 5edcefc16..0de9517c3 100644 --- a/externals/mrpeach/cmos/cd4076.c +++ b/externals/mrpeach/cmos/cd4076.c @@ -9,20 +9,20 @@ typedef struct _cd4076 t_outlet *x_output_B; t_outlet *x_output_C; t_outlet *x_output_D; - t_int x_clock; - t_int x_QA; - t_int x_QB; - t_int x_QC; - t_int x_QD; - t_int x_inA; - t_int x_inB; - t_int x_inC; - t_int x_inD; - t_int x_InDis1; - t_int x_InDis2; - t_int x_OutDis1; - t_int x_OutDis2; - t_int x_Clear; + int x_clock; + int x_QA; + int x_QB; + int x_QC; + int x_QD; + int x_inA; + int x_inB; + int x_inC; + int x_inD; + int x_InDis1; + int x_InDis2; + int x_OutDis1; + int x_OutDis2; + int x_Clear; t_inlet *x_clear;/* clear takes one or zero as acceptable inputs. */ t_inlet *x_input_disable_1;/* input_disable_1 takes one or zero as acceptable inputs. */ t_inlet *x_input_disable_2;/* input_disable_2 takes one or zero as acceptable inputs. */ diff --git a/externals/mrpeach/cmos/cd4081.c b/externals/mrpeach/cmos/cd4081.c index 0770bccb2..a7bf4e154 100644 --- a/externals/mrpeach/cmos/cd4081.c +++ b/externals/mrpeach/cmos/cd4081.c @@ -5,8 +5,8 @@ typedef struct _cd4081 { t_object x_obj; - t_int x_in1; - t_int x_in2; + int x_in1; + int x_in2; t_outlet *x_out; t_inlet *x_inlet2;/* Second inlet is 'live' like the first */ } t_cd4081; diff --git a/externals/mrpeach/cmos/cd4082.c b/externals/mrpeach/cmos/cd4082.c index 1ee6f91ec..89d15512a 100644 --- a/externals/mrpeach/cmos/cd4082.c +++ b/externals/mrpeach/cmos/cd4082.c @@ -5,10 +5,10 @@ typedef struct _cd4082 { t_object x_obj; - t_int x_in1; - t_int x_in2; - t_int x_in3; - t_int x_in4; + int x_in1; + int x_in2; + int x_in3; + int x_in4; t_outlet *x_out; t_inlet *x_inlet2;/* Second inlet is 'live' like the first */ t_inlet *x_inlet3;/* Third inlet is 'live' like the first */ diff --git a/externals/mrpeach/cmos/cd4094.c b/externals/mrpeach/cmos/cd4094.c index 0d7097a5a..03d503dd5 100644 --- a/externals/mrpeach/cmos/cd4094.c +++ b/externals/mrpeach/cmos/cd4094.c @@ -15,12 +15,12 @@ typedef struct _cd4094 t_outlet *x_Q8Out; t_outlet *x_QSOut; t_outlet *x_QprimeSOut; - t_int x_clock; - t_int x_data; - t_int x_data_in; - t_int x_strobe; - t_int x_output_enable; - t_int x_qprime; + int x_clock; + int x_data; + int x_data_in; + int x_strobe; + int x_output_enable; + int x_qprime; t_inlet *x_StrobeIn;/* Strobe takes one or zero as acceptable inputs. */ t_inlet *x_DataIn;/* Data takes one or zero as acceptable inputs. */ t_inlet *x_OutputEnable;/* Output Enable takes one or zero as acceptable inputs. */ diff --git a/externals/mrpeach/cmos/cd4516.c b/externals/mrpeach/cmos/cd4516.c index 2949dcfc8..7f6b09165 100644 --- a/externals/mrpeach/cmos/cd4516.c +++ b/externals/mrpeach/cmos/cd4516.c @@ -10,16 +10,16 @@ typedef struct _cd4516 t_outlet *x_Q3Out; t_outlet *x_Q4Out; t_outlet *x_CarryOut; - t_int x_clock; - t_int x_upDown; - t_int x_preset_enable; - t_int x_carry; - t_int x_P1; - t_int x_P2; - t_int x_P3; - t_int x_P4; - t_int x_reset; - t_int x_count; + int x_clock; + int x_upDown; + int x_preset_enable; + int x_carry; + int x_P1; + int x_P2; + int x_P3; + int x_P4; + int x_reset; + int x_count; t_inlet *x_UpDownIn;/* All inlets take one or zero as acceptable inputs. */ t_inlet *x_ResetIn; t_inlet *x_PresetEnableIn; diff --git a/externals/mrpeach/cmos/cmos-meta.pd b/externals/mrpeach/cmos/cmos-meta.pd new file mode 100644 index 000000000..52bedab65 --- /dev/null +++ b/externals/mrpeach/cmos/cmos-meta.pd @@ -0,0 +1,6 @@ +#N canvas 15 49 200 200 10; +#N canvas 25 49 420 300 META 1; +#X text 13 41 NAME cmos; +#X text 10 25 AUTHOR Martin Peach; +#X text 10 10 VERSION 0.1; +#X restore 10 10 pd META; diff --git a/externals/mrpeach/midifile/midifile.c b/externals/mrpeach/midifile/midifile.c index 57764d761..747e79471 100644 --- a/externals/mrpeach/midifile/midifile.c +++ b/externals/mrpeach/midifile/midifile.c @@ -1,5 +1,5 @@ /* midifile.c An external for Pure Data that reads and writes MIDI files -* Copyright (C) 2005-2008 Martin Peach +* Copyright (C) 2005-2014 Martin Peach * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,6 +24,13 @@ #include <stdio.h> #include <string.h> +/* support older Pd versions without sys_open(), sys_fopen(), sys_fclose() */ +#if PD_MAJOR_VERSION == 0 && PD_MINOR_VERSION < 44 +#define sys_open open +#define sys_fopen fopen +#define sys_fclose fclose +#endif + #define NO_MORE_ELEMENTS 0xFFFFFFFF static t_class *midifile_class; @@ -38,11 +45,11 @@ typedef enum {mfReset, mfReading, mfWriting} mfstate; typedef struct mf_header_chunk { - char chunk_type[4]; /* each chunk begins with a 4-character ASCII type.*/ - size_t chunk_length ; /* followed by a 32-bit length */ - int chunk_format; - int chunk_ntrks; - int chunk_division; + char chunk_type[4]; /* each chunk begins with a 4-character ASCII type.*/ + size_t chunk_length ; /* followed by a 32-bit length */ + int chunk_format; + int chunk_ntrks; + int chunk_division; } mf_header_chunk; typedef struct mf_track_chunk @@ -53,7 +60,7 @@ typedef struct mf_track_chunk size_t total_time ; /* sum of delta_times so far */ size_t track_index ; /* current byte offset to next track_data element */ unsigned char running_status; - char *track_data; + unsigned char *track_data; } mf_track_chunk; typedef struct t_midifile @@ -82,12 +89,12 @@ static void midifile_get_next_track_chunk_data(t_midifile *x, int mfindex); static size_t midifile_get_next_track_chunk_delta_time(t_midifile *x, int mfindex); static void midifile_output_long_list (t_outlet *outlet, unsigned char *cP, size_t len, unsigned char first_byte); static void midifile_dump_track_chunk_data(t_midifile *x, int mfindex); -static char *midifile_read_var_len (char *cP, size_t *delta); +static unsigned char *midifile_read_var_len (unsigned char *cP, size_t *delta); static int midifile_write_variable_length_value (FILE *fP, size_t value); static unsigned short midifile_combine_bytes(unsigned char data1, unsigned char data2); -static unsigned short midifile_get_multibyte_2(char*n); -static unsigned long midifile_get_multibyte_3(char*n); -static unsigned long midifile_get_multibyte_4(char*n); +static unsigned short midifile_get_multibyte_2(unsigned char*n); +static unsigned long midifile_get_multibyte_3(unsigned char*n); +static unsigned long midifile_get_multibyte_4(unsigned char*n); static int midifile_read_track_chunk(t_midifile *x, int mfindex); static int midifile_read_header_chunk(t_midifile *x); static void midifile_rewind (t_midifile *x); @@ -114,6 +121,8 @@ void midifile_setup(void); void midifile_setup(void) { + char aStr[] = "midifile 20140127 by Martin Peach"; + midifile_class = class_new (gensym("midifile"), (t_newmethod) midifile_new, (t_method)midifile_free, sizeof(t_midifile), @@ -130,7 +139,12 @@ void midifile_setup(void) class_addmethod(midifile_class, (t_method)midifile_single_track, gensym("track"), A_DEFFLOAT, 0); class_addmethod(midifile_class, (t_method)midifile_rewind, gensym("rewind"), 0); class_addmethod(midifile_class, (t_method)midifile_verbosity, gensym("verbose"), A_DEFFLOAT, 0); - class_sethelpsymbol(midifile_class, gensym("midifile")); + class_sethelpsymbol(midifile_class, gensym("midifile-help")); +#if PD_MAJOR_VERSION==0 && PD_MINOR_VERSION<43 + post(aStr); +#else + logpost(NULL, 3, aStr); +#endif } static void *midifile_new(t_symbol *s, int argc, t_atom *argv) @@ -147,6 +161,11 @@ static void *midifile_new(t_symbol *s, int argc, t_atom *argv) x->fP = NULL; x->fPath[0] = '\0'; x->our_directory = canvas_getcurrentdir();/* get the current directory to use as the base for relative file paths */ +//#if PD_MAJOR_VERSION==0 && PD_MINOR_VERSION<43 +// post(x->our_directory->s_name); +//#else +// logpost(NULL, 3, x->our_directory->s_name); +//#endif x->track = ALL_TRACKS; /* startup playing anything */ x->midi_data[0].a_type = x->midi_data[1].a_type = x->midi_data[2].a_type = A_FLOAT; x->state = mfReset; @@ -177,7 +196,6 @@ static void *midifile_new(t_symbol *s, int argc, t_atom *argv) x->midi_list_outlet = outlet_new(&x->x_obj, &s_list); x->total_time_outlet = outlet_new(&x->x_obj, &s_float); /* current total_time */ x->status_outlet = outlet_new(&x->x_obj, &s_anything);/* last outlet for everything else */ - post("midifile 20110212 by Martin Peach"); return (void *)x; } @@ -185,12 +203,12 @@ static void midifile_close(t_midifile *x) { if (x->fP != NULL) { - fclose (x->fP); + sys_fclose (x->fP); x->fP = NULL; } if (x->tmpFP != NULL) { - fclose(x->tmpFP); + sys_fclose(x->tmpFP); x->tmpFP = NULL; } x->fPath[0] = '\0'; @@ -238,7 +256,7 @@ static int midifile_open_path(t_midifile *x, char *path, char *mode) /* ...if it doesn't work we won't mess up x->fPath */ tryPath[PATH_BUF_SIZE-1] = '\0'; /* just make sure there is a null termination */ if (x->verbosity > 1)post("midifile_open_path (absolute): %s\n", tryPath); - fP = fopen(tryPath, mode); + fP = sys_fopen(tryPath, mode); } if (fP == NULL) { @@ -249,7 +267,7 @@ static int midifile_open_path(t_midifile *x, char *path, char *mode) /* ...if it doesn't work we won't mess up x->fPath */ tryPath[PATH_BUF_SIZE-1] = '\0'; /* just make sure there is a null termination */ if (x->verbosity > 1)post("midifile_open_path (relative): %s\n", tryPath); - fP = fopen(tryPath, mode); + fP = sys_fopen(tryPath, mode); } if (fP == NULL) return 0; x->fP = fP; @@ -330,7 +348,7 @@ static size_t midifile_write_header(t_midifile *x) static void midifile_write(t_midifile *x, t_symbol *s, int argc, t_atom *argv) /* open the file for writing and write the header */ { - char *path; + char *path = NULL; int frames_per_second = 0;/* default */ int ticks_per_frame = 90; /* default*/ @@ -436,7 +454,7 @@ static void midifile_bang(t_midifile *x) static void midifile_list(t_midifile *x, t_symbol *s, int argc, t_atom *argv) /* add a list containing time and midi packet to the temporary file in MIDI file format */ { - int i, j, k, m, dt_written = 0; + int i, j, k, m = 0, dt_written = 0; size_t len, written = 0L; static int warnings = 0; @@ -586,12 +604,12 @@ static int midifle_read_chunks(t_midifile *x) static int midifile_read_header_chunk(t_midifile *x) { - char *cP = x->header_chunk.chunk_type; - char *sP; - char buf[4]; - size_t n; - int div, smpte, ticks; - t_atom output_atom; + unsigned char *cP = (unsigned char *)x->header_chunk.chunk_type; + char *sP; + char buf[4]; + size_t n; + int div, smpte, ticks; + t_atom output_atom; if (x->fP == NULL) { @@ -604,7 +622,7 @@ static int midifile_read_header_chunk(t_midifile *x) x->offset += n; if (n != 4L) { - error("midifile: read %lu instead of 4", n); + error("midifile: read %zu instead of 4", n); return 0; } if (x->verbosity) post("midifile: Header chunk type: %c%c%c%c", cP[0], cP[1], cP[2], cP[3]); @@ -613,12 +631,12 @@ static int midifile_read_header_chunk(t_midifile *x) error ("midifile: bad file format: bad header chunk type"); return 0; } - cP = buf; + cP = (unsigned char *)buf; n = fread(cP, 1L, 4L, x->fP); x->offset += n; if (n != 4L) { - error("midifile: read %lu instead of 4", n); + error("midifile: read %zu instead of 4", n); return 0; } x->header_chunk.chunk_length = midifile_get_multibyte_4(cP); @@ -632,7 +650,7 @@ static int midifile_read_header_chunk(t_midifile *x) x->offset += n; if (n != 2L) { - error("midifile: read %lu instead of 2", n); + error("midifile: read %zu instead of 2", n); return 0; } x->header_chunk.chunk_format = midifile_get_multibyte_2(cP); @@ -658,7 +676,7 @@ static int midifile_read_header_chunk(t_midifile *x) x->offset += n; if (n != 2L) { - error("midifile: read %lu instead of 2", n); + error("midifile: read %zu instead of 2", n); return 0; } x->header_chunk.chunk_ntrks = midifile_get_multibyte_2(cP); @@ -675,7 +693,7 @@ static int midifile_read_header_chunk(t_midifile *x) x->offset += n; if (n != 2L) { - error("midifile: read %lu instead of 2", n); + error("midifile: read %zu instead of 2", n); return 0; } x->header_chunk.chunk_division = midifile_get_multibyte_2(cP); @@ -705,10 +723,10 @@ static int midifile_read_track_chunk(t_midifile *x, int mfindex) /* read the data part of a track chunk into track_data */ /* after allocating the space for it */ { - char *cP = x->track_chunk[mfindex].chunk_type; - char buf[4]; - char type[5]; - size_t n, len; + unsigned char *cP = (unsigned char *)x->track_chunk[mfindex].chunk_type; + char buf[4]; + char type[5]; + size_t n, len; if (x->fP == NULL) { @@ -719,7 +737,7 @@ static int midifile_read_track_chunk(t_midifile *x, int mfindex) x->offset += n; if (n != 4L) { - error("midifile: read %lu instead of 4", n); + error("midifile: read %zu instead of 4", n); return 0; } if (!(cP[0] == 'M' && cP[1] == 'T' && cP[2] == 'r' && cP[3] == 'k')) @@ -732,23 +750,23 @@ static int midifile_read_track_chunk(t_midifile *x, int mfindex) type[2] = cP[2]; type[3] = cP[3]; type[4] = '\0'; - cP = buf; + cP = (unsigned char *)buf; n = fread(cP, 1L, 4L, x->fP); x->offset += n; if (n != 4L) { - error("midifile: read %lu instead of 4", n); + error("midifile: read %zu instead of 4", n); return 0; } len = midifile_get_multibyte_4(cP); x->track_chunk[mfindex].chunk_length = len; - if (x->verbosity) post("midifile: Track chunk %d type: %s, length %lu", mfindex, type, len); + if (x->verbosity) post("midifile: Track chunk %d type: %s, length %zu", mfindex, type, len); if ((cP = getbytes(len)) == NULL) { - error ("midifile: Unable to allocate %lu bytes for track data", len); + error ("midifile: Unable to allocate %zu bytes for track data", len); return 0; } - x->track_chunk[mfindex].track_data = cP; + x->track_chunk[mfindex].track_data = (unsigned char*)cP; n = fread(cP, 1L, len, x->fP); return 1; @@ -766,7 +784,7 @@ static unsigned short midifile_combine_bytes(unsigned char data1, unsigned char return ((((unsigned short)data2)<< 7) | ((unsigned short)data1)); } -static unsigned long midifile_get_multibyte_4(char*n) +static unsigned long midifile_get_multibyte_4(unsigned char*n) /* make a long from 4 consecutive bytes in big-endian format */ { unsigned long a, b, c, d, e; @@ -778,7 +796,7 @@ static unsigned long midifile_get_multibyte_4(char*n) return e; } -static unsigned long midifile_get_multibyte_3(char*n) +static unsigned long midifile_get_multibyte_3(unsigned char*n) /* make a long from 3 consecutive bytes in big-endian format */ { unsigned long a, b, c, d; @@ -789,7 +807,7 @@ static unsigned long midifile_get_multibyte_3(char*n) return d; } -static unsigned short midifile_get_multibyte_2(char*n) +static unsigned short midifile_get_multibyte_2(unsigned char*n) /* make a short from 2 consecutive bytes in big-endian format */ { unsigned short a, b, c; @@ -826,7 +844,7 @@ static int midifile_write_variable_length_value (FILE *fP, size_t value) return i; } -static char *midifile_read_var_len (char *cP, size_t *delta) +static unsigned char *midifile_read_var_len (unsigned char *cP, size_t *delta) { /* enter with cP pointing to deltatime */ /* set delta to deltatime */ @@ -929,7 +947,7 @@ static void midifile_output_long_list (t_outlet *outlet, unsigned char *cP, size return; } slist[0].a_type = A_FLOAT; - slist[0].a_w.w_float = 0xF0; + slist[0].a_w.w_float = first_byte;//0xF0; for (si = 0; si < len; ++si) { slist[si+1].a_type = A_FLOAT; @@ -943,8 +961,9 @@ static void midifile_dump_track_chunk_data(t_midifile *x, int mfindex) /* parse entire track chunk and output it to the main window */ { unsigned char *cP, *last_cP, *str; - size_t total_time, delta_time, time_sig, len; - unsigned char status, running_status, c, d, nn, dd, cc, bb, mi, mcp, ch; + size_t total_time, delta_time, len; + unsigned long time_sig; + unsigned char status, running_status = 0, c, d, nn, dd, cc, bb, mi, mcp, ch; char sf; unsigned short sn; unsigned char tt[3]; @@ -962,7 +981,7 @@ static void midifile_dump_track_chunk_data(t_midifile *x, int mfindex) cP = midifile_read_var_len(cP, &delta_time); status = *cP++; total_time += delta_time; - msgPtr += sprintf (msgPtr, "tick %lu delta %lu status %02X ", total_time, delta_time, status); + msgPtr += sprintf (msgPtr, "tick %zu delta %zu status %02X ", total_time, delta_time, status); if ((status & 0xF0) == 0xF0) { switch (status) @@ -970,7 +989,7 @@ static void midifile_dump_track_chunk_data(t_midifile *x, int mfindex) case 0xF0: case 0xF7: cP = midifile_read_var_len(cP, &len);/* not a time but the same variable length format */ - msgPtr += sprintf(msgPtr, "Sysex: %02X length %lu ", status, len); + msgPtr += sprintf(msgPtr, "Sysex: %02X length %zu ", status, len); cP += len; break; case 0xF3: /* song select */ @@ -1009,7 +1028,7 @@ static void midifile_dump_track_chunk_data(t_midifile *x, int mfindex) case 0xFF: c = *cP++; cP = midifile_read_var_len(cP, &len);/* not a time but the same variable length format */ - msgPtr += sprintf(msgPtr, "Meta 0x%02X length %lu \n", c, len); + msgPtr += sprintf(msgPtr, "Meta 0x%02X length %zu \n", c, len); switch (c) { case 0x58: @@ -1175,7 +1194,7 @@ static void midifile_get_next_track_chunk_data(t_midifile *x, int mfindex) /* Sets the delta_time of the element or NO_MORE_ELEMENTS if no more elements */ { unsigned char *cP, *last_cP, *str; - size_t delta_time, time_sig, len, i; + size_t delta_time, time_sig, len; unsigned char status, c, d, nn, dd, cc, bb, mi, mcp, n; char sf; char fps, hour, min, sec, frame, subframe; @@ -1199,7 +1218,7 @@ static void midifile_get_next_track_chunk_data(t_midifile *x, int mfindex) case 0xF0: case 0xF7: cP = midifile_read_var_len(cP, &len); /* packet length */ - if (x->verbosity) post("midifile: Sysex: %02X length %lu", status, len); + if (x->verbosity) post("midifile: Sysex: %02X length %zu", status, len); midifile_output_long_list(x->midi_list_outlet, cP, len, 0xF0); cP += len; x->track_chunk[mfindex].running_status = 0; @@ -1242,7 +1261,7 @@ static void midifile_get_next_track_chunk_data(t_midifile *x, int mfindex) case 0xFF: /* meta event */ c = *cP++; cP = midifile_read_var_len(cP, &len);/* meta length */ - if (x->verbosity) post("midifile: Track %d Meta: %02X length %lu", mfindex, c, len); + if (x->verbosity) post("midifile: Track %d Meta: %02X length %zu", mfindex, c, len); switch (c) { case 0x59: /* key signature */ @@ -1294,7 +1313,7 @@ static void midifile_get_next_track_chunk_data(t_midifile *x, int mfindex) sec = *cP++; frame = *cP++; subframe = *cP++; - if (x->verbosity) post ("midifile: %lu SMPTE offset: %d:%d:%d:%d:%d, %d fps", hour, min, sec, frame, subframe, fps); + if (x->verbosity) post ("midifile: SMPTE offset: %d:%d:%d:%d:%d, %d fps", hour, min, sec, frame, subframe, fps); SETFLOAT(&output_atom[0], hour); SETFLOAT(&output_atom[1], min); SETFLOAT(&output_atom[2], sec); @@ -1336,7 +1355,7 @@ static void midifile_get_next_track_chunk_data(t_midifile *x, int mfindex) c = cP[len]; cP[len] = '\0'; /* null terminate temporarily */ if (x->verbosity) post ("midifile: Cue Point: %s", str); - SETSYMBOL(&output_atom[0], gensym(str)); + SETSYMBOL(&output_atom[0], gensym((char *)str)); outlet_anything( x->status_outlet, gensym("cue"), 1, output_atom); cP[len] = c; cP += len; @@ -1346,7 +1365,7 @@ static void midifile_get_next_track_chunk_data(t_midifile *x, int mfindex) c = cP[len]; cP[len] = '\0'; /* null terminate temporarily */ if (x->verbosity) post ("midifile: Marker: %s", str); - SETSYMBOL(&output_atom[0], gensym(str)); + SETSYMBOL(&output_atom[0], gensym((char *)str)); outlet_anything( x->status_outlet, gensym("marker"), 1, output_atom); cP[len] = c; cP += len; @@ -1356,7 +1375,7 @@ static void midifile_get_next_track_chunk_data(t_midifile *x, int mfindex) c = cP[len]; cP[len] = '\0'; /* null terminate temporarily */ if (x->verbosity) post ("midifile: Lyric: %s", str); - SETSYMBOL(&output_atom[0], gensym(str)); + SETSYMBOL(&output_atom[0], gensym((char *)str)); outlet_anything( x->status_outlet, gensym("lyrics"), 1, output_atom); cP[len] = c; cP += len; @@ -1366,7 +1385,7 @@ static void midifile_get_next_track_chunk_data(t_midifile *x, int mfindex) c = cP[len]; cP[len] = '\0'; /* null terminate temporarily */ if (x->verbosity) post ("midifile: Instrument Name: %s", str); - SETSYMBOL(&output_atom[0], gensym(str)); + SETSYMBOL(&output_atom[0], gensym((char *)str)); outlet_anything( x->status_outlet, gensym("instr_name"), 1, output_atom); cP[len] = c; cP += len; @@ -1377,7 +1396,7 @@ static void midifile_get_next_track_chunk_data(t_midifile *x, int mfindex) cP[len] = '\0'; /* null terminate temporarily */ if (x->verbosity) post ("midifile: Sequence/Track Name: %s", str); SETFLOAT(&output_atom[0], mfindex); - SETSYMBOL(&output_atom[1], gensym(str)); + SETSYMBOL(&output_atom[1], gensym((char *)str)); outlet_anything( x->status_outlet, gensym("name"), 2, output_atom); cP[len] = c; cP += len; @@ -1387,7 +1406,7 @@ static void midifile_get_next_track_chunk_data(t_midifile *x, int mfindex) c = cP[len]; cP[len] = '\0'; /* null terminate temporarily */ if (x->verbosity) post ("midifile: Copyright Notice: %s", str); - SETSYMBOL(&output_atom[0], gensym(str)); + SETSYMBOL(&output_atom[0], gensym((char *)str)); outlet_anything( x->status_outlet, gensym("copyright"), 1, output_atom); cP[len] = c; cP += len; @@ -1397,7 +1416,7 @@ static void midifile_get_next_track_chunk_data(t_midifile *x, int mfindex) c = cP[len]; cP[len] = '\0'; /* null terminate temporarily */ if (x->verbosity) post ("midifile: Text Event: %s", str); - SETSYMBOL(&output_atom[0], gensym(str)); + SETSYMBOL(&output_atom[0], gensym((char *)str)); outlet_anything( x->status_outlet, gensym("text"), 1, output_atom); cP[len] = c; cP += len; @@ -1452,7 +1471,7 @@ static void midifile_get_next_track_chunk_data(t_midifile *x, int mfindex) x->midi_data[2].a_w.w_float = (n == 3)?d:0; if (x->midi_data[0].a_w.w_float != 0) outlet_list(x->midi_list_outlet, &s_list, n, x->midi_data); if (x->track_chunk[mfindex].running_status == 0) - error ("midifile: No running status on track %d at %lu", + error ("midifile: No running status on track %d at %zu", mfindex, x->track_chunk[mfindex].total_time + delta_time); } } @@ -1559,7 +1578,7 @@ static void midifile_skip_next_track_chunk_data(t_midifile *x, int mfindex) static t_symbol *midifile_key_name(int sf, int mi) { /* set a symbole to the key name baseed on */ - /* sf= number of sharps if positive, else flats + /* sf= number of sharps if positive, else flats */ /* mi = 0=major 1= minor */ char *maj_key[15]={"B", "Gb", "Db", "Ab", "Eb", "Bb", "F", "C", "G", "D", "A", "E", "B", "F#", "Db"}; char *min_key[15]={"G#", "Eb", "Bb", "F", "C", "G", "D", "A", "E", "B", "F#", "C#", "G#", "D#", "Bb"}; diff --git a/externals/mrpeach/mrpeach-meta.pd b/externals/mrpeach/mrpeach-meta.pd new file mode 100644 index 000000000..85596447c --- /dev/null +++ b/externals/mrpeach/mrpeach-meta.pd @@ -0,0 +1,6 @@ +#N canvas 15 49 200 200 10; +#N canvas 25 49 420 300 META 1; +#X text 13 41 NAME mrpeach; +#X text 10 25 AUTHOR Martin Peach; +#X text 10 10 VERSION 0.1; +#X restore 10 10 pd META; diff --git a/externals/mrpeach/net/tcpclient.c b/externals/mrpeach/net/tcpclient.c index bba25f1d8..f530834b5 100644 --- a/externals/mrpeach/net/tcpclient.c +++ b/externals/mrpeach/net/tcpclient.c @@ -47,6 +47,13 @@ #include <ws2tcpip.h> /* for socklen_t */ #endif +/* support older Pd versions without sys_open(), sys_fopen(), sys_fclose() */ +#if PD_MAJOR_VERSION == 0 && PD_MINOR_VERSION < 44 +#define sys_open open +#define sys_fopen fopen +#define sys_fclose fclose +#endif + #ifdef _MSC_VER #define snprintf sprintf_s #endif @@ -63,7 +70,7 @@ static char objName[] = "tcpclient"; typedef struct _tcpclient_sender_params { char x_sendbuf[MAX_TCPCLIENT_SEND_BUF]; /* possibly allocate this dynamically for space over speed */ - int x_buf_len; + size_t x_buf_len; int x_sendresult; pthread_t sendthreadid; int threadisvalid; /* non-zero if sendthreadid is an active thread */ @@ -89,7 +96,7 @@ typedef struct _tcpclient char *x_hostname; // address we want to connect to as text int x_connectstate; // 0 = not connected, 1 = connected int x_port; // port we're connected to - long x_addr; // address we're connected to as 32bit int + uint32_t x_addr; // address we're connected to as 32bit int t_atom x_addrbytes[4]; // address we're connected to as 4 bytes t_atom x_msgoutbuf[MAX_TCPCLIENT_SEND_BUF]; // received data as float atoms unsigned char x_msginbuf[MAX_TCPCLIENT_SEND_BUF]; // received data as bytes @@ -215,7 +222,7 @@ static void *tcpclient_child_connect(void *w) return (x); } x->x_fd = sockfd; - x->x_addr = ntohl(*(long *)hp->h_addr); + x->x_addr = ntohl(*(uint32_t *)hp->h_addr); /* outlet_float is not threadsafe ! */ // outlet_float(x->x_obj.ob_outlet, 1); x->x_connectstate = 1; @@ -305,7 +312,7 @@ static void tcpclient_send(t_tcpclient *x, t_symbol *s, int argc, t_atom *argv) else if (argv[i].a_type == A_SYMBOL) { atom_string(&argv[i], fpath, FILENAME_MAX); - fptr = fopen(fpath, "rb"); + fptr = sys_fopen(fpath, "rb"); if (fptr == NULL) { post("%s_send: unable to open \"%s\"", objName, fpath); @@ -322,7 +329,7 @@ static void tcpclient_send(t_tcpclient *x, t_symbol *s, int argc, t_atom *argv) j = 0; } } - fclose(fptr); + sys_fclose(fptr); fptr = NULL; if (x->x_verbosity) post("%s_send: read \"%s\" length %d byte%s", objName, fpath, j, ((d==1)?"":"s")); } @@ -376,8 +383,11 @@ static void *tcpclient_child_send(void *w) { t_tcpclient_sender_params *tsp = (t_tcpclient_sender_params*) w; - tsp->x_sendresult = send(tsp->x_x->x_fd, tsp->x_sendbuf, tsp->x_buf_len, 0); - clock_delay(tsp->x_x->x_sendclock, 0); // calls tcpclient_sent when it's safe to do so + if (tsp->x_x->x_fd >= 0) + { + tsp->x_sendresult = send(tsp->x_x->x_fd, tsp->x_sendbuf, tsp->x_buf_len, 0); + clock_delay(tsp->x_x->x_sendclock, 0); // calls tcpclient_sent when it's safe to do so + } tsp->threadisvalid = 0; /* this thread is over */ return(tsp); } @@ -605,12 +615,15 @@ static void tcpclient_free(t_tcpclient *x) if (x->x_verbosity) post("...tcpclient_free"); } +#ifndef BUILD_DATE +# define BUILD_DATE __DATE__ " " __TIME__ +#endif void tcpclient_setup(void) { char aboutStr[MAXPDSTRING]; - snprintf(aboutStr, MAXPDSTRING, "%s: (GPL) 20111103 Martin Peach, compiled for pd-%d.%d on %s %s", - objName, PD_MAJOR_VERSION, PD_MINOR_VERSION, __DATE__, __TIME__); + snprintf(aboutStr, MAXPDSTRING, "%s: (GPL) 20111103 Martin Peach, compiled for pd-%d.%d on %s", + objName, PD_MAJOR_VERSION, PD_MINOR_VERSION, BUILD_DATE ); #if PD_MAJOR_VERSION==0 && PD_MINOR_VERSION<43 post(aboutStr); diff --git a/externals/mrpeach/net/tcpsend.c b/externals/mrpeach/net/tcpsend.c index 7aef49188..5af788cff 100644 --- a/externals/mrpeach/net/tcpsend.c +++ b/externals/mrpeach/net/tcpsend.c @@ -20,6 +20,13 @@ #include <netdb.h> #endif +/* support older Pd versions without sys_open(), sys_fopen(), sys_fclose() */ +#if PD_MAJOR_VERSION == 0 && PD_MINOR_VERSION < 44 +#define sys_open open +#define sys_fopen fopen +#define sys_fclose fclose +#endif + static t_class *tcpsend_class; typedef struct _tcpsend @@ -163,7 +170,7 @@ static void tcpsend_send(t_tcpsend *x, t_symbol *s, int argc, t_atom *argv) #ifdef DEBUG post ("tcpsend fname: %s", fpath); #endif - fptr = fopen(fpath, "rb"); + fptr = sys_fopen(fpath, "rb"); if (fptr == NULL) { post("tcpsend: unable to open \"%s\"", fpath); @@ -185,7 +192,7 @@ static void tcpsend_send(t_tcpsend *x, t_symbol *s, int argc, t_atom *argv) break; } } - fclose(fptr); + sys_fclose(fptr); fptr = NULL; post("tcpsend: read \"%s\" length %d byte%s", fpath, j, ((d==1)?"":"s")); } diff --git a/externals/mrpeach/net/tcpserver-help.pd b/externals/mrpeach/net/tcpserver-help.pd index 097b785f1..9cafbea0d 100644 --- a/externals/mrpeach/net/tcpserver-help.pd +++ b/externals/mrpeach/net/tcpserver-help.pd @@ -1,20 +1,20 @@ -#N canvas 1 53 1284 779 12; +#N canvas 4 103 1272 816 12; #X msg 39 -10 print; -#X floatatom 344 316 5 0 0 0 - - -; -#X floatatom 368 366 5 0 0 0 - - -; -#X obj 392 317 unpack 0 0 0 0; -#X floatatom 392 340 3 0 0 0 - - -; -#X floatatom 423 340 3 0 0 0 - - -; -#X floatatom 455 340 3 0 0 0 - - -; -#X floatatom 489 340 3 0 0 0 - - -; -#X text 349 339 from; -#X text 260 316 connections; -#X obj 321 441 print received; +#X floatatom 404 376 5 0 0 0 - - -; +#X floatatom 428 426 5 0 0 0 - - -; +#X obj 452 377 unpack 0 0 0 0; +#X floatatom 452 400 3 0 0 0 - - -; +#X floatatom 483 400 3 0 0 0 - - -; +#X floatatom 515 400 3 0 0 0 - - -; +#X floatatom 549 400 3 0 0 0 - - -; +#X text 409 399 from; +#X text 320 376 connections; +#X obj 381 501 print received; #X msg 135 86 client 1 1 2 3; #X msg 63 14 broadcast 1 2 3; #X text 91 -9 list of connections; #X text 186 14 send to all clients; -#X text 298 366 on socket; +#X text 358 426 on socket; #X msg -11 -60 send 504 1 2 3; #X text 100 -65 send to client on socket 504; #X msg 647 -209 client 1 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 @@ -53,7 +53,7 @@ #X msg -41 -90 disconnectsocket \$1; #X msg -84 -133 disconnectclient \$1; #X obj 647 257 s toserver; -#X obj 321 264 r toserver; +#X obj 376 327 r toserver; #X floatatom 143 -172 5 0 0 0 - - -; #X obj 121 -153 f; #X obj 121 -172 bng 15 250 50 0 empty empty empty 17 7 0 10 -258699 @@ -63,12 +63,12 @@ #X obj 163 -129 bng 15 250 50 0 empty empty empty 17 7 0 10 -258699 -241291 -1; #X text -109 -110 disconnect by socket or client number; -#X text 428 291 argument is port number; -#X text -8 293 Received messages are output as lists of bytes; -#X text -69 397 ***WARNING*** Attempting to print long messages can +#X text 488 351 argument is port number; +#X text 52 353 Received messages are output as lists of bytes; +#X text -9 457 ***WARNING*** Attempting to print long messages can hang pd!; -#X obj 321 419 spigot; -#X obj 360 399 tgl 15 0 empty empty enable_print 17 7 0 10 -24198 -258699 +#X obj 381 479 spigot; +#X obj 420 459 tgl 15 0 empty empty enable_print 17 7 0 10 -24198 -258699 -45076 0 1; #X msg 159 110 dump \$1; #X obj -17 95 tgl 15 0 empty empty enable_dump 17 7 0 10 -4034 -257985 @@ -77,7 +77,7 @@ hang pd!; #X text -85 61 characters to main; #X text -85 76 window in hexdump; #X text -85 92 format:; -#X obj 321 292 tcpserver 9997; +#X obj 381 352 tcpserver 9997; #X msg -132 -181 client 1 test.txt; #X text 647 -234 [tcpserver] sends and receives bytes on [0...255] ; @@ -85,42 +85,41 @@ hang pd!; ; #X text -137 -202 send a file to client 1; #X msg 183 134 client 1 72 101 108 108 111 13 10; -#X floatatom 578 377 9 0 0 0 - - -; -#X obj 710 336 print status; -#X floatatom 538 400 5 0 0 0 - - -; -#X text 468 399 to_client; +#X floatatom 638 437 9 0 0 0 - - -; +#X obj 770 396 print status; +#X floatatom 598 460 5 0 0 0 - - -; +#X text 528 459 to_client; #X msg 111 62 client; #X msg 88 39 client 1; #X text 156 38 get state of client 1; #X text 249 86 send (binary) 1 2 3 to client 1; -#X floatatom 712 469 5 0 0 0 - - -; -#X symbolatom 744 442 20 0 0 0 - - -; -#X floatatom 681 442 5 0 0 0 - - -; -#X text 645 376 bytes; -#X text 538 376 sent; +#X floatatom 772 529 5 0 0 0 - - -; +#X symbolatom 804 502 20 0 0 0 - - -; +#X floatatom 741 502 5 0 0 0 - - -; +#X text 705 436 bytes; +#X text 598 436 sent; #X msg 209 160 clientbuf 1 65536; -#X obj 681 418 unpack 0 0 s 0; -#X floatatom 776 490 7 0 0 0 - - -; -#X text 621 490 length of send buffer:; -#X text 661 468 socket:; -#X text 630 441 client:; -#X text 721 441 ip:; +#X obj 741 478 unpack 0 0 s 0; +#X floatatom 836 550 7 0 0 0 - - -; +#X text 681 550 length of send buffer:; +#X text 721 528 socket:; +#X text 690 501 client:; +#X text 781 501 ip:; #X text 339 159 set send-buffer size for client 1; #X text 163 62 get state of all clients (list on right outlet); -#X obj 538 351 unpack 0 0 0; -#X floatatom 619 418 5 0 0 0 - - -; -#X text 549 417 on_socket; +#X obj 598 411 unpack 0 0 0; +#X floatatom 679 478 5 0 0 0 - - -; +#X text 609 477 on_socket; #X msg 233 184 send; #X msg 258 209 1156; #X text 276 183 output 'client' message for all sockets; #X text 298 209 output 'client' message for socket 1156; #X msg 283 234 unblock; -#X obj 538 312 route sent client blocked; +#X obj 598 372 route sent client blocked; #X text -143 233 If sending too many messages blocks the system \, tcpserver will stop sending until it receives an unblock message; -#X obj 652 359 print blocked; -#X text -69 476 2010/03/27 Martin Peach; -#N canvas 529 82 494 344 META 0; +#X obj 712 419 print blocked; +#N canvas 530 81 494 344 META 0; #X text 12 225 HELP_PATCH_AUTHORS "pd meta" information added by Jonathan Wilkes for Pd version 0.42.; #X text 12 205 AUTHOR Martin Peach; @@ -134,7 +133,15 @@ send print broadcast dump clientbuf unblock; #X text 12 145 OUTLET_2 float; #X text 12 165 OUTLET_3 list; #X text 12 185 OUTLET_4 sent client blocked; -#X restore 839 398 pd META; +#X restore 899 458 pd META; +#X msg 354 305 port 12345; +#X text 436 304 change listening port (only if no connections are active) +; +#X msg 332 283 verbosity \$1; +#X obj 332 263 hradio 15 1 0 4 empty empty empty 0 -8 0 10 -1 -4034 +-1 0; +#X text 425 281 set verbosity level; +#X text -9 536 2014/02/13 Martin Peach; #X connect 0 0 60 0; #X connect 3 0 4 0; #X connect 3 1 5 0; @@ -197,3 +204,6 @@ send print broadcast dump clientbuf unblock; #X connect 96 1 80 0; #X connect 96 2 98 0; #X connect 96 3 67 0; +#X connect 100 0 60 0; +#X connect 102 0 60 0; +#X connect 103 0 102 0; diff --git a/externals/mrpeach/net/tcpserver.c b/externals/mrpeach/net/tcpserver.c index b7cc25477..0842e1de2 100644 --- a/externals/mrpeach/net/tcpserver.c +++ b/externals/mrpeach/net/tcpserver.c @@ -50,14 +50,21 @@ #define SOCKET_ERROR -1 #else #include <winsock2.h> +#include <ws2tcpip.h> /* for socklen_t */ #endif +/* support older Pd versions without sys_open(), sys_fopen(), sys_fclose() */ +#if PD_MAJOR_VERSION == 0 && PD_MINOR_VERSION < 44 +#define sys_open open +#define sys_fopen fopen +#define sys_fclose fclose +#endif #ifdef _MSC_VER #define snprintf sprintf_s #endif -#define MAX_CONNECT 32 /* maximum number of connections */ +#define MAX_CONNECT 1024 /* maximum number of connections to reserve space for */ #define INBUFSIZE 65536L /* was 4096: size of receiving data buffer */ #define MAX_UDP_RECEIVE 65536L /* longer than data in maximum UDP packet */ @@ -72,8 +79,8 @@ typedef void (*t_tcpserver_socketreceivefn)(void *x, t_binbuf *b); typedef struct _tcpserver_socketreceiver { t_symbol *sr_host; - t_int sr_fd; - t_int sr_fdbuf; + int sr_fd; + int sr_fdbuf; u_long sr_addr; unsigned char *sr_inbuf; int sr_inhead; @@ -89,6 +96,7 @@ typedef struct _tcpserver_send_params int sockfd; char *byte_buf; size_t length; + int verbosity; } t_tcpserver_send_params; typedef struct _tcpserver @@ -99,25 +107,27 @@ typedef struct _tcpserver t_outlet *x_sockout; t_outlet *x_addrout; t_outlet *x_status_outlet; - t_int x_dump; // 1 = hexdump received bytes + int x_dump; // 1 = hexdump received bytes t_tcpserver_socketreceiver *x_sr[MAX_CONNECT]; t_atom x_addrbytes[4]; - t_int x_sock_fd; - t_int x_connectsocket; - t_int x_nconnections; - t_int x_blocked; + int x_sock_fd; + int x_connectsocket; + int x_port; + int x_nconnections; + int x_blocked; + int x_verbosity; t_atom x_msgoutbuf[MAX_UDP_RECEIVE]; char x_msginbuf[MAX_UDP_RECEIVE]; } t_tcpserver; -typedef struct _tcpserver_broadcast_params -{ - t_tcpserver *x; - t_int argc; - t_atom argv[MAX_UDP_RECEIVE]; -} t_tcpserver_broadcast_params; +typedef struct _tcpserver_broadcast_params +{ + t_tcpserver *x; + int argc; + t_atom argv[MAX_UDP_RECEIVE]; +} t_tcpserver_broadcast_params; static t_tcpserver_socketreceiver *tcpserver_socketreceiver_new(void *owner, t_tcpserver_socketnotifier notifier, t_tcpserver_socketreceivefn socketreceivefn); @@ -130,7 +140,7 @@ static void tcpserver_send_bytes(int sockfd, t_tcpserver *x, int argc, t_atom *a static int tcpserver_send_buffer_avaliable_for_client(t_tcpserver *x, int client); #endif static void *tcpserver_send_buf_thread(void *arg); -static void *tcpserver_broadcast_thread(void *arg); +static void *tcpserver_broadcast_thread(void *arg); static void tcpserver_client_send(t_tcpserver *x, t_symbol *s, int argc, t_atom *argv); static void tcpserver_output_client_state(t_tcpserver *x, int client); static int tcpserver_get_socket_send_buf_size(int sockfd); @@ -139,31 +149,39 @@ static void tcpserver_buf_size(t_tcpserver *x, t_symbol *s, int argc, t_atom *ar static void tcpserver_disconnect(t_tcpserver *x); static void tcpserver_client_disconnect(t_tcpserver *x, t_floatarg fclient); static void tcpserver_socket_disconnect(t_tcpserver *x, t_floatarg fsocket); +static void tcpserver_verbosity(t_tcpserver *x, t_floatarg verbosity_level); static void tcpserver_broadcast(t_tcpserver *x, t_symbol *s, int argc, t_atom *argv); static void tcpserver_notify(t_tcpserver *x); static void tcpserver_connectpoll(t_tcpserver *x); static void tcpserver_print(t_tcpserver *x); static void tcpserver_unblock(t_tcpserver *x); static void *tcpserver_new(t_floatarg fportno); +static void tcpserver_port(t_tcpserver *x, t_floatarg fportno); static void tcpserver_free(t_tcpserver *x); void tcpserver_setup(void); static void tcpserver_dump(t_tcpserver *x, t_float dump); -static void tcpserver_hexdump(unsigned char *buf, long len); +static void tcpserver_hexdump(unsigned char *buf, long len, int verbosity); + + +static void tcpserver_verbosity(t_tcpserver *x, t_floatarg verbosity_level) +{ + x->x_verbosity = verbosity_level; + if (x->x_verbosity > 0) post("tcpserver_verbosity now %d", x->x_verbosity); +} static void tcpserver_dump(t_tcpserver *x, t_float dump) { x->x_dump = (dump == 0)?0:1; } -static void tcpserver_hexdump(unsigned char *buf, long len) +static void tcpserver_hexdump(unsigned char *buf, long len, int verbosity) { #define BYTES_PER_LINE 16 char hexStr[(3*BYTES_PER_LINE)+1]; char ascStr[BYTES_PER_LINE+1]; long i, j, k = 0L; -#ifdef DEBUG - post("tcpserver_hexdump %d", len); -#endif + + if (verbosity > 0) post("tcpserver_hexdump of %d bytes", len); while (k < len) { for (i = j = 0; i < BYTES_PER_LINE; ++i, ++k, j+=3) @@ -189,7 +207,7 @@ static t_tcpserver_socketreceiver *tcpserver_socketreceiver_new(void *owner, t_t t_tcpserver_socketreceiver *x = (t_tcpserver_socketreceiver *)getbytes(sizeof(*x)); if (!x) { - error("%s_socketreceiver: unable to allocate %d bytes", objName, sizeof(*x)); + error("%s_socketreceiver: unable to allocate %zu bytes", objName, sizeof(*x)); } else { @@ -221,9 +239,7 @@ static int tcpserver_socketreceiver_doread(t_tcpserver_socketreceiver *x) unsigned char *inbuf = x->sr_inbuf; if (intail == inhead) return (0); -#ifdef DEBUG - post ("%s_socketreceiver_doread: intail=%d inhead=%d", objName, intail, inhead); -#endif + if (y->x_verbosity > 1) post ("%s_socketreceiver_doread: intail=%d inhead=%d", objName, intail, inhead); for (indx = intail, i = 0; indx != inhead; indx = (indx+1)&(INBUFSIZE-1), ++i) { @@ -231,7 +247,7 @@ static int tcpserver_socketreceiver_doread(t_tcpserver_socketreceiver *x) y->x_msgoutbuf[i].a_w.w_float = (float)c; } - if (y->x_dump)tcpserver_hexdump(&inbuf[intail], i); + if (y->x_dump)tcpserver_hexdump(&inbuf[intail], i, y->x_verbosity); if (i > 1) outlet_list(y->x_msgout, &s_list, i, y->x_msgoutbuf); else outlet_float(y->x_msgout, y->x_msgoutbuf[0].a_w.w_float); @@ -252,7 +268,7 @@ static void tcpserver_socketreceiver_read(t_tcpserver_socketreceiver *x, int fd) /* the input buffer might be full. If so, drop the whole thing */ if (readto == x->sr_inhead) { - post("%s: dropped message", objName); + if (y->x_verbosity > 0) post("%s: dropped message", objName); x->sr_inhead = x->sr_intail = 0; readto = INBUFSIZE; } @@ -269,16 +285,14 @@ static void tcpserver_socketreceiver_read(t_tcpserver_socketreceiver *x, int fd) } else if (ret == 0) { - post("%s: connection closed on socket %d", objName, fd); + if (y->x_verbosity > 0) post("%s: connection closed on socket %d", objName, fd); if (x->sr_notifier) (*x->sr_notifier)(x->sr_owner); sys_rmpollfn(fd); sys_closesocket(fd); } else { -#ifdef DEBUG - post ("%s_socketreceiver_read: ret = %d", objName, ret); -#endif + if (y->x_verbosity > 1) post ("%s_socketreceiver_read: received %d byte%s", objName, ret, (ret==1)?"":"s"); x->sr_inhead += ret; if (x->sr_inhead >= INBUFSIZE) x->sr_inhead = 0; /* output client's IP and socket no. */ @@ -286,7 +300,6 @@ static void tcpserver_socketreceiver_read(t_tcpserver_socketreceiver *x, int fd) { if(y->x_sr[i]->sr_fd == y->x_sock_fd) { -// outlet_symbol(x->x_connectionip, x->x_sr[i].sr_host); /* find sender's ip address and output it */ y->x_addrbytes[0].a_w.w_float = (y->x_sr[i]->sr_addr & 0xFF000000)>>24; y->x_addrbytes[1].a_w.w_float = (y->x_sr[i]->sr_addr & 0x0FF0000)>>16; @@ -304,9 +317,17 @@ static void tcpserver_socketreceiver_read(t_tcpserver_socketreceiver *x, int fd) static void tcpserver_socketreceiver_free(t_tcpserver_socketreceiver *x) { + t_tcpserver *y = x->sr_owner; + + if (y->x_verbosity > 1) post("tcpserver_socketreceiver_free x=%p", x); if (x != NULL) { - free(x->sr_inbuf); + if (NULL != x->sr_inbuf) + { + if (y->x_verbosity > 1) post("tcpserver_socketreceiver_free freeing x->sr_inbuf %p", x->sr_inbuf); + free(x->sr_inbuf); + x->sr_inbuf = NULL; + } freebytes(x, sizeof(*x)); } } @@ -327,7 +348,7 @@ static void tcpserver_send_bytes(int client, t_tcpserver *x, int argc, t_atom *a t_atom output_atom[3]; t_tcpserver_send_params *ttsp; pthread_t sender_thread; - pthread_attr_t sender_attr; + pthread_attr_t sender_attr = {{0}}; int sender_thread_result; /* process & send data */ @@ -352,9 +373,7 @@ static void tcpserver_send_bytes(int client, t_tcpserver *x, int argc, t_atom *a f = argv[i].a_w.w_float; d = (int)f; e = f - d; -#ifdef DEBUG - post("%s: argv[%d]: float:%f int:%d delta:%f", objName, i, f, d, e); -#endif + if (x->x_verbosity > 2) post("%s: argv[%d]: float:%f int:%d delta:%f", objName, i, f, d, e); if (e != 0) { error("%s: item %d (%f) is not an integer", objName, i, f); @@ -366,9 +385,7 @@ static void tcpserver_send_bytes(int client, t_tcpserver *x, int argc, t_atom *a goto failed; } c = (unsigned char)d; /* make sure it doesn't become negative; this only matters for post() */ -#ifdef DEBUG - post("%s: argv[%d]: %d", objName, i, c); -#endif + if (x->x_verbosity > 2) post("%s: argv[%d]: %d", objName, i, c); byte_buf[j++] = c; if (j >= MAX_UDP_RECEIVE) { /* if the argument list is longer than our buffer, send the buffer whenever it's full */ @@ -382,18 +399,23 @@ static void tcpserver_send_bytes(int client, t_tcpserver *x, int argc, t_atom *a ttsp = (t_tcpserver_send_params *)getbytes(sizeof(t_tcpserver_send_params)); if (ttsp == NULL) { - error("%s: unable to allocate %d bytes for t_tcpserver_send_params", objName, sizeof(t_tcpserver_send_params)); + error("%s: unable to allocate %zu bytes for t_tcpserver_send_params", objName, sizeof(t_tcpserver_send_params)); goto failed; } ttsp->client = client; ttsp->sockfd = sockfd; ttsp->byte_buf = byte_buf; ttsp->length = j; + ttsp->verbosity = x->x_verbosity; if (0 != (sender_thread_result = pthread_create(&sender_thread, &sender_attr, tcpserver_send_buf_thread, (void *)ttsp))) { ++x->x_blocked; error("%s: couldn't create sender thread (%d)", objName, sender_thread_result); - freebytes (ttsp, sizeof (t_tcpserver_send_params)); + if (NULL != ttsp) + { + freebytes (ttsp, sizeof (t_tcpserver_send_params)); + ttsp = NULL; + } goto failed; } flen += j; @@ -404,25 +426,19 @@ static void tcpserver_send_bytes(int client, t_tcpserver *x, int argc, t_atom *a { /* symbols are interpreted to be file names; attempt to load the file and send it */ atom_string(&argv[i], fpath, FILENAME_MAX); -#ifdef DEBUG - post ("%s: fname: %s", objName, fpath); -#endif - fptr = fopen(fpath, "rb"); + if (x->x_verbosity > 2) post ("%s: fname: %s", objName, fpath); + fptr = sys_fopen(fpath, "rb"); if (fptr == NULL) { error("%s: unable to open \"%s\"", objName, fpath); goto failed; } rewind(fptr); -#ifdef DEBUG - post("%s: d is %d", objName, d); -#endif while ((d = fgetc(fptr)) != EOF) { + if (x->x_verbosity > 2) post("%s: d is %d", objName, d); byte_buf[j++] = (char)(d & 0x0FF); -#ifdef DEBUG - post("%s: byte_buf[%d] = %d", objName, j-1, byte_buf[j-1]); -#endif + if (x->x_verbosity > 2) post("%s: byte_buf[%d] = %d", objName, j-1, byte_buf[j-1]); if (j >= MAX_UDP_RECEIVE) { /* if the file is longer than our buffer, send the buffer whenever it's full */ /* this might be better than allocating huge amounts of memory */ @@ -436,18 +452,23 @@ static void tcpserver_send_bytes(int client, t_tcpserver *x, int argc, t_atom *a ttsp = (t_tcpserver_send_params *)getbytes(sizeof(t_tcpserver_send_params)); if (ttsp == NULL) { - error("%s: unable to allocate %d bytes for t_tcpserver_send_params", objName, sizeof(t_tcpserver_send_params)); + error("%s: unable to allocate %zu bytes for t_tcpserver_send_params", objName, sizeof(t_tcpserver_send_params)); goto failed; } ttsp->client = client; ttsp->sockfd = sockfd; ttsp->byte_buf = byte_buf; ttsp->length = j; + ttsp->verbosity = x->x_verbosity; if ( 0!= (sender_thread_result = pthread_create(&sender_thread, &sender_attr, tcpserver_send_buf_thread, (void *)ttsp))) { ++x->x_blocked; error("%s: couldn't create sender thread (%d)", objName, sender_thread_result); - freebytes (ttsp, sizeof (t_tcpserver_send_params)); + if (NULL != ttsp) + { + freebytes (ttsp, sizeof (t_tcpserver_send_params)); + ttsp = NULL; + } goto failed; } flen += j; @@ -455,9 +476,9 @@ static void tcpserver_send_bytes(int client, t_tcpserver *x, int argc, t_atom *a } } flen += j; - fclose(fptr); + sys_fclose(fptr); fptr = NULL; - post("%s: read \"%s\" length %d byte%s", objName, fpath, flen, ((d==1)?"":"s")); + if (x->x_verbosity > 0) post("%s: read \"%s\" length %d byte%s", objName, fpath, flen, ((d==1)?"":"s")); } else { /* arg was neither a float nor a valid file name */ @@ -478,18 +499,23 @@ static void tcpserver_send_bytes(int client, t_tcpserver *x, int argc, t_atom *a ttsp = (t_tcpserver_send_params *)getbytes(sizeof(t_tcpserver_send_params)); if (ttsp == NULL) { - error("%s: unable to allocate %d bytes for t_tcpserver_send_params", objName, sizeof(t_tcpserver_send_params)); + error("%s: unable to allocate %zu bytes for t_tcpserver_send_params", objName, sizeof(t_tcpserver_send_params)); goto failed; } ttsp->client = client; ttsp->sockfd = sockfd; ttsp->byte_buf = byte_buf; ttsp->length = length; + ttsp->verbosity = x->x_verbosity; if ( 0!= (sender_thread_result = pthread_create(&sender_thread, &sender_attr, tcpserver_send_buf_thread, (void *)ttsp))) { ++x->x_blocked; error("%s: couldn't create sender thread (%d)", objName, sender_thread_result); - freebytes (ttsp, sizeof (t_tcpserver_send_params)); + if (NULL != ttsp) + { + freebytes (ttsp, sizeof (t_tcpserver_send_params)); + ttsp = NULL; + } goto failed; } flen += length; @@ -497,6 +523,11 @@ static void tcpserver_send_bytes(int client, t_tcpserver *x, int argc, t_atom *a } else post("%s: not a valid socket number (%d)", objName, sockfd); failed: + if (0!= (sender_thread_result = pthread_attr_destroy(&sender_attr))) + { + error("%s_broadcast: pthread_attr_destroy failed: %d", objName, sender_thread_result); + } + SETFLOAT(&output_atom[0], client+1); SETFLOAT(&output_atom[1], flen); SETFLOAT(&output_atom[2], sockfd); @@ -526,9 +557,9 @@ static void *tcpserver_send_buf_thread(void *arg) if (result <= 0) { sys_sockerror("tcpserver: send"); - post("%s_send_buf: could not send data to client %d", objName, ttsp->client+1); + if (ttsp->verbosity > 0) post("%s_send_buf: could not send data to client %d", objName, ttsp->client+1); } - freebytes (arg, sizeof (t_tcpserver_send_params)); + if (NULL != arg) freebytes (arg, sizeof (t_tcpserver_send_params)); return NULL; } @@ -540,7 +571,7 @@ static void tcpserver_send(t_tcpserver *x, t_symbol *s, int argc, t_atom *argv) if(x->x_nconnections <= 0) { - post("%s_send: no clients connected", objName); + if (x->x_verbosity > 0) post("%s_send: no clients connected", objName); return; } if(argc == 0) /* no socket specified: output state of all sockets */ @@ -562,13 +593,13 @@ static void tcpserver_send(t_tcpserver *x, t_symbol *s, int argc, t_atom *argv) } if(client == -1) { - post("%s_send: no connection on socket %d", objName, sockfd); + if (x->x_verbosity > 0) post("%s_send: no connection on socket %d", objName, sockfd); return; } } else { - post("%s_send: no socket specified", objName); + if (x->x_verbosity > 0) post("%s_send: no socket specified", objName); return; } if (argc < 2) /* nothing to send: output state of this socket */ @@ -602,7 +633,7 @@ static void tcpserver_disconnect(t_tcpserver *x) } } } - post("%s__disconnect: no connection on socket %d", objName, x->x_sock_fd); + if (x->x_verbosity > 0) post("%s__disconnect: no connection on socket %d", objName, x->x_sock_fd); } /* disconnect a client by socket */ @@ -612,7 +643,7 @@ static void tcpserver_socket_disconnect(t_tcpserver *x, t_floatarg fsocket) if(x->x_nconnections <= 0) { - post("%s_socket_disconnect: no clients connected", objName); + if (x->x_verbosity > 0) post("%s_socket_disconnect: no clients connected", objName); return; } x->x_sock_fd = sock; @@ -626,12 +657,12 @@ static void tcpserver_client_disconnect(t_tcpserver *x, t_floatarg fclient) if(x->x_nconnections <= 0) { - post("%s_client_disconnect: no clients connected", objName); + if (x->x_verbosity > 0) post("%s_client_disconnect: no clients connected", objName); return; } if (!((client > 0) && (client < MAX_CONNECT))) { - post("%s: client %d out of range [1..%d]", objName, client, MAX_CONNECT); + if (x->x_verbosity > 0) post("%s: client %d out of range [1..%d]", objName, client, MAX_CONNECT); return; } --client;/* zero based index*/ @@ -649,7 +680,7 @@ static void tcpserver_client_send(t_tcpserver *x, t_symbol *s, int argc, t_atom if(x->x_nconnections <= 0) { - post("%s_client_send: no clients connected", objName); + if (x->x_verbosity > 0) post("%s_client_send: no clients connected", objName); return; } if(argc > 0) @@ -659,12 +690,12 @@ static void tcpserver_client_send(t_tcpserver *x, t_symbol *s, int argc, t_atom client = atom_getfloatarg(0, argc, argv); else { - post("%s_client_send: specify client by number", objName); + if (x->x_verbosity > 0) post("%s_client_send: specify client by number", objName); return; } if (!((client > 0) && (client < MAX_CONNECT))) { - post("%s_client_send: client %d out of range [1..%d]", objName, client, MAX_CONNECT); + if (x->x_verbosity > 0) post("%s_client_send: client %d out of range [1..%d]", objName, client, MAX_CONNECT); return; } } @@ -698,14 +729,19 @@ static void tcpserver_output_client_state(t_tcpserver *x, int client) else { client -= 1;/* zero-based client index conflicts with 1-based user index !!! */ - /* output client parameters via status outlet */ - x->x_sr[client]->sr_fdbuf = tcpserver_get_socket_send_buf_size(x->x_sr[client]->sr_fd); - SETFLOAT(&output_atom[0], client+1);/* user sees client 0 as 1 */ - SETFLOAT(&output_atom[1], x->x_sr[client]->sr_fd); - output_atom[2].a_type = A_SYMBOL; - output_atom[2].a_w.w_symbol = x->x_sr[client]->sr_host; - SETFLOAT(&output_atom[3], x->x_sr[client]->sr_fdbuf); - outlet_anything( x->x_status_outlet, gensym("client"), 4, output_atom); + + if (client < x->x_nconnections) + { // only if there is such a client + /* output client parameters via status outlet */ + x->x_sr[client]->sr_fdbuf = tcpserver_get_socket_send_buf_size(x->x_sr[client]->sr_fd); + SETFLOAT(&output_atom[0], client+1);/* user sees client 0 as 1 */ + SETFLOAT(&output_atom[1], x->x_sr[client]->sr_fd); + output_atom[2].a_type = A_SYMBOL; + output_atom[2].a_w.w_symbol = x->x_sr[client]->sr_host; + SETFLOAT(&output_atom[3], x->x_sr[client]->sr_fdbuf); + outlet_anything( x->x_status_outlet, gensym("client"), 4, output_atom); + } + else if (x->x_verbosity > 0) post("%s: no such client (%d)", objName, client+1); } } @@ -748,11 +784,11 @@ static void tcpserver_buf_size(t_tcpserver *x, t_symbol *s, int argc, t_atom *ar { int client = -1; float buf_size = 0; - t_atom output_atom[3]; +// t_atom output_atom[3]; if(x->x_nconnections <= 0) { - post("%s_buf_size: no clients connected", objName); + if (x->x_verbosity > 0) post("%s_buf_size: no clients connected", objName); return; } /* get number of client (first element in list) */ @@ -762,12 +798,12 @@ static void tcpserver_buf_size(t_tcpserver *x, t_symbol *s, int argc, t_atom *ar client = atom_getfloatarg(0, argc, argv); else { - post("%s_buf_size: specify client by number", objName); + if (x->x_verbosity > 0) post("%s_buf_size: specify client by number", objName); return; } if (!((client > 0) && (client < MAX_CONNECT))) { - post("%s__buf_size: client %d out of range [1..%d]", objName, client, MAX_CONNECT); + if (x->x_verbosity > 0) post("%s__buf_size: client %d out of range [1..%d]", objName, client, MAX_CONNECT); return; } } @@ -775,248 +811,246 @@ static void tcpserver_buf_size(t_tcpserver *x, t_symbol *s, int argc, t_atom *ar { if (argv[1].a_type != A_FLOAT) { - post("%s_buf_size: specify buffer size with a float", objName); + if (x->x_verbosity > 0) post("%s_buf_size: specify buffer size with a float", objName); return; } buf_size = atom_getfloatarg(1, argc, argv); --client;/* zero based index*/ x->x_sr[client]->sr_fdbuf = tcpserver_set_socket_send_buf_size(x->x_sr[client]->sr_fd, (int)buf_size); - post("%s_buf_size: client %d set to %d", objName, client+1, x->x_sr[client]->sr_fdbuf); + if (x->x_verbosity > 0) post("%s_buf_size: client %d set to %d", objName, client+1, x->x_sr[client]->sr_fdbuf); return; } - post("%s_buf_size: specify client and buffer size", objName); + if (x->x_verbosity > 0) post("%s_buf_size: specify client and buffer size", objName); return; } -/* broadcasts messages to all clients */ -/* Ivica Ico Bukvic <ico@bukvic.net> 5/6/10 rewrote broadcast to be xrun-free */ -static void *tcpserver_broadcast_thread(void *arg) -{ - t_tcpserver_broadcast_params *ttbp = (t_tcpserver_broadcast_params *)arg; - int client; - static char byte_buf[MAX_UDP_RECEIVE];// arbitrary maximum similar to max IP packet size - int i, j, d; - unsigned char c; - float f, e; - int length; - size_t flen = 0; - int sockfd = 0; - char fpath[FILENAME_MAX]; - FILE *fptr; - t_atom output_atom[3]; - t_tcpserver_send_params *ttsp; - pthread_t sender_thread; - pthread_attr_t sender_attr; - int sender_thread_result; - int result; - - for (i = j = 0; i < ttbp->argc; ++i) - { - if (ttbp->argv[i].a_type == A_FLOAT) - { /* load floats into buffer as long as they are integers on [0..255]*/ - f = ttbp->argv[i].a_w.w_float; - d = (int)f; - e = f - d; -#ifdef DEBUG - post("%s: argv[%d]: float:%f int:%d delta:%f", objName, i, f, d, e); -#endif - if (e != 0) - { - error("%s_broadcast_thread: item %d (%f) is not an integer", objName, i, f); - freebytes (arg, sizeof (t_tcpserver_broadcast_params)); - return NULL; - } - if ((d < 0) || (d > 255)) - { - error("%s_broadcast_thread: item %d (%f) is not between 0 and 255", objName, i, f); - freebytes (arg, sizeof (t_tcpserver_broadcast_params)); - return NULL; - } - c = (unsigned char)d; /* make sure it doesn't become negative; this only matters for post() */ -#ifdef DEBUG - post("%s_broadcast_thread: argv[%d]: %d", objName, i, c); -#endif - byte_buf[j++] = c; - if (j >= MAX_UDP_RECEIVE) - { /* if the argument list is longer than our buffer, send the buffer whenever it's full */ -//LOOP - /* enumerate through the clients and send each the message */ - for(client = 0; client < ttbp->x->x_nconnections; client++) /* check if connection exists */ - { -#ifdef SIOCOUTQ - if (tcpserver_send_buffer_avaliable_for_client(ttbp->x, client) < j) - { - error("%s_broadcast_thread: buffer too small for client(%d)", objName, client); - freebytes (arg, sizeof (t_tcpserver_broadcast_params)); - return NULL; - } -#endif // SIOCOUTQ - if(ttbp->x->x_sr[client]->sr_fd >= 0) - { /* socket exists for this client */ - sockfd = ttbp->x->x_sr[client]->sr_fd; - result = send(sockfd, byte_buf, j, 0); - if (result <= 0) - { - sys_sockerror("tcpserver_broadcast_thread: send"); - post("%s_broadcast_thread: could not send data to client %d", objName, client+1); - freebytes (arg, sizeof (t_tcpserver_broadcast_params)); - return NULL; - } - } - } - flen += j; - j = 0; - } - } - else if (ttbp->argv[i].a_type == A_SYMBOL) - { /* symbols are interpreted to be file names; attempt to load the file and send it */ - atom_string(&ttbp->argv[i], fpath, FILENAME_MAX); -#ifdef DEBUG - post ("%s_broadcast_thread: fname: %s", objName, fpath); -#endif - fptr = fopen(fpath, "rb"); - if (fptr == NULL) - { - error("%s_broadcast_thread: unable to open \"%s\"", objName, fpath); - freebytes (arg, sizeof (t_tcpserver_broadcast_params)); - return NULL; - } - rewind(fptr); -#ifdef DEBUG - post("%s_broadcast_thread: d is %d", objName, d); -#endif - while ((d = fgetc(fptr)) != EOF) - { - byte_buf[j++] = (char)(d & 0x0FF); -#ifdef DEBUG - post("%s_broadcast_thread: byte_buf[%d] = %d", objName, j-1, byte_buf[j-1]); -#endif - if (j >= MAX_UDP_RECEIVE) - { /* if the file is longer than our buffer, send the buffer whenever it's full */ -//LOOP - /* enumerate through the clients and send each the message */ - for(client = 0; client < ttbp->x->x_nconnections; client++) /* check if connection exists */ - { - /* this might be better than allocating huge amounts of memory */ -#ifdef SIOCOUTQ - if (tcpserver_send_buffer_avaliable_for_client(x, client) < j) - { - error("%s_broadcast_thread: buffer too small for client(%d)", objName, client); - freebytes (arg, sizeof (t_tcpserver_broadcast_params)); - return NULL; - } -#endif // SIOCOUTQ - if(ttbp->x->x_sr[client]->sr_fd >= 0) - { /* socket exists for this client */ - sockfd = ttbp->x->x_sr[client]->sr_fd; - result = send(sockfd, byte_buf, j, 0); - if (result <= 0) - { - sys_sockerror("tcpserver_broadcast_thread: send"); - post("%s_broadcast_thread: could not send data to client %d", objName, client+1); - freebytes (arg, sizeof (t_tcpserver_broadcast_params)); - return NULL; - } - } - } - flen += j; - j = 0; - } - } - flen += j; - fclose(fptr); - fptr = NULL; - post("%s_broadcast_thread: read \"%s\" length %d byte%s", objName, fpath, flen, ((d==1)?"":"s")); - } - else - { /* arg was neither a float nor a valid file name */ - error("%s_broadcast_thread: item %d is not a float or a file name", objName, i); - freebytes (arg, sizeof (t_tcpserver_broadcast_params)); - return NULL; - } - } - length = j; - if (length > 0) - { /* send whatever remains in our buffer */ - /* enumerate through the clients and send each the message */ - for(client = 0; client < ttbp->x->x_nconnections; client++) /* check if connection exists */ - { -#ifdef SIOCOUTQ - if (tcpserver_send_buffer_avaliable_for_client(x, client) < length) - { - error("%s_broadcast_thread: buffer too small for client(%d)", objName, client); - freebytes (arg, sizeof (t_tcpserver_broadcast_params)); - return NULL; - } -#endif // SIOCOUTQ - if(ttbp->x->x_sr[client]->sr_fd >= 0) - { /* socket exists for this client */ - sockfd = ttbp->x->x_sr[client]->sr_fd; - result = send(sockfd, byte_buf, length, 0); - if (result <= 0) - { - sys_sockerror("tcpserver_broadcast_thread: send"); - post("%s_broadcast_thread: could not send data to client %d", objName, client+1); - freebytes (arg, sizeof (t_tcpserver_broadcast_params)); - return NULL; - } - } - } - flen += length; - } - else post("%s_broadcast_thread: not a valid socket number (%d)", objName, sockfd); - freebytes (arg, sizeof (t_tcpserver_broadcast_params)); - return NULL; -} - -static void tcpserver_broadcast(t_tcpserver *x, t_symbol *s, int argc, t_atom *argv) -/* initializes separate thread that broadcasts to all clients */ -/* Ivica Ico Bukvic <ico@bukvic.net> 5/6/10 rewrote broadcast to be xrun-free */ -{ - int i; - t_tcpserver_broadcast_params *ttbp; - pthread_t broadcast_thread; - pthread_attr_t broadcast_attr; - int broadcast_thread_result; - - if (x->x_nconnections != 0) - { - /* sender thread should start out detached so its resouces will be freed when it is done */ - if (0!= (broadcast_thread_result = pthread_attr_init(&broadcast_attr))) - { - error("%s_broadcast: pthread_attr_init failed: %d", objName, broadcast_thread_result); - } - else - { - if(0 != (broadcast_thread_result = pthread_attr_setdetachstate(&broadcast_attr, PTHREAD_CREATE_DETACHED))) - { - error("%s_broadcast: pthread_attr_setdetachstate failed: %d", objName, broadcast_thread_result); - } - else - { - ttbp = (t_tcpserver_broadcast_params *)getbytes(sizeof(t_tcpserver_broadcast_params)); - if (ttbp == NULL) - { - error("%s_broadcast: unable to allocate %d bytes for t_tcpserver_broadcast_params", objName, sizeof(t_tcpserver_broadcast_params)); - } - else - { - ttbp->x = x; - ttbp->argc = argc; - for (i = 0; i < argc; i++) ttbp->argv[i] = argv[i]; - if (0 != (broadcast_thread_result = pthread_create(&broadcast_thread, &broadcast_attr, tcpserver_broadcast_thread, (void *)ttbp))) - { - error("%s_broadcast: couldn't create broadcast thread (%d)", objName, broadcast_thread_result); - freebytes (ttbp, sizeof (t_tcpserver_broadcast_params)); - } - } - } - } - } -} +/* broadcasts messages to all clients */ +/* Ivica Ico Bukvic <ico@bukvic.net> 5/6/10 rewrote broadcast to be xrun-free */ +static void *tcpserver_broadcast_thread(void *arg) +{ + t_tcpserver_broadcast_params *ttbp = (t_tcpserver_broadcast_params *)arg; + int client; + static char byte_buf[MAX_UDP_RECEIVE];// arbitrary maximum similar to max IP packet size + int i, j, d; + unsigned char c; + float f, e; + int length; + size_t flen = 0; + int sockfd = 0; + char fpath[FILENAME_MAX]; + FILE *fptr; +// t_atom output_atom[3]; +// t_tcpserver_send_params *ttsp; +// pthread_t sender_thread; +// pthread_attr_t sender_attr; +// int sender_thread_result; + int result; + + for (i = j = 0; i < ttbp->argc; ++i) + { + if (ttbp->argv[i].a_type == A_FLOAT) + { /* load floats into buffer as long as they are integers on [0..255]*/ + f = ttbp->argv[i].a_w.w_float; + d = (int)f; + e = f - d; + if (ttbp->x->x_verbosity > 1) post("%s: argv[%d]: float:%f int:%d delta:%f", objName, i, f, d, e); + if (e != 0) + { + error("%s_broadcast_thread: item %d (%f) is not an integer", objName, i, f); + if (NULL != arg) freebytes (arg, sizeof (t_tcpserver_broadcast_params)); + return NULL; + } + if ((d < 0) || (d > 255)) + { + error("%s_broadcast_thread: item %d (%f) is not between 0 and 255", objName, i, f); + if (NULL != arg) freebytes (arg, sizeof (t_tcpserver_broadcast_params)); + return NULL; + } + c = (unsigned char)d; /* make sure it doesn't become negative; this only matters for post() */ + if (ttbp->x->x_verbosity > 1) post("%s_broadcast_thread: argv[%d]: %d", objName, i, c); + byte_buf[j++] = c; + if (j >= MAX_UDP_RECEIVE) + { /* if the argument list is longer than our buffer, send the buffer whenever it's full */ +//LOOP + /* enumerate through the clients and send each the message */ + for(client = 0; client < ttbp->x->x_nconnections; client++) /* check if connection exists */ + { +#ifdef SIOCOUTQ + if (tcpserver_send_buffer_avaliable_for_client(ttbp->x, client) < j) + { + error("%s_broadcast_thread: buffer too small for client(%d)", objName, client); + if (NULL != arg) freebytes (arg, sizeof (t_tcpserver_broadcast_params)); + return NULL; + } +#endif // SIOCOUTQ + if(ttbp->x->x_sr[client]->sr_fd >= 0) + { /* socket exists for this client */ + sockfd = ttbp->x->x_sr[client]->sr_fd; + result = send(sockfd, byte_buf, j, 0); + if (result <= 0) + { + sys_sockerror("tcpserver_broadcast_thread: send"); + if (ttbp->x->x_verbosity > 0) post("%s_broadcast_thread: could not send data to client %d", objName, client+1); + if (NULL != arg) freebytes (arg, sizeof (t_tcpserver_broadcast_params)); + return NULL; + } + } + } + flen += j; + j = 0; + } + } + else if (ttbp->argv[i].a_type == A_SYMBOL) + { /* symbols are interpreted to be file names; attempt to load the file and send it */ + atom_string(&ttbp->argv[i], fpath, FILENAME_MAX); + if (ttbp->x->x_verbosity > 1) post ("%s_broadcast_thread: fname: %s", objName, fpath); + fptr = sys_fopen(fpath, "rb"); + if (fptr == NULL) + { + error("%s_broadcast_thread: unable to open \"%s\"", objName, fpath); + if (NULL != arg) freebytes (arg, sizeof (t_tcpserver_broadcast_params)); + return NULL; + } + rewind(fptr); + while ((d = fgetc(fptr)) != EOF) + { + if (ttbp->x->x_verbosity > 1) post("%s_broadcast_thread: d is %d", objName, d); + byte_buf[j++] = (char)(d & 0x0FF); + if (ttbp->x->x_verbosity > 1) post("%s_broadcast_thread: byte_buf[%d] = %d", objName, j-1, byte_buf[j-1]); + if (j >= MAX_UDP_RECEIVE) + { /* if the file is longer than our buffer, send the buffer whenever it's full */ +//LOOP + /* enumerate through the clients and send each the message */ + for(client = 0; client < ttbp->x->x_nconnections; client++) /* check if connection exists */ + { + /* this might be better than allocating huge amounts of memory */ +#ifdef SIOCOUTQ + if (tcpserver_send_buffer_avaliable_for_client(x, client) < j) + { + error("%s_broadcast_thread: buffer too small for client(%d)", objName, client); + if (NULL != arg) freebytes (arg, sizeof (t_tcpserver_broadcast_params)); + return NULL; + } +#endif // SIOCOUTQ + if(ttbp->x->x_sr[client]->sr_fd >= 0) + { /* socket exists for this client */ + sockfd = ttbp->x->x_sr[client]->sr_fd; + result = send(sockfd, byte_buf, j, 0); + if (result <= 0) + { + sys_sockerror("tcpserver_broadcast_thread: send"); + if (ttbp->x->x_verbosity > 1) post("%s_broadcast_thread: could not send data to client %d", objName, client+1); + if (NULL != arg) freebytes (arg, sizeof (t_tcpserver_broadcast_params)); + return NULL; + } + } + } + flen += j; + j = 0; + } + } + flen += j; + sys_fclose(fptr); + fptr = NULL; + if (ttbp->x->x_verbosity > 1) post("%s_broadcast_thread: read \"%s\" length %d byte%s", objName, fpath, flen, ((d==1)?"":"s")); + } + else + { /* arg was neither a float nor a valid file name */ + error("%s_broadcast_thread: item %d is not a float or a file name", objName, i); + if (NULL != arg) freebytes (arg, sizeof (t_tcpserver_broadcast_params)); + return NULL; + } + } + length = j; + if (length > 0) + { /* send whatever remains in our buffer */ + /* enumerate through the clients and send each the message */ + for(client = 0; client < ttbp->x->x_nconnections; client++) /* check if connection exists */ + { +#ifdef SIOCOUTQ + if (tcpserver_send_buffer_avaliable_for_client(x, client) < length) + { + error("%s_broadcast_thread: buffer too small for client(%d)", objName, client); + if (NULL != arg) freebytes (arg, sizeof (t_tcpserver_broadcast_params)); + return NULL; + } +#endif // SIOCOUTQ + if(ttbp->x->x_sr[client]->sr_fd >= 0) + { /* socket exists for this client */ + sockfd = ttbp->x->x_sr[client]->sr_fd; + result = send(sockfd, byte_buf, length, 0); + if (result <= 0) + { + sys_sockerror("tcpserver_broadcast_thread: send"); + if (ttbp->x->x_verbosity > 0) post("%s_broadcast_thread: could not send data to client %d", objName, client+1); + if (NULL != arg) freebytes (arg, sizeof (t_tcpserver_broadcast_params)); + return NULL; + } + } + } + flen += length; + } + else if (ttbp->x->x_verbosity > 0) post("%s_broadcast_thread: not a valid socket number (%d)", objName, sockfd); + if (NULL != arg) freebytes (arg, sizeof (t_tcpserver_broadcast_params)); + return NULL; +} + +static void tcpserver_broadcast(t_tcpserver *x, t_symbol *s, int argc, t_atom *argv) +/* initializes separate thread that broadcasts to all clients */ +/* Ivica Ico Bukvic <ico@bukvic.net> 5/6/10 rewrote broadcast to be xrun-free */ +{ + int i; + t_tcpserver_broadcast_params *ttbp; + pthread_t broadcast_thread; + pthread_attr_t broadcast_attr = {{0}}; + int broadcast_thread_result; + + if (x->x_nconnections != 0) + { + /* sender thread should start out detached so its resouces will be freed when it is done */ + if (0!= (broadcast_thread_result = pthread_attr_init(&broadcast_attr))) + { + error("%s_broadcast: pthread_attr_init failed: %d", objName, broadcast_thread_result); + } + else + { + if(0 != (broadcast_thread_result = pthread_attr_setdetachstate(&broadcast_attr, PTHREAD_CREATE_DETACHED))) + { + error("%s_broadcast: pthread_attr_setdetachstate failed: %d", objName, broadcast_thread_result); + } + else + { + ttbp = (t_tcpserver_broadcast_params *)getbytes(sizeof(t_tcpserver_broadcast_params)); + if (ttbp == NULL) + { + error("%s_broadcast: unable to allocate %zu bytes for t_tcpserver_broadcast_params", objName, sizeof(t_tcpserver_broadcast_params)); + } + else + { + ttbp->x = x; + ttbp->argc = argc; + for (i = 0; i < argc; i++) ttbp->argv[i] = argv[i]; + if (0 != (broadcast_thread_result = pthread_create(&broadcast_thread, &broadcast_attr, tcpserver_broadcast_thread, (void *)ttbp))) + { + error("%s_broadcast: couldn't create broadcast thread (%d)", objName, broadcast_thread_result); + if (NULL != ttbp) + { + freebytes (ttbp, sizeof (t_tcpserver_broadcast_params)); + ttbp = NULL; + } + } + } + } + if (0!= (broadcast_thread_result = pthread_attr_destroy(&broadcast_attr))) + { + error("%s_broadcast: pthread_attr_destroy failed: %d", objName, broadcast_thread_result); + } + } + } +} /* ---------------- main tcpserver (receive) stuff --------------------- */ -/* tcpserver_notify is called by */ +/* tcpserver_notify is called when socket has closed */ static void tcpserver_notify(t_tcpserver *x) { int i, k; @@ -1036,7 +1070,7 @@ static void tcpserver_notify(t_tcpserver *x) outlet_float(x->x_sockout, x->x_sr[i]->sr_fd); /* the socket number */ outlet_float(x->x_connectout, x->x_nconnections); /* /Ivica Ico Bukvic */ - post("%s: \"%s\" removed from list of clients", objName, x->x_sr[i]->sr_host->s_name); + if (x->x_verbosity > 0) post("%s: \"%s\" removed from list of clients", objName, x->x_sr[i]->sr_host->s_name); tcpserver_socketreceiver_free(x->x_sr[i]); x->x_sr[i] = NULL; @@ -1054,12 +1088,18 @@ static void tcpserver_connectpoll(t_tcpserver *x) { struct sockaddr_in incomer_address; unsigned int sockaddrl = sizeof( struct sockaddr ); - int fd = accept(x->x_connectsocket, (struct sockaddr*)&incomer_address, &sockaddrl); + int fd; int i; int optVal; unsigned int optLen = sizeof(int); - if (fd < 0) post("%s: accept failed", objName); + if (MAX_CONNECT <= x->x_nconnections) + { /* no more free space for t_tcpserver_socketreceiver pointers, maybe increase MAX_CONNECT? */ + if (x->x_verbosity > 0) post("%s: too many connections (MAX_CONNECT is %d)", objName, x->x_nconnections); + return; + } + fd = accept(x->x_connectsocket, (struct sockaddr*)&incomer_address, &sockaddrl); + if ((fd < 0)&&(x->x_verbosity > 1)) post("%s: accept failed", objName); else { t_tcpserver_socketreceiver *y = tcpserver_socketreceiver_new((void *)x, @@ -1079,8 +1119,8 @@ static void tcpserver_connectpoll(t_tcpserver *x) x->x_sr[i] = y; x->x_sr[i]->sr_host = gensym(inet_ntoa(incomer_address.sin_addr)); x->x_sr[i]->sr_fd = fd; - post("%s: accepted connection from %s on socket %d", - objName, x->x_sr[i]->sr_host->s_name, x->x_sr[i]->sr_fd); + if (x->x_verbosity > 0) post("%s: accepted connection from %s on socket %d (client %d)", + objName, x->x_sr[i]->sr_host->s_name, x->x_sr[i]->sr_fd, i+1); /* see how big the send buffer is on this socket */ x->x_sr[i]->sr_fdbuf = 0; #ifdef _WIN32 @@ -1089,14 +1129,14 @@ static void tcpserver_connectpoll(t_tcpserver *x) /* post("%s_connectpoll: send buffer is %ld\n", objName, optVal); */ x->x_sr[i]->sr_fdbuf = optVal; } - else post("%s_connectpoll: getsockopt returned %d\n", objName, WSAGetLastError()); + else if (x->x_verbosity > 1) post("%s_connectpoll: getsockopt returned %d\n", objName, WSAGetLastError()); #else if (getsockopt(x->x_sr[i]->sr_fd, SOL_SOCKET, SO_SNDBUF, (char*)&optVal, &optLen) == 0) { /* post("%s_connectpoll: send buffer is %ld\n", objName, optVal); */ x->x_sr[i]->sr_fdbuf = optVal; } - else post("%s_connectpoll: getsockopt returned %d\n", objName, errno); + else if (x->x_verbosity > 1) post("%s_connectpoll: getsockopt returned %d\n", objName, errno); #endif x->x_sr[i]->sr_addr = ntohl(incomer_address.sin_addr.s_addr); x->x_addrbytes[0].a_w.w_float = (x->x_sr[i]->sr_addr & 0xFF000000)>>24; @@ -1130,6 +1170,94 @@ static void tcpserver_unblock(t_tcpserver *x) x->x_blocked = 0; } +static void tcpserver_port(t_tcpserver*x, t_floatarg fportno) +{ + t_atom output_atom; + int portno = fportno; + struct sockaddr_in server; + socklen_t serversize = sizeof(server); + int sockfd = x->x_connectsocket; + int optVal = 1; + int optLen = sizeof(int); + + + if(x->x_port == portno) return; + + if(x->x_nconnections > 0) + { + if (x->x_verbosity > 0) post ("%s: can't change port (connection count is %d)", objName, x->x_nconnections); + return; + } + + SETFLOAT(&output_atom, -1); + + /* shut down the old socket */ + if (sockfd >= 0) + { + sys_rmpollfn(sockfd); + sys_closesocket(sockfd); + x->x_connectsocket = -1; + x->x_port = -1; + } + + /* create a whole new socket */ + sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (x->x_verbosity > 1) post("%s: receive socket %d", objName, sockfd); + if (sockfd < 0) + { + sys_sockerror("tcpserver: socket"); + return; + } + server.sin_family = AF_INET; + server.sin_addr.s_addr = INADDR_ANY; + /* enable reuse of local address */ +#ifdef _WIN32 + if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char*)&optVal, optLen) == SOCKET_ERROR) +#else + if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char*)&optVal, optLen) == -1) +#endif + sys_sockerror("tcpserver: setsockopt SO_REUSEADDR"); + + /* assign server port number */ + server.sin_port = htons((u_short)portno); + /* name the socket */ + if (bind(sockfd, (struct sockaddr *)&server, serversize) < 0) + { + sys_sockerror("tcpserver: bind"); + sys_closesocket(sockfd); + outlet_anything(x->x_status_outlet, gensym("port"), 1, &output_atom); + return; + } + + /* streaming protocol */ + if (listen(sockfd, 5) < 0) + { + sys_sockerror("tcpserver: listen"); + sys_closesocket(sockfd); + sockfd = -1; + outlet_anything(x->x_status_outlet, gensym("port"), 1, &output_atom); + return; + } + else + { + sys_addpollfn(sockfd, (t_fdpollfn)tcpserver_connectpoll, x); // wait for new connections + } + + x->x_connectsocket = sockfd; + x->x_nconnections = 0; + x->x_blocked = 0; + + + // find out which port is actually used (useful when assigning "0") + if(!getsockname(sockfd, (struct sockaddr *)&server, &serversize)) + { + x->x_port=ntohs(server.sin_port); + } + + SETFLOAT(&output_atom, x->x_port); + outlet_anything(x->x_status_outlet, gensym("port"), 1, &output_atom); +} + static void *tcpserver_new(t_floatarg fportno) { t_tcpserver *x; @@ -1141,9 +1269,6 @@ static void *tcpserver_new(t_floatarg fportno) /* create a socket */ sockfd = socket(AF_INET, SOCK_STREAM, 0); -#ifdef DEBUG - post("%s: receive socket %d", objName, sockfd); -#endif if (sockfd < 0) { sys_sockerror("tcpserver: socket"); @@ -1203,33 +1328,40 @@ static void *tcpserver_new(t_floatarg fportno) x->x_addrbytes[i].a_type = A_FLOAT; x->x_addrbytes[i].a_w.w_float = 0; } - post ("tcpserver listening on port %d", portno); + x->x_port = portno; + post ("tcpserver listening on port %d, socket %d", x->x_port, sockfd); + x->x_verbosity = 0; // stop talking to console unless we're asked return (x); } + static void tcpserver_free(t_tcpserver *x) { int i; - post("tcp_server_free..."); + if (x->x_verbosity > 1) post("tcp_server_free..."); for(i = 0; i < MAX_CONNECT; i++) { if (x->x_sr[i] != NULL) { + if (x->x_verbosity > 1) post("tcp_server_free...freeing client %d", i+1); if (x->x_sr[i]->sr_fd >= 0) { - sys_rmpollfn(x->x_sr[i]->sr_fd); + if (x->x_verbosity > 1) post("tcp_server_free...freeing fd %d", x->x_sr[i]->sr_fd); + sys_rmpollfn(x->x_sr[i]->sr_fd); // sometimes is not found as poll function was already removed sys_closesocket(x->x_sr[i]->sr_fd); } tcpserver_socketreceiver_free(x->x_sr[i]); + x->x_sr[i] = NULL; } } if (x->x_connectsocket >= 0) { + if (x->x_verbosity > 1) post("tcp_server_free...freeing connectsocket %d", x->x_connectsocket); sys_rmpollfn(x->x_connectsocket); sys_closesocket(x->x_connectsocket); } - post("...tcp_server_free"); + if (x->x_verbosity > 1) post("tcp_server_free end"); } void tcpserver_setup(void) @@ -1245,6 +1377,8 @@ void tcpserver_setup(void) class_addmethod(tcpserver_class, (t_method)tcpserver_dump, gensym("dump"), A_FLOAT, 0); class_addmethod(tcpserver_class, (t_method)tcpserver_unblock, gensym("unblock"), 0); class_addmethod(tcpserver_class, (t_method)tcpserver_broadcast, gensym("broadcast"), A_GIMME, 0); + class_addmethod(tcpserver_class, (t_method)tcpserver_port, gensym("port"), A_FLOAT, 0); + class_addmethod(tcpserver_class, (t_method)tcpserver_verbosity, gensym("verbosity"), A_DEFFLOAT, 0); class_addlist(tcpserver_class, (t_method)tcpserver_send); } diff --git a/externals/mrpeach/net/udpreceive~-help.pd b/externals/mrpeach/net/udpreceive~-help.pd index d0eb6ea51..c7ed70ac3 100644 --- a/externals/mrpeach/net/udpreceive~-help.pd +++ b/externals/mrpeach/net/udpreceive~-help.pd @@ -1,72 +1,65 @@ -#N canvas 221 129 832 415 10; -#N canvas 872 257 494 344 META 0; -#X text 12 188 HELP_PATCH_AUTHORS "pd meta" information added by Jonathan +#N canvas 221 129 767 415 10; +#N canvas 874 257 494 344 META 0; +#X text 12 155 HELP_PATCH_AUTHORS "pd meta" information added by Jonathan Wilkes for Pd version 0.42.; #X text 12 25 LICENSE GPL v2 or later; +#X text 12 135 AUTHOR Martin Peach; #X text 12 5 KEYWORDS control network; #X text 12 45 DESCRIPTION receive datagrams over a udp connection and outputs them as a signal; -#X text 12 161 AUTHOR Martin Peach with additional features by Ivica -Ico Bukvic; -#X text 11 76 INLET_0 signal port reset info buffer; -#X text 11 99 OUTLET_N incoming signal over network (variable); -#X text 11 124 OUTLET_R last three outlets are for signal level \, -object status \, and incoming data packet address info; -#X restore 753 382 pd META; -#X obj 580 270 print udpreceive~; -#X symbolatom 235 357 10 0 0 0 - - -; -#X floatatom 269 291 5 0 0 0 - - -; -#X floatatom 304 270 7 0 0 0 - - -; -#X floatatom 338 335 9 0 0 0 - - -; -#X obj 235 316 prepend set; -#X text 205 290 channels:; -#X text 189 356 format:; -#X text 289 334 bitrate:; -#X text 240 269 framesize:; -#X floatatom 373 292 9 0 0 0 - - -; -#X floatatom 407 270 9 0 0 0 - - -; -#X floatatom 442 313 5 0 0 0 - - -; -#X floatatom 476 292 5 0 0 0 - - -; -#X text 316 291 overflow:; -#X text 347 269 underflow:; -#X text 381 312 queuesize:; -#X text 428 291 average:; -#X msg 93 61 info; -#X msg 73 41 reset; -#X text 126 60 status info to rightmost outlet; -#X text 111 40 reset underflow & overflow counters; -#X floatatom 268 172 3 0 0 0 - - -; -#X floatatom 291 172 3 0 0 0 - - -; -#X floatatom 314 172 3 0 0 0 - - -; -#X floatatom 337 172 3 0 0 0 - - -; -#X floatatom 361 172 5 0 0 0 - - -; -#X obj 268 146 unpack 0 0 0 0 0; -#X text 231 171 from:; -#X obj 140 155 dac~ 1 2; -#X floatatom 511 335 9 0 0 0 - - -; -#X text 459 334 packets:; -#X text 406 145 To communicate \, a [udpreceive~] and [udpsend~] pair +#X restore 695 379 pd META; +#X obj 522 267 print udpreceive~; +#X symbolatom 177 354 10 0 0 0 - - -; +#X floatatom 211 288 5 0 0 0 - - -; +#X floatatom 246 267 7 0 0 0 - - -; +#X floatatom 280 332 9 0 0 0 - - -; +#X obj 177 313 prepend set; +#X text 147 287 channels:; +#X text 131 353 format:; +#X text 231 331 bitrate:; +#X text 182 266 framesize:; +#X floatatom 315 289 9 0 0 0 - - -; +#X floatatom 349 267 9 0 0 0 - - -; +#X floatatom 384 310 5 0 0 0 - - -; +#X floatatom 418 289 5 0 0 0 - - -; +#X text 258 288 overflow:; +#X text 289 266 underflow:; +#X text 323 309 queuesize:; +#X text 370 288 average:; +#X msg 35 58 info; +#X msg 15 38 reset; +#X text 68 57 status info to rightmost outlet; +#X text 53 37 reset underflow & overflow counters; +#X floatatom 210 169 3 0 0 0 - - -; +#X floatatom 233 169 3 0 0 0 - - -; +#X floatatom 256 169 3 0 0 0 - - -; +#X floatatom 279 169 3 0 0 0 - - -; +#X floatatom 303 169 5 0 0 0 - - -; +#X obj 210 143 unpack 0 0 0 0 0; +#X text 173 168 from:; +#X obj 82 152 dac~ 1 2; +#X floatatom 453 332 9 0 0 0 - - -; +#X text 401 331 packets:; +#X text 348 142 To communicate \, a [udpreceive~] and [udpsend~] pair must have the same number of channels and the same blocksize. Also [udpsend~] must [connect( to the port on which [udpreceive~] is listening. ; -#X msg 113 81 buffer 2; -#X text 176 81 set number of frames to buffer before playback; -#X obj 235 233 route format channels framesize bitrate overflow underflow +#X msg 56 79 buffer 2; +#X text 118 78 set number of frames to buffer before playback; +#X obj 177 230 route format channels framesize bitrate overflow underflow queuesize average packets tag_errors; -#X floatatom 545 313 9 0 0 0 - - -; -#X text 479 312 tag errors:; -#X obj 202 184 env~; -#X floatatom 202 207 9 0 0 0 - - -; -#X text 262 196 The rightmost signal outlet outputs 1 if the stream +#X floatatom 487 310 9 0 0 0 - - -; +#X text 421 309 tag errors:; +#X obj 144 181 env~; +#X floatatom 144 204 9 0 0 0 - - -; +#X text 204 193 The rightmost signal outlet outputs 1 if the stream is valid \, else 0; -#X text 478 80 Arguments: port \, channels \, blocksize \, multicast_address. +#X text 420 77 Arguments: port \, channels \, blocksize \, multicast_address. Blocksize should match [udpsend~]. multicast_address is optional. Arguments must be in that order.; -#X obj 139 124 udpreceive~ 9999 2 512; -#X text 279 123 receives 2 channels on port 9999 Same blocksize as +#X obj 81 121 udpreceive~ 9999 2 512; +#X text 221 120 receives 2 channels on port 9999 Same blocksize as udpsend~; -#X msg 53 21 port 9000; -#X text 114 20 change port after creation; #X connect 6 0 2 0; #X connect 19 0 43 0; #X connect 20 0 43 0; @@ -93,4 +86,3 @@ udpsend~; #X connect 43 2 39 0; #X connect 43 3 36 0; #X connect 43 4 28 0; -#X connect 45 0 43 0; diff --git a/externals/mrpeach/net/udpreceive~.c b/externals/mrpeach/net/udpreceive~.c index 115858fd1..86a7f082b 100644 --- a/externals/mrpeach/net/udpreceive~.c +++ b/externals/mrpeach/net/udpreceive~.c @@ -389,11 +389,6 @@ static int udpreceive_tilde_createsocket(t_udpreceive_tilde* x, char *address, i return 1; } -static int udpreceive_tilde_setsocket(t_udpreceive_tilde* x, t_float portno) -{ - udpreceive_tilde_createsocket(x, x->x_addr_name, (int)portno); -} - /* Queue is 1 to 16 frames long */ #define QUEUESIZE (int)((x->x_framein + DEFAULT_AUDIO_BUFFER_FRAMES - x->x_frameout) % DEFAULT_AUDIO_BUFFER_FRAMES) /* Block is a set of sample vectors inside a frame, one vector per channel */ @@ -797,10 +792,9 @@ void udpreceive_tilde_setup(void) class_addmethod(udpreceive_tilde_class, nullfn, gensym("signal"), 0); class_addmethod(udpreceive_tilde_class, (t_method)udpreceive_tilde_info, gensym("info"), 0); - class_addmethod(udpreceive_tilde_class, (t_method)udpreceive_tilde_dsp, gensym("dsp"), A_CANT, 0); + class_addmethod(udpreceive_tilde_class, (t_method)udpreceive_tilde_dsp, gensym("dsp"), 0); class_addmethod(udpreceive_tilde_class, (t_method)udpreceive_tilde_reset, gensym("reset"), A_DEFFLOAT, 0); class_addmethod(udpreceive_tilde_class, (t_method)udpreceive_tilde_reset, gensym("buffer"), A_DEFFLOAT, 0); - class_addmethod(udpreceive_tilde_class, (t_method)udpreceive_tilde_setsocket, gensym("port"), A_DEFFLOAT, 0); post("udpreceive~ v%s, (c) 2004 Olaf Matthes, 2010 Martin Peach", VERSION); ps_format = gensym("format"); diff --git a/externals/mrpeach/net/udpsend.c b/externals/mrpeach/net/udpsend.c index 9c84f2b41..cbef2f874 100644 --- a/externals/mrpeach/net/udpsend.c +++ b/externals/mrpeach/net/udpsend.c @@ -29,6 +29,13 @@ #include <ifaddrs.h> // for getifaddrs #endif // __APPLE__ +/* support older Pd versions without sys_open(), sys_fopen(), sys_fclose() */ +#if PD_MAJOR_VERSION == 0 && PD_MINOR_VERSION < 44 +#define sys_open open +#define sys_fopen fopen +#define sys_fclose fclose +#endif + static t_class *udpsend_class; typedef struct _udpsend @@ -482,7 +489,7 @@ static void udpsend_send(t_udpsend *x, t_symbol *s, int argc, t_atom *argv) #ifdef DEBUG post ("udpsend fname: %s", fpath); #endif - fptr = fopen(fpath, "rb"); + fptr = sys_fopen(fpath, "rb"); if (fptr == NULL) { post("udpsend: unable to open \"%s\"", fpath); @@ -504,7 +511,7 @@ static void udpsend_send(t_udpsend *x, t_symbol *s, int argc, t_atom *argv) break; } } - fclose(fptr); + sys_fclose(fptr); fptr = NULL; post("udpsend: read \"%s\" length %d byte%s", fpath, j, ((d==1)?"":"s")); } diff --git a/externals/mrpeach/net/udpsend~-help.pd b/externals/mrpeach/net/udpsend~-help.pd index e38e128f3..8b1db8665 100644 --- a/externals/mrpeach/net/udpsend~-help.pd +++ b/externals/mrpeach/net/udpsend~-help.pd @@ -6,7 +6,7 @@ #X msg -311 147 format 8bit; #X msg -440 18 connect localhost 8008; #X text -244 103 float is the most expensive with the best resolution -(32bit) \, default is 16bit; +(32bit) \, default is float; #X msg -419 39 connect 255.255.255.255 8008; #X obj 52 687 print udpreceive~; #X obj 224 369 print udpsend~; diff --git a/externals/mrpeach/net/udpsend~.c b/externals/mrpeach/net/udpsend~.c index dd521db0a..5846524ab 100644 --- a/externals/mrpeach/net/udpsend~.c +++ b/externals/mrpeach/net/udpsend~.c @@ -914,7 +914,7 @@ void udpsend_tilde_setup(void) udpsend_tilde_class = class_new(gensym("udpsend~"), (t_newmethod)udpsend_tilde_new, (t_method)udpsend_tilde_free, sizeof(t_udpsend_tilde), 0, A_DEFFLOAT, A_DEFFLOAT, A_NULL); class_addmethod(udpsend_tilde_class, nullfn, gensym("signal"), 0); - class_addmethod(udpsend_tilde_class, (t_method)udpsend_tilde_dsp, gensym("dsp"), A_CANT, 0); + class_addmethod(udpsend_tilde_class, (t_method)udpsend_tilde_dsp, gensym("dsp"), 0); class_addfloat(udpsend_tilde_class, udpsend_tilde_float); class_addmethod(udpsend_tilde_class, (t_method)udpsend_tilde_info, gensym("info"), 0); class_addmethod(udpsend_tilde_class, (t_method)udpsend_tilde_connect, gensym("connect"), A_DEFSYM, A_DEFFLOAT, 0); diff --git a/externals/mrpeach/net/udpsndrcv-help.pd b/externals/mrpeach/net/udpsndrcv-help.pd new file mode 100644 index 000000000..d2ae4bdb2 --- /dev/null +++ b/externals/mrpeach/net/udpsndrcv-help.pd @@ -0,0 +1,73 @@ +#N canvas 193 98 901 628 12; +#X declare -lib mrpeach; +#X msg 166 354 status; +#X text 18 334 get status on right outlet:; +#N canvas 510 620 494 344 META 0; +#X text 12 155 HELP_PATCH_AUTHORS "pd meta" information added by Jonathan +Wilkes for Pd version 0.42.; +#X text 12 25 LICENSE GPL v2 or later; +#X text 12 5 KEYWORDS control network; +#X text 12 45 DESCRIPTION receive datagrams over a udp connection and +outputs them as raw bytes; +#X text 12 95 OUTLET_0 anything; +#X text 12 135 AUTHOR Martin Peach \, Dennis Engdahl; +#X text 12 75 INLET_0 status port connect disconnect float(s); +#X text 12 115 OUTLET_1 received total; +#X restore 821 567 pd META; +#X obj 208 416 udpsndrcv; +#X msg 197 385 disconnect; +#X msg 105 260 send /info; +#X text -12 3 [udpsndrcv] sends datagrams over udp and receives datagrams +over a udp connection and outputs them as raw bytes. It uses the same +port for both send and receive.; +#X text 168 134 IP address to send to/listen on (required); +#X text 323 447 Total bytes received.; +#X text 242 544 Data received.; +#X text -3 60 This was cadged together by Dennis Engdahl (engdahl@snowcrest.net) +to allow communication with a Behringer X32. The program below demonstrates +this.; +#X obj 105 293 packOSC; +#X obj 238 481 unpackOSC; +#X text 169 149 Port number to send to (required); +#X text 31 132 Creation Arguments:; +#X obj 490 78 import mrpeach; +#X text 202 176 (Must be unique among instances - see below); +#X msg 25 213 connect 192.168.1.101 10023 10023; +#X text 584 598 Dennis Engdahl \, Martin Peach 20104/02/26; +#X obj 268 447 print a; +#X obj 238 518 print Instance_1; +#X obj 208 455 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 +1; +#X msg 496 354 status; +#X text 348 334 get status on right outlet:; +#X obj 538 416 udpsndrcv; +#X msg 527 385 disconnect; +#X msg 435 260 send /info; +#X text 653 447 Total bytes received.; +#X text 572 544 Data received.; +#X obj 435 293 packOSC; +#X obj 568 481 unpackOSC; +#X obj 538 455 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 +1; +#X msg 355 213 connect 192.168.1.101 10023 10024; +#X obj 598 447 print b; +#X obj 568 518 print Instance_2; +#X text 168 163 Port number to send from and listen on (required); +#X connect 0 0 3 0; +#X connect 3 0 21 0; +#X connect 3 1 12 0; +#X connect 3 2 19 0; +#X connect 4 0 3 0; +#X connect 5 0 11 0; +#X connect 11 0 3 0; +#X connect 12 0 20 0; +#X connect 17 0 3 0; +#X connect 22 0 24 0; +#X connect 24 0 31 0; +#X connect 24 1 30 0; +#X connect 24 2 33 0; +#X connect 25 0 24 0; +#X connect 26 0 29 0; +#X connect 29 0 24 0; +#X connect 30 0 34 0; +#X connect 32 0 24 0; diff --git a/externals/mrpeach/net/udpsndrcv.c b/externals/mrpeach/net/udpsndrcv.c new file mode 100644 index 000000000..dee0f1a53 --- /dev/null +++ b/externals/mrpeach/net/udpsndrcv.c @@ -0,0 +1,398 @@ +/* udpsndrcv.c 20140221. Dennis Engdahl did it based on: 20060424. Martin Peach did it based on x_net.c. x_net.c header follows: */ +/* Copyright (c) 1997-1999 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* network */ + +#include "m_pd.h" +#include "s_stuff.h" + +#include <stdio.h> +#include <string.h> +#ifdef _WIN32 +#include <winsock2.h> +#include <ws2tcpip.h> +#else +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <netinet/tcp.h> +#include <netdb.h> +#include <sys/ioctl.h> // for SIOCGIFCONF +#include <net/if.h> // for SIOCGIFCONF +#include <arpa/inet.h> +#include <errno.h> +#include <unistd.h> +#endif // _WIN32 + +/* support older Pd versions without sys_open(), sys_fopen(), sys_fclose() */ +#if PD_MAJOR_VERSION == 0 && PD_MINOR_VERSION < 44 +#define sys_open open +#define sys_fopen fopen +#define sys_fclose fclose +#endif + +static t_class *udpsndrcv_class; + +#define MAX_UDP_RECEIVE 65536L // longer than data in maximum UDP packet + +typedef struct _udpsndrcv +{ + t_object x_obj; + int x_fd; /* the socket */ + t_outlet *x_msgout; + t_outlet *x_addrout; + long x_total_received; + t_atom x_addrbytes[5]; + t_atom x_msgoutbuf[MAX_UDP_RECEIVE]; + char x_msginbuf[MAX_UDP_RECEIVE]; + char x_addr_name[256]; // a multicast address or 0 +} t_udpsndrcv; + +void udpsndrcv_setup(void); +static void udpsndrcv_free(t_udpsndrcv *x); +static void udpsndrcv_send(t_udpsndrcv *x, t_symbol *s, int argc, t_atom *argv); +static void udpsndrcv_disconnect(t_udpsndrcv *x); +static void udpsndrcv_connect(t_udpsndrcv *x, t_symbol *hostname, t_floatarg fportno, t_floatarg ffromport); +static void udpsndrcv_sock_err(t_udpsndrcv *x, char *err_string); +static void *udpsndrcv_new(void); +static void udpsndrcv_sock_err(t_udpsndrcv *x, char *err_string); +static void udpsndrcv_status(t_udpsndrcv *x); +static void udpsndrcv_read(t_udpsndrcv *x, int sockfd); + +static void *udpsndrcv_new(void) +{ + t_udpsndrcv *x; + int i; + + x = (t_udpsndrcv *)pd_new(udpsndrcv_class); /* if something fails we return 0 instead of x. Is this OK? */ + if (NULL == x) return x; + x->x_addr_name[0] = '\0'; + /* convert the bytes in the buffer to floats in a list */ + for (i = 0; i < MAX_UDP_RECEIVE; ++i) + { + x->x_msgoutbuf[i].a_type = A_FLOAT; + x->x_msgoutbuf[i].a_w.w_float = 0; + } + for (i = 0; i < 5; ++i) + { + x->x_addrbytes[i].a_type = A_FLOAT; + x->x_addrbytes[i].a_w.w_float = 0; + } + + outlet_new(&x->x_obj, &s_float); + x->x_msgout = outlet_new(&x->x_obj, &s_anything); + x->x_addrout = outlet_new(&x->x_obj, &s_anything); + + x->x_fd = -1; + return (x); +} + +static void udpsndrcv_read(t_udpsndrcv *x, int sockfd) +{ + int i, read = 0; + struct sockaddr_in from; + socklen_t fromlen = sizeof(from); + t_atom output_atom; + long addr; + unsigned short port; + + read = recvfrom(sockfd, x->x_msginbuf, MAX_UDP_RECEIVE, 0, (struct sockaddr *)&from, &fromlen); +#ifdef DEBUG + post("udpsndrcv_read: read %lu x->x_fd = %d", + read, x->x_fd); +#endif + /* get the sender's ip */ + addr = ntohl(from.sin_addr.s_addr); + port = ntohs(from.sin_port); + + x->x_addrbytes[0].a_w.w_float = (addr & 0xFF000000)>>24; + x->x_addrbytes[1].a_w.w_float = (addr & 0x0FF0000)>>16; + x->x_addrbytes[2].a_w.w_float = (addr & 0x0FF00)>>8; + x->x_addrbytes[3].a_w.w_float = (addr & 0x0FF); + x->x_addrbytes[4].a_w.w_float = port; + outlet_anything(x->x_addrout, gensym("from"), 5L, x->x_addrbytes); + + if (read < 0) + { + udpsndrcv_sock_err(x, "udpsndrcv_read"); + sys_closesocket(x->x_fd); + return; + } + if (read > 0) + { + for (i = 0; i < read; ++i) + { + /* convert the bytes in the buffer to floats in a list */ + x->x_msgoutbuf[i].a_w.w_float = (float)(unsigned char)x->x_msginbuf[i]; + } + x->x_total_received += read; + SETFLOAT(&output_atom, read); + outlet_anything(x->x_addrout, gensym("received"), 1, &output_atom); + /* send the list out the outlet */ + if (read > 1) outlet_list(x->x_msgout, &s_list, read, x->x_msgoutbuf); + else outlet_float(x->x_msgout, x->x_msgoutbuf[0].a_w.w_float); + } +} + +static void udpsndrcv_connect(t_udpsndrcv *x, t_symbol *hostname, t_floatarg fportno, t_floatarg ffromport) +{ + struct sockaddr_in server; + struct hostent *hp; + int sockfd; + int portno = fportno; + int fromport = ffromport; + + if (x->x_fd >= 0) + { + pd_error(x, "udpsndrcv: already connected"); + return; + } + + /* create a socket */ + sockfd = socket(AF_INET, SOCK_DGRAM, 0); +#ifdef DEBUG + post("udpsndrcv_connect: socket %d port %d fromport %d", sockfd, portno, fromport); +#endif + if (sockfd < 0) + { + udpsndrcv_sock_err(x, "udpsndrcv socket"); + return; + } + + /* assign client port number */ + if (fromport == 0) fromport = portno; + server.sin_family = AF_INET; + server.sin_port = htons((u_short)fromport); + + /* bind the socket to INADDR_ANY and port as specified */ + server.sin_addr.s_addr = INADDR_ANY; + if (bind(sockfd, (struct sockaddr *) &server, sizeof (server)) < 0) + { + udpsndrcv_sock_err(x, "udpsndrcv: bind"); + sys_closesocket(sockfd); + return; + } + + /* connect socket using hostname provided in command line */ + hp = gethostbyname(hostname->s_name); + if (hp == 0) + { + post("udpsndrcv: bad host?\n"); + return; + } + memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length); + server.sin_port = htons((u_short)portno); + + post("udpsndrcv: connecting to port %d from %d", portno, fromport); + /* try to connect. */ + if (connect(sockfd, (struct sockaddr *) &server, sizeof (server)) < 0) + { + udpsndrcv_sock_err(x, "udpsndrcv connect"); +#ifdef _WIN32 + closesocket(sockfd); +#else + close(sockfd); +#endif + return; + } + x->x_fd = sockfd; + x->x_total_received = 0L; + sys_addpollfn(x->x_fd, (t_fdpollfn)udpsndrcv_read, x); + outlet_float(x->x_obj.ob_outlet, 1); + return; +} + +static void udpsndrcv_sock_err(t_udpsndrcv *x, char *err_string) +{ +/* prints the last error from errno or WSAGetLastError() */ +#ifdef _WIN32 + void *lpMsgBuf; + unsigned long errornumber = WSAGetLastError(); + int len = 0, i; + char *cp; + + if ((len = FormatMessageA((FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS), + NULL, errornumber, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&lpMsgBuf, 0, NULL))) + { + cp = (char *)lpMsgBuf; + for(i = 0; i < len; ++i) + { + if (cp[i] < 0x20) + { /* end string at first weird character */ + cp[i] = 0; + break; + } + } + pd_error(x, "%s: %s (%ld)", err_string, (char *)lpMsgBuf, errornumber); + LocalFree(lpMsgBuf); + } +#else + pd_error(x, "%s: %s (%d)", err_string, strerror(errno), errno); +#endif +} + +static void udpsndrcv_status(t_udpsndrcv *x) +{ + t_atom output_atom; + + SETFLOAT(&output_atom, x->x_total_received); + outlet_anything(x->x_addrout, gensym("total"), 1, &output_atom); +} + +static void udpsndrcv_disconnect(t_udpsndrcv *x) +{ + if (x->x_fd >= 0) + { + post("udpsndrcv: disconnecting."); +#ifdef _WIN32 + closesocket(x->x_fd); +#else + close(x->x_fd); +#endif + sys_rmpollfn(x->x_fd); + x->x_fd = -1; + outlet_float(x->x_obj.ob_outlet, 0); + } +} + +static void udpsndrcv_send(t_udpsndrcv *x, t_symbol *s, int argc, t_atom *argv) +{ +#define BYTE_BUF_LEN 65536 // arbitrary maximum similar to max IP packet size + static char byte_buf[BYTE_BUF_LEN]; + int d; + int i, j; + unsigned char c; + float f, e; + char *bp; + int length, sent; + int result; + static double lastwarntime; + static double pleasewarn; + double timebefore; + double timeafter; + int late; + char fpath[FILENAME_MAX]; + FILE *fptr; + +#ifdef DEBUG + post("s: %s", s->s_name); + post("argc: %d", argc); +#endif + for (i = j = 0; i < argc; ++i) + { + if (argv[i].a_type == A_FLOAT) + { + f = argv[i].a_w.w_float; + d = (int)f; + e = f - d; + if (e != 0) + { + pd_error(x, "udpsndrcv_send: item %d (%f) is not an integer", i, f); + return; + } + c = (unsigned char)d; + if (c != d) + { + pd_error(x, "udpsndrcv_send: item %d (%f) is not between 0 and 255", i, f); + return; + } +#ifdef DEBUG + post("udpsndrcv_send: argv[%d]: %d", i, c); +#endif + byte_buf[j++] = c; + } + else if (argv[i].a_type == A_SYMBOL) + { + + atom_string(&argv[i], fpath, FILENAME_MAX); +#ifdef DEBUG + post ("udpsndrcv fname: %s", fpath); +#endif + fptr = sys_fopen(fpath, "rb"); + if (fptr == NULL) + { + post("udpsndrcv: unable to open \"%s\"", fpath); + return; + } + rewind(fptr); + while ((d = fgetc(fptr)) != EOF) + { +#ifdef DEBUG + post("udpsndrcv: d is %d", d); +#endif + byte_buf[j++] = (char)(d & 0x0FF); +#ifdef DEBUG + post("udpsndrcv: byte_buf[%d] = %d", j-1, byte_buf[j-1]); +#endif + if (j >= BYTE_BUF_LEN) + { + post ("udpsndrcv: file too long, truncating at %lu", BYTE_BUF_LEN); + break; + } + } + fclose(fptr); + fptr = NULL; + post("udpsndrcv: read \"%s\" length %d byte%s", fpath, j, ((d==1)?"":"s")); + } + else + { + pd_error(x, "udpsndrcv_send: item %d is not a float or a file name", i); + return; + } + } + + length = j; + if ((x->x_fd >= 0) && (length > 0)) + { + for (bp = byte_buf, sent = 0; sent < length;) + { + timebefore = sys_getrealtime(); + result = send(x->x_fd, byte_buf, length-sent, 0); + timeafter = sys_getrealtime(); + late = (timeafter - timebefore > 0.005); + if (late || pleasewarn) + { + if (timeafter > lastwarntime + 2) + { + post("udpsndrcv blocked %d msec", + (int)(1000 * ((timeafter - timebefore) + pleasewarn))); + pleasewarn = 0; + lastwarntime = timeafter; + } + else if (late) pleasewarn += timeafter - timebefore; + } + if (result <= 0) + { + udpsndrcv_sock_err(x, "udpsndrcv send"); + udpsndrcv_disconnect(x); + break; + } + else + { + sent += result; + bp += result; + } + } + } + else pd_error(x, "udpsndrcv: not connected"); +} + +static void udpsndrcv_free(t_udpsndrcv *x) +{ + udpsndrcv_disconnect(x); +} + +void udpsndrcv_setup(void) +{ + udpsndrcv_class = class_new(gensym("udpsndrcv"), (t_newmethod)udpsndrcv_new, (t_method)udpsndrcv_free, sizeof(t_udpsndrcv), 0, 0); + class_addmethod(udpsndrcv_class, (t_method)udpsndrcv_connect, gensym("connect"), A_SYMBOL, A_FLOAT, A_FLOAT, 0); + class_addmethod(udpsndrcv_class, (t_method)udpsndrcv_disconnect, gensym("disconnect"), 0); + class_addmethod(udpsndrcv_class, (t_method)udpsndrcv_send, gensym("send"), A_GIMME, 0); + class_addmethod(udpsndrcv_class, (t_method)udpsndrcv_status, + gensym("status"), 0); + class_addlist(udpsndrcv_class, (t_method)udpsndrcv_send); +} + +/* end udpsndrcv.c*/ diff --git a/externals/mrpeach/op~/op~.c b/externals/mrpeach/op~/op~.c index ec3062524..8a15bc3a3 100644 --- a/externals/mrpeach/op~/op~.c +++ b/externals/mrpeach/op~/op~.c @@ -228,7 +228,7 @@ void op_tilde_setup(void) { op_tilde_class = class_new(gensym("op~"), (t_newmethod)op_tilde_new, 0, sizeof(t_op_tilde), 0, A_GIMME, 0); - class_addmethod(op_tilde_class, (t_method)op_tilde_dsp, gensym("dsp"), A_CANT, 0); + class_addmethod(op_tilde_class, (t_method)op_tilde_dsp, gensym("dsp"), 0); class_addmethod(op_tilde_class, (t_method)op_tilde_help, gensym("help"), 0); class_addmethod(op_tilde_class, (t_method)op_tilde_op, gensym("op"), A_DEFSYMBOL, 0); CLASS_MAINSIGNALIN(op_tilde_class, t_op_tilde, x_f); diff --git a/externals/mrpeach/osc/osc-meta.pd b/externals/mrpeach/osc/osc-meta.pd index d676e3b98..290efa39b 100644 --- a/externals/mrpeach/osc/osc-meta.pd +++ b/externals/mrpeach/osc/osc-meta.pd @@ -1,7 +1,7 @@ #N canvas 18 212 200 200 10; #N canvas 28 50 420 300 META 1; #X text 13 61 NAME OSC; -#X text 13 85 VERSION 0.1; +#X text 13 85 VERSION 0.2; #X text 13 129 AUTHOR Martin Peach; #X text 19 189 NOTE:; #X restore 10 10 pd META; diff --git a/externals/mrpeach/osc/packOSC-help.pd b/externals/mrpeach/osc/packOSC-help.pd index c47837301..4ffb19925 100644 --- a/externals/mrpeach/osc/packOSC-help.pd +++ b/externals/mrpeach/osc/packOSC-help.pd @@ -1,4 +1,4 @@ -#N canvas 1 53 1141 651 12; +#N canvas 201 81 1158 705 12; #X obj 301 434 cnv 15 100 40 empty empty empty 20 12 0 14 -4034 -66577 0; #X obj 330 548 udpsend; @@ -6,7 +6,7 @@ #X msg 301 499 connect 127.0.0.1 9997; #X obj 330 447 packOSC; #X obj 330 583 tgl 15 0 empty empty 1=connected 20 8 0 8 -4034 -257985 --1 0 1; +-1 1 1; #X msg -130 -33 send /test/one/two/three zz 88 T; #X msg -84 13 send /test 1 2 3; #X msg -107 -10 send /west 35; @@ -20,57 +20,56 @@ of floats instead of directly connecting to the network; #X msg 318 415 typetags \$1; #X obj 318 397 tgl 15 0 empty empty empty 17 7 0 10 -257985 -258113 -1 0 1; -#X text 401 414 typetags are on by default; -#X text 529 107 Useable types are:; -#X text 529 125 i: 32 bit integer; -#X text 529 143 f: 32-bit float; -#X text 529 161 s: string; -#X text 310 107 send a type-forced message; +#X text 414 414 typetags are on by default; +#X text 578 107 Useable types are:; +#X text 578 125 i: 32 bit integer; +#X text 578 143 f: 32-bit float; +#X text 578 161 s: string; +#X text 359 107 send a type-forced message; #X msg 10 107 sendtyped /test/one/two/three sis zz 88 T; #X msg 33 130 sendtyped /left/right TTiTIFNfisf 1.1 2.1 3.1 4.1 5.1 ; -#X text 529 179 T: true (no argument); -#X text 529 197 F: false (no argument); -#X text 529 215 I: infinitum (no argument); -#X text 529 232 N: Nil (no argument); +#X text 578 179 T: true (no argument); +#X text 578 197 F: false (no argument); +#X text 578 215 I: infinitum (no argument); +#X text 578 232 N: Nil (no argument); #X msg 277 374 bufsize 100; -#X text 364 374 set buffer size (default is 64000 bytes); +#X text 376 374 set buffer size (default is 64000 bytes); #X msg 79 176 prefix /test; -#X text 174 175 set the OSC path prefix for subsequent messages; +#X text 186 175 set the OSC path prefix for subsequent messages; #X msg -61 36 /left one two; #X msg 56 153 /right 88; -#X text 129 153 'send' prefix is not required; +#X text 139 153 'send' prefix is not required; #X msg 55 209 [; #X msg 9 210 ]; -#X text -81 211 close bundle; +#X text -97 211 close bundle; #X msg 157 254 timetagoffset 0; #X msg 180 277 timetagoffset -1; -#X text 270 254 send current time as timetag; +#X text 319 254 send current time as timetag; #X text 135 229 (timetags are sent in bundle messages only); #X obj 9 186 t b a b; #X msg -90 166 /test 5 6 7; -#X text 301 277 immediate time tag (default); -#X floatatom 376 476 5 0 0 0 - - -; +#X text 323 277 immediate time tag (default); +#X floatatom 376 476 5 0 0 0 - - -, f 5; #X text 426 476 bundle depth; -#X obj 469 499 cnv 15 380 30 empty empty empty 20 12 0 14 -24198 -66577 +#X obj 495 499 cnv 15 380 30 empty empty empty 20 12 0 14 -24198 -66577 0; -#X text 597 540 and http://opensoundcontrol.org/cnmat; +#X text 589 540 and http://opensoundcontrol.org/cnmat; #X msg 203 300 timetagoffset 1e+06; -#X text 473 506 <- First open routeOSC-help \, then connect; -#X text 85 210 open a bundle (and generate time tag); +#X text 499 506 <- First open routeOSC-help \, then connect; +#X text 88 210 open a bundle (and generate time tag); #X obj 418 568 packOSCstream; #X text 383 567 see:; -#X text 518 568 for a way to send OSC over TCP or serial connections. +#X text 534 568 for a way to send OSC over TCP or serial connections. ; -#X text 353 299 current time plus 1 second (delay is in microseconds) +#X text 366 299 current time plus 1 second (delay is in microseconds) ; -#X text -75 570 2009_06_08 Martin Peach; -#X text 529 248 b: blob (a list of bytes \, or floats on [0..255]) +#X text 578 248 b: blob (a list of bytes \, or floats on [0..255]) ; -#X text 659 341 send a blob; +#X text 722 341 send a blob; #X msg 253 334 sendtyped /left b 0 1 2 3 124 125 126 127 128 129 255 254 253 252 -14 -15 -16 17 18 19 20 21 22 23 24 25 26 27 28; -#N canvas 497 62 494 344 META 0; +#N canvas 496 61 548 344 META 0; #X text 12 185 HELP_PATCH_AUTHORS "pd meta" information added by Jonathan Wilkes for Pd version 0.42.; #X text 12 25 LICENSE GPL v2 or later; @@ -83,10 +82,20 @@ bufsize typetags; #X text 12 125 OUTLET_0 anything; #X text 12 145 OUTLET_1 float; #X restore 832 595 pd META; +#X msg 150 65 sendtyped /a/midi/message mm 0 144 60 64 0 144 62 32 +; +#X obj 175 530 print >>; +#X text 578 263 m: MIDI (4 bytes per MIDI message:; +#X text 601 278 Port \, Status \, Param1 \, Param2; +#X text -75 570 2009-2016 Martin Peach; +#X obj 175 506 spigot; +#X obj 220 473 tgl 15 0 empty empty raw 17 7 0 12 -257985 -258113 -1 +0 1; #X connect 1 0 5 0; #X connect 2 0 1 0; #X connect 3 0 1 0; #X connect 4 0 1 0; +#X connect 4 0 66 0; #X connect 4 1 46 0; #X connect 6 0 4 0; #X connect 7 0 4 0; @@ -110,4 +119,7 @@ bufsize typetags; #X connect 43 2 36 0; #X connect 44 0 43 0; #X connect 50 0 4 0; -#X connect 60 0 4 0; +#X connect 59 0 4 0; +#X connect 61 0 4 0; +#X connect 66 0 62 0; +#X connect 67 0 66 1; diff --git a/externals/mrpeach/osc/packOSC.c b/externals/mrpeach/osc/packOSC.c index 8af87700c..4a70f0dca 100644 --- a/externals/mrpeach/osc/packOSC.c +++ b/externals/mrpeach/osc/packOSC.c @@ -3,6 +3,7 @@ /* Started by Martin Peach 20060403 */ /* 20060425 version independent of libOSC */ /* 20070620 added packOSC_path and packOSC_anything methods by zmoelnig */ +/* 20160713 added 'm' typetag for MIDI messages */ /* packOSC.c makes extensive use of code from OSC-client.c and sendOSC.c */ /* as well as some from OSC-timetag.c. These files have the following header: */ /* @@ -31,6 +32,8 @@ MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. The OSC webpage is http://cnmat.cnmat.berkeley.edu/OpenSoundControl */ +//define DEBUG + #define SC_BUFFER_SIZE 64000 #include "packingOSC.h" @@ -84,11 +87,8 @@ The OSC webpage is http://cnmat.cnmat.berkeley.edu/OpenSoundControl static OSCTimeTag OSCTT_Immediately(void); static OSCTimeTag OSCTT_Infinite(void); -static OSCTimeTag OSCTT_CurrentTimePlusOffset(uint4 offset); +static OSCTimeTag OSCTT_CurrentTimePlusOffset(uint32_t offset); -/* The int4byte type has to be a 4-byte integer. You may have to - change this to long or something else on your system. */ -typedef int int4byte; /* Don't ever manipulate the data in the OSCbuf struct directly. (It's declared here in the header file only so your program will be able to @@ -101,9 +101,9 @@ typedef struct OSCbuf_struct size_t size; /* Size of the buffer */ char *bufptr; /* Current position as we fill the buffer */ int state; /* State of partially-constructed message */ - int4byte *thisMsgSize; /* Pointer to count field before */ + uint32_t *thisMsgSize; /* Pointer to count field before */ /* currently-being-written message */ - int4byte *prevCounts[MAX_BUNDLE_NESTING]; /* Pointers to count */ + uint32_t *prevCounts[MAX_BUNDLE_NESTING]; /* Pointers to count */ /* field before each currently open bundle */ int bundleDepth; /* How many sub-sub-bundles are we in now? */ char *typeStringPtr; /* This pointer advances through the type */ @@ -200,7 +200,7 @@ static int OSC_closeBundle(OSCbuf *buf); static int OSC_writeAddress(OSCbuf *buf, char *name); static int OSC_writeAddressAndTypes(OSCbuf *buf, char *name, char *types); static int OSC_writeFloatArg(OSCbuf *buf, float arg); -static int OSC_writeIntArg(OSCbuf *buf, int4byte arg); +static int OSC_writeIntArg(OSCbuf *buf, uint32_t arg); static int OSC_writeBlobArg(OSCbuf *buf, typedArg *arg, size_t nArgs); static int OSC_writeStringArg(OSCbuf *buf, char *arg); static int OSC_writeNullArg(OSCbuf *buf, char type); @@ -215,8 +215,8 @@ static t_class *packOSC_class; typedef struct _packOSC { t_object x_obj; - t_int x_typetags; /* typetag flag */ - t_int x_timeTagOffset; + int x_typetags; /* typetag flag */ + int x_timeTagOffset; int x_bundle; /* bundle open flag */ OSCbuf x_oscbuf[1]; /* OSCbuffer */ t_outlet *x_bdpthout; /* bundle-depth floatoutlet */ @@ -225,6 +225,7 @@ typedef struct _packOSC char *x_bufferForOSCbuf; /*[SC_BUFFER_SIZE];*/ t_atom *x_bufferForOSClist; /*[SC_BUFFER_SIZE];*/ char *x_prefix; + int x_reentry_count; } t_packOSC; static void *packOSC_new(void); @@ -241,6 +242,7 @@ static void packOSC_anything(t_packOSC *x, t_symbol *s, int argc, t_atom *argv); static void packOSC_free(t_packOSC *x); void packOSC_setup(void); static typedArg packOSC_parseatom(t_atom *a); +static typedArg packOSC_packMIDI(t_atom *a); static typedArg packOSC_forceatom(t_atom *a, char ctype); static typedArg packOSC_blob(t_atom *a); static int packOSC_writetypedmessage(t_packOSC *x, OSCbuf *buf, char *messageName, int numArgs, typedArg *args, char *typeStr); @@ -255,16 +257,27 @@ static void *packOSC_new(void) x->x_buflength = SC_BUFFER_SIZE; x->x_bufferForOSCbuf = (char *)getbytes(sizeof(char)*x->x_buflength); if(x->x_bufferForOSCbuf == NULL) - error("packOSC: unable to allocate %lu bytes for x_bufferForOSCbuf", (long)(sizeof(char)*x->x_buflength)); + { + pd_error(x, "packOSC: unable to allocate %lu bytes for x_bufferForOSCbuf", (long)(sizeof(char)*x->x_buflength)); + goto fail; + } x->x_bufferForOSClist = (t_atom *)getbytes(sizeof(t_atom)*x->x_buflength); if(x->x_bufferForOSClist == NULL) - error("packOSC: unable to allocate %lu bytes for x_bufferForOSClist", (long)(sizeof(t_atom)*x->x_buflength)); + { + pd_error(x, "packOSC: unable to allocate %lu bytes for x_bufferForOSClist", (long)(sizeof(t_atom)*x->x_buflength)); + goto fail; + } if (x->x_oscbuf != NULL) OSC_initBuffer(x->x_oscbuf, x->x_buflength, x->x_bufferForOSCbuf); x->x_listout = outlet_new(&x->x_obj, &s_list); x->x_bdpthout = outlet_new(&x->x_obj, &s_float); x->x_timeTagOffset = -1; /* immediately */ + x->x_reentry_count = 0; return (x); +fail: + if(x->x_bufferForOSCbuf != NULL) freebytes(x->x_bufferForOSCbuf, (long)(sizeof(char)*x->x_buflength)); + if(x->x_bufferForOSClist != NULL) freebytes(x->x_bufferForOSClist, (long)(sizeof(char)*x->x_buflength)); + return NULL; } static void packOSC_path(t_packOSC *x, t_symbol*s) @@ -286,33 +299,34 @@ static void packOSC_path(t_packOSC *x, t_symbol*s) static void packOSC_openbundle(t_packOSC *x) { int result; + t_float bundledepth=(t_float)x->x_oscbuf->bundleDepth; if (x->x_timeTagOffset == -1) result = OSC_openBundle(x->x_oscbuf, OSCTT_Immediately()); else - result = OSC_openBundle(x->x_oscbuf, OSCTT_CurrentTimePlusOffset((uint4)x->x_timeTagOffset)); + result = OSC_openBundle(x->x_oscbuf, OSCTT_CurrentTimePlusOffset((uint32_t)x->x_timeTagOffset)); if (result != 0) { /* reset the buffer */ OSC_initBuffer(x->x_oscbuf, x->x_buflength, x->x_bufferForOSCbuf); x->x_bundle = 0; } else x->x_bundle = 1; - outlet_float(x->x_bdpthout, (float)x->x_oscbuf->bundleDepth); + outlet_float(x->x_bdpthout, bundledepth); } static void packOSC_closebundle(t_packOSC *x) { + t_float bundledepth=(t_float)x->x_oscbuf->bundleDepth; if (OSC_closeBundle(x->x_oscbuf)) { - error("packOSC: Problem closing bundle."); + pd_error(x, "packOSC: Problem closing bundle."); return; } - outlet_float(x->x_bdpthout, (float)x->x_oscbuf->bundleDepth); + outlet_float(x->x_bdpthout, bundledepth); /* in bundle mode we send when bundle is closed */ if(!OSC_isBufferEmpty(x->x_oscbuf) > 0 && OSC_isBufferDone(x->x_oscbuf)) { + x->x_bundle = 0; /* call this before _sendbuffer() to be ready for recursive calls */ packOSC_sendbuffer(x); - OSC_initBuffer(x->x_oscbuf, x->x_buflength, x->x_bufferForOSCbuf); - x->x_bundle = 0; return; } } @@ -331,10 +345,10 @@ static void packOSC_setbufsize(t_packOSC *x, t_floatarg f) x->x_buflength = (long)f; x->x_bufferForOSCbuf = (char *)getbytes(sizeof(char)*x->x_buflength); if(x->x_bufferForOSCbuf == NULL) - error("packOSC unable to allocate %lu bytes for x_bufferForOSCbuf", (long)(sizeof(char)*x->x_buflength)); + pd_error(x, "packOSC unable to allocate %lu bytes for x_bufferForOSCbuf", (long)(sizeof(char)*x->x_buflength)); x->x_bufferForOSClist = (t_atom *)getbytes(sizeof(t_atom)*x->x_buflength); if(x->x_bufferForOSClist == NULL) - error("packOSC unable to allocate %lu bytes for x_bufferForOSClist", (long)(sizeof(t_atom)*x->x_buflength)); + pd_error(x, "packOSC unable to allocate %lu bytes for x_bufferForOSClist", (long)(sizeof(t_atom)*x->x_buflength)); OSC_initBuffer(x->x_oscbuf, x->x_buflength, x->x_bufferForOSCbuf); post("packOSC: bufsize is now %d",x->x_buflength); } @@ -342,7 +356,7 @@ static void packOSC_setbufsize(t_packOSC *x, t_floatarg f) static void packOSC_setTimeTagOffset(t_packOSC *x, t_floatarg f) { - x->x_timeTagOffset = (t_int)f; + x->x_timeTagOffset = (int)f; } /* this is the real and only sending routine now, for both typed and */ /* undtyped mode. */ @@ -355,12 +369,16 @@ static void packOSC_sendtyped(t_packOSC *x, t_symbol *s, int argc, t_atom *argv) char* typeStr = NULL; /* might not be used */ typedArg* args = (typedArg*)getbytes(argsSize); unsigned int i, nTagsWithData, nArgs, blobCount; - unsigned int m, j, k; + unsigned int m, tagIndex, typedArgIndex, argvIndex; char c; +#ifdef DEBUG + printf("*** packOSC_sendtyped bundle %d reentry %d\n", x->x_bundle, x->x_reentry_count); +#endif + x->x_reentry_count++; if (args == NULL) { - error("packOSC: unable to allocate %lu bytes for args", (long)argsSize); + pd_error(x, "packOSC: unable to allocate %lu bytes for args", (long)argsSize); return; } messageName[0] = '\0'; /* empty */ @@ -384,24 +402,25 @@ static void packOSC_sendtyped(t_packOSC *x, t_symbol *s, int argc, t_atom *argv) typeStr = (char*)getzbytes(typeStrTotalSize); if (typeStr == NULL) { - error("packOSC: unable to allocate %u bytes for typeStr", nTypeTags); + pd_error(x, "packOSC: unable to allocate %u bytes for typeStr", nTypeTags); return; } typeStr[0] = ','; atom_string(&argv[1], &typeStr[1], typeStrTotalSize); #ifdef DEBUG - post("typeStr: %s, nTypeTags %lu", typeStr, nTypeTags); + printf("packOSC_sendtyped typeStr: %s, nTypeTags %u\n", typeStr, nTypeTags); #endif nArgs = argc-2; for (m = nTagsWithData = blobCount = 0; m < nTypeTags; ++m) { #ifdef DEBUG - post("typeStr[%d] %c", m+1, typeStr[m+1]); + printf("packOSC_sendtyped typeStr[%d] %c\n", m+1, typeStr[m+1]); #endif if ((c = typeStr[m+1]) == 0) break; if (!(c == 'T' || c == 'F' || c == 'N' || c == 'I')) { ++nTagsWithData; /* anything other than these tags have at least one data byte */ + if (c == 'm') nTagsWithData += 3; // MIDI tag should have four data bytes /* OSC-blob An int32 size count, followed by that many 8-bit bytes of arbitrary binary data, @@ -412,39 +431,49 @@ static void packOSC_sendtyped(t_packOSC *x, t_symbol *s, int argc, t_atom *argv) } if (((blobCount == 0)&&(nTagsWithData != nArgs)) || ((blobCount != 0)&&(nTagsWithData > nArgs))) { - error("packOSC: Tags count %d doesn't match argument count %d", nTagsWithData, nArgs); + pd_error(x, "packOSC: Tags count %d doesn't match argument count %d", nTagsWithData, nArgs); goto cleanup; } if (blobCount > 1) { - error("packOSC: Only one blob per packet at the moment..."); + pd_error(x, "packOSC: Only one blob per packet at the moment..."); goto cleanup; } - for (j = k = 0; j < m; ++j) /* m is the number of tags */ + for (tagIndex = typedArgIndex = 0, argvIndex = 2; tagIndex < m; ++tagIndex) /* m is the number of tags */ { - c = typeStr[j+1]; + c = typeStr[tagIndex+1]; if (c == 'b') { /* A blob has to be the last item, until we get more elaborate. */ - if (j != m-1) + if (tagIndex != m-1) { - error("packOSC: Since I don't know how big the blob is, Blob must be the last item in the list"); + pd_error(x, "packOSC: Since I don't know how big the blob is, Blob must be the last item in the list"); goto cleanup; } /* Pack all the remaining arguments as a blob */ - for (; k < nArgs; ++k) + for (; typedArgIndex < nArgs; ++typedArgIndex, ++argvIndex) { - args[k] = packOSC_blob(&argv[k+2]); +#ifdef DEBUG + printf("packOSC_blob %d:\n", nArgs); +#endif + args[typedArgIndex] = packOSC_blob(&argv[argvIndex]); + /* Make sure it was blobbable */ + if (args[typedArgIndex].type != BLOB_osc) goto cleanup; } } else if (!(c == 'T' || c == 'F' || c == 'N' || c == 'I')) /* not no data */ { - args[k] = packOSC_forceatom(&argv[k+2], c); - ++k; + if (c == 'm') + { // pack the next four arguments into one int + args[typedArgIndex++] = packOSC_packMIDI(&argv[argvIndex]); + argvIndex += 4; + } + else args[typedArgIndex++] = packOSC_forceatom(&argv[argvIndex++], c); } } - if(packOSC_writetypedmessage(x, x->x_oscbuf, messageName, nArgs, args, typeStr)) + //if(packOSC_writetypedmessage(x, x->x_oscbuf, messageName, nArgs, args, typeStr)) + if(packOSC_writetypedmessage(x, x->x_oscbuf, messageName, typedArgIndex, args, typeStr)) { - error("packOSC: usage error, write-msg failed."); + pd_error(x, "packOSC: usage error, packOSC_writetypedmessage failed."); goto cleanup; } } @@ -457,24 +486,28 @@ static void packOSC_sendtyped(t_packOSC *x, t_symbol *s, int argc, t_atom *argv) switch (args[i].type) { case INT_osc: - post("packOSC: cell-cont: %d\n", args[i].datum.i); + printf("packOSC: cell-cont: %d\n", args[i].datum.i); break; case FLOAT_osc: - post("packOSC: cell-cont: %f\n", args[i].datum.f); + printf("packOSC: cell-cont: %f\n", args[i].datum.f); break; case STRING_osc: - post("packOSC: cell-cont: %s\n", args[i].datum.s); + printf("packOSC: cell-cont: %s\n", args[i].datum.s); + break; + case BLOB_osc: + printf("packOSC: blob\n"); break; case NOTYPE_osc: - post("packOSC: unknown type\n"); + printf("packOSC: unknown type\n"); break; + } - post("packOSC: type-id: %d\n", args[i].type); + printf("packOSC: type-id: %d\n", args[i].type); #endif } if(packOSC_writemessage(x, x->x_oscbuf, messageName, i, args)) { - error("packOSC: usage error, write-msg failed."); + pd_error(x, "packOSC: usage error, packOSC_writemessage failed."); goto cleanup; } } @@ -482,12 +515,12 @@ static void packOSC_sendtyped(t_packOSC *x, t_symbol *s, int argc, t_atom *argv) if(!x->x_bundle) { packOSC_sendbuffer(x); - OSC_initBuffer(x->x_oscbuf, x->x_buflength, x->x_bufferForOSCbuf); } cleanup: if (typeStr != NULL) freebytes(typeStr, typeStrTotalSize); if (args != NULL) freebytes(args, argsSize); + x->x_reentry_count--; } static void packOSC_send_type_forced(t_packOSC *x, t_symbol *s, int argc, t_atom *argv) @@ -501,7 +534,7 @@ static void packOSC_send(t_packOSC *x, t_symbol *s, int argc, t_atom *argv) { if(!argc) { - post("packOSC: not sending empty message."); + pd_error(x, "packOSC: not sending empty message."); return; } packOSC_sendtyped(x, s, argc, argv); @@ -564,13 +597,13 @@ static typedArg packOSC_parseatom(t_atom *a) { typedArg returnVal; t_float f; - t_int i; + int i; t_symbol s; char buf[MAXPDSTRING]; atom_string(a, buf, MAXPDSTRING); #ifdef DEBUG - post("packOSC: atom type %d (%s)", a->a_type, buf); + printf("packOSC: atom type %d (%s)\n", a->a_type, buf); #endif /* It might be an int, a float, or a string */ switch (a->a_type) @@ -607,15 +640,10 @@ static typedArg packOSC_blob(t_atom *a) { /* ctype is one of i,f,s,T,F,N,I*/ typedArg returnVal; t_float f; - t_int i; - t_symbol s; - static char buf[MAXPDSTRING]; + int i; returnVal.type = NOTYPE_osc; returnVal.datum.s = NULL; -#ifdef DEBUG - post("packOSC_blob %d:", nArgs); -#endif /* the atoms must all be bytesl */ if(a->a_type != A_FLOAT) { @@ -639,17 +667,61 @@ static typedArg packOSC_blob(t_atom *a) return returnVal; } +static typedArg packOSC_packMIDI(t_atom *a) +{ /* pack four bytes at a into one int32 */ + int i; + typedArg returnVal; + int m[4]; + static char buf[MAXPDSTRING]; + + for (i = 0; i < 4; ++i, ++a) + { +#ifdef DEBUG + atom_string(a, buf, MAXPDSTRING); + printf("packOSC: atom type %d (%s)\n", a->a_type, buf); +#endif + if ((a->a_type != A_FLOAT)) + { + error("packOSC: MIDI parameters must be floats"); + returnVal.type = NOTYPE_osc; + returnVal.datum.s = NULL; + return returnVal; + } + m[i] = atom_getint(a); +#ifdef DEBUG + printf("packOSC_packMIDI: float to integer %d\n", m[i]); +#endif + if ((i < 2) && (m[i] != (m[i] & 0x0FF))) + { + error("packOSC: MIDI parameters must be less than 256"); + returnVal.type = NOTYPE_osc; + returnVal.datum.s = NULL; + return returnVal; + } + else if ((i > 1) && (m[i] != (m[i] & 0x07F))) + { + error("packOSC: MIDI parameters must be less than 128"); + returnVal.type = NOTYPE_osc; + returnVal.datum.s = NULL; + return returnVal; + } + } + returnVal.type = INT_osc; + returnVal.datum.i = (m[0]<<24) + (m[1]<<16) + (m[2]<<8) + m[3]; + return returnVal; +} + static typedArg packOSC_forceatom(t_atom *a, char ctype) { /* ctype is one of i,f,s,T,F,N,I*/ typedArg returnVal; t_float f; - t_int i; + int i; t_symbol s; static char buf[MAXPDSTRING]; #ifdef DEBUG atom_string(a, buf, MAXPDSTRING); - post("packOSC: atom type %d (%s)", a->a_type, buf); + printf("packOSC: atom type %d (%s)\n", a->a_type, buf); #endif /* the atom might be a float, or a symbol */ switch (a->a_type) @@ -661,14 +733,14 @@ static typedArg packOSC_forceatom(t_atom *a, char ctype) returnVal.type = INT_osc; returnVal.datum.i = atom_getint(a); #ifdef DEBUG - post("packOSC_forceatom: float to integer %d", returnVal.datum.i); + printf("packOSC_forceatom: float to integer %d\n", returnVal.datum.i); #endif break; case 'f': returnVal.type = FLOAT_osc; returnVal.datum.f = atom_getfloat(a); #ifdef DEBUG - post("packOSC_forceatom: float to float %f", returnVal.datum.f); + printf("packOSC_forceatom: float to float %f\n", returnVal.datum.f); #endif break; case 's': @@ -677,7 +749,7 @@ static typedArg packOSC_forceatom(t_atom *a, char ctype) returnVal.type = STRING_osc; returnVal.datum.s = buf; #ifdef DEBUG - post("packOSC_forceatom: float to string %s", returnVal.datum.s); + printf("packOSC_forceatom: float to string %s\n", returnVal.datum.s); #endif break; default: @@ -696,7 +768,7 @@ static typedArg packOSC_forceatom(t_atom *a, char ctype) returnVal.type = INT_osc; returnVal.datum.i = i; #ifdef DEBUG - post("packOSC_forceatom: symbol to integer %d", returnVal.datum.i); + printf("packOSC_forceatom: symbol to integer %d\n", returnVal.datum.i); #endif break; case 'f': @@ -704,14 +776,14 @@ static typedArg packOSC_forceatom(t_atom *a, char ctype) returnVal.type = FLOAT_osc; returnVal.datum.f = f; #ifdef DEBUG - post("packOSC_forceatom: symbol to float %f", returnVal.datum.f); + printf("packOSC_forceatom: symbol to float %f\n", returnVal.datum.f); #endif break; case 's': returnVal.type = STRING_osc; returnVal.datum.s = s.s_name; #ifdef DEBUG - post("packOSC_forceatom: symbol to string %s", returnVal.datum.s); + printf("packOSC_forceatom: symbol to string %s\n", returnVal.datum.s); #endif break; default: @@ -734,7 +806,13 @@ static typedArg packOSC_forceatom(t_atom *a, char ctype) static int packOSC_writetypedmessage (t_packOSC *x, OSCbuf *buf, char *messageName, int numArgs, typedArg *args, char *typeStr) { - int i, j, returnVal = OSC_writeAddressAndTypes(buf, messageName, typeStr); + int i, j, returnVal; + +#ifdef DEBUG + printf("packOSC_writetypedmessage: messageName %p (%s) typeStr %p (%s)\n", + messageName, messageName, typeStr, typeStr); +#endif + returnVal = OSC_writeAddressAndTypes(buf, messageName, typeStr); if (returnVal) { @@ -746,7 +824,7 @@ static int packOSC_writetypedmessage while (typeStr[i+1] == 'T' || typeStr[i+1] == 'F' || typeStr[i+1] == 'I' || typeStr[i+1] == 'N') { #ifdef DEBUG - post("packOSC_writetypedmessage: NULL [%c]", typeStr[i+1]); + printf("packOSC_writetypedmessage: NULL [%c]\n", typeStr[i+1]); #endif returnVal = OSC_writeNullArg(buf, typeStr[i+1]); ++i; @@ -757,26 +835,26 @@ static int packOSC_writetypedmessage { case INT_osc: #ifdef DEBUG - post("packOSC_writetypedmessage: int [%d]", args[j].datum.i); + printf("packOSC_writetypedmessage: int [%d]\n", args[j].datum.i); #endif returnVal = OSC_writeIntArg(buf, args[j].datum.i); break; case FLOAT_osc: #ifdef DEBUG - post("packOSC_writetypedmessage: float [%f]", args[j].datum.f); + printf("packOSC_writetypedmessage: float [%f]\n", args[j].datum.f); #endif returnVal = OSC_writeFloatArg(buf, args[j].datum.f); break; case STRING_osc: #ifdef DEBUG - post("packOSC_writetypedmessage: string [%s]", args[j].datum.s); + printf("packOSC_writetypedmessage: string [%s]\n", args[j].datum.s); #endif returnVal = OSC_writeStringArg(buf, args[j].datum.s); break; case BLOB_osc: /* write all the blob elements at once */ #ifdef DEBUG - post("packOSC_writetypedmessage calling OSC_writeBlobArg\n"); + printf("packOSC_writetypedmessage calling OSC_writeBlobArg\n"); #endif return OSC_writeBlobArg(buf, &args[j], numArgs-j); default: @@ -791,9 +869,15 @@ static int packOSC_writetypedmessage static int packOSC_writemessage(t_packOSC *x, OSCbuf *buf, char *messageName, int numArgs, typedArg *args) { int j, returnVal = 0, numTags; +#ifdef DEBUG + printf("packOSC_writemessage buf %p bufptr %p messageName %s %d args typetags %d\n", buf, buf->bufptr, messageName, numArgs, x->x_typetags); +#endif if (!x->x_typetags) { +#ifdef DEBUG + printf("packOSC_writemessage calling OSC_writeAddress with x->x_typetags %d\n", x->x_typetags); +#endif returnVal = OSC_writeAddress(buf, messageName); if (returnVal) { @@ -834,6 +918,9 @@ static int packOSC_writemessage(t_packOSC *x, OSCbuf *buf, char *messageName, in } } typeTags[j+1] = '\0'; +#ifdef DEBUG + printf("packOSC_writemessage calling OSC_writeAddressAndTypes with x->x_typetags %d typeTags %p (%s)\n", x->x_typetags, typeTags, typeTags); +#endif returnVal = OSC_writeAddressAndTypes(buf, messageName, typeTags); if (returnVal) { @@ -856,7 +943,7 @@ static int packOSC_writemessage(t_packOSC *x, OSCbuf *buf, char *messageName, in break; case BLOB_osc: #ifdef DEBUG - post ("packOSC_writemessage calling OSC_writeBlobArg\n"); + printf("packOSC_writemessage calling OSC_writeBlobArg\n"); #endif return OSC_writeBlobArg(buf, &args[j], numArgs-j); /* All the remaining args are blob */ default: @@ -871,9 +958,20 @@ static void packOSC_sendbuffer(t_packOSC *x) int i; int length; unsigned char *buf; + int reentry_count=x->x_reentry_count; /* must be on stack for recursion */ + size_t bufsize=sizeof(t_atom)*x->x_buflength; /* must be on stack for recursion */ + t_atom *atombuffer=x->x_bufferForOSClist; /* must be on stack in the case of recursion */ + + if(reentry_count>0) /* if we are recurse, let's move atombuffer to the stack */ + atombuffer=(t_atom *)getbytes(bufsize); + + if(!atombuffer) { + pd_error(x, "packOSC: unable to allocate %lu bytes for atombuffer", (long)bufsize); + return; + } #ifdef DEBUG - post("packOSC_sendbuffer: Sending buffer...\n"); + printf("packOSC_sendbuffer: Sending buffer...\n"); #endif if (OSC_isBufferEmpty(x->x_oscbuf)) { @@ -888,12 +986,21 @@ static void packOSC_sendbuffer(t_packOSC *x) length = OSC_packetSize(x->x_oscbuf); buf = (unsigned char *)OSC_getPacket(x->x_oscbuf); #ifdef DEBUG - post ("packOSC_sendbuffer: length: %lu", length); + printf("packOSC_sendbuffer: length: %u\n", length); #endif + /* convert the bytes in the buffer to floats in a list */ - for (i = 0; i < length; ++i) SETFLOAT(&x->x_bufferForOSClist[i], buf[i]); + for (i = 0; i < length; ++i) SETFLOAT(&atombuffer[i], buf[i]); + + /* cleanup the OSCbuffer structure (so we are ready for recursion) */ + OSC_initBuffer(x->x_oscbuf, x->x_buflength, x->x_bufferForOSCbuf); + /* send the list out the outlet */ - outlet_list(x->x_listout, &s_list, length, x->x_bufferForOSClist); + outlet_list(x->x_listout, &s_list, length, atombuffer); + + /* cleanup our 'stack'-allocated atombuffer in the case of reentrancy */ + if(reentry_count>0) + freebytes(atombuffer, bufsize); } /* The next part is copied and morphed from OSC-client.c. */ @@ -970,7 +1077,7 @@ static int OSC_CheckOverflow(OSCbuf *buf, size_t bytesNeeded) static void PatchMessageSize(OSCbuf *buf) { - int4byte size = buf->bufptr - ((char *) buf->thisMsgSize) - 4; + uint32_t size = buf->bufptr - ((char *) buf->thisMsgSize) - 4; *(buf->thisMsgSize) = htonl(size); } @@ -1011,8 +1118,8 @@ static int OSC_openBundle(OSCbuf *buf, OSCTimeTag tt) /* This bundle is inside another bundle, so we need to leave a blank size count for the size of this current bundle. */ if(OSC_CheckOverflow(buf, 20))return 1; - *((int4byte *)buf->bufptr) = 0xaaaaaaaa; - buf->prevCounts[buf->bundleDepth] = (int4byte *)buf->bufptr; + *((uint32_t *)buf->bufptr) = 0xaaaaaaaa; + buf->prevCounts[buf->bundleDepth] = (uint32_t *)buf->bufptr; buf->bufptr += 4; } @@ -1025,7 +1132,7 @@ static int OSC_openBundle(OSCbuf *buf, OSCTimeTag tt) if (htonl(1) != 1) { /* Byte swap the 8-byte integer time tag */ - int4byte *intp = (int4byte *)buf->bufptr; + uint32_t *intp = (uint32_t *)buf->bufptr; intp[0] = htonl(intp[0]); intp[1] = htonl(intp[1]); @@ -1081,8 +1188,10 @@ static int OSC_closeBundle(OSCbuf *buf) static int OSC_writeAddress(OSCbuf *buf, char *name) { - int4byte paddedLength; - + uint32_t paddedLength; +#ifdef DEBUG + printf("-->OSC_writeAddress buf %p bufptr %p name %s\n", buf, buf->bufptr, name); +#endif if (buf->state == ONE_MSG_ARGS) { post("packOSC: This packet is not a bundle, so you can't write another address"); @@ -1098,6 +1207,9 @@ static int OSC_writeAddress(OSCbuf *buf, char *name) if (CheckTypeTag(buf, '\0')) return 9; paddedLength = OSC_effectiveStringLength(name); +#ifdef DEBUG + printf("OSC_writeAddress paddedLength %d\n", paddedLength); +#endif if (buf->state == EMPTY) { @@ -1114,7 +1226,7 @@ static int OSC_writeAddress(OSCbuf *buf, char *name) /* Close the old message */ PatchMessageSize(buf); } - buf->thisMsgSize = (int4byte *)buf->bufptr; + buf->thisMsgSize = (uint32_t *)buf->bufptr; *(buf->thisMsgSize) = 0xbbbbbbbb; buf->bufptr += 4; buf->state = GET_ARGS; @@ -1131,8 +1243,11 @@ static int OSC_writeAddress(OSCbuf *buf, char *name) static int OSC_writeAddressAndTypes(OSCbuf *buf, char *name, char *types) { int result; - int4byte paddedLength; + uint32_t paddedLength; +#ifdef DEBUG + printf("OSC_writeAddressAndTypes buf %p name %s types %s\n", buf, name, types); +#endif if (buf == NULL) return 10; if (CheckTypeTag(buf, '\0')) return 9; @@ -1146,8 +1261,13 @@ static int OSC_writeAddressAndTypes(OSCbuf *buf, char *name, char *types) buf->typeStringPtr = buf->bufptr + 1; /* skip comma */ buf->bufptr += OSC_padString(buf->bufptr, types); +#ifdef DEBUG + printf("OSC_writeAddressAndTypes buf->typeStringPtr now %p (%s) buf->bufptr now %p (%s)\n", + buf->typeStringPtr, buf->typeStringPtr, buf->bufptr, buf->bufptr); +#endif buf->gettingFirstUntypedArg = 0; + buf->typeStringPtr = 0;// ready for a new type string return 0; } @@ -1157,7 +1277,13 @@ static int CheckTypeTag(OSCbuf *buf, char expectedType) if (buf->typeStringPtr) { +#ifdef DEBUG + printf("CheckTypeTag buf->typeStringPtr %p (%s)\n", buf->typeStringPtr, buf->typeStringPtr); +#endif c = *(buf->typeStringPtr); +#ifdef DEBUG + printf("CheckTypeTag buf %p expectedType %c c is %c\n", buf, expectedType, c); +#endif if (c != expectedType) { if (expectedType == '\0') @@ -1196,7 +1322,7 @@ static int OSC_writeFloatArg(OSCbuf *buf, float arg) /* Pretend arg is a long int so we can use htonl() */ if32.f = arg; - *((int4byte *) buf->bufptr) = htonl(if32.i); + *((uint32_t *) buf->bufptr) = htonl(if32.i); buf->bufptr += 4; @@ -1204,12 +1330,12 @@ static int OSC_writeFloatArg(OSCbuf *buf, float arg) return 0; } -static int OSC_writeIntArg(OSCbuf *buf, int4byte arg) +static int OSC_writeIntArg(OSCbuf *buf, uint32_t arg) { if(OSC_CheckOverflow(buf, 4))return 1; if (CheckTypeTag(buf, 'i')) return 9; - *((int4byte *) buf->bufptr) = htonl(arg); + *((uint32_t *) buf->bufptr) = htonl(arg); buf->bufptr += 4; buf->gettingFirstUntypedArg = 0; @@ -1225,9 +1351,9 @@ static int OSC_writeBlobArg(OSCbuf *buf, typedArg *arg, size_t nArgs) if(OSC_CheckOverflow(buf, nArgs+4))return 1; if (CheckTypeTag(buf, 'b')) return 9; - *((int4byte *) buf->bufptr) = htonl(nArgs); + *((uint32_t *) buf->bufptr) = htonl(nArgs); #ifdef DEBUG - post ("OSC_writeBlobArg length : %lu", nArgs); + printf("OSC_writeBlobArg length : %lu\n", nArgs); #endif buf->bufptr += 4; @@ -1235,12 +1361,12 @@ static int OSC_writeBlobArg(OSCbuf *buf, typedArg *arg, size_t nArgs) { if (arg[i].type != BLOB_osc) { - error("packOSC: blob element %i not blob type", i); + error("packOSC: blob element %lu not blob type", i); return 9; } b = (unsigned char)((arg[i].datum.i)&0x0FF);/* force int to 8-bit byte */ #ifdef DEBUG - post ("OSC_writeBlobArg : %d, %d", arg[i].datum.i, b); + printf("OSC_writeBlobArg : %d, %d\n", arg[i].datum.i, b); #endif buf->bufptr[i] = b; } @@ -1377,12 +1503,12 @@ static OSCTimeTag OSCTT_Infinite(void) #define SECONDS_FROM_1900_to_1970 2208988800LL /* 17 leap years */ #define TWO_TO_THE_32_OVER_ONE_MILLION 4295LL -static OSCTimeTag OSCTT_CurrentTimePlusOffset(uint4 offset) +static OSCTimeTag OSCTT_CurrentTimePlusOffset(uint32_t offset) { /* offset is in microseconds */ OSCTimeTag tt; static unsigned int onemillion = 1000000; - static unsigned int onethousand = 1000; #ifdef _WIN32 + static unsigned int onethousand = 1000; struct _timeb tb; _ftime(&tb); diff --git a/externals/mrpeach/osc/packingOSC.h b/externals/mrpeach/osc/packingOSC.h index 19002260a..a7b831c37 100644 --- a/externals/mrpeach/osc/packingOSC.h +++ b/externals/mrpeach/osc/packingOSC.h @@ -27,13 +27,10 @@ This is the size of a static array. If you exceed this limit you'll get an error message. */ #define MAX_BUNDLE_NESTING 32 -/* You may have to redefine this typedef if ints on your system - aren't 4 bytes. */ -typedef unsigned int uint4; typedef struct { - uint4 seconds; - uint4 fraction; + uint32_t seconds; + uint32_t fraction; } OSCTimeTag; typedef union @@ -42,4 +39,5 @@ typedef union float f; } intfloat32; -#endif // _PACKINGOSC \ No newline at end of file +#endif // _PACKINGOSC +/* end of packingOSC.h */ diff --git a/externals/mrpeach/osc/routeOSC-help.pd b/externals/mrpeach/osc/routeOSC-help.pd index c40d89e84..cc343876a 100644 --- a/externals/mrpeach/osc/routeOSC-help.pd +++ b/externals/mrpeach/osc/routeOSC-help.pd @@ -1,36 +1,35 @@ -#N canvas 156 138 996 758 12; -#X declare -lib mrpeach; -#X obj -34 554 cnv 15 820 130 empty empty empty 20 12 0 14 -261207 --66577 0; -#X obj -76 40 udpreceive 9997; -#X floatatom 91 111 3 0 0 0 - - -; -#X floatatom 118 111 3 0 0 0 - - -; -#X floatatom 145 111 3 0 0 0 - - -; -#X floatatom 172 111 3 0 0 0 - - -; -#X text 51 110 from; -#X obj -76 164 unpackOSC; -#X text 324 108 see also:; -#X obj 396 109 packOSC; -#X floatatom 483 184 10 0 0 1 millisecond_delay - -; -#X obj -76 191 pipelist; -#X text 484 559 arguments are OSC addresses to be routed; -#X text 43 707 see:; -#X text 190 708 for a way to send OSC over TCP or serial connections. +#N canvas 81 134 1070 758 12; +#X obj 11 524 cnv 15 820 130 empty empty empty 20 12 0 14 -261207 -66577 +0; +#X obj -31 10 udpreceive 9997; +#X floatatom 160 82 3 0 0 0 - - -, f 3; +#X floatatom 191 82 3 0 0 0 - - -, f 3; +#X floatatom 222 82 3 0 0 0 - - -, f 3; +#X floatatom 253 82 3 0 0 0 - - -, f 3; +#X text 120 81 from; +#X obj -31 134 unpackOSC; +#X text 369 78 see also:; +#X obj 445 79 packOSC; +#X floatatom 528 154 10 0 0 1 millisecond_delay - -, f 10; +#X obj -31 161 pipelist; +#X text 529 529 arguments are OSC addresses to be routed; +#X text 88 677 see:; +#X text 248 678 for a way to send OSC over TCP or serial connections. ; -#X obj 78 708 unpackOSCstream; -#X obj -110 218 print unpacked; -#X obj 91 87 unpack 0 0 0 0 0; -#X floatatom 200 111 8 0 0 0 - - -; -#X obj 26 64 route received from; -#X floatatom 26 132 5 0 0 0 - - -; -#X text 66 132 bytes; -#X text 43 40 Open [packOSC-help] to send packets to this patch.; -#X text -6 186 If the OSC packet has a timetag \, [pipelist] will delay +#X obj 123 678 unpackOSCstream; +#X obj -65 188 print unpacked; +#X obj 160 58 unpack 0 0 0 0 0; +#X floatatom 285 82 8 0 0 0 - - -, f 8; +#X obj 86 35 route received from; +#X floatatom 86 103 5 0 0 0 - - -, f 5; +#X text 129 103 bytes; +#X text 98 9 Open [packOSC-help] to send packets to this patch.; +#X text 39 156 If the OSC packet has a timetag \, [pipelist] will delay it until the time occurs; -#X obj 272 653 print match_1; -#X obj 338 631 print match_2; -#X obj 472 587 print no_match; -#N canvas 500 255 494 344 META 0; +#X obj 317 623 print match_1; +#X obj 393 601 print match_2; +#X obj 546 557 print no_match; +#N canvas 499 254 494 344 META 0; #X text 12 155 HELP_PATCH_AUTHORS "pd meta" information added by Jonathan Wilkes for Pd version 0.42.; #X text 12 25 LICENSE GPL v2 or later; @@ -40,52 +39,51 @@ Wilkes for Pd version 0.42.; #X text 12 115 OUTLET_R list; #X text 12 135 AUTHOR Martin Peach; #X text 12 45 DESCRIPTION routes lists as OSC packets.; -#X restore 788 685 pd META; -#X obj -7 8 import mrpeach; -#X text 612 657 2012/03/13 Martin Peach; -#X text -5 149 [unpackOSC] parses lists of floats (only integers on +#X restore 833 655 pd META; +#X text 657 627 2012/03/13 Martin Peach; +#X text 44 119 [unpackOSC] parses lists of floats (only integers on [0..255]) as OSC packets.; -#X obj -34 249 cnv 15 600 160 empty empty empty 20 12 0 14 -204786 --66577 0; -#X obj 127 412 cnv 15 600 140 empty empty empty 20 12 0 14 -261234 +#X obj 11 219 cnv 15 600 160 empty empty empty 20 12 0 14 -204786 -66577 +0; +#X obj 172 382 cnv 15 600 140 empty empty empty 20 12 0 14 -261234 -66577 0; -#X msg 76 343 set /left; -#X msg 53 320 set /left /right; -#X text 181 341 (but new outlets can't be created); -#X msg 27 294 paths; -#X msg 4 271 verbosity \$1; -#X obj 4 253 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 1 1 -; -#X text 22 249 set to 1 for debugging; -#X text 233 365 routeOSC will match deep paths; -#X text 177 319 [set( reassigns outputs from left to right; -#X text 81 294 [paths( will print the current OSC addresses to Pd console -; -#X msg 145 412 /test any2 4 5; -#X msg 257 524 1 2 3; -#X msg 99 366 set /one/two/three; -#X msg 122 389 set /*; -#X text 175 388 this will match any OSC message; -#X msg 212 479 /* zap!; -#X msg 235 502 zorro trope; -#X text 323 502 not a valid OSC message; -#X text 301 523 not a valid OSC message; -#X text 260 412 input is a message whose selector is an OSC path; -#X text 352 434 or a list whose first element is an OSC path; -#X obj 405 609 print match_3; -#X obj 272 559 routeOSC /test /west /one/two; -#X msg 189 456 /one/two/three yikes!; -#X msg 167 434 list /west/rate any1 2 3; -#X text -34 586 [routeOSC] routes Open Sound Control* messages \, or +#X msg 121 313 set /left; +#X msg 98 290 set /left /right; +#X text 226 311 (but new outlets can't be created); +#X msg 72 264 paths; +#X msg 49 241 verbosity \$1; +#X obj 49 223 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 +1; +#X text 67 219 set to 1 for debugging; +#X text 295 335 routeOSC will match deep paths; +#X text 232 289 [set( reassigns outputs from left to right; +#X text 126 264 [paths( will print the current OSC addresses to Pd +console; +#X msg 190 382 /test any2 4 5; +#X msg 302 494 1 2 3; +#X msg 144 336 set /one/two/three; +#X msg 167 359 set /*; +#X text 220 358 this will match any OSC message; +#X msg 257 449 /* zap!; +#X msg 280 472 zorro trope; +#X text 379 472 not a valid OSC message; +#X text 350 493 not a valid OSC message; +#X text 308 382 input is a message whose selector is an OSC path; +#X text 411 404 or a list whose first element is an OSC path; +#X obj 469 579 print match_3; +#X obj 317 529 routeOSC /test /west /one/two; +#X msg 234 426 /one/two/three yikes!; +#X msg 212 404 list /west/rate any1 2 3; +#X text 11 556 [routeOSC] routes Open Sound Control* messages \, or lists of anything beginning with a /path; -#X text -32 629 *See http://opensoundcontrol.org/spec-1_0; +#X text 13 599 *See http://opensoundcontrol.org/spec-1_0; #X connect 1 0 7 0; #X connect 1 1 19 0; #X connect 7 0 11 0; #X connect 7 0 16 0; #X connect 7 1 10 0; #X connect 7 1 11 1; -#X connect 11 0 55 0; +#X connect 11 0 54 0; #X connect 17 0 2 0; #X connect 17 1 3 0; #X connect 17 2 4 0; @@ -93,20 +91,20 @@ lists of anything beginning with a /path; #X connect 17 4 18 0; #X connect 19 0 20 0; #X connect 19 1 17 0; -#X connect 33 0 55 0; -#X connect 34 0 55 0; -#X connect 36 0 55 0; -#X connect 37 0 55 0; -#X connect 38 0 37 0; -#X connect 43 0 55 0; -#X connect 44 0 55 0; -#X connect 45 0 55 0; -#X connect 46 0 55 0; -#X connect 48 0 55 0; -#X connect 49 0 55 0; -#X connect 55 0 24 0; -#X connect 55 1 25 0; -#X connect 55 2 54 0; -#X connect 55 3 26 0; -#X connect 56 0 55 0; -#X connect 57 0 55 0; +#X connect 32 0 54 0; +#X connect 33 0 54 0; +#X connect 35 0 54 0; +#X connect 36 0 54 0; +#X connect 37 0 36 0; +#X connect 42 0 54 0; +#X connect 43 0 54 0; +#X connect 44 0 54 0; +#X connect 45 0 54 0; +#X connect 47 0 54 0; +#X connect 48 0 54 0; +#X connect 54 0 24 0; +#X connect 54 1 25 0; +#X connect 54 2 53 0; +#X connect 54 3 26 0; +#X connect 55 0 54 0; +#X connect 56 0 54 0; diff --git a/externals/mrpeach/osc/routeOSC.c b/externals/mrpeach/osc/routeOSC.c index 118623499..de610a632 100644 --- a/externals/mrpeach/osc/routeOSC.c +++ b/externals/mrpeach/osc/routeOSC.c @@ -88,11 +88,8 @@ The OpenSound Control WWW page is typedef struct _routeOSC { t_object x_obj; /* required header */ - t_int x_num; /* Number of prefixes we store */ - t_int x_verbosity; /* level of debug output required */ -// char *x_prefixes[MAX_NUM]; /* the OSC addresses to be matched */ -// int x_prefix_depth[MAX_NUM]; /* the number of slashes in each prefix */ -// void *x_outlets[MAX_NUM+1]; /* one for each prefix plus one for everything else */ + int x_num; /* Number of prefixes we store */ + int x_verbosity; /* level of debug output required */ char **x_prefixes; /* the OSC addresses to be matched */ int *x_prefix_depth; /* the number of slashes in each prefix */ void **x_outlets; /* one for each prefix plus one for everything else */ @@ -104,6 +101,9 @@ void routeOSC_setup(void); static void routeOSC_free(t_routeOSC *x); static int MyPatternMatch (const char *pattern, const char *test); static void routeOSC_doanything(t_routeOSC *x, t_symbol *s, int argc, t_atom *argv); +static void routeOSC_bang(t_routeOSC *x); +static void routeOSC_float(t_routeOSC *x, t_floatarg f); +static void routeOSC_symbol(t_routeOSC *x, t_symbol *s); static void routeOSC_list(t_routeOSC *x, t_symbol *s, int argc, t_atom *argv); static void *routeOSC_new(t_symbol *s, int argc, t_atom *argv); static void routeOSC_set(t_routeOSC *x, t_symbol *s, int argc, t_atom *argv); @@ -144,12 +144,15 @@ static void routeOSC_free(t_routeOSC *x) } /* initialization routine */ -// setup + void routeOSC_setup(void) { routeOSC_class = class_new(gensym("routeOSC"), (t_newmethod)routeOSC_new, (t_method)routeOSC_free, sizeof(t_routeOSC), 0, A_GIMME, 0); class_addanything(routeOSC_class, routeOSC_doanything); + class_addbang(routeOSC_class, routeOSC_bang); + class_addfloat(routeOSC_class, routeOSC_float); + class_addsymbol(routeOSC_class, routeOSC_symbol); class_addlist(routeOSC_class, routeOSC_list); class_addmethod(routeOSC_class, (t_method)routeOSC_set, gensym("set"), A_GIMME, 0); class_addmethod(routeOSC_class, (t_method)routeOSC_paths, gensym("paths"), A_GIMME, 0); @@ -273,19 +276,18 @@ static int routeOSC_count_slashes(char *prefix) static void routeOSC_doanything(t_routeOSC *x, t_symbol *s, int argc, t_atom *argv) { char *pattern, *nextSlash; - int i, pattern_depth = 0, matchedAnything = 0; + int i = 0, pattern_depth = 0, matchedAnything = 0; int noPath = 0; // nonzero if we are dealing with a simple list (as from a previous [routeOSC]) pattern = s->s_name; if (x->x_verbosity) post("routeOSC_doanything(%p): pattern is %s", x, pattern); if (pattern[0] != '/') - { // make a path '/'. Now s is actually the first item in the arguments list - pattern = gensym("/")->s_name; - noPath = 1; - if (x->x_verbosity) - post("routeOSC_doanything(%p): message pattern \"%s\" does not begin with /, setting path to %s", x, s->s_name, pattern); + { + /* output unmatched data on rightmost outlet */ + if (x->x_verbosity) post("routeOSC_doanything no OSC path(%p) , %d args", x, argc); + outlet_anything(x->x_outlets[x->x_num], s, argc, argv); + return; } - pattern_depth = routeOSC_count_slashes(pattern); if (x->x_verbosity) post("routeOSC_doanything(%p): pattern_depth is %i", x, pattern_depth); nextSlash = NextSlashOrNull(pattern+1); @@ -396,7 +398,6 @@ static void routeOSC_doanything(t_routeOSC *x, t_symbol *s, int argc, t_atom *ar } } } - if (!matchedAnything) { // output unmatched data on rightmost outlet a la normal 'route' object, jdl 20020908 @@ -405,14 +406,41 @@ static void routeOSC_doanything(t_routeOSC *x, t_symbol *s, int argc, t_atom *ar } } +static void routeOSC_bang(t_routeOSC *x) +{ + /* output non-OSC data on rightmost outlet */ + if (x->x_verbosity) post("routeOSC_bang (%p)", x); + + outlet_bang(x->x_outlets[x->x_num]); +} +static void routeOSC_float(t_routeOSC *x, t_floatarg f) +{ + /* output non-OSC data on rightmost outlet */ + if (x->x_verbosity) post("routeOSC_float (%p) %f", x, f); + + outlet_float(x->x_outlets[x->x_num], f); +} +static void routeOSC_symbol(t_routeOSC *x, t_symbol *s) +{ + /* output non-OSC data on rightmost outlet */ + if (x->x_verbosity) post("routeOSC_symbol (%p) %s", x, s->s_name); + + outlet_symbol(x->x_outlets[x->x_num], s); +} + static void routeOSC_list(t_routeOSC *x, t_symbol *s, int argc, t_atom *argv) { - if (argv[0].a_type == A_SYMBOL) routeOSC_doanything(x, argv[0].a_w.w_symbol, argc-1, &argv[1]); - else + /* output non-OSC data on rightmost outlet */ + if (x->x_verbosity) post("routeOSC_list (%p) s=%s argc is %d", x, s->s_name, argc); + + if (0 == argc) post("routeOSC_list (%p) empty list", x);/* this should never happen but catch it just in case... */ + + else if (argv[0].a_type == A_SYMBOL) routeOSC_doanything(x, argv[0].a_w.w_symbol, argc-1, &argv[1]); + + else if (argv[0].a_type == A_FLOAT) { - routeOSC_doanything(x, gensym("/"), argc, argv); - if (x->x_verbosity) - post("routeOSC_doanything(%p): message pattern is not a symbol, setting path to /", x); + if (x->x_verbosity) post("routeOSC_list (%p) floats:", x); + outlet_list(x->x_outlets[x->x_num], 0L, argc, argv); } } diff --git a/externals/mrpeach/osc/unpackOSC.c b/externals/mrpeach/osc/unpackOSC.c index 45405a7fe..54b8b9b97 100644 --- a/externals/mrpeach/osc/unpackOSC.c +++ b/externals/mrpeach/osc/unpackOSC.c @@ -64,7 +64,7 @@ The OSC webpage is http://cnmat.cnmat.berkeley.edu/OpenSoundControl on OSX anyway. */ - +//define DEBUG #include "packingOSC.h" @@ -75,23 +75,20 @@ typedef struct _unpackOSC t_object x_obj; t_outlet *x_data_out; t_outlet *x_delay_out; - t_atom x_data_at[MAX_MESG];/* symbols making up the path + payload */ - int x_data_atc;/* number of symbols to be output */ - char x_raw[MAX_MESG];/* bytes making up the entire OSC message */ - int x_raw_c;/* number of bytes in OSC message */ int x_bundle_flag;/* non-zero if we are processing a bundle */ int x_recursion_level;/* number of times we reenter unpackOSC_list */ int x_abort_bundle;/* non-zero if unpackOSC_list is not well formed */ + int x_reentry_count; } t_unpackOSC; void unpackOSC_setup(void); static void *unpackOSC_new(void); static void unpackOSC_free(t_unpackOSC *x); static void unpackOSC_list(t_unpackOSC *x, t_symbol *s, int argc, t_atom *argv); -static int unpackOSC_path(t_unpackOSC *x, char *path); -static void unpackOSC_Smessage(t_unpackOSC *x, void *v, int n); -static void unpackOSC_PrintTypeTaggedArgs(t_unpackOSC *x, void *v, int n); -static void unpackOSC_PrintHeuristicallyTypeGuessedArgs(t_unpackOSC *x, void *v, int n, int skipComma); +static int unpackOSC_path(t_atom *data_at, char *path); +static void unpackOSC_Smessage(t_atom *data_at, int *data_atc, void *v, int n); +static void unpackOSC_PrintTypeTaggedArgs(t_atom *data_at, int *data_atc, void *v, int n); +static void unpackOSC_PrintHeuristicallyTypeGuessedArgs(t_atom *data_at, int *data_atc, void *v, int n, int skipComma); static char *unpackOSC_DataAfterAlignedString(char *string, char *boundary); static int unpackOSC_IsNiceString(char *string, char *boundary); static t_float unpackOSC_DeltaTime(OSCTimeTag tt); @@ -102,7 +99,6 @@ static void *unpackOSC_new(void) x = (t_unpackOSC *)pd_new(unpackOSC_class); x->x_data_out = outlet_new(&x->x_obj, &s_list); x->x_delay_out = outlet_new(&x->x_obj, &s_float); - x->x_raw_c = x->x_data_atc = 0; x->x_bundle_flag = 0; x->x_recursion_level = 0; x->x_abort_bundle = 0; @@ -127,19 +123,26 @@ static void unpackOSC_list(t_unpackOSC *x, t_symbol *s, int argc, t_atom *argv) int size, messageLen, i, j; char *messageName, *args, *buf; OSCTimeTag tt; + t_atom data_at[MAX_MESG] ={{0}};/* symbols making up the path + payload */ + int data_atc = 0;/* number of symbols to be output */ + char raw[MAX_MESG];/* bytes making up the entire OSC message */ + int raw_c;/* number of bytes in OSC message */ +#ifdef DEBUG + printf(">>> unpackOSC_list: %d bytes, abort=%d, reentry_count %d recursion_level %d\n", + argc, x->x_abort_bundle, x->x_reentry_count, x->x_recursion_level); +#endif if(x->x_abort_bundle) return; /* if backing quietly out of the recursive stack */ + x->x_reentry_count++; if ((argc%4) != 0) { post("unpackOSC: Packet size (%d) not a multiple of 4 bytes: dropping packet", argc); - x->x_recursion_level = 0; - return; + goto unpackOSC_list_out; } if(argc > MAX_MESG) { post("unpackOSC: Packet size (%d) greater than max (%d). Change MAX_MESG and recompile if you want more.", argc, MAX_MESG); - x->x_recursion_level = 0; - return; + goto unpackOSC_list_out; } /* copy the list to a byte buffer, checking for bytes only */ for (i = 0; i < argc; ++i) @@ -152,48 +155,45 @@ static void unpackOSC_list(t_unpackOSC *x, t_symbol *s, int argc, t_atom *argv) /* , so change to this: */ if ((j == argv[i].a_w.w_float) && (j >= -128) && (j <= 255)) { - x->x_raw[i] = (char)j; + raw[i] = (char)j; } else { post("unpackOSC: Data out of range (%d), dropping packet", argv[i].a_w.w_float); - x->x_recursion_level = 0; - return; + goto unpackOSC_list_out; } } else { post("unpackOSC: Data not float, dropping packet"); - x->x_recursion_level = 0; - return; + goto unpackOSC_list_out; } } - x->x_raw_c = argc; - buf = x->x_raw; + raw_c = argc; + buf = raw; if ((argc >= 8) && (strncmp(buf, "#bundle", 8) == 0)) { /* This is a bundle message. */ #ifdef DEBUG - post("unpackOSC: bundle msg:\n"); + printf("unpackOSC: bundle msg:\n"); #endif if (argc < 16) { post("unpackOSC: Bundle message too small (%d bytes) for time tag", argc); - x->x_recursion_level = 0; - return; + goto unpackOSC_list_out; } x->x_bundle_flag = 1; /* Print the time tag */ #ifdef DEBUG - printf("unpackOSC: [ %lx%08lx\n", ntohl(*((unsigned long *)(buf+8))), - ntohl(*((unsigned long *)(buf+12)))); + printf("unpackOSC bundle timetag: [ %x.%0x\n", ntohl(*((uint32_t *)(buf+8))), + ntohl(*((uint32_t *)(buf+12)))); #endif /* convert the timetag into a millisecond delay from now */ - tt.seconds = ntohl(*((unsigned long *)(buf+8))); - tt.fraction = ntohl(*((unsigned long *)(buf+12))); + tt.seconds = ntohl(*((uint32_t *)(buf+8))); + tt.fraction = ntohl(*((uint32_t *)(buf+12))); /* pd can use a delay in milliseconds */ outlet_float(x->x_delay_out, unpackOSC_DeltaTime(tt)); /* Note: if we wanted to actually use the time tag as a little-endian @@ -207,26 +207,30 @@ static void unpackOSC_list(t_unpackOSC *x, t_symbol *s, int argc, t_atom *argv) if ((size % 4) != 0) { post("unpackOSC: Bad size count %d in bundle (not a multiple of 4)", size); - x->x_recursion_level = 0; - return; + goto unpackOSC_list_out; } if ((size + i + 4) > argc) { post("unpackOSC: Bad size count %d in bundle (only %d bytes left in entire bundle)", size, argc-i-4); - x->x_recursion_level = 0; - return; + goto unpackOSC_list_out; } /* Recursively handle element of bundle */ x->x_recursion_level++; +#ifdef DEBUG + printf("unpackOSC: bundle depth %d\n", x->x_recursion_level); +#endif if (x->x_recursion_level > MAX_BUNDLE_NESTING) { post("unpackOSC: bundle depth %d exceeded", MAX_BUNDLE_NESTING); - x->x_recursion_level = 0; x->x_abort_bundle = 1;/* we need to back out of the recursive stack*/ - return; + goto unpackOSC_list_out; } +#ifdef DEBUG + printf("unpackOSC: bundle calling unpackOSC_list(x=%p, s=%s, size=%d, argv[%d]=%p)\n", + x, s->s_name, size, i+4, &argv[i+4]); +#endif unpackOSC_list(x, s, size, &argv[i+4]); i += 4 + size; } @@ -238,49 +242,51 @@ static void unpackOSC_list(t_unpackOSC *x, t_symbol *s, int argc, t_atom *argv) x->x_bundle_flag = 0; /* end of bundle */ #ifdef DEBUG - printf("]\n"); + printf("unpackOSC: bundle end ] depth is %d\n", x->x_recursion_level); #endif } else if ((argc == 24) && (strcmp(buf, "#time") == 0)) { post("unpackOSC: Time message: %s\n :).\n", buf); - x->x_recursion_level = 0; - return; + goto unpackOSC_list_out; } else { /* This is not a bundle message or a time message */ messageName = buf; - args = unpackOSC_DataAfterAlignedString(messageName, buf+x->x_raw_c); +#ifdef DEBUG + printf("unpackOSC: message name string: %s length %d\n", messageName, raw_c); +#endif + args = unpackOSC_DataAfterAlignedString(messageName, buf+raw_c); if (args == 0) { post("unpackOSC: Bad message name string: Dropping entire message."); - x->x_recursion_level = 0; - return; + goto unpackOSC_list_out; } -#ifdef DEBUG - post("unpackOSC: message name string: %s", messageName); -#endif messageLen = args-messageName; /* put the OSC path into a single symbol */ - x->x_data_atc = unpackOSC_path(x, messageName); /* returns 1 if path OK, else 0 */ - if (x->x_data_atc == 1) + data_atc = unpackOSC_path(data_at, messageName); /* returns 1 if path OK, else 0 */ + if (data_atc == 1) { - unpackOSC_Smessage(x, (void *)args, x->x_raw_c-messageLen); +#ifdef DEBUG + printf("unpackOSC_list calling unpackOSC_Smessage: message length %d\n", raw_c-messageLen); +#endif + unpackOSC_Smessage(data_at, &data_atc, (void *)args, raw_c-messageLen); if (0 == x->x_bundle_flag) outlet_float(x->x_delay_out, 0); /* no delay for message not in a bundle */ } } - /*if (x->x_data_atc >= 1) outlet_list(x->x_data_out, &s_list, x->x_data_atc, x->x_data_at);*/ - if (x->x_data_atc >= 1) - outlet_anything(x->x_data_out, atom_getsymbol(x->x_data_at), x->x_data_atc-1, x->x_data_at+1); - x->x_data_atc = 0; - x->x_recursion_level = 0; + if (data_atc >= 1) + outlet_anything(x->x_data_out, atom_getsymbol(data_at), data_atc-1, data_at+1); + data_atc = 0; x->x_abort_bundle = 0; +unpackOSC_list_out: + x->x_recursion_level = 0; + x->x_reentry_count--; } -static int unpackOSC_path(t_unpackOSC *x, char *path) +static int unpackOSC_path(t_atom *data_at, char *path) { int i; @@ -295,7 +301,7 @@ static int unpackOSC_path(t_unpackOSC *x, char *path) { if (path[i] == '\0') { /* the end of the path: turn path into a symbol */ - SETSYMBOL(&x->x_data_at[0],gensym(path)); + SETSYMBOL(data_at, gensym(path)); return 1; } } @@ -304,7 +310,7 @@ static int unpackOSC_path(t_unpackOSC *x, char *path) } #define SMALLEST_POSITIVE_FLOAT 0.000001f -static void unpackOSC_Smessage(t_unpackOSC *x, void *v, int n) +static void unpackOSC_Smessage(t_atom *data_at, int *data_atc, void *v, int n) { char *chars = v; @@ -314,40 +320,58 @@ static void unpackOSC_Smessage(t_unpackOSC *x, void *v, int n) { if (chars[1] != ',') { +#ifdef DEBUG + printf("unpackOSC_Smessage calling unpackOSC_PrintTypeTaggedArgs: message length %d\n", n); +#endif /* This message begins with a type-tag string */ - unpackOSC_PrintTypeTaggedArgs(x, v, n); + unpackOSC_PrintTypeTaggedArgs(data_at, data_atc, v, n); } else { +#ifdef DEBUG + printf("unpackOSC_Smessage calling unpackOSC_PrintHeuristicallyTypeGuessedArgs: message length %d, skipComma 1\n", n); +#endif /* Double comma means an escaped real comma, not a type string */ - unpackOSC_PrintHeuristicallyTypeGuessedArgs(x, v, n, 1); + unpackOSC_PrintHeuristicallyTypeGuessedArgs(data_at, data_atc, v, n, 1); } } else { - unpackOSC_PrintHeuristicallyTypeGuessedArgs(x, v, n, 0); +#ifdef DEBUG + printf("unpackOSC_Smessage calling unpackOSC_PrintHeuristicallyTypeGuessedArgs: message length %d, skipComma 0\n", n); +#endif + unpackOSC_PrintHeuristicallyTypeGuessedArgs(data_at, data_atc, v, n, 0); } } } -static void unpackOSC_PrintTypeTaggedArgs(t_unpackOSC *x, void *v, int n) +static void unpackOSC_PrintTypeTaggedArgs(t_atom *data_at, int *data_atc, void *v, int n) { char *typeTags, *thisType, *p; - int myargc = x->x_data_atc; - t_atom *mya = x->x_data_at; + int myargc = *data_atc; + t_atom *mya = data_at; typeTags = v; if (!unpackOSC_IsNiceString(typeTags, typeTags+n)) { +#ifdef DEBUG + printf("unpackOSC_PrintTypeTaggedArgs not nice string\n"); +#endif /* No null-termination, so maybe it wasn't a type tag string after all */ - unpackOSC_PrintHeuristicallyTypeGuessedArgs(x, v, n, 0); + unpackOSC_PrintHeuristicallyTypeGuessedArgs(data_at, data_atc, v, n, 0); return; } +#ifdef DEBUG + printf("unpackOSC_PrintTypeTaggedArgs calling unpackOSC_DataAfterAlignedString %p to %p\n", typeTags, typeTags+n); +#endif p = unpackOSC_DataAfterAlignedString(typeTags, typeTags+n); - +#ifdef DEBUG + printf("unpackOSC_PrintTypeTaggedArgs p is %p: ", p); +#endif + if (p == NULL) return; /* malformed message */ for (thisType = typeTags + 1; *thisType != 0; ++thisType) { switch (*thisType) @@ -356,7 +380,7 @@ static void unpackOSC_PrintTypeTaggedArgs(t_unpackOSC *x, void *v, int n) { int i, blob_bytes = ntohl(*((int *) p)); #ifdef DEBUG - post("blob: %lu bytes", blob_bytes); + printf("blob: %u bytes\n", blob_bytes); #endif p += 4; for (i = 0; i < blob_bytes; ++i, ++p, ++myargc) @@ -368,9 +392,19 @@ static void unpackOSC_PrintTypeTaggedArgs(t_unpackOSC *x, void *v, int n) } break; } - case 'i': case 'r': case 'm': case 'c': + case 'm': /* MIDI message is the next four bytes*/ + { + int i; #ifdef DEBUG - post("integer: %d", ntohl(*((int *) p))); + printf("MIDI: 0x%08X\n", ntohl(*((int *) p))); +#endif + for (i = 0; i < 4; ++i, ++p, ++myargc) + SETFLOAT(mya+myargc, (*(unsigned char *)p)); + break; + } + case 'i': case 'r': case 'c': +#ifdef DEBUG + printf("integer: %d\n", ntohl(*((int *) p))); #endif SETFLOAT(mya+myargc,(signed)ntohl(*((int *) p))); myargc++; @@ -381,7 +415,7 @@ static void unpackOSC_PrintTypeTaggedArgs(t_unpackOSC *x, void *v, int n) intfloat32 thisif; thisif.i = ntohl(*((int *) p)); #ifdef DEBUG - post("float: %f", thisif.f); + printf("float: %f\n", thisif.f); #endif SETFLOAT(mya+myargc, thisif.f); myargc++; @@ -390,14 +424,14 @@ static void unpackOSC_PrintTypeTaggedArgs(t_unpackOSC *x, void *v, int n) } case 'h': case 't': #ifdef DEBUG - printf("[A 64-bit int] "); + printf("[A 64-bit int]\n"); #endif post("unpackOSC: PrintTypeTaggedArgs: [A 64-bit int] not implemented"); p += 8; break; case 'd': #ifdef DEBUG - printf("[A 64-bit float] "); + printf("[A 64-bit float]\n"); #endif post("unpackOSC: PrintTypeTaggedArgs: [A 64-bit float] not implemented"); p += 8; @@ -411,7 +445,7 @@ static void unpackOSC_PrintTypeTaggedArgs(t_unpackOSC *x, void *v, int n) else { #ifdef DEBUG - post("string: \"%s\"", p); + printf("string: \"%s\"\n", p); #endif SETSYMBOL(mya+myargc,gensym(p)); myargc++; @@ -421,48 +455,51 @@ static void unpackOSC_PrintTypeTaggedArgs(t_unpackOSC *x, void *v, int n) break; case 'T': #ifdef DEBUG - printf("[True] "); + printf("[True]\n"); #endif SETFLOAT(mya+myargc,1.); myargc++; break; case 'F': #ifdef DEBUG - printf("[False] "); + printf("[False]\n"); #endif SETFLOAT(mya+myargc,0.); myargc++; break; case 'N': #ifdef DEBUG - printf("[Nil]"); + printf("[Nil]\n"); #endif SETFLOAT(mya+myargc,0.); myargc++; break; case 'I': #ifdef DEBUG - printf("[Infinitum]"); + printf("[Infinitum]\n"); #endif SETSYMBOL(mya+myargc,gensym("INF")); myargc++; break; default: +#ifdef DEBUG + printf("unpackOSC_PrintTypeTaggedArgs unknown typetag %c (%0X)\n", *thisType, *thisType); +#endif post("unpackOSC: PrintTypeTaggedArgs: [Unrecognized type tag %c]", *thisType); - myargc++; + return; } } - x->x_data_atc = myargc; + *data_atc = myargc; } -static void unpackOSC_PrintHeuristicallyTypeGuessedArgs(t_unpackOSC *x, void *v, int n, int skipComma) +static void unpackOSC_PrintHeuristicallyTypeGuessedArgs(t_atom *data_at, int *data_atc, void *v, int n, int skipComma) { int i; int *ints; intfloat32 thisif; char *chars, *string, *nextString; - int myargc= x->x_data_atc; - t_atom* mya = x->x_data_at; + int myargc = *data_atc; + t_atom* mya = data_at; /* Go through the arguments 32 bits at a time */ ints = v; @@ -509,7 +546,7 @@ static void unpackOSC_PrintHeuristicallyTypeGuessedArgs(t_unpackOSC *x, void *v, post("unpackOSC: PrintHeuristicallyTypeGuessedArgs: indeterminate type: 0x%x xx", ints[i]); i++; } - x->x_data_atc = myargc; + *data_atc = myargc; } } @@ -529,6 +566,9 @@ static char *unpackOSC_DataAfterAlignedString(char *string, char *boundary) int i; +#ifdef DEBUG + printf("unpackOSC_DataAfterAlignedString boundary - string = %ld\n", boundary-string); +#endif if ((boundary - string) %4 != 0) { post("unpackOSC: DataAfterAlignedString: bad boundary"); @@ -537,6 +577,9 @@ static char *unpackOSC_DataAfterAlignedString(char *string, char *boundary) for (i = 0; string[i] != '\0'; i++) { +#ifdef DEBUG + printf("%0X(%c) ", string[i], string[i]); +#endif if (string + i >= boundary) { post("unpackOSC: DataAfterAlignedString: Unreasonably long string"); @@ -545,7 +588,10 @@ static char *unpackOSC_DataAfterAlignedString(char *string, char *boundary) } /* Now string[i] is the first null character */ - i++; +#ifdef DEBUG + printf("\nunpackOSC_DataAfterAlignedString first null character at %p\n", &string[i]); +#endif + i++; for (; (i % STRING_ALIGN_PAD) != 0; i++) { @@ -560,15 +606,20 @@ static char *unpackOSC_DataAfterAlignedString(char *string, char *boundary) return 0; } } - +#ifdef DEBUG + printf("unpackOSC_DataAfterAlignedString first non-null character at %p\n", &string[i]); +#endif + return string+i; } static int unpackOSC_IsNiceString(char *string, char *boundary) { /* Arguments same as DataAfterAlignedString(). Is the given "string" - really a string? I.e., is it a sequence of isprint() characters - terminated with 1-4 null characters to align on a 4-byte boundary? + really an OSC-string? I.e., is it + "A sequence of non-null ASCII characters followed by a null, followed + by 0-3 additional null characters to make the total number of bits a + multiple of 32"? (OSC 1.0) Returns 1 if true, else 0. */ int i; @@ -579,12 +630,13 @@ static int unpackOSC_IsNiceString(char *string, char *boundary) return 0; } - /* anything less than space (0x20) is no good, UTF-8 sequences will be accepted -- not strictly OSC v1.0 */ + /* any non-zero byte will be accepted, so UTF-8 sequences will also be accepted -- not strictly OSC v1.0 */ for (i = 0; string[i] != '\0'; i++) /* if ((!isprint(string[i])) || (string + i >= boundary)) return 0; */ /* only ASCII printable chars */ - if ((0==(string[i]&0xE0)) || (string + i >= boundary)) return 0; - /* If we made it this far, it's a null-terminated sequence of printing characters - in the given boundary. Now we just make sure it's null padded... */ + /*if ((0==(string[i]&0xE0)) || (string + i >= boundary)) return 0;*/ /* onl;y ASCII space (0x20) and above */ + if (string + i >= boundary) return 0; /* anything non-zero */ + /* If we made it this far, it's a null-terminated sequence of characters + within the given boundary. Now we just make sure it's null padded... */ /* Now string[i] is the first null character */ i++; diff --git a/externals/mrpeach/rcosc~/rcosc~.c b/externals/mrpeach/rcosc~/rcosc~.c index 43087d5ba..0ab1c9de6 100644 --- a/externals/mrpeach/rcosc~/rcosc~.c +++ b/externals/mrpeach/rcosc~/rcosc~.c @@ -109,7 +109,7 @@ void rcosc_tilde_setup(void) CLASS_DEFAULT, A_DEFFLOAT, 0); - class_addmethod(rcosc_tilde_class, (t_method)rcosc_tilde_dsp, gensym("dsp"), A_CANT, 0); + class_addmethod(rcosc_tilde_class, (t_method)rcosc_tilde_dsp, gensym("dsp"), 0); CLASS_MAINSIGNALIN(rcosc_tilde_class, t_rcosc_tilde, rc_f); } diff --git a/externals/mrpeach/rc~/rc~.c b/externals/mrpeach/rc~/rc~.c index a7deefadc..5cc750aca 100644 --- a/externals/mrpeach/rc~/rc~.c +++ b/externals/mrpeach/rc~/rc~.c @@ -64,7 +64,7 @@ void rc_tilde_setup(void) CLASS_DEFAULT, A_DEFFLOAT, 0); - class_addmethod(rc_tilde_class, (t_method)rc_tilde_dsp, gensym("dsp"), A_CANT, 0); + class_addmethod(rc_tilde_class, (t_method)rc_tilde_dsp, gensym("dsp"), 0); CLASS_MAINSIGNALIN(rc_tilde_class, t_rc_tilde, rc_f); } diff --git a/externals/mrpeach/rojo~/rojo~.c b/externals/mrpeach/rojo~/rojo~.c index 96db57dbb..13c2f6b66 100644 --- a/externals/mrpeach/rojo~/rojo~.c +++ b/externals/mrpeach/rojo~/rojo~.c @@ -65,7 +65,7 @@ void rojo_tilde_setup(void) { rojo_class = class_new(gensym("rojo~"), (t_newmethod)rojo_new, 0, sizeof(t_rojo), CLASS_NOINLET, A_GIMME, 0); - class_addmethod(rojo_class, (t_method)rojo_dsp, gensym("dsp"), A_CANT, 0); + class_addmethod(rojo_class, (t_method)rojo_dsp, gensym("dsp"), 0); } /*------------------------------------------------------------------*/ static t_int *perform0(t_int *w) diff --git a/externals/mrpeach/runningmean/runningmean-help.pd b/externals/mrpeach/runningmean/runningmean-help.pd index 59e1357c6..a584a2911 100644 --- a/externals/mrpeach/runningmean/runningmean-help.pd +++ b/externals/mrpeach/runningmean/runningmean-help.pd @@ -1,28 +1,25 @@ -#N canvas 1 53 624 294 10; -#X obj 141 181 runningmean 128; -#X msg 141 117 clear; -#X msg 167 138 length 10; -#X msg 228 159 22; -#X text 179 117 clear the array to zero; -#X text 233 138 set length (also clears the array); -#X floatatom 141 212 5 0 0 0 - - -; +#N canvas 216 528 808 369 10; +#X obj 191 231 runningmean 128; +#X msg 121 144 clear; +#X msg 165 189 length 10; +#X msg 278 209 22; +#X floatatom 191 262 5 0 0 0 - - -; #X obj 11 36 bng 15 250 50 0 empty empty empty 17 7 0 10 -257985 -1 -1; #X text 29 35 bang outputs current mean; #X msg 76 99 1; #X msg 98 121 2; -#X text 105 211 mean:; -#X text 254 158 another way to set length (also clears the array); +#X text 155 261 mean:; #X text 63 69 Incoming floats are added to the array. The mean is recalculated for each incoming float; -#X text 237 181 Argument sets initial length. Default (no argument) +#X text 287 231 Argument sets initial length. Default (no argument) is 128; #X text 10 4 [runningmean] outputs the running mean of the last n floats to arrive on the left inlet.; -#X text 199 201 Length can be changed to any positive value less than +#X text 249 251 Length can be changed to any positive value less than or equal to the length set by the creation argumwent; -#X text 455 239 Martin Peach 2009/04/10; -#N canvas 446 134 494 344 META 0; +#X text 505 289 Martin Peach 2009/04/10; +#N canvas 701 617 494 344 META 0; #X text 12 155 HELP_PATCH_AUTHORS "pd meta" information added by Jonathan Wilkes for Pd version 0.42.; #X text 12 25 LICENSE GPL v2 or later; @@ -33,11 +30,18 @@ to arrive on the left inlet; #X text 12 75 INLET_0 float bang clear length; #X text 12 95 INLET_1 float; #X text 12 115 OUTLET_0 float; -#X restore 571 269 pd META; -#X connect 0 0 6 0; +#X restore 621 319 pd META; +#X msg 145 168 clear 10; +#X text 231 189 set length (and sets the new array to the current mean) +; +#X text 304 208 another way to set length; +#X text 203 167 set the array to all 10s; +#X text 159 144 clear the array to all zeroes; +#X connect 0 0 4 0; #X connect 1 0 0 0; #X connect 2 0 0 0; #X connect 3 0 0 1; +#X connect 5 0 0 0; #X connect 7 0 0 0; -#X connect 9 0 0 0; -#X connect 10 0 0 0; +#X connect 8 0 0 0; +#X connect 16 0 0 0; diff --git a/externals/mrpeach/runningmean/runningmean.c b/externals/mrpeach/runningmean/runningmean.c index 96cc15777..ac9a4ac24 100644 --- a/externals/mrpeach/runningmean/runningmean.c +++ b/externals/mrpeach/runningmean/runningmean.c @@ -11,16 +11,16 @@ typedef struct _runningmean { t_object x_obj; - t_int x_in1; - t_int x_in2; - t_int x_in3; + int x_in1; + int x_in2; + int x_in3; t_outlet *x_out; t_inlet *x_inlet2; - t_int x_n; - t_int x_originalsize; + int x_n; + int x_originalsize; t_float *x_data; t_float x_mean; - t_int x_pointer; + int x_pointer; } t_runningmean; static t_class *runningmean_class; @@ -31,7 +31,7 @@ static void runningmean_free(t_runningmean *x); static void runningmean_bang(t_runningmean *x); static void runningmean_float(t_runningmean *x, t_float f); static void runningmean_length(t_runningmean *x, t_float f); -static void runningmean_zero(t_runningmean *x); +static void runningmean_zero(t_runningmean *x, t_float f); static void runningmean_float(t_runningmean *x, t_float f) { @@ -63,20 +63,20 @@ static void runningmean_length(t_runningmean *x, t_float f) if ((f >= 1) && ((int)f == f) && (f <= x->x_originalsize)) { x->x_n = (int)f; - runningmean_zero(x); + runningmean_zero(x, x->x_mean); // set the entire new array to the old mean } else post("runningmean length must be an integer between 1 and %d.", x->x_originalsize); return; } -static void runningmean_zero(t_runningmean *x) +static void runningmean_zero(t_runningmean *x, t_float f) { float *p = x->x_data; int i; - /* zero the entire array */ - for (i = 0; i < x->x_n; ++i) *p++ = 0; - x->x_mean = 0; + /* set the entire array to f */ + for (i = 0; i < x->x_n; ++i) *p++ = f; + x->x_mean = f; x->x_pointer = 0; return; } @@ -118,7 +118,7 @@ static void *runningmean_new(t_floatarg f) } } x->x_originalsize = x->x_n; - runningmean_zero(x); + runningmean_zero(x, 0); } return (x); } @@ -138,7 +138,7 @@ void runningmean_setup(void) class_addbang(runningmean_class, runningmean_bang); class_addfloat(runningmean_class, runningmean_float); class_addmethod(runningmean_class, (t_method)runningmean_length, gensym("length"), A_FLOAT, 0); - class_addmethod(runningmean_class, (t_method)runningmean_zero, gensym("clear"), 0); + class_addmethod(runningmean_class, (t_method)runningmean_zero, gensym("clear"), A_DEFFLOAT, 0); } /* end runningmean.c */ diff --git a/externals/mrpeach/serializer/b2f-help.pd b/externals/mrpeach/serializer/b2f-help.pd new file mode 100644 index 000000000..fc5a295ab --- /dev/null +++ b/externals/mrpeach/serializer/b2f-help.pd @@ -0,0 +1,14 @@ +#N canvas 666 174 450 300 10; +#X obj 103 178 b2f; +#X msg 103 83 0 1 2 3; +#X text 77 53 [b2f] converts lists of 4 bytes to floats.; +#X text 43 17 Assuming you received 4 bytes as a binary representation +of a floating-point number \,; +#X text 234 258 Martin Peach 2013_03_13; +#X msg 181 83 208 15 73 64; +#X floatatom 103 209 12 0 0 0 - - -; +#X msg 269 83 219 15 73 64; +#X connect 0 0 6 0; +#X connect 1 0 0 0; +#X connect 5 0 0 0; +#X connect 7 0 0 0; diff --git a/externals/mrpeach/serializer/b2f.c b/externals/mrpeach/serializer/b2f.c new file mode 100644 index 000000000..61b622b18 --- /dev/null +++ b/externals/mrpeach/serializer/b2f.c @@ -0,0 +1,88 @@ +/* b2f.c MP 20130313 */ +/* Convert a list of 4 bytes to a Pd float */ +#include "m_pd.h" +#include <string.h> + +typedef struct _b2f +{ + t_object x_obj; + t_outlet *x_out; +} t_b2f; + +static t_class *b2f_class; + +void b2f_setup(void); +static void *b2f_new(t_symbol *s, int argc, t_atom *argv); +static void b2f_free(t_b2f *x); +static void b2f_list(t_b2f *x, t_symbol *s, int argc, t_atom *argv); + +union fbuf +{ + t_float f; + unsigned char b[4]; +}; + +static void b2f_list(t_b2f *x, t_symbol *s, int argc, t_atom *argv) +{ + int i, d; + union fbuf buf; + + //post("b2f_list: s is %s, argc is %d", s->s_name, argc); + if (0 != strncmp("list", s->s_name, 4)) + { + post("b2f_list: not a list of floats"); + return; + } + if (argc != 4) + { + post("b2f_list: need 4 floats"); + return; + } + for (i = 0; i < 4; ++i) + { + if (argv[i].a_type != A_FLOAT) + { + post("b2f_list: list element %d is not a float", i); + return; + } + d = argv[i].a_w.w_float; + if (d != argv[i].a_w.w_float) + { + post("b2f_list: list element %d is not an integer", i); + return; + } + if (d < 0 || d > 255) + { + post("b2f_list: list element %d is not an integer on [0..255]", i); + return; + } + buf.b[i] = d; + } + outlet_float(x->x_out, buf.f); +} + +static void b2f_free(t_b2f *x) +{ + return; +} + +static void *b2f_new(t_symbol *s, int argc, t_atom *argv) +{ + t_b2f *x; + + x = (t_b2f *)pd_new(b2f_class); + if (x == NULL) return (x); + x->x_out = outlet_new((t_object *)x, &s_float); + return (x); +} + +void b2f_setup(void) +{ + b2f_class = class_new(gensym("b2f"), + (t_newmethod)b2f_new, + (t_method)b2f_free, + sizeof(t_b2f), 0, 0); /* no arguments */ + class_addlist(b2f_class, b2f_list); +} +/* end b2f.c */ + diff --git a/externals/mrpeach/serializer/f2b-help.pd b/externals/mrpeach/serializer/f2b-help.pd new file mode 100644 index 000000000..3e7c7dd24 --- /dev/null +++ b/externals/mrpeach/serializer/f2b-help.pd @@ -0,0 +1,28 @@ +#N canvas 626 544 450 300 10; +#X obj 57 151 f2b; +#X msg 57 118 3.14159; +#X obj 57 187 unpack 0 0 0 0; +#X floatatom 57 228 5 0 0 0 - - -; +#X floatatom 92 228 5 0 0 0 - - -; +#X floatatom 127 228 5 0 0 0 - - -; +#X floatatom 162 228 5 0 0 0 - - -; +#X text 244 268 Martin Peach 2013_03_13; +#X msg 135 118 100000; +#X text 53 8 [f2b] converts floats to lists of four bytes suitable +for sending through a serial connection. This is the binary representation +\, so the receiver must use the same floating-point format.; +#X obj 213 114 * 4; +#X floatatom 213 141 12 0 0 0 - - -; +#X obj 213 91 atan; +#X msg 213 68 1; +#X connect 0 0 2 0; +#X connect 1 0 0 0; +#X connect 2 0 3 0; +#X connect 2 1 4 0; +#X connect 2 2 5 0; +#X connect 2 3 6 0; +#X connect 8 0 0 0; +#X connect 10 0 11 0; +#X connect 10 0 0 0; +#X connect 12 0 10 0; +#X connect 13 0 12 0; diff --git a/externals/mrpeach/serializer/f2b.c b/externals/mrpeach/serializer/f2b.c new file mode 100644 index 000000000..2dff5bb84 --- /dev/null +++ b/externals/mrpeach/serializer/f2b.c @@ -0,0 +1,63 @@ +/* f2b.c MP 20130313 */ +/* Convert a Pd float to a list of 4 bytes */ +#include "m_pd.h" +#include <string.h> + +typedef struct _f2b +{ + t_object x_obj; + t_outlet *x_out; +} t_f2b; + +static t_class *f2b_class; + +void f2b_setup(void); +static void *f2b_new(t_symbol *s, int argc, t_atom *argv); +static void f2b_free(t_f2b *x); +static void f2b_float(t_f2b *x, t_float f); + +union fbuf +{ + t_float f; + unsigned char b[4]; +}; + +static void f2b_float(t_f2b *x, t_float f) +{ + int i; + union fbuf buf; + t_atom outs[4]; + + + //post("f2b_float: f is %f", f); + buf.f = f; + for (i = 0; i < 4; ++i) SETFLOAT(&outs[i], buf.b[i]); + + outlet_list(x->x_out, gensym("list"), 4, outs); +} + +static void f2b_free(t_f2b *x) +{ + return; +} + +static void *f2b_new(t_symbol *s, int argc, t_atom *argv) +{ + t_f2b *x; + + x = (t_f2b *)pd_new(f2b_class); + if (x == NULL) return (x); + x->x_out = outlet_new((t_object *)x, &s_float); + return (x); +} + +void f2b_setup(void) +{ + f2b_class = class_new(gensym("f2b"), + (t_newmethod)f2b_new, + (t_method)f2b_free, + sizeof(t_f2b), 0, 0); /* no arguments */ + class_addfloat(f2b_class, f2b_float); +} +/* end f2b.c */ + diff --git a/externals/mrpeach/slipdec/slipdec.c b/externals/mrpeach/slipdec/slipdec.c index ce80ccea5..5ede6397e 100644 --- a/externals/mrpeach/slipdec/slipdec.c +++ b/externals/mrpeach/slipdec/slipdec.c @@ -21,11 +21,11 @@ typedef struct _slipdec t_outlet *x_slipdec_out; t_outlet *x_status_out; t_atom *x_slip_buf; - t_int x_slip_length; - t_int x_slip_max_length; - t_int x_valid_SLIP; - t_int x_esced; - t_int x_verbose; + int x_slip_length; + int x_slip_max_length; + int x_valid_SLIP; + int x_esced; + int x_verbose; } t_slipdec; static void *slipdec_new(t_symbol *s, int argc, t_atom *argv); @@ -105,9 +105,9 @@ static void slipdec_list(t_slipdec *x, t_symbol *s, int ac, t_atom *av) if (c != f) { /* abort, input list needs to be fixed before this is gonna wuk */ - pd_error (x, "slipdec: input %d out of range [0..255]", f); - x->x_valid_SLIP = 0; /* not valid SLIP */ - slipdec_dump(x,0);// reset + pd_error (x, "slipdec: input %f out of range [0..255]", f); + x->x_valid_SLIP = 0; /* not valid SLIP */ + slipdec_dump(x,0);// reset return; } if(SLIP_END == c) @@ -159,9 +159,9 @@ static void slipdec_float(t_slipdec *x, t_float f) if (c != f) { /* abort, input list needs to be fixed before this is gonna wuk */ - pd_error (x, "slipdec: input %d out of range [0..255]", f); - x->x_valid_SLIP = 0; /* not valid SLIP */ - slipdec_dump(x,0);/* reset */ + pd_error (x, "slipdec: input %f out of range [0..255]", f); + x->x_valid_SLIP = 0; /* not valid SLIP */ + slipdec_dump(x,0);/* reset */ return; } if(SLIP_END == c) diff --git a/externals/mrpeach/slipenc/slipenc.c b/externals/mrpeach/slipenc/slipenc.c index 74b1b2972..816efbac3 100644 --- a/externals/mrpeach/slipenc/slipenc.c +++ b/externals/mrpeach/slipenc/slipenc.c @@ -54,8 +54,8 @@ typedef struct _slipenc t_object x_obj; t_outlet *x_slipenc_out; t_atom *x_slip_buf; - t_int x_slip_length; - t_int x_slip_max_length; + int x_slip_length; + int x_slip_max_length; } t_slipenc; static void *slipenc_new(t_symbol *s, int argc, t_atom *argv); diff --git a/externals/mrpeach/sqosc~/sqosc~.c b/externals/mrpeach/sqosc~/sqosc~.c index cf182143f..b62500647 100644 --- a/externals/mrpeach/sqosc~/sqosc~.c +++ b/externals/mrpeach/sqosc~/sqosc~.c @@ -341,7 +341,7 @@ void sqosc_tilde_setup(void) sqosc_class = class_new(gensym("sqosc~"), (t_newmethod)sqosc_new, 0, sizeof(t_sqosc), 0, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0); CLASS_MAINSIGNALIN(sqosc_class, t_sqosc, x_f);/* x_f is used when no signal is input */ - class_addmethod(sqosc_class, (t_method)sqosc_dsp, gensym("dsp"), A_CANT, 0); + class_addmethod(sqosc_class, (t_method)sqosc_dsp, gensym("dsp"), 0); class_addmethod(sqosc_class, (t_method)sqosc_ft1, gensym("ft1"), A_FLOAT, 0); class_addmethod(sqosc_class, (t_method)sqosc_pw, gensym("pw"), A_FLOAT, 0); diff --git a/externals/mrpeach/str/str.c b/externals/mrpeach/str/str.c index c5c564fe3..0e4d7e957 100644 --- a/externals/mrpeach/str/str.c +++ b/externals/mrpeach/str/str.c @@ -6,6 +6,13 @@ #include <errno.h> #include "m_pd.h" +/* support older Pd versions without sys_open(), sys_fopen(), sys_fclose() */ +#if PD_MAJOR_VERSION == 0 && PD_MINOR_VERSION < 44 +#define sys_open open +#define sys_fopen fopen +#define sys_fclose fclose +#endif + #ifndef PD_BLOBS /* PD_BLOBS is not defined in m_pd.h: No PD blob support: Make a dummy str object */ typedef struct _str { @@ -378,7 +385,7 @@ static void str_fread(t_str *x, t_symbol *s, int argc, t_atom *argv) return; } errno = 0; - fp = fopen((char *)x->x_buf.s_data, "rb"); + fp = sys_fopen((char *)x->x_buf.s_data, "rb"); if(NULL == fp) { post ("str file_read: error opening file \"%s\": %d", x->x_buf.s_data, errno); @@ -396,7 +403,7 @@ static void str_fread(t_str *x, t_symbol *s, int argc, t_atom *argv) x->x_string_in1_end = limit; post ("str file_read: read %lu bytes", limit); } - fclose(fp); + sys_fclose(fp); return; } @@ -422,7 +429,7 @@ static void str_fwrite(t_str *x, t_symbol *s, int argc, t_atom *argv) return; } errno = 0; - fp = fopen((char *)x->x_buf.s_data, "wb"); + fp = sys_fopen((char *)x->x_buf.s_data, "wb"); if(NULL == fp) { post ("str file_write: error opening file \"%s\": %d", x->x_buf.s_data, errno); @@ -434,7 +441,7 @@ static void str_fwrite(t_str *x, t_symbol *s, int argc, t_atom *argv) if (0 != (err = ferror(fp))) post ("str file_write: error writing file \"%s\": %d", x->x_buf.s_data, errno); else post ("str file_write: wrote %lu bytes to \"%s\"", limit, x->x_buf.s_data); - fclose(fp); + sys_fclose(fp); return; } diff --git a/externals/mrpeach/tabfind/tabfind.c b/externals/mrpeach/tabfind/tabfind.c index b0a6502ae..87dd197b2 100644 --- a/externals/mrpeach/tabfind/tabfind.c +++ b/externals/mrpeach/tabfind/tabfind.c @@ -16,7 +16,7 @@ typedef struct _tabfind { t_object x_obj; t_symbol *x_arrayname; - t_int x_nth; /* which match to find */ + int x_nth; /* which match to find */ } t_tabfind; static void tabfind_bang(t_tabfind *x); @@ -51,7 +51,7 @@ static void tabfind_list(t_tabfind *x, t_symbol *s, int argc, t_atom *argv) t_float *vec; #endif int n, count = 0; - int i, j; + int i; /* first check the list for floatness... */ for (i = 0; i < argc; ++i) diff --git a/externals/mrpeach/which/which-help.pd b/externals/mrpeach/which/which-help.pd index 21e19bebb..bfacf455d 100644 --- a/externals/mrpeach/which/which-help.pd +++ b/externals/mrpeach/which/which-help.pd @@ -1,4 +1,4 @@ -#N canvas 1 53 569 267 10; +#N canvas 354 468 693 285 10; #X obj 129 170 which tcpclient; #X obj 9 35 bng 15 250 50 0 empty empty output_path_to_object 17 7 0 10 -4034 -257985 -1; @@ -6,15 +6,14 @@ #X obj 57 56 bng 15 250 50 0 empty empty set_object_name 17 7 0 10 -4034 -257985 -1; #X msg 78 102 set tabdump; -#X symbolatom 129 193 64 0 0 0 - - -; +#X symbolatom 129 193 64 0 0 0 - - -, f 64; #X obj 57 81 symbol Gem; #X msg 120 144 expr; #X msg 99 123 counter; -#X text 156 101 set object name; +#X text 165 101 set object name; #X text 155 122 set object name and output path; -#X text 227 169 argument is object name; -#X text 130 222 2009/03/03 Martin Peach; -#N canvas 457 202 494 344 META 0; +#X text 245 169 argument is object name; +#N canvas 334 661 494 344 META 0; #X text 12 125 HELP_PATCH_AUTHORS "pd meta" information added by Jonathan Wilkes for Pd version 0.42.; #X text 12 25 LICENSE GPL v2 or later; @@ -24,6 +23,7 @@ Wilkes for Pd version 0.42.; #X text 12 65 INLET_0 anything set; #X text 12 85 OUTLET_0 symbol; #X restore 515 236 pd META; +#X text 130 222 2016/08/26 Martin Peach; #X connect 0 0 5 0; #X connect 1 0 0 0; #X connect 3 0 6 0; diff --git a/externals/mrpeach/which/which.c b/externals/mrpeach/which/which.c index ae9930253..0559d11f5 100644 --- a/externals/mrpeach/which/which.c +++ b/externals/mrpeach/which/which.c @@ -81,7 +81,7 @@ static void which_any(t_which *x, t_symbol *s, int argc, t_atom *argv) static void which_bang(t_which *x) { - int fd = -1, result = 0; + int fd = -1; char *nameptr = 0; char filename[MAXPDSTRING]; char dirbuf[MAXPDSTRING]; @@ -128,7 +128,7 @@ static void which_bang(t_which *x) outlet_symbol(x->x_obj.te_outlet, gensym("not found")); return; } - result = close(fd); + close(fd); //post("which_bang: dirbuf: %s", dirbuf); //post("which_bang: nameptr: %s", nameptr); /* rebuild the absolute pathname */ @@ -157,7 +157,7 @@ static void *which_new(t_symbol *s, int argc, t_atom *argv) void which_setup(void) { which_class = class_new(gensym("which"), (t_newmethod)which_new, - 0, sizeof(t_which), 0, A_DEFSYM, 0); + 0, sizeof(t_which), 0, A_GIMME, 0); class_addbang(which_class, (t_method)which_bang); class_addsymbol(which_class, (t_method)which_symbol); class_addanything(which_class, (t_method)which_any); diff --git a/externals/mrpeach/xbee/bits.pd b/externals/mrpeach/xbee/bits.pd new file mode 100644 index 000000000..29534aa8b --- /dev/null +++ b/externals/mrpeach/xbee/bits.pd @@ -0,0 +1,100 @@ +#N canvas 218 231 1058 225 10; +#X obj 37 29 inlet; +#X obj 37 159 outlet; +#X obj 37 77 & 32768; +#X obj 87 77 & 16384; +#X obj 137 77 & 8192; +#X obj 187 77 & 4096; +#X obj 237 77 & 2048; +#X obj 287 77 & 1024; +#X obj 337 77 & 512; +#X obj 387 77 & 256; +#X obj 437 77 & 128; +#X obj 487 77 & 64; +#X obj 537 77 & 32; +#X obj 587 77 & 16; +#X obj 637 77 & 8; +#X obj 687 77 & 4; +#X obj 737 77 & 2; +#X obj 787 77 & 1; +#X text 837 84 Martin Peach 2013_02_21; +#X obj 37 118 != 0; +#X obj 87 159 outlet; +#X obj 87 118 != 0; +#X obj 137 159 outlet; +#X obj 137 118 != 0; +#X obj 187 159 outlet; +#X obj 187 118 != 0; +#X obj 237 159 outlet; +#X obj 237 118 != 0; +#X obj 287 159 outlet; +#X obj 287 118 != 0; +#X obj 337 159 outlet; +#X obj 337 118 != 0; +#X obj 387 159 outlet; +#X obj 387 118 != 0; +#X obj 437 159 outlet; +#X obj 437 118 != 0; +#X obj 487 159 outlet; +#X obj 487 118 != 0; +#X obj 537 159 outlet; +#X obj 537 118 != 0; +#X obj 587 159 outlet; +#X obj 587 118 != 0; +#X obj 637 159 outlet; +#X obj 637 118 != 0; +#X obj 687 159 outlet; +#X obj 687 118 != 0; +#X obj 737 159 outlet; +#X obj 737 118 != 0; +#X obj 787 159 outlet; +#X obj 787 118 != 0; +#X text 104 30 [bits] outputs up to 16 bits of a number; +#X connect 0 0 2 0; +#X connect 0 0 3 0; +#X connect 0 0 4 0; +#X connect 0 0 5 0; +#X connect 0 0 6 0; +#X connect 0 0 7 0; +#X connect 0 0 8 0; +#X connect 0 0 9 0; +#X connect 0 0 10 0; +#X connect 0 0 11 0; +#X connect 0 0 12 0; +#X connect 0 0 13 0; +#X connect 0 0 14 0; +#X connect 0 0 15 0; +#X connect 0 0 16 0; +#X connect 0 0 17 0; +#X connect 2 0 19 0; +#X connect 3 0 21 0; +#X connect 4 0 23 0; +#X connect 5 0 25 0; +#X connect 6 0 27 0; +#X connect 7 0 29 0; +#X connect 8 0 31 0; +#X connect 9 0 33 0; +#X connect 10 0 35 0; +#X connect 11 0 37 0; +#X connect 12 0 39 0; +#X connect 13 0 41 0; +#X connect 14 0 43 0; +#X connect 15 0 45 0; +#X connect 16 0 47 0; +#X connect 17 0 49 0; +#X connect 19 0 1 0; +#X connect 21 0 20 0; +#X connect 23 0 22 0; +#X connect 25 0 24 0; +#X connect 27 0 26 0; +#X connect 29 0 28 0; +#X connect 31 0 30 0; +#X connect 33 0 32 0; +#X connect 35 0 34 0; +#X connect 37 0 36 0; +#X connect 39 0 38 0; +#X connect 41 0 40 0; +#X connect 43 0 42 0; +#X connect 45 0 44 0; +#X connect 47 0 46 0; +#X connect 49 0 48 0; diff --git a/externals/mrpeach/xbee/packxbee-example.pd b/externals/mrpeach/xbee/packxbee-example.pd new file mode 100644 index 000000000..0efed5944 --- /dev/null +++ b/externals/mrpeach/xbee/packxbee-example.pd @@ -0,0 +1,132 @@ +#N canvas 300 169 770 718 10; +#X text 84 159 data packet: 64-bit_destination 16-bit_destination broadcast_radius +options data; +#X obj 80 115 hsl 128 15 0 127 0 0 empty empty empty -2 -8 0 10 -262144 +-1 -1 5800 0; +#X obj 77 134 nbx 5 14 -1e+37 1e+37 0 0 empty empty empty 0 -8 0 10 +-262144 -1 -1 58 256; +#X obj 77 10 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1 +; +#X obj 77 247 packxbee 2; +#X msg 49 309 devices; +#X obj 77 354 comport 4 9600; +#X msg 6 266 info; +#X msg 28 288 open 4; +#X obj 77 424 print data; +#X obj 77 396 unpackxbee 2; +#X obj 77 30 metro 500; +#X obj 77 58 random 32; +#X obj 77 88 + 32; +#X floatatom 146 470 5 0 0 0 - - -; +#X floatatom 167 490 5 0 0 0 - - -; +#X symbolatom 188 510 10 0 0 0 - - -; +#X floatatom 209 530 5 0 0 0 - - -; +#X floatatom 230 550 5 0 0 0 - - -; +#X obj 590 470 print other_status; +#X floatatom 251 571 5 0 0 0 - - -; +#X text 109 489 packet_#; +#X text 23 509 destination 16-bit address; +#X text 103 529 transmit_retries; +#X text 131 549 delivery_status; +#X obj 146 448 unpack 0 0 s 0 0 0; +#X text 146 570 discovery_status; +#X floatatom 128 8 10 0 0 0 - - -; +#X floatatom 294 597 5 0 0 0 - - -; +#X floatatom 317 618 5 0 0 0 - - -; +#X symbolatom 340 638 20 0 0 0 - - -; +#X floatatom 387 679 5 0 0 0 - - -; +#X text 259 617 packet_#; +#X symbolatom 363 658 10 0 0 0 - - -; +#X text 195 637 sender's 64-bit address; +#X text 217 657 sender's 16-bit address; +#X obj 294 448 unpack 0 0 s s 0; +#X text 288 678 receive options; +#X text 46 469 frame_type (139); +#X text 194 596 frame_type (144); +#X msg 18 171 AT AI; +#X obj 146 424 route ZigBee_Transmit_Status ZigBee_Receive_Packet; +#X obj 443 448 route AT_Command_Response; +#X floatatom 443 492 5 0 0 0 - - -; +#X floatatom 462 512 5 0 0 0 - - -; +#X text 406 511 packet_#; +#X obj 443 470 unpack 0 0 0 s 0 0 0; +#X floatatom 482 532 5 0 0 0 - - -; +#X symbolatom 501 550 5 0 0 0 - - -; +#X text 434 549 AT command; +#X floatatom 521 572 5 0 0 0 - - -; +#X floatatom 540 592 5 0 0 0 - - -; +#X text 484 591 packet_#; +#X floatatom 560 612 5 0 0 0 - - -; +#X text 494 611 data bytes; +#X text 416 531 data_bytes; +#X text 343 491 frame_type (136); +#X text 476 571 status; +#X msg 304 379 verbosity \$1; +#X obj 304 352 hradio 15 1 0 3 empty empty empty 0 -8 0 10 -4034 -204786 +-1 0; +#X text 188 53 This example transmits a single byte of "data" through +an xbee in API mode 2 connected to serial port 4 at 9600 baud.; +#X msg 77 211 TX 0x0013A200406BFD76 0xFA99 0 0 \$1; +#X msg 480 171 TX 0x0013A200406BFEDF 0x1100 0 0 \$1; +#X text 700 172 yellow; +#X text 297 210 green; +#X text 700 148 blue; +#X msg 516 230 verbosity \$1; +#X obj 516 203 hradio 15 1 0 3 empty empty empty 0 -8 0 10 -4034 -204786 +-1 0; +#X text 439 679 Martin Peach 2014_10_29; +#X msg 480 147 TX 0x0013A200406BFE6C 0x9ED2 0 0 \$1; +#X text 700 124 blue; +#X msg 480 123 TX 0x0013A200406BFE6C 0xFFFE 0 0 \$1; +#X text 83 184 The destination xbee 64-bit address and the 16-bit address +must be set first (16-bit address can be 0xFFFE if unknown):; +#X obj 157 375 print comport_status; +#X msg 70 330 ports; +#X text 108 329 <-list available serial ports via outlet 2; +#X text 38 267 <-list current serial port state via outlet 2; +#X text 98 309 <-list available serial ports in console window; +#X connect 1 0 2 0; +#X connect 2 0 61 0; +#X connect 3 0 11 0; +#X connect 4 0 6 0; +#X connect 5 0 6 0; +#X connect 6 0 10 0; +#X connect 6 1 73 0; +#X connect 7 0 6 0; +#X connect 8 0 6 0; +#X connect 10 0 9 0; +#X connect 10 2 41 0; +#X connect 11 0 12 0; +#X connect 12 0 13 0; +#X connect 13 0 1 0; +#X connect 25 0 14 0; +#X connect 25 1 15 0; +#X connect 25 2 16 0; +#X connect 25 3 17 0; +#X connect 25 4 18 0; +#X connect 25 5 20 0; +#X connect 27 0 11 1; +#X connect 36 0 28 0; +#X connect 36 1 29 0; +#X connect 36 2 30 0; +#X connect 36 3 33 0; +#X connect 36 4 31 0; +#X connect 40 0 4 0; +#X connect 41 0 25 0; +#X connect 41 1 36 0; +#X connect 41 2 42 0; +#X connect 42 0 46 0; +#X connect 42 1 19 0; +#X connect 46 0 43 0; +#X connect 46 1 44 0; +#X connect 46 2 47 0; +#X connect 46 3 48 0; +#X connect 46 4 50 0; +#X connect 46 5 51 0; +#X connect 46 6 53 0; +#X connect 58 0 10 0; +#X connect 59 0 58 0; +#X connect 61 0 4 0; +#X connect 66 0 4 0; +#X connect 67 0 66 0; +#X connect 74 0 6 0; diff --git a/externals/mrpeach/xbee/packxbee-help.pd b/externals/mrpeach/xbee/packxbee-help.pd index b1fdd3ab1..37e51ee5c 100644 --- a/externals/mrpeach/xbee/packxbee-help.pd +++ b/externals/mrpeach/xbee/packxbee-help.pd @@ -1,211 +1,37 @@ -#N canvas 154 423 1227 436 10; +#N canvas 468 125 626 764 10; #X declare -lib mrpeach; -#X msg 80 53 AT DH 0x0013A200; -#X text 193 52 set upper 32 bits of destination address; -#X msg 103 76 AT DL 0x407694DB; -#X msg 128 101 AT MY; -#X text 80 9 get upper 32 bits of destination address; -#X text 97 31 get loweer 32 bits of destination address; -#X msg 37 10 AT DH; -#X msg 60 33 AT DL; -#X msg 148 121 AT MP; -#X text 171 99 get our 16-bit address (Read Only); -#X msg 171 144 AT NC; -#X text 210 141 get number of remaining children (Read Only); -#X msg 193 166 AT SH; -#X text 232 163 get serial number high 32 bits (Read Only); -#X text 253 184 get serial number low 32 bits (Read Only); -#X msg 214 187 AT SL; -#X msg 234 207 AT NI diddley; -#X text 321 204 set node identifier string; -#X msg 254 227 AT NI; -#X text 299 225 get node identifier string; -#X text 527 50 prefix hexadecimal parameters with 0x; -#X msg 274 247 AT NP; -#X text 319 245 get maximum payload; -#X msg 294 267 AT DD; -#X text 336 264 get device type identifier; -#X text 191 119 get endpoint parent's 16-bit address (Read Only); -#X msg 328 301 AT CH; -#X text 366 300 get operating channel; -#X msg 348 321 AT ID; -#X text 386 320 get 64-bit PAN ID; -#X text 529 342 set 64-bit PAN ID; -#X msg 390 363 AT ID 0x0; -#X text 458 362 set coordinator chosen 64-bit PAN ID; -#X msg 370 343 AT ID 0xFEEAFEEBFEECFEED; -#X text 210 74 set lower 32 bits of destination address; -#X msg 412 385 AT OP; -#X text 455 383 get operating 64-bit PAN ID; -#X msg 432 405 AT NH; -#X msg 452 425 AT NH 0xFF; -#X text 528 443 set maximum unicast hops (float arg); -#X text 525 423 set maximum unicast hops (symbol arg); -#X text 475 403 get maximum unicast hops (no arg); -#X msg 492 465 AT BH; -#X text 535 463 get maximum broadcastcast hops (no arg); -#X text 585 483 set maximum broadcast hops (symbol arg); -#X msg 512 485 AT BH 0x1E; -#X msg 532 505 AT BH 3; -#X text 585 502 set maximum broadcast hops (float arg); -#X msg 552 525 AT OI; -#X text 595 523 get operating 16-bit PAN ID; -#X msg 472 445 AT NH 2; -#X msg 573 546 AT NT; -#X text 616 544 get node discovery timeout; -#X text 662 564 set node discovery timeout; -#X msg 593 566 AT NT 0xFF; -#X msg 613 586 AT NO; -#X msg 633 606 AT NO 3; -#X text 656 584 get node discovery options; -#X text 684 604 set node discovery options; -#X msg 654 627 AT SC; -#X msg 673 646 AT SC 0xFFFF; -#X text 697 625 get scan channel bitmask; -#X text 754 645 set scan channels; -#X msg 692 665 AT SD; -#X msg 711 684 AT SD 3; -#X text 735 663 get scan duration; -#X text 762 683 set scan duration; -#X text 66 300 get zigbee stack profile; -#X text 94 320 set zigbee stack profile; -#X msg 28 301 AT ZS; -#X msg 47 320 AT ZS 0; -#X msg 68 341 AT NJ; -#X msg 88 361 AT NJ 0xFF; -#X text 106 340 get node join time; -#X text 161 360 set node join time; -#X obj 410 700 s topackxbee; -#X obj 614 688 r topackxbee; -#X msg 108 381 AT JV; -#X text 146 380 get channel verification; -#X text 181 400 set channel verification; -#X msg 128 401 AT JV 1; -#X text 203 437 get power level; -#X msg 165 438 AT PL; -#X msg 185 458 AT PM; -#X text 223 457 get power mode; -#X msg 205 478 AT DB; -#X msg 225 498 AT PP; -#X text 263 497 get peak power dBm; -#X text 243 477 get received signal strength -dBm; -#X text 283 517 get API mode; -#X msg 245 518 AT AP; -#X msg 325 598 AT AO; -#X text 363 597 get API options; -#X msg 345 618 AT BD; -#X text 383 617 get interface data rate; -#X msg 365 638 AT NB; -#X text 403 637 get interface parity; -#X msg 385 658 AT SB; -#X text 423 657 get interface stop bits; -#X msg 405 678 AT RO; -#X text 443 677 get packetization timeout; -#X obj 1080 736 s topackxbee; -#X msg 954 593 AT D7; -#X msg 936 575 AT D6; -#X msg 708 347 AT IR; -#X text 746 346 get IO sample rate; -#X msg 728 367 AT IC; -#X text 766 366 get IO digital change detection; -#X msg 748 387 AT P0; -#X text 786 386 get PWM0 function; -#X msg 768 407 AT P1; -#X text 806 406 get PWM1 function; -#X msg 788 427 AT P2; -#X text 826 426 get PWM2 function; -#X msg 808 447 AT P3; -#X text 846 446 get PWM3 function; -#X msg 828 467 AT D0; -#X text 872 466 get AD0/DIO0 function; -#X msg 846 485 AT D1; -#X msg 864 503 AT D2; -#X text 908 502 get AD2/DIO2 function; -#X text 890 484 get AD1/DIO1 function; -#X msg 882 521 AT D3; -#X msg 900 539 AT D4; -#X msg 918 557 AT D5; -#X text 926 520 get AD3/DIO3 function; -#X text 944 538 get DIO4 function; -#X text 962 556 get DIO5 function; -#X text 974 574 get DIO6 configuration; -#X text 992 592 get DIO7 configuration; -#X msg 972 611 AT D8; -#X text 1010 610 get DIO8 configuration; -#X msg 991 630 AT LT; -#X text 1026 628 get Associate LED blink time 10ms; -#X msg 1009 648 AT PR; -#X text 1044 646 get pullup resistors; -#X text 1067 664 get supply voltage 1200/1024mV; -#X msg 1028 667 AT %V; -#X msg 1048 687 AT V+; -#X text 1087 684 get supply voltage threshold 1200/1024mV; -#X msg 1068 707 AT TP; -#X text 1107 704 get temperature C; -#X obj 1275 662 s topackxbee; -#X msg 979 349 AT VR; -#X text 1018 346 get firmware version; -#X msg 999 369 AT HV; -#X text 1038 366 get hardware version; -#X msg 1019 389 AT AI; -#X text 1058 386 get association indication; -#X msg 1039 409 AT CC; -#X text 1078 406 get AT command sequence character; -#X msg 1069 439 AT ND; -#X text 1108 436 node discover; -#X text 1179 459 resolve destination node; -#X msg 1109 479 AT IS; -#X msg 1129 499 AT 1S; -#X text 1157 477 force sample; -#X text 1167 497 force xbee sample; -#X msg 143 705 devices; -#X msg 11 546 API 1; -#X msg 33 568 API 2; -#X obj 84 636 s topackxbee; -#X text 50 545 set API mode 1; -#X text 74 569 set API mode 2 (escaped characters); -#X text 55 583 mode 2 is the default setting; -#X text 314 537 set API mode; -#X msg 265 538 AT AP 1; -#X text 334 557 set API mode; -#X msg 285 558 AT AP 2; -#X msg 1162 532 AT AC; -#X text 1202 530 apply changes; -#X msg 1182 552 AT WR; -#X text 1222 550 write parameters to non-volatile memory; -#X msg 1202 572 AT RE; -#X text 1242 570 restore defaults; -#X msg 1222 592 AT FR; -#X text 1262 590 software reset; -#X msg 1242 612 AT NR; -#X text 1282 610 network reset; -#X msg 1262 632 AT CB 1; -#X text 1312 630 commisioning pushbutton; -#X text 1115 515 ***DANGEROUS***; -#X text 14 704 list available ports; -#X obj 792 322 s topackxbee; -#X text 640 79 queue set interface data rate; -#X msg 566 79 ATQ BD 7; -#X msg 183 652 baud 115200; -#X msg 207 676 baud 9600; -#X text 660 99 queue set interface data rate; -#X msg 586 99 ATQ BD 3; -#X msg 150 751 verbosity \$1; -#X obj 96 736 hradio 15 1 0 3 empty empty verbosity 0 -8 0 10 -4034 +#X obj 400 56 cnv 15 150 160 empty empty empty 20 12 0 14 -232576 -66577 +0; +#X obj -15 8 cnv 15 400 280 empty empty empty 20 12 0 14 -232576 -66577 +0; +#X obj -15 290 cnv 15 600 240 empty empty empty 20 12 0 14 -204786 +-66577 0; +#X obj -15 533 cnv 15 600 200 empty empty empty 20 12 0 14 -262130 +-66577 0; +#X obj 269 664 cnv 15 300 25 empty empty unpackxbee: 1 12 0 14 -257985 +-159808 0; +#X obj 74 181 cnv 15 300 25 empty empty packxbee: 1 12 0 14 -159808 +-257985 0; +#X obj 119 134 r topackxbee; +#X msg 251 301 devices; +#X msg -1 14 API 1; +#X msg 21 36 API 2; +#X text 38 13 set API mode 1; +#X text 62 37 set API mode 2 (escaped characters); +#X text 43 51 mode 2 is the default setting; +#X msg 326 376 baud 115200; +#X msg 350 400 baud 9600; +#X msg 280 570 verbosity \$1; +#X obj 280 549 hradio 15 1 0 3 empty empty verbosity 0 -8 0 10 -4034 -1 -1 0; -#X msg 713 226 verbosity \$1; -#X obj 659 211 hradio 15 1 0 3 empty empty verbosity 0 -8 0 10 -4034 --1 -1 2; -#X msg 656 169 TX 0x0013A200406ADE1E 0x79D6 0 0 64; -#X obj 237 742 t f f; -#X obj 237 796 print data; -#N canvas 43 599 1232 329 status 1; +#X obj 360 446 t f f; +#X obj 360 695 print data; +#N canvas 23 645 1232 329 status 0; #X obj 73 16 inlet; #X floatatom 184 218 5 0 0 0 - - -; #X obj 254 99 print unpack5; #X obj 73 46 route AT_Command_Response; #X obj 73 82 list split 3; -#X obj 184 142 route ND; #X obj 184 120 list trim; #X symbolatom 201 234 7 0 0 0 - - -; #X symbolatom 219 251 20 0 0 0 - - -; @@ -306,7 +132,7 @@ #X text 983 280 data length; #X text 991 256 status; #X obj 936 124 unpack 0 0 s s s 0 0; -#X obj 229 162 print AT_response; +#X obj 247 167 print AT_response; #X text 948 192 addr16; #X obj 1101 160 select 0 1 2 3 4; #X symbolatom 1101 360 32 0 0 0 - - -; @@ -316,269 +142,622 @@ #X msg 1138 226 set Invalid_Command; #X msg 1157 246 set Invalid_Parameter; #X msg 1175 269 set Transmission_Failed; +#X obj 184 142 route ND SL; +#X obj 61 309 print SL; #X connect 0 0 3 0; #X connect 3 0 4 0; -#X connect 3 1 19 0; -#X connect 4 0 9 0; -#X connect 4 1 6 0; +#X connect 3 1 18 0; +#X connect 4 0 8 0; +#X connect 4 1 5 0; #X connect 4 2 2 0; -#X connect 5 0 36 0; -#X connect 5 1 102 0; -#X connect 6 0 5 0; -#X connect 9 0 10 0; -#X connect 9 1 11 0; -#X connect 9 2 12 0; -#X connect 19 0 45 0; -#X connect 19 1 46 0; -#X connect 36 0 1 0; -#X connect 36 1 7 0; -#X connect 36 2 8 0; -#X connect 36 3 32 0; -#X connect 36 4 33 0; -#X connect 36 5 37 0; -#X connect 36 6 38 0; -#X connect 36 7 34 0; -#X connect 36 8 35 0; -#X connect 45 0 20 0; -#X connect 45 1 21 0; -#X connect 45 2 24 0; -#X connect 45 3 28 0; -#X connect 45 4 27 0; -#X connect 45 4 67 0; -#X connect 45 5 26 0; -#X connect 45 5 81 0; -#X connect 46 0 64 0; -#X connect 46 1 87 0; -#X connect 54 0 60 0; -#X connect 54 0 61 0; -#X connect 54 0 62 0; -#X connect 54 0 63 0; +#X connect 5 0 111 0; +#X connect 8 0 9 0; +#X connect 8 1 10 0; +#X connect 8 2 11 0; +#X connect 18 0 44 0; +#X connect 18 1 45 0; +#X connect 35 0 1 0; +#X connect 35 1 6 0; +#X connect 35 2 7 0; +#X connect 35 3 31 0; +#X connect 35 4 32 0; +#X connect 35 5 36 0; +#X connect 35 6 37 0; +#X connect 35 7 33 0; +#X connect 35 8 34 0; +#X connect 44 0 19 0; +#X connect 44 1 20 0; +#X connect 44 2 23 0; +#X connect 44 3 27 0; +#X connect 44 4 26 0; +#X connect 44 4 66 0; +#X connect 44 5 25 0; +#X connect 44 5 80 0; +#X connect 45 0 63 0; +#X connect 45 1 86 0; +#X connect 53 0 59 0; +#X connect 53 0 60 0; +#X connect 53 0 61 0; +#X connect 53 0 62 0; +#X connect 59 0 55 0; #X connect 60 0 56 0; #X connect 61 0 57 0; #X connect 62 0 58 0; -#X connect 63 0 59 0; -#X connect 64 0 52 0; -#X connect 64 1 65 0; -#X connect 64 2 49 0; -#X connect 64 3 48 0; -#X connect 64 4 54 0; -#X connect 67 0 69 0; -#X connect 67 1 71 0; -#X connect 67 2 73 0; -#X connect 67 3 72 0; -#X connect 67 4 74 0; -#X connect 67 5 75 0; -#X connect 67 6 76 0; -#X connect 67 7 77 0; -#X connect 67 8 70 0; -#X connect 69 0 68 0; -#X connect 70 0 68 0; -#X connect 71 0 68 0; -#X connect 72 0 68 0; -#X connect 73 0 68 0; -#X connect 74 0 68 0; -#X connect 75 0 68 0; -#X connect 76 0 68 0; -#X connect 77 0 68 0; -#X connect 80 0 79 0; -#X connect 81 0 82 0; -#X connect 81 1 83 0; -#X connect 81 2 84 0; -#X connect 81 3 85 0; -#X connect 81 4 80 0; -#X connect 82 0 79 0; -#X connect 83 0 79 0; -#X connect 84 0 79 0; -#X connect 85 0 79 0; -#X connect 87 0 101 0; -#X connect 87 1 47 0; -#X connect 101 0 88 0; -#X connect 101 1 89 0; -#X connect 101 2 93 0; -#X connect 101 3 95 0; -#X connect 101 4 96 0; -#X connect 101 5 98 0; -#X connect 101 5 104 0; -#X connect 101 6 92 0; -#X connect 104 0 107 0; -#X connect 104 1 108 0; -#X connect 104 2 109 0; -#X connect 104 3 110 0; -#X connect 104 4 111 0; -#X connect 107 0 105 0; -#X connect 108 0 105 0; -#X connect 109 0 105 0; -#X connect 110 0 105 0; -#X connect 111 0 105 0; -#X restore 317 783 pd status; -#X obj 385 759 spigot; -#X obj 385 781 print raw; -#X obj 418 733 tgl 15 0 empty empty print_raw 17 7 0 10 -4034 -1 -1 -0 1; -#X obj 715 780 print packed; -#X obj 715 754 spigot; -#X obj 748 730 tgl 15 0 empty empty print_packed 17 7 0 10 -4034 -1 +#X connect 63 0 51 0; +#X connect 63 1 64 0; +#X connect 63 2 48 0; +#X connect 63 3 47 0; +#X connect 63 4 53 0; +#X connect 66 0 68 0; +#X connect 66 1 70 0; +#X connect 66 2 72 0; +#X connect 66 3 71 0; +#X connect 66 4 73 0; +#X connect 66 5 74 0; +#X connect 66 6 75 0; +#X connect 66 7 76 0; +#X connect 66 8 69 0; +#X connect 68 0 67 0; +#X connect 69 0 67 0; +#X connect 70 0 67 0; +#X connect 71 0 67 0; +#X connect 72 0 67 0; +#X connect 73 0 67 0; +#X connect 74 0 67 0; +#X connect 75 0 67 0; +#X connect 76 0 67 0; +#X connect 79 0 78 0; +#X connect 80 0 81 0; +#X connect 80 1 82 0; +#X connect 80 2 83 0; +#X connect 80 3 84 0; +#X connect 80 4 79 0; +#X connect 81 0 78 0; +#X connect 82 0 78 0; +#X connect 83 0 78 0; +#X connect 84 0 78 0; +#X connect 86 0 100 0; +#X connect 86 1 46 0; +#X connect 100 0 87 0; +#X connect 100 1 88 0; +#X connect 100 2 92 0; +#X connect 100 3 94 0; +#X connect 100 4 95 0; +#X connect 100 5 97 0; +#X connect 100 5 103 0; +#X connect 100 6 91 0; +#X connect 103 0 106 0; +#X connect 103 1 107 0; +#X connect 103 2 108 0; +#X connect 103 3 109 0; +#X connect 103 4 110 0; +#X connect 106 0 104 0; +#X connect 107 0 104 0; +#X connect 108 0 104 0; +#X connect 109 0 104 0; +#X connect 110 0 104 0; +#X connect 111 0 35 0; +#X connect 111 1 112 0; +#X connect 111 2 101 0; +#X restore 429 695 pd status; +#X obj 387 487 spigot; +#X obj 420 467 tgl 15 0 empty empty print_serial_in 17 7 0 10 -4034 +-1 -1 0 1; +#X obj 178 227 spigot; +#X obj 211 208 tgl 15 0 empty empty print_packets 17 7 0 10 -4034 -1 -1 0 1; -#X obj 715 705 packxbee 2; -#X obj 237 768 unpackxbee 2; -#X msg 636 149 TX 0x0013A20040769444 0xFFFE 0 0 1 2 3 4; -#X obj 412 2 import mrpeach; -#X text 891 135 data packet: 64-bit_destination 16-bit_destination +#X obj 153 185 packxbee 2; +#X obj 360 667 unpackxbee 2; +#X obj 491 6 import mrpeach; +#N canvas 24 396 595 216 META 0; +#X text 22 55 LICENSE GPL v2 or later; +#X text 22 153 AUTHOR Martin Peach; +#X text 22 15 KEYWORDS control network wireless xbee; +#X text 22 173 HELP_PATCH_AUTHORS Martin Peach; +#X text 22 35 NAME packxbee; +#X text 22 130 OUTLET_0 list data; +#X text 22 110 INLET_0 API TX TX64 TX16 AT ATQ RAT verbosity; +#X text 22 75 DESCRIPTION [packxbee] builds packets for Series 1 or +2 XBees in API modes 1 or 2; +#X restore 534 26 pd META; +#X msg 291 341 info; +#X msg 271 321 open 4; +#N canvas 501 298 758 479 IO_COMMANDS 0; +#X obj 400 426 s topackxbee; +#X msg 274 283 AT D7; +#X msg 256 265 AT D6; +#X msg 28 37 AT IR; +#X text 66 36 get IO sample rate; +#X msg 48 57 AT IC; +#X text 86 56 get IO digital change detection; +#X msg 68 77 AT P0; +#X text 106 76 get PWM0 function; +#X msg 88 97 AT P1; +#X text 126 96 get PWM1 function; +#X msg 108 117 AT P2; +#X text 146 116 get PWM2 function; +#X msg 128 137 AT P3; +#X text 166 136 get PWM3 function; +#X msg 148 157 AT D0; +#X text 192 156 get AD0/DIO0 function; +#X msg 166 175 AT D1; +#X msg 184 193 AT D2; +#X text 228 192 get AD2/DIO2 function; +#X text 210 174 get AD1/DIO1 function; +#X msg 202 211 AT D3; +#X msg 220 229 AT D4; +#X msg 238 247 AT D5; +#X text 246 210 get AD3/DIO3 function; +#X text 264 228 get DIO4 function; +#X text 282 246 get DIO5 function; +#X text 294 264 get DIO6 configuration; +#X text 312 282 get DIO7 configuration; +#X msg 292 301 AT D8; +#X text 330 300 get DIO8 configuration; +#X msg 311 320 AT LT; +#X text 346 318 get Associate LED blink time 10ms; +#X msg 329 338 AT PR; +#X text 364 336 get pullup resistors; +#X text 387 354 get supply voltage 1200/1024mV; +#X msg 348 357 AT %V; +#X msg 368 377 AT V+; +#X text 407 374 get supply voltage threshold 1200/1024mV; +#X msg 388 397 AT TP; +#X text 427 394 get temperature C; +#X msg 451 213 AT IS; +#X msg 471 233 AT 1S; +#X text 499 211 force sample; +#X text 509 231 force xbee sample; +#X obj 507 286 s topackxbee; +#X connect 1 0 0 0; +#X connect 2 0 0 0; +#X connect 3 0 0 0; +#X connect 5 0 0 0; +#X connect 7 0 0 0; +#X connect 9 0 0 0; +#X connect 11 0 0 0; +#X connect 13 0 0 0; +#X connect 15 0 0 0; +#X connect 17 0 0 0; +#X connect 18 0 0 0; +#X connect 21 0 0 0; +#X connect 22 0 0 0; +#X connect 23 0 0 0; +#X connect 29 0 0 0; +#X connect 31 0 0 0; +#X connect 33 0 0 0; +#X connect 36 0 0 0; +#X connect 37 0 0 0; +#X connect 39 0 0 0; +#X connect 41 0 45 0; +#X connect 42 0 45 0; +#X restore 408 148 pd IO_COMMANDS; +#N canvas 3 90 1158 513 NETWORK_COMMANDS 0; +#X msg 80 53 AT DH 0x0013A200; +#X text 193 52 set upper 32 bits of destination address; +#X msg 103 76 AT DL 0x407694DB; +#X msg 128 101 AT MY; +#X text 80 9 get upper 32 bits of destination address; +#X msg 37 10 AT DH; +#X msg 60 33 AT DL; +#X msg 148 121 AT MP; +#X text 171 99 get our 16-bit address (Read Only); +#X msg 171 144 AT NC; +#X text 210 141 get number of remaining children (Read Only); +#X msg 193 166 AT SH; +#X text 232 163 get serial number high 32 bits (Read Only); +#X text 253 184 get serial number low 32 bits (Read Only); +#X msg 214 187 AT SL; +#X msg 234 207 AT NI diddley; +#X text 321 204 set node identifier string; +#X msg 254 227 AT NI; +#X text 299 225 get node identifier string; +#X msg 274 247 AT NP; +#X text 319 245 get maximum payload; +#X msg 294 267 AT DD; +#X text 336 264 get device type identifier; +#X text 191 119 get endpoint parent's 16-bit address (Read Only); +#X text 210 74 set lower 32 bits of destination address; +#X text 97 31 get lower 32 bits of destination address; +#X obj 497 487 s topackxbee; +#X msg 448 11 AT CH; +#X text 486 10 get operating channel; +#X msg 468 31 AT ID; +#X text 506 30 get 64-bit PAN ID; +#X text 649 52 set 64-bit PAN ID; +#X msg 510 73 AT ID 0x0; +#X text 578 72 set coordinator chosen 64-bit PAN ID; +#X msg 490 53 AT ID 0xFEEAFEEBFEECFEED; +#X msg 532 95 AT OP; +#X text 575 93 get operating 64-bit PAN ID; +#X msg 552 115 AT NH; +#X msg 572 135 AT NH 0xFF; +#X text 648 153 set maximum unicast hops (float arg); +#X text 645 133 set maximum unicast hops (symbol arg); +#X text 595 113 get maximum unicast hops (no arg); +#X msg 612 175 AT BH; +#X text 655 173 get maximum broadcastcast hops (no arg); +#X text 705 193 set maximum broadcast hops (symbol arg); +#X msg 632 195 AT BH 0x1E; +#X msg 652 215 AT BH 3; +#X text 705 212 set maximum broadcast hops (float arg); +#X msg 672 235 AT OI; +#X text 715 233 get operating 16-bit PAN ID; +#X msg 592 155 AT NH 2; +#X msg 693 256 AT NT; +#X text 736 254 get node discovery timeout; +#X text 782 274 set node discovery timeout; +#X msg 713 276 AT NT 0xFF; +#X msg 733 296 AT NO; +#X msg 753 316 AT NO 3; +#X text 776 294 get node discovery options; +#X text 804 314 set node discovery options; +#X msg 774 337 AT SC; +#X msg 793 356 AT SC 0xFFFF; +#X text 817 335 get scan channel bitmask; +#X text 874 355 set scan channels; +#X msg 812 375 AT SD; +#X msg 831 394 AT SD 3; +#X text 855 373 get scan duration; +#X text 882 393 set scan duration; +#X obj 907 487 s topackxbee; +#X text 66 230 get zigbee stack profile; +#X text 94 250 set zigbee stack profile; +#X msg 28 231 AT ZS; +#X msg 47 250 AT ZS 0; +#X msg 68 271 AT NJ; +#X msg 88 291 AT NJ 0xFF; +#X text 106 270 get node join time; +#X text 161 290 set node join time; +#X msg 108 311 AT JV; +#X text 146 310 get channel verification; +#X text 181 330 set channel verification; +#X msg 128 331 AT JV 1; +#X obj 267 487 s topackxbee; +#X msg 429 402 AT AI; +#X text 468 399 get association indication; +#X msg 386 359 AT ND; +#X text 425 356 node discover; +#X text 436 319 resolve destination node; +#X msg 346 319 AT DN IMCA_R1; +#X connect 0 0 26 0; +#X connect 2 0 26 0; +#X connect 3 0 26 0; +#X connect 5 0 26 0; +#X connect 6 0 26 0; +#X connect 7 0 26 0; +#X connect 9 0 26 0; +#X connect 11 0 26 0; +#X connect 14 0 26 0; +#X connect 15 0 26 0; +#X connect 17 0 26 0; +#X connect 19 0 26 0; +#X connect 21 0 26 0; +#X connect 27 0 67 0; +#X connect 29 0 67 0; +#X connect 32 0 67 0; +#X connect 34 0 67 0; +#X connect 35 0 67 0; +#X connect 37 0 67 0; +#X connect 38 0 67 0; +#X connect 42 0 67 0; +#X connect 45 0 67 0; +#X connect 46 0 67 0; +#X connect 48 0 67 0; +#X connect 50 0 67 0; +#X connect 51 0 67 0; +#X connect 54 0 67 0; +#X connect 55 0 67 0; +#X connect 56 0 67 0; +#X connect 59 0 67 0; +#X connect 60 0 67 0; +#X connect 63 0 67 0; +#X connect 64 0 67 0; +#X connect 70 0 80 0; +#X connect 71 0 80 0; +#X connect 72 0 80 0; +#X connect 73 0 80 0; +#X connect 76 0 80 0; +#X connect 79 0 80 0; +#X connect 81 0 26 0; +#X connect 83 0 26 0; +#X connect 86 0 26 0; +#X restore 408 167 pd NETWORK_COMMANDS; +#N canvas 3 90 450 300 RADIO_COMMANDS 0; +#X text 129 52 get power level; +#X msg 91 53 AT PL; +#X msg 111 73 AT PM; +#X text 149 72 get power mode; +#X msg 131 93 AT DB; +#X msg 151 113 AT PP; +#X text 189 112 get peak power dBm; +#X text 169 92 get received signal strength -dBm; +#X obj 187 166 s topackxbee; +#X connect 1 0 8 0; +#X connect 2 0 8 0; +#X connect 4 0 8 0; +#X connect 5 0 8 0; +#X restore 408 129 pd RADIO_COMMANDS; +#N canvas 3 90 675 320 SERIAL_COMMANDS 0; +#X obj 280 290 s topackxbee; +#X text 83 37 get API mode; +#X msg 45 38 AT AP; +#X msg 125 118 AT AO; +#X text 163 117 get API options; +#X msg 155 148 AT BD; +#X text 193 147 get interface data rate; +#X msg 175 168 AT NB; +#X text 213 167 get interface parity; +#X msg 195 188 AT SB; +#X text 233 187 get interface stop bits; +#X msg 215 208 AT RO; +#X text 253 207 get packetization timeout; +#X text 114 57 set API mode; +#X msg 65 58 AT AP 1; +#X text 134 77 set API mode; +#X msg 85 78 AT AP 2; +#X msg 106 99 AT CC; +#X text 145 96 get AT command sequence character; +#X text 440 79 queue set interface data rate; +#X msg 366 79 ATQ BD 7; +#X text 460 99 queue set interface data rate; +#X msg 386 99 ATQ BD 3; +#X obj 490 220 s topackxbee; +#X msg 246 239 AT VR; +#X text 285 236 get firmware version; +#X msg 266 259 AT HV; +#X text 305 256 get hardware version; +#X msg 419 132 AT AC; +#X text 459 130 apply changes; +#X connect 2 0 0 0; +#X connect 3 0 0 0; +#X connect 5 0 0 0; +#X connect 7 0 0 0; +#X connect 9 0 0 0; +#X connect 11 0 0 0; +#X connect 14 0 0 0; +#X connect 16 0 0 0; +#X connect 17 0 0 0; +#X connect 20 0 23 0; +#X connect 22 0 23 0; +#X connect 24 0 0 0; +#X connect 26 0 0 0; +#X connect 28 0 23 0; +#X restore 408 110 pd SERIAL_COMMANDS; +#N canvas 3 90 450 233 DANGEROUS_COMMANDS 0; +#X obj 185 172 s topackxbee; +#X msg 72 42 AT AC; +#X text 112 40 apply changes; +#X msg 92 62 AT WR; +#X text 132 60 write parameters to non-volatile memory; +#X msg 112 82 AT RE; +#X text 152 80 restore defaults; +#X msg 132 102 AT FR; +#X text 172 100 software reset; +#X msg 152 122 AT NR; +#X text 192 120 network reset; +#X msg 172 142 AT CB 1; +#X text 222 140 commisioning pushbutton; +#X text 25 25 ***DANGEROUS***; +#X connect 1 0 0 0; +#X connect 3 0 0 0; +#X connect 5 0 0 0; +#X connect 7 0 0 0; +#X connect 9 0 0 0; +#X connect 11 0 0 0; +#X restore 408 187 pd DANGEROUS_COMMANDS; +#N canvas 368 164 744 407 TRANSMIT_COMMANDS 0; +#X obj 172 292 s topackxbee; +#X msg 79 182 TX 0x0013A20040769444 0xFFFE 0 0 1 2 3 4; +#X obj 60 107 hsl 128 15 0 127 0 0 empty empty empty -2 -8 0 10 -262144 +-1 -1 0 0; +#X obj 57 126 nbx 5 14 -1e+37 1e+37 0 0 empty empty empty 0 -8 0 10 +-262144 -1 -1 0 256; +#X obj 57 84 f; +#X obj 100 84 + 1; +#X obj 144 82 % 128; +#X obj 57 42 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1 +; +#X obj 57 62 metro 2000; +#X text 22 326 (prefix hexadecimal parameters with 0x to force Pd to +see them as symbols); +#X text 314 225 Series 1 data packet: 64-bit_destination options data +; +#X msg 121 224 TX64 0x0013A200406ADE1E 0 255; +#X msg 144 247 TX16 0x79D5 0 255; +#X text 257 248 Series 1 data packet: 16-bit_destination options data +; +#X text 281 151 Series 2 data packet: 64-bit_destination 16-bit_destination broadcast_radius options data; -#X obj 898 97 hsl 128 15 0 127 0 0 empty empty empty -2 -8 0 10 -262144 --1 -1 1900 0; -#X obj 895 116 nbx 5 14 -1e+37 1e+37 0 0 empty empty empty 0 -8 0 10 --262144 -1 -1 19 256; -#X obj 895 74 f; -#X obj 938 74 + 1; -#X obj 1337 160 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 -0 1; -#X obj 982 72 % 128; -#X obj 237 723 comport 4 9600; -#X msg 617 130 TX 0x0013A200406BFE6C 0x51D6 0 0 136 \$1; -#X msg 1337 273 4; -#X msg 1356 253 5; -#X obj 1337 209 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 -1 1; -#X obj 1337 230 sel 0 1; -#X msg 777 290 RAT 0x0013A200406BFE6C 0x51D6 2 D0 \$1; -#X obj 1337 185 metro 200; -#X msg 753 266 RAT 0x0013A200406BFE6C 0x51D6 0 SL; -#X msg 733 246 RAT 0x0013A200406BFE6C 0x51D6 0 SH; -#X obj 895 32 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 -1; -#X obj 895 52 metro 200; -#X text 856 220 remote AT command: 64-bit address \, 16-bit address +#X msg 57 160 TX 0x0013A200406BFE6C 0x9A17 0 0 \$1; +#X msg 100 203 TX 0x0013A200406ADE1E 0x79D6 0 0 64; +#X connect 1 0 0 0; +#X connect 2 0 3 0; +#X connect 3 0 15 0; +#X connect 4 0 5 0; +#X connect 4 0 2 0; +#X connect 5 0 6 0; +#X connect 6 0 4 1; +#X connect 7 0 8 0; +#X connect 8 0 4 0; +#X connect 11 0 0 0; +#X connect 12 0 0 0; +#X connect 15 0 0 0; +#X connect 16 0 0 0; +#X restore 408 70 pd TRANSMIT_COMMANDS; +#X msg 85 100 verbosity \$1; +#X obj 83 79 hradio 15 1 0 3 empty empty verbosity 0 -8 0 10 -4034 +-1 -1 0; +#X obj 58 244 print packet; +#X obj 457 444 print serial_info; +#X text 148 375 set the interface baud rate; +#X text 302 300 (find the one with an xbee connected to it); +#X text 6 300 list available serial ports to console; +#X text 65 320 open a port by number or by name; +#X text 128 340 get current serial status; +#X obj 214 264 spigot; +#X obj 247 245 tgl 15 0 empty empty transmit_packets 17 7 0 10 -4034 +-1 -1 0 1; +#X obj 387 509 print serial_in; +#X obj 249 135 packxbee-example; +#X text -9 113 [packxbee] formats packets for use with xbees in API +modes 1 or 2; +#X text -9 150 [packxbee] outputs lists of bytes that are typically +passed to a [comport] object.; +#X obj 360 427 comport 98 9600; +#X text -10 626 The output of [comport] can be connected to an [unpackxbee] +object to (at least partially) unpack the received packets.; +#N canvas 195 133 741 379 REMOTE_COMMANDS 0; +#X obj 72 25 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1 +; +#X msg 72 138 4; +#X msg 117 138 5; +#X obj 72 74 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1 +; +#X obj 72 95 sel 0 1; +#X obj 72 50 metro 200; +#X msg 223 206 RAT 0x0013A200406BFE6C 0x51D6 0 SL; +#X text 169 123 remote AT command: 64-bit address \, 16-bit address \, options \, command \, parameters; -#X text 1008 290 switch remote IO pin 0 high/low (options = 2 = apply -changes immediately); -#X msg 1089 459 AT DN IMCA_R1; -#X connect 0 0 204 0; -#X connect 2 0 204 0; -#X connect 3 0 204 0; -#X connect 6 0 204 0; -#X connect 7 0 204 0; -#X connect 8 0 204 0; -#X connect 10 0 204 0; -#X connect 12 0 204 0; -#X connect 15 0 204 0; -#X connect 16 0 204 0; -#X connect 18 0 204 0; -#X connect 21 0 204 0; -#X connect 23 0 204 0; -#X connect 26 0 204 0; -#X connect 28 0 204 0; -#X connect 31 0 204 0; -#X connect 33 0 204 0; -#X connect 35 0 204 0; -#X connect 37 0 204 0; -#X connect 38 0 204 0; -#X connect 42 0 204 0; -#X connect 45 0 204 0; -#X connect 46 0 204 0; -#X connect 48 0 204 0; -#X connect 50 0 204 0; -#X connect 51 0 204 0; -#X connect 54 0 204 0; -#X connect 55 0 204 0; -#X connect 56 0 204 0; -#X connect 59 0 204 0; -#X connect 60 0 204 0; -#X connect 63 0 204 0; -#X connect 64 0 204 0; -#X connect 69 0 75 0; -#X connect 70 0 75 0; -#X connect 71 0 75 0; -#X connect 72 0 75 0; -#X connect 76 0 204 0; -#X connect 77 0 75 0; -#X connect 80 0 75 0; -#X connect 82 0 75 0; -#X connect 83 0 75 0; -#X connect 85 0 75 0; -#X connect 86 0 75 0; -#X connect 90 0 75 0; -#X connect 91 0 75 0; -#X connect 93 0 75 0; -#X connect 95 0 75 0; -#X connect 97 0 75 0; -#X connect 99 0 75 0; -#X connect 102 0 101 0; -#X connect 103 0 101 0; -#X connect 104 0 101 0; -#X connect 106 0 101 0; -#X connect 108 0 101 0; -#X connect 110 0 101 0; -#X connect 112 0 101 0; -#X connect 114 0 101 0; -#X connect 116 0 101 0; -#X connect 118 0 101 0; -#X connect 119 0 101 0; -#X connect 122 0 101 0; -#X connect 123 0 101 0; -#X connect 124 0 101 0; -#X connect 130 0 101 0; -#X connect 132 0 101 0; -#X connect 134 0 101 0; -#X connect 137 0 101 0; -#X connect 138 0 101 0; -#X connect 140 0 101 0; -#X connect 143 0 142 0; -#X connect 145 0 142 0; -#X connect 147 0 142 0; -#X connect 149 0 142 0; -#X connect 151 0 142 0; -#X connect 154 0 142 0; -#X connect 155 0 142 0; -#X connect 158 0 215 0; -#X connect 159 0 161 0; -#X connect 160 0 161 0; -#X connect 166 0 75 0; -#X connect 168 0 75 0; -#X connect 169 0 142 0; -#X connect 171 0 142 0; -#X connect 173 0 142 0; -#X connect 175 0 142 0; -#X connect 177 0 142 0; -#X connect 179 0 142 0; -#X connect 185 0 183 0; -#X connect 186 0 215 0; -#X connect 187 0 215 0; -#X connect 189 0 183 0; -#X connect 190 0 205 0; -#X connect 191 0 190 0; -#X connect 192 0 183 0; -#X connect 193 0 192 0; -#X connect 194 0 183 0; -#X connect 195 0 205 0; -#X connect 195 1 198 0; -#X connect 198 0 199 0; -#X connect 200 0 198 1; -#X connect 202 0 201 0; -#X connect 203 0 202 1; -#X connect 204 0 202 0; -#X connect 204 0 215 0; -#X connect 205 0 196 0; -#X connect 205 1 197 0; -#X connect 206 0 183 0; -#X connect 209 0 210 0; -#X connect 210 0 216 0; -#X connect 211 0 212 0; -#X connect 211 0 209 0; -#X connect 212 0 214 0; -#X connect 213 0 222 0; -#X connect 214 0 211 1; -#X connect 215 0 195 0; -#X connect 216 0 183 0; -#X connect 217 0 221 0; -#X connect 218 0 221 0; -#X connect 219 0 220 0; -#X connect 220 0 217 0; -#X connect 220 1 218 0; -#X connect 221 0 183 0; -#X connect 222 0 219 0; -#X connect 223 0 183 0; -#X connect 224 0 183 0; -#X connect 225 0 226 0; -#X connect 226 0 211 0; -#X connect 229 0 142 0; +#X obj 294 294 s topackxbee; +#X msg 171 154 RAT 0x0013A200406BFE6C 0x9A17 2 P1 \$1; +#X msg 246 230 RAT 0x0013A200406BFE6C 0x9A17 2 D0 4; +#X text 324 250 switch remote IO pin 0 low (options = 2 = apply changes +immediately); +#X text 203 169 set PWM1/DIO11 (pin 7) on remote xbee to digital out +high or low immediately; +#X msg 29 263 RAT 0x0013A200406BFE6C 0x9A17 0; +#X obj 29 285 list append; +#X obj 29 306 list trim; +#X obj 29 232 t b a; +#X msg 29 195 IS; +#X text 56 194 force sample; +#X obj 28 326 s topackxbee; +#X connect 0 0 5 0; +#X connect 1 0 9 0; +#X connect 2 0 9 0; +#X connect 3 0 4 0; +#X connect 4 0 1 0; +#X connect 4 1 2 0; +#X connect 5 0 3 0; +#X connect 6 0 8 0; +#X connect 9 0 8 0; +#X connect 10 0 8 0; +#X connect 13 0 14 0; +#X connect 14 0 15 0; +#X connect 15 0 19 0; +#X connect 16 0 13 0; +#X connect 16 1 14 1; +#X connect 17 0 16 0; +#X restore 408 90 pd REMOTE_COMMANDS; +#N canvas 235 602 596 319 sample_frame 0; +#X obj 62 53 inlet; +#X obj 62 106 route D0 D1 D2 D3 D4 D5 D10 D11 D12 A0 A1 A2 A3 A7; +#X obj 56 136 cnv 15 300 50 empty empty Digital_Inputs 20 12 0 14 -204786 +-13381 0; +#X obj 56 187 cnv 15 400 90 empty empty Analog_Inputs 20 12 0 14 -232576 +-45076 0; +#X obj 59 220 nbx 5 14 -1e+37 1e+37 0 0 empty empty A0 40 8 0 10 -204800 +-13330 -159808 0 256; +#X obj 119 220 nbx 5 14 -1e+37 1e+37 0 0 empty empty A1 40 8 0 10 -204800 +-13330 -159808 0 256; +#X obj 179 220 nbx 5 14 -1e+37 1e+37 0 0 empty empty A2 40 8 0 10 -204800 +-13330 -159808 0 256; +#X obj 239 220 nbx 5 14 -1e+37 1e+37 0 0 empty empty A3 40 8 0 10 -204800 +-13330 -159808 0 256; +#X obj 299 220 nbx 5 14 -1e+37 1e+37 0 0 empty empty V+ 40 8 0 10 -204800 +-13330 -159808 0 256; +#X obj 62 162 nbx 2 14 -1e+37 1e+37 0 0 empty empty D0 8 20 0 10 -4034 +-1 -258113 0 256; +#X obj 102 162 nbx 2 14 -1e+37 1e+37 0 0 empty empty D1 8 20 0 10 -4034 +-1 -258113 0 256; +#X obj 132 162 nbx 2 14 -1e+37 1e+37 0 0 empty empty D2 8 20 0 10 -4034 +-1 -258113 0 256; +#X obj 162 162 nbx 2 14 -1e+37 1e+37 0 0 empty empty D3 8 20 0 10 -4034 +-1 -258113 0 256; +#X obj 192 162 nbx 2 14 -1e+37 1e+37 0 0 empty empty D4 8 20 0 10 -4034 +-1 -258113 0 256; +#X obj 222 162 nbx 2 14 -1e+37 1e+37 0 0 empty empty D5 8 20 0 10 -4034 +-1 -258113 0 256; +#X obj 252 162 nbx 2 14 -1e+37 1e+37 0 0 empty empty P0 8 20 0 10 -4034 +-1 -258113 0 256; +#X obj 282 162 nbx 2 14 -1e+37 1e+37 0 0 empty empty P1 8 20 0 10 -4034 +-1 -258113 0 256; +#X obj 312 162 nbx 2 14 -1e+37 1e+37 0 0 empty empty P2 8 20 0 10 -4034 +-1 -258113 0 256; +#X obj 59 259 nbx 5 14 -1e+37 1e+37 0 0 empty empty A0_mV 40 8 0 10 +-204800 -13330 -159808 0 256; +#X obj 59 239 * 1.17302; +#X obj 139 259 nbx 5 14 -1e+37 1e+37 0 0 empty empty A1_mV 40 8 0 10 +-204800 -13330 -159808 0 256; +#X obj 139 239 * 1.17302; +#X obj 219 259 nbx 5 14 -1e+37 1e+37 0 0 empty empty A2_mV 40 8 0 10 +-204800 -13330 -159808 0 256; +#X obj 219 239 * 1.17302; +#X obj 299 259 nbx 5 14 -1e+37 1e+37 0 0 empty empty A3_mV 40 8 0 10 +-204800 -13330 -159808 0 256; +#X obj 299 239 * 1.17302; +#X obj 379 259 nbx 5 14 -1e+37 1e+37 0 0 empty empty V+_mV 40 8 0 10 +-204800 -13330 -159808 0 256; +#X obj 379 239 * 1.17302; +#X obj 62 78 list trim; +#X obj 359 130 print more_sample_frame_stuff; +#X connect 0 0 28 0; +#X connect 1 0 9 0; +#X connect 1 1 10 0; +#X connect 1 2 11 0; +#X connect 1 3 12 0; +#X connect 1 4 13 0; +#X connect 1 5 14 0; +#X connect 1 6 15 0; +#X connect 1 7 16 0; +#X connect 1 8 17 0; +#X connect 1 9 4 0; +#X connect 1 9 19 0; +#X connect 1 10 5 0; +#X connect 1 10 21 0; +#X connect 1 11 6 0; +#X connect 1 11 23 0; +#X connect 1 12 7 0; +#X connect 1 12 25 0; +#X connect 1 13 8 0; +#X connect 1 13 27 0; +#X connect 1 14 29 0; +#X connect 19 0 18 0; +#X connect 21 0 20 0; +#X connect 23 0 22 0; +#X connect 25 0 24 0; +#X connect 27 0 26 0; +#X connect 28 0 1 0; +#X restore 394 714 pd sample_frame; +#X obj 401 222 cnv 15 150 60 empty empty empty 20 12 0 14 -261234 -66577 +0; +#X text 404 221 remote xbee pin control:; +#X obj 426 251 xbeeio; +#X connect 6 0 24 0; +#X connect 7 0 51 0; +#X connect 8 0 24 0; +#X connect 9 0 24 0; +#X connect 13 0 51 0; +#X connect 14 0 51 0; +#X connect 15 0 25 0; +#X connect 16 0 15 0; +#X connect 17 0 25 0; +#X connect 17 1 20 0; +#X connect 20 0 47 0; +#X connect 21 0 20 1; +#X connect 22 0 38 0; +#X connect 23 0 22 1; +#X connect 24 0 22 0; +#X connect 24 0 45 0; +#X connect 25 0 18 0; +#X connect 25 1 54 0; +#X connect 25 2 19 0; +#X connect 28 0 51 0; +#X connect 29 0 51 0; +#X connect 36 0 24 0; +#X connect 37 0 36 0; +#X connect 45 0 51 0; +#X connect 46 0 45 1; +#X connect 51 0 17 0; +#X connect 51 1 39 0; diff --git a/externals/mrpeach/xbee/packxbee.c b/externals/mrpeach/xbee/packxbee.c index 33a020197..cd831790b 100644 --- a/externals/mrpeach/xbee/packxbee.c +++ b/externals/mrpeach/xbee/packxbee.c @@ -3,6 +3,7 @@ /* Started by Martin Peach 20110731 */ /* Information taken from "XBee®/XBee-PRO® ZB RF Modules" (document 90000976_G, 11/15/2010)*/ /* by Digi International Inc. http://www.digi.com */ +/* Series 1 info from "XBee®/XBee-PRO® RF Modules" (document 90000982_L 4/30/2013) */ #include <stdio.h> #include <string.h> @@ -29,6 +30,8 @@ static void packxbee_AT(t_packxbee *x, t_symbol *s, int argc, t_atom *argv); static void packxbee_RAT(t_packxbee *x, t_symbol *s, int argc, t_atom *argv); static void packxbee_ATQ(t_packxbee *x, t_symbol *s, int argc, t_atom *argv); static void packxbee_TX(t_packxbee *x, t_symbol *s, int argc, t_atom *argv); +static void packxbee_TX64(t_packxbee *x, t_symbol *s, int argc, t_atom *argv); +static void packxbee_TX16(t_packxbee *x, t_symbol *s, int argc, t_atom *argv); static void packxbee_pack_remote_frame(t_packxbee *x, t_symbol *s, int argc, t_atom *argv); static void packxbee_pack_frame(t_packxbee *x, t_symbol *s, int argc, t_atom *argv); static void packxbee_API(t_packxbee *x, t_float api); @@ -94,7 +97,7 @@ static int packxbee_outbuf_add(t_packxbee *x, int index, unsigned char val) return i; } -/* send a packet given a 64-bit address, a 16-bit address, broadcast radius, options, followed by raw data */ +/* send a packet given a 64-bit address, a 16-bit address, broadcast radius, options, followed by raw data (Series2 ZB only) */ static void packxbee_TX(t_packxbee *x, t_symbol *s, int argc, t_atom *argv) { unsigned char floatstring[256]; /* longer than the longest hex number with each character escaped plus the header and checksum overhead */ @@ -164,11 +167,11 @@ static void packxbee_TX(t_packxbee *x, t_symbol *s, int argc, t_atom *argv) return; } f = argv[2].a_w.w_float; - if (x->x_verbosity > 1) post("packxbee_TX float parameter %f", f); + if (x->x_verbosity > 1) post("packxbee_TX: float parameter %f", f); d = ((unsigned int)f)&0x0FF; if (f != d) { - post ("packxbee_TX third argument not a positive integer from 0 to 255"); + error ("packxbee_TX: third argument is not a positive integer from 0 to 255"); return; } else broadcast_radius = d; @@ -181,11 +184,11 @@ static void packxbee_TX(t_packxbee *x, t_symbol *s, int argc, t_atom *argv) return; } f = argv[3].a_w.w_float; - if (x->x_verbosity > 1) post("packxbee_TX float parameter %f", f); + if (x->x_verbosity > 1) post("packxbee_TX: float parameter %f", f); d = ((unsigned int)f)&0x0FF; if (f != d) { - post ("packxbee_TX fourth argument not a positive integer from 0 to 255"); + error ("packxbee_TX: fourth argument is not a positive integer from 0 to 255"); return; } else options = d; @@ -234,11 +237,11 @@ static void packxbee_TX(t_packxbee *x, t_symbol *s, int argc, t_atom *argv) if (A_FLOAT == argv[k].a_type) { f = argv[k].a_w.w_float; - if (x->x_verbosity > 1) post("packxbee_TX float parameter %f", f); + if (x->x_verbosity > 1) post("packxbee_TX: float parameter %f", f); d = ((unsigned int)f)&0x0FF; if (f != d) { - post ("packxbee_TX %dth argument not a positive integer from 0 to 255", k+1); + error ("packxbee_TX: argument %d is not a positive integer from 0 to 255", k+1); return; } floatstring[i++] = d; @@ -246,14 +249,269 @@ static void packxbee_TX(t_packxbee *x, t_symbol *s, int argc, t_atom *argv) } else if (A_SYMBOL == argv[k].a_type) { - if (x->x_verbosity > 1) post("packxbee_TX symbol parameter %s", argv[k].a_w.w_symbol->s_name); + if (x->x_verbosity > 1) post("packxbee_TX: symbol parameter %s", argv[k].a_w.w_symbol->s_name); j = i; i += sprintf((char *)&floatstring[i], "%s", argv[k].a_w.w_symbol->s_name); for (;j < i; ++j) checksum -= floatstring[j]; } else { - error("packxbee_TX %dth argument neither a float nor a symbol", k); + error("packxbee_TX: argument %d is not a float or a symbol", k+1); + return; + } + } + length = i-3; + floatstring[LENGTH_LSB_INDEX] = length & 0x0FF; + floatstring[LENGTH_MSB_INDEX] = length >> 8; + floatstring[i++] = checksum; + k = j = 0; /* j indexes the outbuf, k indexes the floatbuf, i is the length of floatbuf */ + for (k = 0; k < i; ++k) j = packxbee_outbuf_add(x, j, floatstring[k]); + outlet_list(x->x_listout, &s_list, j, x->x_outbuf); + if(x->x_verbosity > 1) + { + for (k = 0; k < j; ++k) + { + c = (unsigned char)atom_getfloat(&x->x_outbuf[k]); + post("buf[%d]: %d [0x%02X]", k, c, c); + } + } +} + +/* send a packet given a 64-bit address, options, followed by raw data (Series1 only) */ +static void packxbee_TX64(t_packxbee *x, t_symbol *s, int argc, t_atom *argv) +{ + unsigned char floatstring[256]; /* longer than the longest hex number with each character escaped plus the header and checksum overhead */ + unsigned long long dest64; + int result; + char checksum = 0xFF; + unsigned char options; + t_float f; + int d, i, j, k; + int length = 0; + unsigned char c; + + if (argc < 3) + { + error("packxbee_TX64: not enough parameters"); + return; + } + /* first arg is dest64, a symbol starting with "0x" */ + if (argv[0].a_type != A_SYMBOL) + { + error("packxbee_TX64: first argument is not a symbol"); + return; + } + if ((argv[0].a_w.w_symbol->s_name[0] != '0')||(argv[0].a_w.w_symbol->s_name[1] != 'x')) + { + error("packxbee_TX64: first argument is not a hex string beginning with \"0x\""); + return; + } +#ifdef _MSC_VER + result = sscanf(argv[0].a_w.w_symbol->s_name, "0x%I64X", &dest64); +#else + result = sscanf(argv[0].a_w.w_symbol->s_name, "0x%LX", &dest64); +#endif + if (result == 0) + { + error("packxbee_TX64: first argument is not a hex string"); + return; + } +#ifdef _MSC_VER + if (x->x_verbosity > 1) post ("packxbee_TX64: dest64:0x%016I64X", dest64); +#else + if (x->x_verbosity > 1) post ("packxbee_TX64: dest64:0x%016LX", dest64); +#endif + /* options is a single byte as a float */ + if (argv[1].a_type != A_FLOAT) + { + error("packxbee_TX64: second argument is not a float"); + return; + } + f = argv[1].a_w.w_float; + if (x->x_verbosity > 1) post("packxbee_TX64 float parameter %f", f); + d = ((unsigned int)f)&0x0FF; + if (f != d) + { + error("packxbee_TX64 second argument is not a positive integer from 0 to 255"); + return; + } + else options = d; + if (x->x_verbosity > 1) post("packxbee_TX64: options: %d", d); + + x->x_frameType = Transmit_Request_64_Bit_Address; + floatstring[0] = XFRAME; /* as usual */ + floatstring[1] = 0; /* length MSB */ + floatstring[2] = 0;/* length LSB */ + floatstring[3] = x->x_frameType; + checksum -= x->x_frameType; + if (0 == x->x_frameID) x->x_frameID++; + checksum -= x->x_frameID; /* frame ID */ + floatstring[4] = x->x_frameID++; + /* raw 8 byte address in big-endian order: */ + floatstring[5] = (dest64>>56)&0x0FF; + checksum -= floatstring[5]; + floatstring[6] = (dest64>>48)&0x0FF; + checksum -= floatstring[6]; + floatstring[7] = (dest64>>40)&0x0FF; + checksum -= floatstring[7]; + floatstring[8] = (dest64>>32)&0x0FF; + checksum -= floatstring[8]; + floatstring[9] = (dest64>>24)&0x0FF; + checksum -= floatstring[9]; + floatstring[10] = (dest64>>16)&0x0FF; + checksum -= floatstring[10]; + floatstring[11] = (dest64>>8)&0x0FF; + checksum -= floatstring[11]; + floatstring[12] = (dest64)&0x0FF; + checksum -= floatstring[12]; + floatstring[13] = options; + checksum -= floatstring[13]; + + /* the rest is payload */ + i = 14; + for (k = 2; k < argc; ++k) + { + if (A_FLOAT == argv[k].a_type) + { + f = argv[k].a_w.w_float; + if (x->x_verbosity > 1) post("packxbee_TX64: float parameter %f", f); + d = ((unsigned int)f)&0x0FF; + if (f != d) + { + error("packxbee_TX64: argument %d is not a positive integer from 0 to 255", k+1); + return; + } + floatstring[i++] = d; + checksum -= d; + } + else if (A_SYMBOL == argv[k].a_type) + { + if (x->x_verbosity > 1) post("packxbee_TX64: symbol parameter %s", argv[k].a_w.w_symbol->s_name); + j = i; + i += sprintf((char *)&floatstring[i], "%s", argv[k].a_w.w_symbol->s_name); + for (;j < i; ++j) checksum -= floatstring[j]; + } + else + { + error("packxbee_TX64: argument %d is not a float or a symbol", k+1); + return; + } + } + length = i-3; + floatstring[LENGTH_LSB_INDEX] = length & 0x0FF; + floatstring[LENGTH_MSB_INDEX] = length >> 8; + floatstring[i++] = checksum; + k = j = 0; /* j indexes the outbuf, k indexes the floatbuf, i is the length of floatbuf */ + for (k = 0; k < i; ++k) j = packxbee_outbuf_add(x, j, floatstring[k]); + outlet_list(x->x_listout, &s_list, j, x->x_outbuf); + if(x->x_verbosity > 1) + { + for (k = 0; k < j; ++k) + { + c = (unsigned char)atom_getfloat(&x->x_outbuf[k]); + post("buf[%d]: %d [0x%02X]", k, c, c); + } + } +} + +/* send a packet given a 16-bit address, options, followed by raw data (Series1 only) */ +static void packxbee_TX16(t_packxbee *x, t_symbol *s, int argc, t_atom *argv) +{ + unsigned char floatstring[256]; /* longer than the longest hex number with each character escaped plus the header and checksum overhead */ + unsigned int dest16; + int result; + char checksum = 0xFF; + unsigned char options; + t_float f; + int d, i, j, k; + int length = 0; + unsigned char c; + + if (argc < 3) + { + error("packxbee_TX16: not enough parameters"); + return; + } + /* first arg is dest16 also a symbol starting with "0x" */ + if (argv[0].a_type != A_SYMBOL) + { + error("packxbee_TX16: first argument is not a symbol"); + return; + } + if ((argv[0].a_w.w_symbol->s_name[0] != '0')||(argv[0].a_w.w_symbol->s_name[1] != 'x')) + { + error("packxbee_TX16: first argument is not a hex string beginning with \"0x\""); + return; + } + result = sscanf(argv[0].a_w.w_symbol->s_name, "0x%X", &dest16); + if (result == 0) + { + error("packxbee_TX16: first argument is not a hex string"); + return; + } + if (x->x_verbosity > 1) post ("packxbee_TX16: dest16: 0x%X", dest16); + + /* options is a single byte as a float */ + if (argv[1].a_type != A_FLOAT) + { + error("packxbee_TX16: second argument is not a float"); + return; + } + f = argv[1].a_w.w_float; + if (x->x_verbosity > 1) post("packxbee_TX16: float parameter %f", f); + d = ((unsigned int)f)&0x0FF; + if (f != d) + { + post ("packxbee_TX16: second argument is not a positive integer from 0 to 255"); + return; + } + else options = d; + if (x->x_verbosity > 1) post("packxbee_TX16: options: %d", d); + + x->x_frameType = Transmit_Request_16_bit_Address; + floatstring[0] = XFRAME; /* as usual */ + floatstring[1] = 0; /* length MSB */ + floatstring[2] = 0;/* length LSB */ + floatstring[3] = x->x_frameType; + checksum -= x->x_frameType; + if (0 == x->x_frameID) x->x_frameID++; + checksum -= x->x_frameID; /* frame ID */ + floatstring[4] = x->x_frameID++; + /* 16-bit address in big-endian order */ + floatstring[5] = (dest16>>8)&0x0FF; + checksum -= floatstring[5]; + floatstring[6] = (dest16)&0x0FF; + checksum -= floatstring[6]; + + floatstring[7] = options; + checksum -= floatstring[7]; + /* the rest is payload */ + i = 8; + for (k = 2; k < argc; ++k) + { + if (A_FLOAT == argv[k].a_type) + { + f = argv[k].a_w.w_float; + if (x->x_verbosity > 1) post("packxbee_TX16: float parameter %f", f); + d = ((unsigned int)f)&0x0FF; + if (f != d) + { + error ("packxbee_TX16: argument %d is not a positive integer from 0 to 255", k+1); + return; + } + floatstring[i++] = d; + checksum -= d; + } + else if (A_SYMBOL == argv[k].a_type) + { + if (x->x_verbosity > 1) post("packxbee_TX16: symbol parameter %s", argv[k].a_w.w_symbol->s_name); + j = i; + i += sprintf((char *)&floatstring[i], "%s", argv[k].a_w.w_symbol->s_name); + for (;j < i; ++j) checksum -= floatstring[j]; + } + else + { + error("packxbee_TX16: argument %d is not a float or a symbol", k+1); return; } } @@ -445,9 +703,26 @@ static void packxbee_pack_remote_frame(t_packxbee *x, t_symbol *s, int argc, t_a if (argv[4].a_type == A_SYMBOL) { if (x->x_verbosity > 0) post("packxbee_pack_remote_frame symbol parameter %s", argv[4].a_w.w_symbol->s_name); + if (('0' == argv[4].a_w.w_symbol->s_name[0])&&(('x' == argv[4].a_w.w_symbol->s_name[1]))) - { /* this is a hexadecimal number: strip the "0x" and copy the rest to the buffer as ascii digits */ - i += sprintf((char *)&floatstring[i], "%s", &argv[4].a_w.w_symbol->s_name[2]); + { /* this is a hexadecimal number: copy to the buffer as raw binary */ + result = sscanf(argv[4].a_w.w_symbol->s_name, "0x%X", &d); + if (result == 0) + { + post("packxbee_pack_remote_frame: argument 4 is not a hex string"); + } + else + { + // put the significant part of the raw value into floatstring in big endian order + if (0 != ((d>>24) & 0x0FF)) digits = 4; + else if (0 != ((d>>16) & 0x0FF)) digits = 3; + else if (0 != ((d>>8) & 0x0FF)) digits = 2; + else digits = 1; + if (4 == digits) floatstring[i++] = (d>>24) & 0x0FF; + if (3 <= digits) floatstring[i++] = (d>>16) & 0x0FF; + if (2 <= digits) floatstring[i++] = (d>>8) & 0x0FF; + floatstring[i++] = d & 0x0FF; + } } else // if ((0 == strncmp("NI", argv[0].a_w.w_symbol->s_name, 2))||(0 == strncmp("DN", argv[0].a_w.w_symbol->s_name, 2))) { /* we hope it's just an ascii string for the NI command */ @@ -455,7 +730,6 @@ static void packxbee_pack_remote_frame(t_packxbee *x, t_symbol *s, int argc, t_a { c = argv[4].a_w.w_symbol->s_name[k]; if (0 == c) break; - //checksum -= c; floatstring[i++] = c; } } @@ -464,10 +738,10 @@ static void packxbee_pack_remote_frame(t_packxbee *x, t_symbol *s, int argc, t_a { f = argv[4].a_w.w_float; if (x->x_verbosity > 0) post("packxbee_pack_remote_frame float parameter %f", f); - d = ((unsigned int)f)&0x0FF; + d = (unsigned int)f; if (f != d) { - post ("packxbee_pack_remote_frame parameter not a positive integer from 0 to 255"); + post ("packxbee_pack_remote_frame parameter not an integer"); } else { @@ -528,6 +802,7 @@ static void packxbee_pack_frame(t_packxbee *x, t_symbol *s, int argc, t_atom *ar unsigned char floatstring[256]; /* longer than the longest hex number with each character escaped plus the header and checksum overhead */ int length = 0; unsigned char c, digits; + int result; t_float f; if (x->x_verbosity > 0) post("packxbee_AT s is %s, argc is %d", s->s_name, argc); @@ -574,7 +849,23 @@ static void packxbee_pack_frame(t_packxbee *x, t_symbol *s, int argc, t_atom *ar if (x->x_verbosity > 0) post("packxbee_AT symbol parameter %s", argv[1].a_w.w_symbol->s_name); if (('0' == argv[1].a_w.w_symbol->s_name[0])&&(('x' == argv[1].a_w.w_symbol->s_name[1]))) { /* this is a hexadecimal number: strip the "0x" and copy the rest to the buffer as ascii digits */ - i += sprintf((char *)&floatstring[i], "%s", &argv[1].a_w.w_symbol->s_name[2]); + result = sscanf(argv[1].a_w.w_symbol->s_name, "0x%X", &d); + if (result == 0) + { + post("packxbee_pack_remote_frame: argument 1 is not a hex string"); + } + else + { + // put the significant part of the raw value into floatstring in big endian order + if (0 != ((d>>24) & 0x0FF)) digits = 4; + else if (0 != ((d>>16) & 0x0FF)) digits = 3; + else if (0 != ((d>>8) & 0x0FF)) digits = 2; + else digits = 1; + if (4 == digits) floatstring[i++] = (d>>24) & 0x0FF; + if (3 <= digits) floatstring[i++] = (d>>16) & 0x0FF; + if (2 <= digits) floatstring[i++] = (d>>8) & 0x0FF; + floatstring[i++] = d & 0x0FF; + } } else // if ((0 == strncmp("NI", argv[0].a_w.w_symbol->s_name, 2))||(0 == strncmp("DN", argv[0].a_w.w_symbol->s_name, 2))) { /* we hope it's just an ascii string for the NI command */ @@ -582,7 +873,6 @@ static void packxbee_pack_frame(t_packxbee *x, t_symbol *s, int argc, t_atom *ar { c = argv[1].a_w.w_symbol->s_name[k]; if (0 == c) break; -// checksum -= c; floatstring[i++] = c; } } @@ -591,10 +881,10 @@ static void packxbee_pack_frame(t_packxbee *x, t_symbol *s, int argc, t_atom *ar { f = argv[1].a_w.w_float; if (x->x_verbosity > 0) post("packxbee_AT float parameter %f", f); - d = ((unsigned int)f)&0x0FF; + d = (unsigned int)f; if (f != d) { - post ("packxbee_AT parameter not a positive integer from 0 to 255"); + post ("packxbee_AT parameter not an integer"); } else { @@ -660,6 +950,8 @@ void packxbee_setup(void) class_addmethod(packxbee_class, (t_method)packxbee_ATQ, gensym("ATQ"), A_GIMME, 0); class_addmethod(packxbee_class, (t_method)packxbee_RAT, gensym("RAT"), A_GIMME, 0); class_addmethod(packxbee_class, (t_method)packxbee_TX, gensym("TX"), A_GIMME, 0); + class_addmethod(packxbee_class, (t_method)packxbee_TX64, gensym("TX64"), A_GIMME, 0); + class_addmethod(packxbee_class, (t_method)packxbee_TX16, gensym("TX16"), A_GIMME, 0); class_addmethod(packxbee_class, (t_method)packxbee_API, gensym("API"), A_DEFFLOAT, 0); class_addmethod(packxbee_class, (t_method)packxbee_verbosity, gensym("verbosity"), A_DEFFLOAT, 0); } diff --git a/externals/mrpeach/xbee/pdxbee.h b/externals/mrpeach/xbee/pdxbee.h index d3023c32c..1096dd6ac 100644 --- a/externals/mrpeach/xbee/pdxbee.h +++ b/externals/mrpeach/xbee/pdxbee.h @@ -13,13 +13,20 @@ /* API Frame Names and Values */ +#define Transmit_Request_64_Bit_Address 0x00 +#define Transmit_Request_16_bit_Address 0x01 #define AT_Command 0x08 #define AT_Command_Queue_Parameter_Value 0x09 #define ZigBee_Transmit_Request 0x10 #define Explicit_Addressing_ZigBee_Command_Frame 0x11 #define Remote_Command_Request 0x17 #define Create_Source_Route 0x21 +#define Receive_Packet_64_Bit_Address 0x80 +#define Receive_Packet_16_Bit_Address 0x81 +#define Receive_Packet_64_Bit_Address_IO 0x82 +#define Receive_Packet_16_Bit_Address_IO 0x83 #define AT_Command_Response 0x88 +#define Transmit_Status 0x89 #define Modem_Status 0x8A #define ZigBee_Transmit_Status 0x8B #define ZigBee_Receive_Packet 0x90 diff --git a/externals/mrpeach/xbee/unpackxbee-help.pd b/externals/mrpeach/xbee/unpackxbee-help.pd new file mode 100644 index 000000000..9f95777d5 --- /dev/null +++ b/externals/mrpeach/xbee/unpackxbee-help.pd @@ -0,0 +1,330 @@ +#N canvas 26 77 1250 833 10; +#X declare -lib mrpeach; +#X obj -15 0 cnv 15 600 240 empty empty empty 20 12 0 14 -262130 -66577 +0; +#X obj -15 239 cnv 15 1400 550 empty empty unpackxbee_status: 1 12 +0 14 -203904 -159808 0; +#X msg 280 103 verbosity \$1; +#X obj 280 82 hradio 15 1 0 3 empty empty verbosity 0 -8 0 10 -4034 +-1 -1 0; +#X obj 330 170 unpackxbee 2; +#X obj 591 6 import mrpeach; +#N canvas 771 111 381 332 META 1; +#X text 22 55 LICENSE GPL v2 or later; +#X text 22 183 AUTHOR Martin Peach; +#X text 22 15 KEYWORDS control network wireless xbee; +#X text 22 203 HELP_PATCH_AUTHORS Martin Peach; +#X text 22 35 NAME unpackxbee; +#X text 22 75 DESCRIPTION [unpackxbee] unpacks packets from xbees in +API modes 1 or 2; +#X text 22 110 INLET_0 list; +#X text 23 125 OUTLET_0 list data; +#X text 23 145 OUTLET_1 list sample frame; +#X text 23 165 OUTLET_2 list status; +#X restore 634 26 pd META; +#X obj 330 130 comport 98 9600; +#X text 27 5 [unpackxbee] is used to unpack API mode 1 or 2 packets +received from xbees. Usually the output of a [comport] object is connected +to the inlet.; +#X text 26 53 Packet status comes out the right \, data is emitted +from the left outlet.; +#X floatatom 174 441 5 0 0 0 - - -; +#X obj 244 322 print unpack5; +#X obj 63 269 route AT_Command_Response; +#X obj 63 305 list split 3; +#X obj 174 343 list trim; +#X symbolatom 191 457 7 0 0 0 - - -; +#X symbolatom 209 474 20 0 0 0 - - -; +#X obj 63 343 unpack 0 0 0; +#X floatatom 63 367 5 0 0 0 - - -; +#X floatatom 97 387 5 0 0 0 - - -; +#X floatatom 132 407 5 0 0 0 - - -; +#X text -11 367 packet type; +#X text 29 387 packet ID; +#X text 54 406 data length; +#X text 61 438 AT command status; +#X text 145 456 addr16; +#X text 165 472 addr64; +#X obj 408 286 route ZigBee_Transmit_Status; +#X floatatom 408 328 5 0 0 0 - - -; +#X floatatom 429 346 5 0 0 0 - - -; +#X text 334 328 packet type; +#X text 361 346 packet ID; +#X symbolatom 450 363 7 0 0 0 - - -; +#X text 407 362 addr16; +#X floatatom 513 415 5 0 0 0 - - -; +#X floatatom 492 398 5 0 0 0 - - -; +#X floatatom 471 381 5 0 0 0 - - -; +#X text 340 379 transmit retry count; +#X text 391 396 delivery status; +#X text 407 413 discovery status; +#X symbolatom 226 491 32 0 0 0 - - -; +#X symbolatom 244 509 7 0 0 0 - - -; +#X symbolatom 297 562 7 0 0 0 - - -; +#X symbolatom 315 580 7 0 0 0 - - -; +#X obj 174 419 unpack 0 s s s s 0 0 s s; +#X floatatom 262 527 5 0 0 0 - - -; +#X floatatom 279 544 5 0 0 0 - - -; +#X text 129 490 Node Identifier; +#X text 197 508 parent; +#X text 187 524 device type; +#X text 199 542 source event; +#X text 242 560 profile; +#X text 237 578 manufacturer; +#X obj 408 308 unpack 0 0 s 0 0 0; +#X obj 596 303 route ZigBee_Receive_Packet; +#X obj 1101 337 print someotherpacket; +#X symbolatom 665 400 7 0 0 0 - - -; +#X symbolatom 642 382 17 0 0 0 - - -; +#X text 619 399 addr16; +#X text 598 380 addr64; +#X floatatom 596 346 5 0 0 0 - - -; +#X text 522 346 packet type; +#X floatatom 689 418 5 0 0 0 - - -; +#X text 590 416 receive options; +#X obj 689 468 tgl 15 0 empty empty acknowledged 17 7 0 10 -4034 -1 +-1 0 1; +#X obj 729 488 tgl 15 0 empty empty broadcast 17 7 0 10 -4034 -1 -1 +0 1; +#X obj 769 508 tgl 15 0 empty empty encrypted 17 7 0 10 -4034 -1 -1 +0 1; +#X obj 809 528 tgl 15 0 empty empty from_end_device 17 7 0 10 -4034 +-1 -1 0 1; +#X obj 689 432 & 1; +#X obj 729 432 & 2; +#X obj 769 432 & 32; +#X obj 809 432 & 64; +#X obj 596 324 unpack 0 0 s s 0; +#X floatatom 619 363 5 0 0 0 - - -; +#X text 545 363 data length; +#X obj 491 437 select 0 2 21 33 34 35 36 37; +#X symbolatom 491 634 32 0 0 0 - - -; +#X msg 491 461 set success; +#X msg 656 619 set unknown; +#X msg 511 480 set CCA_failurs; +#X msg 552 520 set Network_ACK_Failure; +#X msg 532 500 set Invalid_Destination_Endpoint; +#X msg 573 540 set Not_Joined_To_Network; +#X msg 592 560 set Self-Addresed; +#X msg 614 579 set Address_Not_Found; +#X msg 635 599 set Route_Not_Found; +#X text 388 633 delivery status:; +#X symbolatom 512 770 32 0 0 0 - - -; +#X msg 593 755 set unknown; +#X obj 512 658 select 0 1 2 3; +#X msg 512 679 set No_Discovery_Overhead; +#X msg 532 698 set Address_Discovery; +#X msg 553 717 set Route_Discovery; +#X msg 573 736 set Address_And_Route_Discovery; +#X text 408 768 discovery status:; +#X obj 856 320 route Remote_Command_Response; +#X floatatom 856 373 5 0 0 0 - - -; +#X floatatom 875 395 5 0 0 0 - - -; +#X text 782 373 packet type; +#X text 807 395 packet ID; +#X floatatom 973 502 5 0 0 0 - - -; +#X symbolatom 895 435 20 0 0 0 - - -; +#X text 851 433 addr64; +#X symbolatom 914 416 7 0 0 0 - - -; +#X symbolatom 934 457 7 0 0 0 - - -; +#X text 888 456 command; +#X floatatom 953 479 5 0 0 0 - - -; +#X text 903 503 data length; +#X text 911 479 status; +#X obj 856 347 unpack 0 0 s s s 0 0; +#X obj 237 390 print AT_response; +#X text 868 415 addr16; +#X obj 1021 383 select 0 1 2 3 4; +#X symbolatom 1021 583 32 0 0 0 - - -; +#X text 978 582 delivery status:; +#X msg 1021 410 set OK; +#X msg 1039 430 set ERROR; +#X msg 1058 449 set Invalid_Command; +#X msg 1077 469 set Invalid_Parameter; +#X msg 1095 492 set Transmission_Failed; +#X obj 174 365 route ND SL; +#X obj 51 532 print SL; +#X obj 330 216 print unpackxbee_data; +#X obj 462 187 print unpackxbee_status; +#X text 645 195 Martin Peach 2013_03_13; +#N canvas 4 77 541 300 sample_frame 0; +#X obj 32 23 inlet; +#X obj 32 76 route D0 D1 D2 D3 D4 D5 D10 D11 D12 A0 A1 A2 A3 A7; +#X obj 26 106 cnv 15 300 50 empty empty Digital_Inputs 20 12 0 14 -204786 +-13381 0; +#X obj 26 157 cnv 15 400 90 empty empty Analog_Inputs 20 12 0 14 -232576 +-45076 0; +#X obj 29 190 nbx 5 14 -1e+37 1e+37 0 0 empty empty A0 40 8 0 10 -204800 +-13330 -159808 0 256; +#X obj 89 190 nbx 5 14 -1e+37 1e+37 0 0 empty empty A1 40 8 0 10 -204800 +-13330 -159808 0 256; +#X obj 149 190 nbx 5 14 -1e+37 1e+37 0 0 empty empty A2 40 8 0 10 -204800 +-13330 -159808 0 256; +#X obj 209 190 nbx 5 14 -1e+37 1e+37 0 0 empty empty A3 40 8 0 10 -204800 +-13330 -159808 0 256; +#X obj 269 190 nbx 5 14 -1e+37 1e+37 0 0 empty empty V+ 40 8 0 10 -204800 +-13330 -159808 0 256; +#X obj 32 132 nbx 2 14 -1e+37 1e+37 0 0 empty empty D0 8 20 0 10 -4034 +-1 -258113 0 256; +#X obj 72 132 nbx 2 14 -1e+37 1e+37 0 0 empty empty D1 8 20 0 10 -4034 +-1 -258113 0 256; +#X obj 102 132 nbx 2 14 -1e+37 1e+37 0 0 empty empty D2 8 20 0 10 -4034 +-1 -258113 0 256; +#X obj 132 132 nbx 2 14 -1e+37 1e+37 0 0 empty empty D3 8 20 0 10 -4034 +-1 -258113 0 256; +#X obj 162 132 nbx 2 14 -1e+37 1e+37 0 0 empty empty D4 8 20 0 10 -4034 +-1 -258113 0 256; +#X obj 192 132 nbx 2 14 -1e+37 1e+37 0 0 empty empty D5 8 20 0 10 -4034 +-1 -258113 0 256; +#X obj 222 132 nbx 2 14 -1e+37 1e+37 0 0 empty empty P0 8 20 0 10 -4034 +-1 -258113 0 256; +#X obj 252 132 nbx 2 14 -1e+37 1e+37 0 0 empty empty P1 8 20 0 10 -4034 +-1 -258113 0 256; +#X obj 282 132 nbx 2 14 -1e+37 1e+37 0 0 empty empty P2 8 20 0 10 -4034 +-1 -258113 0 256; +#X obj 29 229 nbx 5 14 -1e+37 1e+37 0 0 empty empty A0_mV 40 8 0 10 +-204800 -13330 -159808 0 256; +#X obj 29 209 * 1.17302; +#X obj 109 229 nbx 5 14 -1e+37 1e+37 0 0 empty empty A1_mV 40 8 0 10 +-204800 -13330 -159808 0 256; +#X obj 109 209 * 1.17302; +#X obj 189 229 nbx 5 14 -1e+37 1e+37 0 0 empty empty A2_mV 40 8 0 10 +-204800 -13330 -159808 0 256; +#X obj 189 209 * 1.17302; +#X obj 269 229 nbx 5 14 -1e+37 1e+37 0 0 empty empty A3_mV 40 8 0 10 +-204800 -13330 -159808 0 256; +#X obj 269 209 * 1.17302; +#X obj 349 229 nbx 5 14 -1e+37 1e+37 0 0 empty empty V+_mV 40 8 0 10 +-204800 -13330 -159808 0 256; +#X obj 349 209 * 1.17302; +#X obj 32 48 list trim; +#X obj 329 100 print more_sample_frame_stuff; +#X connect 0 0 28 0; +#X connect 1 0 9 0; +#X connect 1 1 10 0; +#X connect 1 2 11 0; +#X connect 1 3 12 0; +#X connect 1 4 13 0; +#X connect 1 5 14 0; +#X connect 1 6 15 0; +#X connect 1 7 16 0; +#X connect 1 8 17 0; +#X connect 1 9 4 0; +#X connect 1 9 19 0; +#X connect 1 10 5 0; +#X connect 1 10 21 0; +#X connect 1 11 6 0; +#X connect 1 11 23 0; +#X connect 1 12 7 0; +#X connect 1 12 25 0; +#X connect 1 13 8 0; +#X connect 1 13 27 0; +#X connect 1 14 29 0; +#X connect 19 0 18 0; +#X connect 21 0 20 0; +#X connect 23 0 22 0; +#X connect 25 0 24 0; +#X connect 27 0 26 0; +#X connect 28 0 1 0; +#X restore 364 197 pd sample_frame; +#X connect 2 0 4 0; +#X connect 3 0 2 0; +#X connect 4 0 122 0; +#X connect 4 1 125 0; +#X connect 4 2 123 0; +#X connect 4 2 12 0; +#X connect 7 0 4 0; +#X connect 12 0 13 0; +#X connect 12 1 27 0; +#X connect 13 0 17 0; +#X connect 13 1 14 0; +#X connect 13 2 11 0; +#X connect 14 0 120 0; +#X connect 17 0 18 0; +#X connect 17 1 19 0; +#X connect 17 2 20 0; +#X connect 27 0 53 0; +#X connect 27 1 54 0; +#X connect 44 0 10 0; +#X connect 44 1 15 0; +#X connect 44 2 16 0; +#X connect 44 3 40 0; +#X connect 44 4 41 0; +#X connect 44 5 45 0; +#X connect 44 6 46 0; +#X connect 44 7 42 0; +#X connect 44 8 43 0; +#X connect 53 0 28 0; +#X connect 53 1 29 0; +#X connect 53 2 32 0; +#X connect 53 3 36 0; +#X connect 53 4 35 0; +#X connect 53 4 75 0; +#X connect 53 5 34 0; +#X connect 53 5 89 0; +#X connect 54 0 72 0; +#X connect 54 1 95 0; +#X connect 62 0 68 0; +#X connect 62 0 69 0; +#X connect 62 0 70 0; +#X connect 62 0 71 0; +#X connect 68 0 64 0; +#X connect 69 0 65 0; +#X connect 70 0 66 0; +#X connect 71 0 67 0; +#X connect 72 0 60 0; +#X connect 72 1 73 0; +#X connect 72 2 57 0; +#X connect 72 3 56 0; +#X connect 72 4 62 0; +#X connect 75 0 77 0; +#X connect 75 1 79 0; +#X connect 75 2 81 0; +#X connect 75 3 80 0; +#X connect 75 4 82 0; +#X connect 75 5 83 0; +#X connect 75 6 84 0; +#X connect 75 7 85 0; +#X connect 75 8 78 0; +#X connect 77 0 76 0; +#X connect 78 0 76 0; +#X connect 79 0 76 0; +#X connect 80 0 76 0; +#X connect 81 0 76 0; +#X connect 82 0 76 0; +#X connect 83 0 76 0; +#X connect 84 0 76 0; +#X connect 85 0 76 0; +#X connect 88 0 87 0; +#X connect 89 0 90 0; +#X connect 89 1 91 0; +#X connect 89 2 92 0; +#X connect 89 3 93 0; +#X connect 89 4 88 0; +#X connect 90 0 87 0; +#X connect 91 0 87 0; +#X connect 92 0 87 0; +#X connect 93 0 87 0; +#X connect 95 0 109 0; +#X connect 95 1 55 0; +#X connect 109 0 96 0; +#X connect 109 1 97 0; +#X connect 109 2 101 0; +#X connect 109 3 103 0; +#X connect 109 4 104 0; +#X connect 109 5 106 0; +#X connect 109 5 112 0; +#X connect 109 6 100 0; +#X connect 112 0 115 0; +#X connect 112 1 116 0; +#X connect 112 2 117 0; +#X connect 112 3 118 0; +#X connect 112 4 119 0; +#X connect 115 0 113 0; +#X connect 116 0 113 0; +#X connect 117 0 113 0; +#X connect 118 0 113 0; +#X connect 119 0 113 0; +#X connect 120 0 44 0; +#X connect 120 1 121 0; +#X connect 120 2 110 0; diff --git a/externals/mrpeach/xbee/unpackxbee.c b/externals/mrpeach/xbee/unpackxbee.c index b8b59006e..f49885d1a 100644 --- a/externals/mrpeach/xbee/unpackxbee.c +++ b/externals/mrpeach/xbee/unpackxbee.c @@ -1,8 +1,11 @@ -/* unpackxbee outputs a list of floats which are the bytes making up an xbee api packet. */ -/* The packet can then be sent through [comport]. */ +/* [unpackxbee] outputs a list of floats which are the bytes making up the data part of an xbee api packet. */ +/* a status outlet provides the address and status information for each packet received */ +/* a sample outlet emits IO samples */ +/* [unpackxbee]'s inlet is typically connected to the data outlet of a [comport] object */ /* Started by Martin Peach 20110731 */ /* Information taken from "XBee®/XBee-PRO® ZB RF Modules" (document 90000976_G, 11/15/2010)*/ /* by Digi International Inc. http://www.digi.com */ +/* Series 1 info from "XBee®/XBee-PRO® RF Modules" (document 90000982_L 4/30/2013) */ #include <stdio.h> //#include <string.h> @@ -16,6 +19,7 @@ typedef struct _unpackxbee { t_object x_obj; t_outlet *x_status_out; + t_outlet *x_sample_out; t_outlet *x_payload_out; int x_api_mode; unsigned char x_frame_ID; @@ -26,13 +30,13 @@ typedef struct _unpackxbee unsigned int x_message_index; int x_escaped; t_atom x_outbuf[MAX_XBEE_PACKET_LENGTH]; - t_atom x_statusbuf[32]; /* some number bigger than we will ever reach */ } t_unpackxbee; static void *unpackxbee_new(t_floatarg f); static void unpackxbee_input(t_unpackxbee *x, t_symbol *s, int argc, t_atom *argv); static void unpackxbee_API(t_unpackxbee *x, t_float api); static void unpackxbee_verbosity(t_unpackxbee *x, t_float verbosity_level); +static int unpackxbee_add(t_unpackxbee *x, unsigned char d); static void unpackxbee_free(t_unpackxbee *x); void unpackxbee_setup(void); @@ -43,8 +47,9 @@ static void *unpackxbee_new(t_floatarg f) t_unpackxbee *x = (t_unpackxbee *)pd_new(unpackxbee_class); if (x) { - x->x_payload_out = outlet_new(&x->x_obj, &s_list); /* the first outlet on the left */ - x->x_status_out = outlet_new(&x->x_obj, &s_list); + x->x_payload_out = outlet_new(&x->x_obj, &s_list); /* the outlet on the left fro raw data */ + x->x_sample_out = outlet_new(&x->x_obj, &s_list); /* the middle outlet for sample frames */ + x->x_status_out = outlet_new(&x->x_obj, &s_list); /* the rightmost outlet for status */ if (1 == f) x->x_api_mode = 1; else x->x_api_mode = 2; /* default to escaped mode */ @@ -66,7 +71,7 @@ static void unpackxbee_verbosity(t_unpackxbee *x, t_float verbosity_level) else error ("packxbee: verbosity_level must be positive"); } -int unpackxbee_add(t_unpackxbee *x, unsigned char d) +static int unpackxbee_add(t_unpackxbee *x, unsigned char d) { if (XFRAME == d) { @@ -116,8 +121,13 @@ static void unpackxbee_input(t_unpackxbee *x, t_symbol *s, int argc, t_atom *arg unsigned char c; t_symbol *type_selector; int statuslength = 0, payloadstart = 0; + int payload_is_sample_frame = 0; + int digital_bits = 0, digital_ins = 0, digital_channel = 0; + int analog_bits = 0, analog_channel = 0; char atbuf[64]; unsigned char floatstring[256]; /* longer than the longest hex number with each character escaped plus the header and checksum overhead */ + t_atom status_atoms[32]; /* some number bigger than we will ever reach */ + t_atom sample_atoms[12]; /* up to 5 analog samples + 1 digital sample + their names */ unsigned long long addr64; unsigned int addr16; @@ -187,12 +197,27 @@ static void unpackxbee_input(t_unpackxbee *x, t_symbol *s, int argc, t_atom *arg case Modem_Status: type_selector = gensym("Modem_Status"); break; + case Transmit_Status: + type_selector = gensym("Transmit_Status"); + break; case ZigBee_Transmit_Status: type_selector = gensym("ZigBee_Transmit_Status"); break; case ZigBee_Receive_Packet: type_selector = gensym("ZigBee_Receive_Packet"); break; + case Receive_Packet_64_Bit_Address: + type_selector = gensym("Receive_Packet_64_Bit_Address"); + break; + case Receive_Packet_16_Bit_Address: + type_selector = gensym("Receive_Packet_16_Bit_Address"); + break; + case Receive_Packet_64_Bit_Address_IO: + type_selector = gensym("Receive_Packet_64_Bit_Address_IO"); + break; + case Receive_Packet_16_Bit_Address_IO: + type_selector = gensym("Receive_Packet_16_Bit_Address_IO"); + break; case ZigBee_Explicit_Rx_Indicator: type_selector = gensym("ZigBee_Explicit_Rx_Indicator"); break; @@ -221,28 +246,26 @@ static void unpackxbee_input(t_unpackxbee *x, t_symbol *s, int argc, t_atom *arg type_selector = gensym("unknown"); } statuslength = 0; - SETFLOAT(&x->x_statusbuf[statuslength], x->x_frame_type); + SETFLOAT(&status_atoms[statuslength], x->x_frame_type); statuslength++; - if - ( - (AT_Command_Response == x->x_frame_type) - ||(AT_Command == x->x_frame_type) - ||(AT_Command_Queue_Parameter_Value == x->x_frame_type) - ) + switch (x->x_frame_type) { + case AT_Command_Response: + case AT_Command: + case AT_Command_Queue_Parameter_Value: if (x->x_verbosity > 0) post("AT_Command_Response AT_Command AT_Command_Queue_Parameter_Value statuslength %d", statuslength); - SETFLOAT(&x->x_statusbuf[statuslength], x->x_frame_ID); + SETFLOAT(&status_atoms[statuslength], x->x_frame_ID); statuslength++; /* data doesn't include 1byte frame type 1byte ID 2byte AT command 1byte AT command status = 5bytes */ - SETFLOAT(&x->x_statusbuf[statuslength], x->x_frame_length-5); + SETFLOAT(&status_atoms[statuslength], x->x_frame_length-5); statuslength++; atbuf[0] = x->x_message[5]; /* the AT command string */ atbuf[1] = x->x_message[6]; atbuf[2] = '\0'; - SETSYMBOL(&x->x_statusbuf[statuslength], gensym(atbuf)); + SETSYMBOL(&status_atoms[statuslength], gensym(atbuf)); statuslength++; - SETFLOAT(&x->x_statusbuf[statuslength], x->x_message[7]);/* AT command status */ + SETFLOAT(&status_atoms[statuslength], x->x_message[7]);/* AT command status */ statuslength++; if ((0 == x->x_message[7]) && ('N' == x->x_message[5]) && ('D' == x->x_message[6])) { /* a succesful node discover response: output the addresses as symbols */ @@ -258,7 +281,7 @@ buf[7]: 0 [0x00] status */ addr16 = (x->x_message[8]<<8) + x->x_message[9]; sprintf((char *)floatstring, "0x%X", addr16); - SETSYMBOL(&x->x_statusbuf[statuslength], gensym((char *)floatstring)); + SETSYMBOL(&status_atoms[statuslength], gensym((char *)floatstring)); statuslength++; /* buf[8]: 121 [0x79] MY @@ -286,7 +309,7 @@ buf[9]: 214 [0xD6] #else sprintf((char *)floatstring, "0x%016LX", addr64); #endif - SETSYMBOL(&x->x_statusbuf[statuslength], gensym((char *)floatstring)); /* addr64 */ + SETSYMBOL(&status_atoms[statuslength], gensym((char *)floatstring)); /* addr64 */ statuslength++; /* buf[10]: 0 [0x00] SH @@ -307,7 +330,7 @@ buf[17]: 30 [0x1E] break;/* Node Identifier should be a null-terminated ascii string */ } } - SETSYMBOL(&x->x_statusbuf[statuslength], gensym((char *)floatstring)); /* Node Identifier */ + SETSYMBOL(&status_atoms[statuslength], gensym((char *)floatstring)); /* Node Identifier */ statuslength++; /* buf[18]: 32 [0x20] NI @@ -316,18 +339,18 @@ buf[19]: 0 [0x00] addr16 = (x->x_message[i]<<8) + x->x_message[i+1]; sprintf((char *)floatstring, "0x%X", addr16); i += 2; - SETSYMBOL(&x->x_statusbuf[statuslength], gensym((char *)floatstring)); /* parent addr16 */ + SETSYMBOL(&status_atoms[statuslength], gensym((char *)floatstring)); /* parent addr16 */ statuslength++; /* buf[20]: 255 [0xFF] parent buf[21]: 254 [0xFE] */ - SETFLOAT(&x->x_statusbuf[statuslength], x->x_message[i++]);/* Device Type */ + SETFLOAT(&status_atoms[statuslength], x->x_message[i++]);/* Device Type */ statuslength++; /* buf[22]: 1 [0x01] device type */ - SETFLOAT(&x->x_statusbuf[statuslength], x->x_message[i++]);/* Source Event */ + SETFLOAT(&status_atoms[statuslength], x->x_message[i++]);/* Source Event */ statuslength++; /* buf[23]: 0 [0x00] source event @@ -335,7 +358,7 @@ buf[23]: 0 [0x00] source event addr16 = x->x_message[i++]<<8; addr16 |= x->x_message[i++]; sprintf((char *)floatstring, "0x%X", addr16); - SETSYMBOL(&x->x_statusbuf[statuslength], gensym((char *)floatstring)); /* Profile ID */ + SETSYMBOL(&status_atoms[statuslength], gensym((char *)floatstring)); /* Profile ID */ statuslength++; /* buf[24]: 193 [0xC1] Profile ID @@ -344,7 +367,7 @@ buf[25]: 5 [0x05] addr16 = (x->x_message[i]<<8) + x->x_message[i+1]; sprintf((char *)floatstring, "0x%X", addr16); i += 2; - SETSYMBOL(&x->x_statusbuf[statuslength], gensym((char *)floatstring)); /* Manufacturer ID */ + SETSYMBOL(&status_atoms[statuslength], gensym((char *)floatstring)); /* Manufacturer ID */ statuslength++; /* buf[26]: 16 [0x10] Manufacturer ID @@ -360,13 +383,12 @@ buf[28]: 36 [0x24] checksum { payloadstart = 8; } - } + break; /* RAT */ - if (Remote_Command_Response == x->x_frame_type) - { + case Remote_Command_Response: if (x->x_verbosity > 0) post("Remote_Command_Response statuslength %d", statuslength); - SETFLOAT(&x->x_statusbuf[statuslength], x->x_frame_ID); + SETFLOAT(&status_atoms[statuslength], x->x_frame_ID); statuslength++; /* buf[0]: 126 [0x7E] packet start @@ -402,50 +424,59 @@ buf[18...] data #else sprintf((char *)floatstring, "0x%016LX", addr64); #endif - SETSYMBOL(&x->x_statusbuf[statuslength], gensym((char *)floatstring)); /* addr64 */ + SETSYMBOL(&status_atoms[statuslength], gensym((char *)floatstring)); /* addr64 */ statuslength++; addr16 = (x->x_message[13]<<8) + x->x_message[14]; sprintf((char *)floatstring, "0x%X", addr16); - SETSYMBOL(&x->x_statusbuf[statuslength], gensym((char *)floatstring)); + SETSYMBOL(&status_atoms[statuslength], gensym((char *)floatstring)); statuslength++; atbuf[0] = x->x_message[15]; /* the remote AT command string */ atbuf[1] = x->x_message[16]; atbuf[2] = '\0'; - SETSYMBOL(&x->x_statusbuf[statuslength], gensym(atbuf)); + SETSYMBOL(&status_atoms[statuslength], gensym(atbuf)); statuslength++; + + if ((atbuf[0] == 'I') && (atbuf[1] == 'S')) payload_is_sample_frame = 1; /* output sample frame via middle outlet */ - SETFLOAT(&x->x_statusbuf[statuslength], x->x_message[17]);/* AT command status */ + SETFLOAT(&status_atoms[statuslength], x->x_message[17]);/* AT command status */ statuslength++; /* data doesn't include 1byte frame type 1byte ID 8byte addr64 2byte addr16 2byte AT command 1byte status = 15bytes */ - SETFLOAT(&x->x_statusbuf[statuslength], x->x_frame_length-15); + SETFLOAT(&status_atoms[statuslength], x->x_frame_length-15); statuslength++; payloadstart = 18; - } + break; /* RAT */ - else if (ZigBee_Transmit_Status == x->x_frame_type) - { + case Transmit_Status: + if (x->x_verbosity > 0) + post("Transmit_Status statuslength %d", statuslength); + SETFLOAT(&status_atoms[statuslength], x->x_frame_ID); + statuslength++; + SETFLOAT(&status_atoms[statuslength], x->x_message[5]);/* Delivery Status */ + statuslength++; + payloadstart = 0; /* no payload */ + break; + case ZigBee_Transmit_Status: if (x->x_verbosity > 0) post("ZigBee_Transmit_Status statuslength %d", statuslength); - SETFLOAT(&x->x_statusbuf[statuslength], x->x_frame_ID); + SETFLOAT(&status_atoms[statuslength], x->x_frame_ID); statuslength++; sprintf(atbuf, "0x%X", (x->x_message[5]<<8) + x->x_message[6]); /* the 16-bit address as a symbol */ - SETSYMBOL(&x->x_statusbuf[statuslength], gensym(atbuf)); + SETSYMBOL(&status_atoms[statuslength], gensym(atbuf)); statuslength++; - SETFLOAT(&x->x_statusbuf[statuslength], x->x_message[7]);/* Transmit Retry Count */ + SETFLOAT(&status_atoms[statuslength], x->x_message[7]);/* Transmit Retry Count */ statuslength++; - SETFLOAT(&x->x_statusbuf[statuslength], x->x_message[8]);/* Delivery Status */ + SETFLOAT(&status_atoms[statuslength], x->x_message[8]);/* Delivery Status */ statuslength++; - SETFLOAT(&x->x_statusbuf[statuslength], x->x_message[9]);/* Discovery Status */ + SETFLOAT(&status_atoms[statuslength], x->x_message[9]);/* Discovery Status */ statuslength++; payloadstart = 0; /* no payload */ - } - else if (ZigBee_Receive_Packet == x->x_frame_type) - { + break; + case ZigBee_Receive_Packet: if (x->x_verbosity > 0) post("ZigBee_Receive_Packet statuslength %d", statuslength); /* data doesn't include 1byte frametype, 8byte addr64, 2byte addr16, 1byte options = 12bytes*/ - SETFLOAT(&x->x_statusbuf[statuslength], x->x_frame_length-12); + SETFLOAT(&status_atoms[statuslength], x->x_frame_length-12); statuslength++; /* frame type */ /* 64-bit source address */ @@ -470,33 +501,194 @@ buf[18...] data #else sprintf((char *)floatstring, "0x%016LX", addr64); #endif - SETSYMBOL(&x->x_statusbuf[statuslength], gensym((char *)floatstring)); /* addr64 */ + SETSYMBOL(&status_atoms[statuslength], gensym((char *)floatstring)); /* addr64 */ statuslength++; /* 16-bit source address */ addr16 = x->x_message[i++]<<8; addr16 |= x->x_message[i++]; sprintf((char *)floatstring, "0x%X", addr16); - SETSYMBOL(&x->x_statusbuf[statuslength], gensym((char *)floatstring)); /* addr16 */ + SETSYMBOL(&status_atoms[statuslength], gensym((char *)floatstring)); /* addr16 */ statuslength++; /* receive options byte */ - SETFLOAT(&x->x_statusbuf[statuslength], x->x_message[i++]);/* 1 2 32 64 */ + SETFLOAT(&status_atoms[statuslength], x->x_message[i++]);/* 1 2 32 64 */ statuslength++; /* data */ payloadstart = i; - } - else - { + break; + case Receive_Packet_64_Bit_Address: + if (x->x_verbosity > 0) + post("Receive_Packet_64_Bit_Address statuslength %d", statuslength); + /* data doesn't include 1byte frametype, 8byte addr64, 1byte RSSI, 1byte options = 11bytes*/ + SETFLOAT(&status_atoms[statuslength], x->x_frame_length-11); + statuslength++; + /* frame type */ + /* 64-bit source address */ + i = 4; + addr64 = x->x_message[i++]; + addr64 <<= 8; + addr64 |= x->x_message[i++]; + addr64 <<= 8; + addr64 |= x->x_message[i++]; + addr64 <<= 8; + addr64 |= x->x_message[i++]; + addr64 <<= 8; + addr64 |= x->x_message[i++]; + addr64 <<= 8; + addr64 |= x->x_message[i++]; + addr64 <<= 8; + addr64 |= x->x_message[i++]; + addr64 <<= 8; + addr64 |= x->x_message[i++]; +#ifdef _MSC_VER + sprintf((char *)floatstring, "0x%016I64X", addr64); +#else + sprintf((char *)floatstring, "0x%016LX", addr64); +#endif + SETSYMBOL(&status_atoms[statuslength], gensym((char *)floatstring)); /* addr64 */ + statuslength++; + /* receive signal strength indicator */ + SETFLOAT(&status_atoms[statuslength], x->x_message[i++]); + statuslength++; + /* receive options byte */ + SETFLOAT(&status_atoms[statuslength], x->x_message[i++]);/* 1 2 32 64 */ + statuslength++; + /* data */ + payloadstart = i; + break; + case Receive_Packet_16_Bit_Address: + if (x->x_verbosity > 0) + post("Receive_Packet_16_Bit_Address statuslength %d", statuslength); + /* data doesn't include 1byte frametype, 2byte addr64, 1byte RSSI, 1byte options = 5bytes*/ + SETFLOAT(&status_atoms[statuslength], x->x_frame_length-5); + statuslength++; + /* frame type */ + /* 16-bit source address */ + i = 4; + /* 16-bit source address */ + addr16 = x->x_message[i++]<<8; + addr16 |= x->x_message[i++]; + sprintf((char *)floatstring, "0x%X", addr16); + SETSYMBOL(&status_atoms[statuslength], gensym((char *)floatstring)); /* addr16 */ + statuslength++; + /* receive signal strength indicator */ + SETFLOAT(&status_atoms[statuslength], x->x_message[i++]); + statuslength++; + /* receive options byte */ + SETFLOAT(&status_atoms[statuslength], x->x_message[i++]);/* 1 2 32 64 */ + statuslength++; + /* data */ + payloadstart = i; + break; + case ZigBee_IO_Data_Sample_Rx_Indicator: + if (x->x_verbosity > 0) + post("ZigBee_IO_Data_Sample_Rx_Indicator statuslength %d", statuslength); + payload_is_sample_frame = 1; + /* data doesn't include 1byte frametype, 8byte addr64, 2byte addr16, 1byte options = 12bytes*/ + SETFLOAT(&status_atoms[statuslength], x->x_frame_length-12); + statuslength++; + /* frame type */ + /* 64-bit source address */ + i = 4; + addr64 = x->x_message[i++]; + addr64 <<= 8; + addr64 |= x->x_message[i++]; + addr64 <<= 8; + addr64 |= x->x_message[i++]; + addr64 <<= 8; + addr64 |= x->x_message[i++]; + addr64 <<= 8; + addr64 |= x->x_message[i++]; + addr64 <<= 8; + addr64 |= x->x_message[i++]; + addr64 <<= 8; + addr64 |= x->x_message[i++]; + addr64 <<= 8; + addr64 |= x->x_message[i++]; +#ifdef _MSC_VER + sprintf((char *)floatstring, "0x%016I64X", addr64); +#else + sprintf((char *)floatstring, "0x%016LX", addr64); +#endif + SETSYMBOL(&status_atoms[statuslength], gensym((char *)floatstring)); /* addr64 */ + statuslength++; + /* 16-bit source address */ + addr16 = x->x_message[i++]<<8; + addr16 |= x->x_message[i++]; + sprintf((char *)floatstring, "0x%X", addr16); + SETSYMBOL(&status_atoms[statuslength], gensym((char *)floatstring)); /* addr16 */ + statuslength++; + /* receive options byte */ + SETFLOAT(&status_atoms[statuslength], x->x_message[i++]);/* 1 2 32 64 */ + statuslength++; + /* data */ + payloadstart = i; + break; + default: if (x->x_verbosity > 0) post("some other packet statuslength %d", statuslength); - SETFLOAT(&x->x_statusbuf[statuslength], x->x_frame_ID);/* may not be valid */ + SETFLOAT(&status_atoms[statuslength], x->x_frame_ID);/* may not be valid */ statuslength++; - SETFLOAT(&x->x_statusbuf[statuslength], x->x_frame_length-2);/* payload doesn't include frame type and ID */ + SETFLOAT(&status_atoms[statuslength], x->x_frame_length-2);/* payload doesn't include frame type and ID */ statuslength++; payloadstart = 5; - } - outlet_anything(x->x_status_out, type_selector, statuslength, x->x_statusbuf); + } /* end of switch */ + + outlet_anything(x->x_status_out, type_selector, statuslength, status_atoms); if (payloadstart > 0) { + if (payload_is_sample_frame) + { + /* sample frame payload first byte is always 1 */ + i = payloadstart; + if (x->x_message[i] != 1) post ("unpackxbee: bad sample frame"); + else + { + digital_bits = (x->x_message[i+1]<<8) + x->x_message[i+2]; + if (x->x_verbosity > 0) + post("digital bitmask %04X", digital_bits); + analog_bits = x->x_message[i+3]; + if (x->x_verbosity > 0) + post("analog bitmask %04X", analog_bits); + i = i+4; + + if (0 != digital_bits) + { + digital_channel = 0; + digital_ins = (x->x_message[i]<<8) + x->x_message[i+1]; + while (0 != digital_bits) + { + while (0 == (digital_bits & 1)) + { + digital_bits >>= 1; + digital_ins >>= 1; + digital_channel++; + } + sprintf(atbuf, "D%d", digital_channel); + SETFLOAT(&sample_atoms[0], ((digital_ins & 1)?1:0)); + outlet_anything(x->x_sample_out, gensym(atbuf), 1, sample_atoms); + digital_bits >>= 1; + digital_ins >>= 1; + digital_channel++; + } + i += 2; + } + analog_channel = 0; + while ((i < k-1) && (0 != analog_bits)) + { + while (0 == (analog_bits & 1)) + { + analog_bits >>= 1; + analog_channel++; + } + sprintf(atbuf, "A%d", analog_channel); + SETFLOAT(&sample_atoms[0], (x->x_message[i]<<8) + x->x_message[i+1]); + outlet_anything(x->x_sample_out, gensym(atbuf), 1, sample_atoms); + analog_bits >>= 1; + analog_channel++; + i += 2; + } + } + } for (j = 0, i = payloadstart; i < k-1; ++j, ++i) SETFLOAT(&x->x_outbuf[j], x->x_message[i]); /* the payload */ if (j > 0) @@ -505,6 +697,7 @@ buf[18...] data } } + static void unpackxbee_free(t_unpackxbee *x) { } diff --git a/externals/mrpeach/xbee/xbeeio.pd b/externals/mrpeach/xbee/xbeeio.pd new file mode 100644 index 000000000..b19d77ac9 --- /dev/null +++ b/externals/mrpeach/xbee/xbeeio.pd @@ -0,0 +1,1114 @@ +#N canvas 263 330 984 636 10; +#X obj -4 -46 cnv 15 220 380 empty empty Get_Current_IO_Parameters +20 12 0 14 -204800 -13330 0; +#X text 2 457 remote AT command: 64-bit address \, 16-bit address \, +options \, command \, parameters; +#X msg 292 136 RAT 0x0013A200406BFE6C 0x9A17 2 D0 4; +#X obj 383 244 packxbee 2; +#X msg 355 306 devices; +#X obj 383 351 comport 4 9600; +#X msg 312 263 info; +#X msg 334 285 open 4; +#X obj 407 305 print data; +#X obj 383 393 unpackxbee 2; +#X obj 464 398 print status; +#X floatatom 759 483 5 0 0 0 - - -; +#X floatatom 780 503 5 0 0 0 - - -; +#X symbolatom 801 523 10 0 0 0 - - -; +#X floatatom 822 543 5 0 0 0 - - -; +#X floatatom 843 563 5 0 0 0 - - -; +#X obj 1557 502 print other_status; +#X floatatom 864 584 5 0 0 0 - - -; +#X text 722 502 packet_#; +#X text 636 522 destination 16-bit address; +#X text 716 542 transmit_retries; +#X text 744 562 delivery_status; +#X obj 759 461 unpack 0 0 s 0 0 0; +#X text 759 583 discovery_status; +#X floatatom 907 610 5 0 0 0 - - -; +#X floatatom 930 631 5 0 0 0 - - -; +#X symbolatom 953 651 20 0 0 0 - - -; +#X floatatom 1000 692 5 0 0 0 - - -; +#X text 872 630 packet_#; +#X symbolatom 976 671 10 0 0 0 - - -; +#X text 808 650 sender's 64-bit address; +#X text 830 670 sender's 16-bit address; +#X obj 907 461 unpack 0 0 s s 0; +#X text 901 691 receive options; +#X text 659 482 frame_type (139); +#X text 807 609 frame_type (144); +#X msg 324 168 AT AI; +#X obj 759 437 route ZigBee_Transmit_Status ZigBee_Receive_Packet; +#X obj 1056 461 route AT_Command_Response; +#X floatatom 1056 505 5 0 0 0 - - -; +#X floatatom 1075 525 5 0 0 0 - - -; +#X text 1019 524 packet_#; +#X obj 1056 483 unpack 0 0 0 s 0 0 0; +#X floatatom 1095 545 5 0 0 0 - - -; +#X symbolatom 1114 563 5 0 0 0 - - -; +#X text 1047 562 AT command; +#X floatatom 1134 585 5 0 0 0 - - -; +#X floatatom 1153 605 5 0 0 0 - - -; +#X text 1097 604 packet_#; +#X floatatom 1173 625 5 0 0 0 - - -; +#X text 1107 624 data bytes; +#X msg 344 188 AT DH; +#X text 1029 544 data_bytes; +#X text 956 504 frame_type (136); +#X text 1089 584 status; +#X msg 478 376 verbosity \$1; +#X obj 478 357 hradio 15 1 0 3 empty empty empty 0 -8 0 10 -4034 -204786 +-1 2; +#X text 1052 692 Martin Peach 2013_02_20; +#X obj 452 420 route Remote_Command_Response; +#X floatatom 452 473 5 0 0 0 - - -; +#X floatatom 471 495 5 0 0 0 - - -; +#X text 1129 537 packet type; +#X text 1154 559 packet ID; +#X floatatom 569 602 5 0 0 0 - - -; +#X symbolatom 491 535 20 0 0 0 - - -; +#X text 447 533 addr64; +#X symbolatom 510 516 7 0 0 0 - - -; +#X symbolatom 530 557 7 0 0 0 - - -; +#X text 484 556 command; +#X floatatom 549 579 5 0 0 0 - - -; +#X text 499 603 data length; +#X text 507 579 status; +#X obj 452 447 unpack 0 0 s s s 0 0; +#X text 464 515 addr16; +#X obj 549 633 select 0 1 2 3 4; +#X symbolatom 623 276 32 0 0 0 - - -; +#X msg 549 653 set OK; +#X msg 567 674 set ERROR; +#X msg 586 693 set Invalid_Command; +#X msg 605 712 set Invalid_Parameter; +#X msg 623 730 set Transmission_Failed; +#X msg 463 227 verbosity \$1; +#X obj 463 208 hradio 15 1 0 3 empty empty empty 0 -8 0 10 -4034 -204786 +-1 0; +#X msg 292 243 close; +#X msg -1 21 IR; +#X msg -1 373 RAT 0x0013A200406BFE6C 0x9A17 0; +#X obj -1 395 list append; +#X obj -1 416 list trim; +#X msg -1 -23 IC; +#X obj -1 342 t b a; +#X msg -1 131 P0; +#X msg -1 154 P1; +#X msg -1 176 P2; +#X msg -1 198 D0; +#X msg -1 219 D1; +#X msg -1 241 D2; +#X msg -1 263 D3; +#X msg -1 285 D4; +#X msg -1 306 D5; +#X msg -1 -1 LT; +#X msg -1 109 PR; +#X msg -1 65 RP; +#X msg -1 43 %V; +#X msg -1 87 V+; +#X text 287 -53 This patcher uses the remote AT command message to +get and set the I/O pins of a remote xbee; +#X obj -2 436 s tox; +#X obj 383 217 r tox; +#X text 28 20 IO sample rate; +#X text 27 42 supply voltage; +#X text 27 64 RSSI PWM time; +#X text 26 86 Voltage Supply Monitoring; +#X text 27 108 Pull-up Resistor bitmap; +#X text 27 130 PWM0 (pin 6)function; +#X text 27 153 DIO11 (pin 7) function; +#X text 27 175 DIO12 (pin 4) function; +#X text 26 197 AD0/DIO0 (pin 20) function; +#X text 27 218 AD1/DIO1 (pin 19) function; +#X text 27 240 AD2/DIO2 (pin 18) function; +#X text 27 262 AD3/DIO3 (pin 17) function; +#X text 27 284 DIO4 (pin 11) function; +#X text 27 305 DIO5 (pin 15) function; +#X obj 383 612 list prepend; +#X obj 383 636 list trim; +#X text 26 -24 I/O Digital Change Detection; +#N canvas 74 83 1202 457 remote_status 0; +#X obj 228 97 cnv 15 320 130 empty empty I/O_Pin_Function 20 12 0 14 +-204786 -13381 0; +#X obj 249 330 cnv 15 300 72 empty empty Pull-up_Resistor_Bitmap 4 +12 0 14 -204786 -13381 0; +#X obj 131 426 cnv 15 300 72 empty empty I/O_Digital_Change_Detection_Bitmap +4 12 0 14 -261682 -86853 0; +#X obj 93 -11 inlet; +#X obj 152 502 unpack 0 0; +#X obj 152 561 +; +#X obj 152 584 * 1.17188; +#X obj 152 605 nbx 7 14 -1e+37 1e+37 0 0 empty empty mV 56 8 0 10 -4034 +-258113 -1 0 256; +#X text 386 309 1024/1200:; +#X obj 171 36 * 100; +#X obj 171 78 nbx 7 14 -1e+37 1e+37 0 0 empty empty ms 56 8 0 10 -4034 +-258113 -1 0 256; +#X obj 191 623 unpack 0 0; +#X obj 191 682 +; +#X obj 191 705 * 1.17188; +#X obj 191 729 nbx 7 14 -1e+37 1e+37 0 0 empty empty mV 56 8 0 10 -4034 +-258113 -1 0 256; +#X text -40 56 Associate LED blink time:; +#X text 85 77 RSSI PWM time:; +#X text 60 602 supply voltage:; +#X text -8 727 supply voltage monitor threshold:; +#X obj 211 230 unpack 0 0; +#X obj 211 289 +; +#X text 281 292 Pull-up Resistor bitmap:; +#X obj 230 134 vradio 15 1 0 6 P0Val empty P0 0 -8 0 10 -4034 -260097 +-1 1; +#X obj 250 134 vradio 15 1 0 6 P1Val empty P1 0 -8 0 10 -4034 -260097 +-1 0; +#X obj 270 134 vradio 15 1 0 6 P2Val empty P2 0 -8 0 10 -4034 -260097 +-1 0; +#X obj 310 134 vradio 15 1 0 6 D1Val empty D1 0 -8 0 10 -4034 -260097 +-1 0; +#X obj 330 134 vradio 15 1 0 6 D2Val empty D2 0 -8 0 10 -4034 -260097 +-1 0; +#X obj 350 134 vradio 15 1 0 6 D3Val empty D3 0 -8 0 10 -4034 -260097 +-1 0; +#X obj 370 134 vradio 15 1 0 6 D4Val empty D4 0 -8 0 10 -4034 -260097 +-1 0; +#X obj 390 134 vradio 15 1 0 6 D5Val empty D5 0 -8 0 10 -4034 -260097 +-1 1; +#X obj 290 134 vradio 15 1 0 6 empty D0Val D0 0 -8 0 10 -4034 -260097 +-1 1; +#X obj 617 3 print other; +#X obj 112 37 * 10; +#X obj 112 59 nbx 7 14 -1e+37 1e+37 0 0 empty empty ms 56 8 0 10 -4034 +-258113 -1 0 256; +#X obj 93 325 unpack 0 0; +#X obj 93 384 +; +#X obj 251 369 vradio 15 1 0 2 empty empty D7 0 -8 0 10 -4034 -260097 +-1 0; +#X obj 271 369 vradio 15 1 0 2 empty empty P1 0 -8 0 10 -4034 -260097 +-1 1; +#X obj 291 369 vradio 15 1 0 2 empty empty P0 0 -8 0 10 -4034 -260097 +-1 1; +#X obj 311 369 vradio 15 1 0 2 empty empty P2 0 -8 0 10 -4034 -260097 +-1 1; +#X obj 331 369 vradio 15 1 0 2 empty empty D9 0 -8 0 10 -4034 -260097 +-1 1; +#X obj 351 369 vradio 15 1 0 2 empty empty D5 0 -8 0 10 -4034 -260097 +-1 1; +#X obj 371 369 vradio 15 1 0 2 empty empty DI 0 -8 0 10 -4034 -260097 +-1 1; +#X obj 391 369 vradio 15 1 0 2 empty empty D8 0 -8 0 10 -4034 -260097 +-1 1; +#X obj 411 369 vradio 15 1 0 2 empty empty D6 0 -8 0 10 -4034 -260097 +-1 1; +#X obj 431 369 vradio 15 1 0 2 empty empty D0 0 -8 0 10 -4034 -260097 +-1 1; +#X obj 451 369 vradio 15 1 0 2 empty empty D1 0 -8 0 10 -4034 -260097 +-1 1; +#X obj 491 369 vradio 15 1 0 2 empty empty D3 0 -8 0 10 -4034 -260097 +-1 1; +#X obj 511 369 vradio 15 1 0 2 empty empty D4 0 -8 0 10 -4034 -260097 +-1 1; +#X obj 471 369 vradio 15 1 0 2 empty empty D2 0 -8 0 10 -4034 -260097 +-1 1; +#X obj 211 311 bits xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +; +#X obj 133 465 vradio 15 1 0 2 empty empty D7 0 -8 0 10 -4034 -260097 +-1 0; +#X obj 153 465 vradio 15 1 0 2 empty empty P1 0 -8 0 10 -4034 -260097 +-1 0; +#X obj 173 465 vradio 15 1 0 2 empty empty P0 0 -8 0 10 -4034 -260097 +-1 0; +#X obj 193 465 vradio 15 1 0 2 empty empty P2 0 -8 0 10 -4034 -260097 +-1 0; +#X obj 213 465 vradio 15 1 0 2 empty empty D9 0 -8 0 10 -4034 -260097 +-1 0; +#X obj 233 465 vradio 15 1 0 2 empty empty D5 0 -8 0 10 -4034 -260097 +-1 0; +#X obj 253 465 vradio 15 1 0 2 empty empty DI 0 -8 0 10 -4034 -260097 +-1 0; +#X obj 273 465 vradio 15 1 0 2 empty empty D8 0 -8 0 10 -4034 -260097 +-1 0; +#X obj 293 465 vradio 15 1 0 2 empty empty D6 0 -8 0 10 -4034 -260097 +-1 0; +#X obj 313 465 vradio 15 1 0 2 empty empty D0 0 -8 0 10 -4034 -260097 +-1 0; +#X obj 333 465 vradio 15 1 0 2 empty empty D1 0 -8 0 10 -4034 -260097 +-1 0; +#X obj 373 465 vradio 15 1 0 2 empty empty D3 0 -8 0 10 -4034 -260097 +-1 0; +#X obj 393 465 vradio 15 1 0 2 empty empty D4 0 -8 0 10 -4034 -260097 +-1 0; +#X obj 353 465 vradio 15 1 0 2 empty empty D2 0 -8 0 10 -4034 -260097 +-1 0; +#X obj 93 406 bits xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; +#X text 402 132 -Disabled; +#X text 402 162 -Analog Input; +#X text 402 177 -Digital Input; +#X text 402 192 -Digital Output Low; +#X text 402 207 -Digital Output High; +#X text 523 365 -OFF; +#X text 523 382 -ON; +#X text 405 462 -OFF; +#X text 405 479 -ON; +#X text 213 584 scale factor (1024/1200); +#X text 252 704 scale factor (1024/1200); +#X text 404 116 _FUNCTION___________; +#X text 402 147 -Special Function; +#X text 33 182 I/O Sample Rate; +#X obj 132 103 unpack 0 0; +#X obj 132 162 +; +#X obj 132 185 nbx 7 14 -1e+37 1e+37 0 0 empty empty ms 56 8 0 10 -4034 +-258113 -1 0 256; +#X obj 587 266 cnv 15 324 68 empty empty Enabled_Digital_Ins 4 12 0 +14 -204786 -13381 0; +#X text 709 214 1024/1200:; +#X obj 587 105 +; +#X obj 587 244 bits xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +; +#X floatatom 566 53 5 0 0 0 - - -; +#X floatatom 587 131 5 0 0 0 - - -; +#X obj 132 125 * 256; +#X obj 212 252 * 256; +#X obj 587 73 * 256; +#X obj 93 347 * 256; +#X obj 152 524 * 256; +#X obj 191 645 * 256; +#X obj 631 361 cnv 15 324 48 empty empty Enabled_Analog_Ins 4 12 0 +14 -204786 -13381 0; +#X text 805 337 1024/1200:; +#X obj 630 339 bits xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +; +#X floatatom 630 53 5 0 0 0 - - -; +#X obj 651 165 cnv 15 348 74 empty empty Digital_In_Values 4 12 0 14 +-261682 -13381 0; +#X text 826 141 1024/1200:; +#X obj 651 95 +; +#X obj 651 143 bits xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +; +#X floatatom 651 121 5 0 0 0 - - -; +#X obj 651 73 * 256; +#X obj 694 95 +; +#X floatatom 694 121 5 0 0 0 - - -; +#X obj 694 73 * 256; +#X obj 737 95 +; +#X floatatom 737 121 5 0 0 0 - - -; +#X obj 737 73 * 256; +#X obj 780 95 +; +#X floatatom 780 121 5 0 0 0 - - -; +#X obj 780 73 * 256; +#X obj 822 95 +; +#X floatatom 822 121 5 0 0 0 - - -; +#X obj 822 73 * 256; +#X obj 865 95 +; +#X floatatom 865 121 5 0 0 0 - - -; +#X obj 865 73 * 256; +#X obj 566 32 unpack 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 +; +#X obj 1000 79 cnv 15 140 160 empty empty IO_Samples 20 12 0 14 -261682 +-66577 0; +#X obj 1016 111 nbx 5 14 -1e+37 1e+37 0 0 empty empty 1st 60 8 0 10 +-260097 -86853 -86853 0 256; +#X obj 1016 131 nbx 5 14 -1e+37 1e+37 0 0 empty empty 2nd 60 8 0 10 +-260097 -86853 -86853 0 256; +#X obj 1016 151 nbx 5 14 -1e+37 1e+37 0 0 empty empty 3rd 60 8 0 10 +-260097 -86853 -86853 0 256; +#X obj 1016 171 nbx 5 14 -1e+37 1e+37 0 0 empty empty 4th 60 8 0 10 +-260097 -86853 -86853 0 256; +#X obj 1016 191 nbx 5 14 -1e+37 1e+37 0 0 empty empty 5th 60 8 0 10 +-260097 -86853 -86853 0 256; +#X obj 1016 211 nbx 5 14 -1e+37 1e+37 0 0 empty empty 6th 60 8 0 10 +-260097 -86853 -86853 0 256; +#X obj 933 375 vradio 15 1 0 2 empty empty A0 0 -8 0 10 -4034 -260097 +-1 0; +#X obj 912 375 vradio 15 1 0 2 empty empty A1 0 -8 0 10 -4034 -260097 +-1 0; +#X obj 892 375 vradio 15 1 0 2 empty empty A2 0 -8 0 10 -4034 -260097 +-1 0; +#X obj 872 375 vradio 15 1 0 2 empty empty A3 0 -8 0 10 -4034 -260097 +-1 0; +#X obj 791 375 vradio 15 1 0 2 empty empty V+ 0 -8 0 10 -4034 -260097 +-1 0; +#X obj 890 300 vradio 15 1 0 2 empty empty D0 0 -8 0 10 -4034 -260097 +-1 0; +#X obj 869 300 vradio 15 1 0 2 empty empty D1 0 -8 0 10 -4034 -260097 +-1 0; +#X obj 849 300 vradio 15 1 0 2 empty empty D2 0 -8 0 10 -4034 -260097 +-1 0; +#X obj 829 300 vradio 15 1 0 2 empty empty D3 0 -8 0 10 -4034 -260097 +-1 0; +#X obj 809 300 vradio 15 1 0 2 empty empty D4 0 -8 0 10 -4034 -260097 +-1 0; +#X obj 789 300 vradio 15 1 0 2 empty empty D5 0 -8 0 10 -4034 -260097 +-1 0; +#X obj 768 300 vradio 15 1 0 2 empty empty D6 0 -8 0 10 -4034 -260097 +-1 0; +#X obj 748 300 vradio 15 1 0 2 empty empty D7 0 -8 0 10 -4034 -260097 +-1 0; +#X obj 687 300 vradio 15 1 0 2 empty empty P0 0 -8 0 10 -4034 -260097 +-1 0; +#X obj 667 300 vradio 15 1 0 2 empty empty P1 0 -8 0 10 -4034 -260097 +-1 0; +#X obj 647 300 vradio 15 1 0 2 empty empty P2 0 -8 0 10 -4034 -260097 +-1 0; +#X text 905 313 -ON; +#X text 905 297 -OFF; +#X text 947 388 -ON; +#X text 947 372 -OFF; +#X obj 954 204 vradio 15 1 0 2 empty empty D0 0 -8 0 10 -4034 -260097 +-1 0; +#X obj 933 204 vradio 15 1 0 2 empty empty D1 0 -8 0 10 -4034 -260097 +-1 0; +#X obj 913 204 vradio 15 1 0 2 empty empty D2 0 -8 0 10 -4034 -260097 +-1 0; +#X obj 893 204 vradio 15 1 0 2 empty empty D3 0 -8 0 10 -4034 -260097 +-1 0; +#X obj 873 204 vradio 15 1 0 2 empty empty D4 0 -8 0 10 -4034 -260097 +-1 0; +#X obj 853 204 vradio 15 1 0 2 empty empty D5 0 -8 0 10 -4034 -260097 +-1 0; +#X obj 832 204 vradio 15 1 0 2 empty empty D6 0 -8 0 10 -4034 -260097 +-1 0; +#X obj 812 204 vradio 15 1 0 2 empty empty D7 0 -8 0 10 -4034 -260097 +-1 0; +#X obj 751 204 vradio 15 1 0 2 empty empty P0 0 -8 0 10 -4034 -260097 +-1 0; +#X obj 731 204 vradio 15 1 0 2 empty empty P1 0 -8 0 10 -4034 -260097 +-1 0; +#X obj 711 204 vradio 15 1 0 2 empty empty P2 0 -8 0 10 -4034 -260097 +-1 0; +#X text 969 217 -ON; +#X text 969 201 -OFF; +#X obj 93 15 route IC LT IR %V RP V+ PR P0 P1 P2 D0 D1 D2 D3 D4 D5 +IS; +#X obj 466 -10 route SAMPLE_FRAME; +#X connect 3 0 161 0; +#X connect 4 0 93 0; +#X connect 4 1 5 1; +#X connect 5 0 6 0; +#X connect 6 0 7 0; +#X connect 9 0 10 0; +#X connect 11 0 94 0; +#X connect 11 1 12 1; +#X connect 12 0 13 0; +#X connect 13 0 14 0; +#X connect 19 0 90 0; +#X connect 19 1 20 1; +#X connect 20 0 50 0; +#X connect 32 0 33 0; +#X connect 34 0 92 0; +#X connect 34 1 35 1; +#X connect 35 0 65 0; +#X connect 50 2 36 0; +#X connect 50 3 37 0; +#X connect 50 4 38 0; +#X connect 50 5 39 0; +#X connect 50 6 40 0; +#X connect 50 7 41 0; +#X connect 50 8 42 0; +#X connect 50 9 43 0; +#X connect 50 10 44 0; +#X connect 50 11 45 0; +#X connect 50 12 46 0; +#X connect 50 13 49 0; +#X connect 50 14 47 0; +#X connect 50 15 48 0; +#X connect 65 2 51 0; +#X connect 65 3 52 0; +#X connect 65 4 53 0; +#X connect 65 5 54 0; +#X connect 65 6 55 0; +#X connect 65 7 56 0; +#X connect 65 8 57 0; +#X connect 65 9 58 0; +#X connect 65 10 59 0; +#X connect 65 11 60 0; +#X connect 65 12 61 0; +#X connect 65 13 64 0; +#X connect 65 14 62 0; +#X connect 65 15 63 0; +#X connect 80 0 89 0; +#X connect 80 1 81 1; +#X connect 81 0 82 0; +#X connect 85 0 86 0; +#X connect 85 0 88 0; +#X connect 86 3 143 0; +#X connect 86 4 142 0; +#X connect 86 5 141 0; +#X connect 86 8 140 0; +#X connect 86 9 139 0; +#X connect 86 10 138 0; +#X connect 86 11 137 0; +#X connect 86 12 136 0; +#X connect 86 13 135 0; +#X connect 86 14 134 0; +#X connect 86 15 133 0; +#X connect 89 0 81 0; +#X connect 90 0 20 0; +#X connect 91 0 85 0; +#X connect 92 0 35 0; +#X connect 93 0 5 0; +#X connect 94 0 12 0; +#X connect 97 8 132 0; +#X connect 97 12 131 0; +#X connect 97 13 130 0; +#X connect 97 14 129 0; +#X connect 97 15 128 0; +#X connect 101 0 102 0; +#X connect 101 0 103 0; +#X connect 101 0 122 0; +#X connect 102 3 158 0; +#X connect 102 4 157 0; +#X connect 102 5 156 0; +#X connect 102 8 155 0; +#X connect 102 9 154 0; +#X connect 102 10 153 0; +#X connect 102 11 152 0; +#X connect 102 12 151 0; +#X connect 102 13 150 0; +#X connect 102 14 149 0; +#X connect 102 15 148 0; +#X connect 104 0 101 0; +#X connect 105 0 106 0; +#X connect 105 0 123 0; +#X connect 107 0 105 0; +#X connect 108 0 109 0; +#X connect 108 0 124 0; +#X connect 110 0 108 0; +#X connect 111 0 112 0; +#X connect 111 0 125 0; +#X connect 113 0 111 0; +#X connect 114 0 115 0; +#X connect 114 0 126 0; +#X connect 116 0 114 0; +#X connect 117 0 118 0; +#X connect 117 0 127 0; +#X connect 119 0 117 0; +#X connect 120 0 87 0; +#X connect 120 1 91 0; +#X connect 120 2 85 1; +#X connect 120 3 98 0; +#X connect 120 3 97 0; +#X connect 120 4 104 0; +#X connect 120 5 101 1; +#X connect 120 6 107 0; +#X connect 120 7 105 1; +#X connect 120 8 110 0; +#X connect 120 9 108 1; +#X connect 120 10 113 0; +#X connect 120 11 111 1; +#X connect 120 12 116 0; +#X connect 120 13 114 1; +#X connect 120 14 119 0; +#X connect 120 15 117 1; +#X connect 161 0 34 0; +#X connect 161 1 32 0; +#X connect 161 2 80 0; +#X connect 161 3 4 0; +#X connect 161 4 9 0; +#X connect 161 5 11 0; +#X connect 161 6 19 0; +#X connect 161 7 22 0; +#X connect 161 8 23 0; +#X connect 161 9 24 0; +#X connect 161 10 30 0; +#X connect 161 11 25 0; +#X connect 161 12 26 0; +#X connect 161 13 27 0; +#X connect 161 14 28 0; +#X connect 161 15 29 0; +#X connect 161 16 120 0; +#X connect 161 17 162 0; +#X connect 162 0 120 0; +#X connect 162 1 31 0; +#X restore 383 659 pd remote_status; +#X obj 714 -44 cnv 15 420 80 empty empty Set_Digital_Outputs 40 12 +0 14 -204786 -13381 0; +#X obj 913 -17 tgl 15 0 empty empty D5 1 8 0 10 -4034 -258113 -1 0 +1; +#X obj 718 -17 tgl 15 0 empty empty P0 1 8 0 10 -4034 -258113 -1 0 +1; +#N canvas 54 264 589 223 digital_outs 0; +#X obj 6 -38 cnv 15 560 200 empty empty empty 20 12 0 14 -232576 -66577 +0; +#X obj 26 37 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1 +; +#X msg 26 83 4; +#X msg 53 83 5; +#X obj 26 58 sel 0 1; +#X obj 26 -27 inlet; +#X obj 86 -27 inlet; +#X obj 146 -27 inlet; +#X obj 206 -27 inlet; +#X obj 266 -27 inlet; +#X obj 326 -27 inlet; +#X obj 386 -27 inlet; +#X obj 446 -27 inlet; +#X obj 506 -27 inlet; +#X obj 86 37 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1 +; +#X msg 86 83 4; +#X msg 113 83 5; +#X obj 86 58 sel 0 1; +#X obj 146 37 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 +1; +#X msg 146 83 4; +#X msg 173 83 5; +#X obj 146 58 sel 0 1; +#X obj 206 37 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 +1; +#X msg 206 83 4; +#X msg 233 83 5; +#X obj 206 58 sel 0 1; +#X obj 266 37 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 +1; +#X msg 266 83 4; +#X msg 293 83 5; +#X obj 266 58 sel 0 1; +#X obj 326 37 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 +1; +#X msg 326 83 4; +#X msg 353 83 5; +#X obj 326 58 sel 0 1; +#X obj 386 37 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 +1; +#X msg 386 83 4; +#X msg 413 83 5; +#X obj 386 58 sel 0 1; +#X obj 446 37 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 +1; +#X msg 446 83 4; +#X msg 473 83 5; +#X obj 446 58 sel 0 1; +#X obj 506 37 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 +1; +#X msg 506 83 4; +#X msg 533 83 5; +#X obj 506 58 sel 0 1; +#X obj 26 127 outlet; +#X obj 86 127 outlet; +#X obj 146 127 outlet; +#X obj 206 127 outlet; +#X obj 266 127 outlet; +#X obj 326 127 outlet; +#X obj 386 127 outlet; +#X obj 446 127 outlet; +#X obj 506 127 outlet; +#X connect 1 0 4 0; +#X connect 2 0 46 0; +#X connect 3 0 46 0; +#X connect 4 0 2 0; +#X connect 4 1 3 0; +#X connect 5 0 1 0; +#X connect 6 0 14 0; +#X connect 7 0 18 0; +#X connect 8 0 22 0; +#X connect 9 0 26 0; +#X connect 10 0 30 0; +#X connect 11 0 34 0; +#X connect 12 0 38 0; +#X connect 13 0 42 0; +#X connect 14 0 17 0; +#X connect 15 0 47 0; +#X connect 16 0 47 0; +#X connect 17 0 15 0; +#X connect 17 1 16 0; +#X connect 18 0 21 0; +#X connect 19 0 48 0; +#X connect 20 0 48 0; +#X connect 21 0 19 0; +#X connect 21 1 20 0; +#X connect 22 0 25 0; +#X connect 23 0 49 0; +#X connect 24 0 49 0; +#X connect 25 0 23 0; +#X connect 25 1 24 0; +#X connect 26 0 29 0; +#X connect 27 0 50 0; +#X connect 28 0 50 0; +#X connect 29 0 27 0; +#X connect 29 1 28 0; +#X connect 30 0 33 0; +#X connect 31 0 51 0; +#X connect 32 0 51 0; +#X connect 33 0 31 0; +#X connect 33 1 32 0; +#X connect 34 0 37 0; +#X connect 35 0 52 0; +#X connect 36 0 52 0; +#X connect 37 0 35 0; +#X connect 37 1 36 0; +#X connect 38 0 41 0; +#X connect 39 0 53 0; +#X connect 40 0 53 0; +#X connect 41 0 39 0; +#X connect 41 1 40 0; +#X connect 42 0 45 0; +#X connect 43 0 54 0; +#X connect 44 0 54 0; +#X connect 45 0 43 0; +#X connect 45 1 44 0; +#X restore 718 4 pd digital_outs xxxxxxxxxxxxxxxxx; +#X obj 742 -17 tgl 15 0 empty empty P1 1 8 0 10 -4034 -258113 -1 0 +1; +#X obj 766 -17 tgl 15 0 empty empty P2 1 8 0 10 -4034 -258113 -1 0 +1; +#X obj 791 -17 tgl 15 0 empty empty D0 1 8 0 10 -4034 -258113 -1 0 +1; +#X obj 815 -17 tgl 15 0 empty empty D1 1 8 0 10 -4034 -258113 -1 0 +1; +#X obj 839 -17 tgl 15 0 empty empty D2 1 8 0 10 -4034 -258113 -1 0 +1; +#X obj 864 -17 tgl 15 0 empty empty D3 1 8 0 10 -4034 -258113 -1 0 +1; +#X obj 888 -17 tgl 15 0 empty empty D4 1 8 0 10 -4034 -258113 -1 0 +1; +#X text 624 132 P0 = pin6; +#X text 624 142 P1 = pin7; +#X text 624 152 P2 = pin4; +#X text 624 162 D0 = pin20; +#X text 624 172 D1 = pin19; +#X text 624 182 D2 = pin18; +#X text 624 192 D3 = pin17; +#X text 624 202 D4 = pin11; +#X text 624 212 D5 = pin15; +#X obj 714 37 cnv 15 420 230 empty empty Set_Remote_IO_Pin_Function +40 12 0 14 -261682 -86853 0; +#N canvas 4 77 1271 611 set_pin_functions 0; +#X obj 26 -23 cnv 15 1200 600 empty empty empty 20 12 0 14 -204800 +-66577 0; +#X obj 176 326 list append; +#X msg 176 228 RAT; +#X msg 41 199 0x0013A200406BFE6C; +#X obj 176 356 list append; +#X msg 305 253 0x9A17; +#X obj 176 406 list append; +#X msg 271 350 2; +#X obj 176 467 list append; +#X msg 273 450 P0; +#X obj 176 493 list append; +#X obj 176 514 list trim; +#X obj 41 -7 inlet; +#X obj 286 -7 inlet; +#X obj 396 -7 inlet; +#X obj 506 -7 inlet; +#X obj 616 -7 inlet; +#X obj 726 -7 inlet; +#X obj 836 -7 inlet; +#X obj 946 -7 inlet; +#X obj 176 541 outlet; +#X obj 1056 -7 inlet; +#X obj 176 147 t b b b b b b f; +#X obj 41 22 route remote64 remote16; +#X obj 41 94 prepend set; +#X obj 108 125 prepend set; +#X obj 286 147 t b b b b b b f; +#X obj 396 147 t b b b b b b f; +#X obj 506 147 t b b b b b b f; +#X obj 616 147 t b b b b b b f; +#X obj 726 147 t b b b b b b f; +#X obj 836 147 t b b b b b b f; +#X obj 946 147 t b b b b b b f; +#X obj 1056 147 t b b b b b b f; +#X msg 303 450 P1; +#X msg 333 450 P2; +#X msg 363 450 D0; +#X msg 393 450 D1; +#X msg 423 450 D2; +#X msg 453 450 D3; +#X msg 483 450 D4; +#X msg 513 450 D5; +#X connect 1 0 4 0; +#X connect 2 0 1 0; +#X connect 3 0 1 1; +#X connect 4 0 6 0; +#X connect 5 0 4 1; +#X connect 6 0 8 0; +#X connect 7 0 6 1; +#X connect 8 0 10 0; +#X connect 9 0 8 1; +#X connect 10 0 11 0; +#X connect 11 0 20 0; +#X connect 12 0 23 0; +#X connect 13 0 26 0; +#X connect 14 0 27 0; +#X connect 15 0 28 0; +#X connect 16 0 29 0; +#X connect 17 0 30 0; +#X connect 18 0 31 0; +#X connect 19 0 32 0; +#X connect 21 0 33 0; +#X connect 22 0 2 0; +#X connect 22 2 3 0; +#X connect 22 3 5 0; +#X connect 22 4 7 0; +#X connect 22 5 9 0; +#X connect 22 6 10 1; +#X connect 23 0 24 0; +#X connect 23 1 25 0; +#X connect 23 2 22 0; +#X connect 24 0 3 0; +#X connect 25 0 5 0; +#X connect 26 0 2 0; +#X connect 26 2 3 0; +#X connect 26 3 5 0; +#X connect 26 4 7 0; +#X connect 26 5 34 0; +#X connect 26 6 10 1; +#X connect 27 0 2 0; +#X connect 27 2 3 0; +#X connect 27 3 5 0; +#X connect 27 4 7 0; +#X connect 27 5 35 0; +#X connect 27 6 10 1; +#X connect 28 0 2 0; +#X connect 28 2 3 0; +#X connect 28 3 5 0; +#X connect 28 4 7 0; +#X connect 28 5 36 0; +#X connect 28 6 10 1; +#X connect 29 0 2 0; +#X connect 29 2 3 0; +#X connect 29 3 5 0; +#X connect 29 5 37 0; +#X connect 29 6 10 1; +#X connect 30 0 2 0; +#X connect 30 2 3 0; +#X connect 30 3 5 0; +#X connect 30 4 7 0; +#X connect 30 5 38 0; +#X connect 30 6 10 1; +#X connect 31 0 2 0; +#X connect 31 2 3 0; +#X connect 31 3 5 0; +#X connect 31 4 7 0; +#X connect 31 5 39 0; +#X connect 31 6 10 1; +#X connect 32 0 2 0; +#X connect 32 2 3 0; +#X connect 32 3 5 0; +#X connect 32 4 7 0; +#X connect 32 5 40 0; +#X connect 32 6 10 1; +#X connect 33 0 2 0; +#X connect 33 2 3 0; +#X connect 33 3 5 0; +#X connect 33 4 7 0; +#X connect 33 5 41 0; +#X connect 33 6 10 1; +#X connect 34 0 8 1; +#X connect 35 0 8 1; +#X connect 36 0 8 1; +#X connect 37 0 8 1; +#X connect 38 0 8 1; +#X connect 39 0 8 1; +#X connect 40 0 8 1; +#X connect 41 0 8 1; +#X restore 718 227 pd set_pin_functions XXXXXXXXXXXXXXXXXXXXXXXXXX +; +#X obj 718 79 vradio 15 1 0 6 empty empty P0 0 -8 0 10 -4034 -260097 +-1 1; +#X obj 752 79 vradio 15 1 0 6 empty empty P1 0 -8 0 10 -4034 -260097 +-1 0; +#X obj 787 79 vradio 15 1 0 6 empty empty P2 0 -8 0 10 -4034 -260097 +-1 0; +#X obj 857 79 vradio 15 1 0 6 empty empty D1 0 -8 0 10 -4034 -260097 +-1 0; +#X obj 892 79 vradio 15 1 0 6 empty empty D2 0 -8 0 10 -4034 -260097 +-1 0; +#X obj 927 79 vradio 15 1 0 6 empty empty D3 0 -8 0 10 -4034 -260097 +-1 0; +#X obj 962 79 vradio 15 1 0 6 empty empty D4 0 -8 0 10 -4034 -260097 +-1 0; +#X obj 997 79 vradio 15 1 0 6 empty empty D5 0 -8 0 10 -4034 -260097 +-1 1; +#X obj 822 79 vradio 15 1 0 6 empty empty D0 0 -8 0 10 -4034 -260097 +-1 0; +#X text 1009 77 -Disabled; +#X text 1009 107 -Analog Input; +#X text 1009 122 -Digital Input; +#X text 1009 137 -Digital Output Low; +#X text 1009 152 -Digital Output High; +#X text 1011 61 _FUNCTION___________; +#X text 1009 92 -Special Function; +#X msg 501 -7 remote64 0x0013A200406BFE6C; +#X msg 536 28 remote16 0x9A17; +#X text 501 -24 set the 64-bit remote address; +#X text 535 10 set the 16-bit remote address; +#X obj 713 297 cnv 15 600 140 empty empty Sample 20 12 0 14 -257985 +-83269 0; +#X msg 722 325 IS; +#X text 749 324 force sample; +#X obj 1139 36 r P0Val; +#X obj 1139 62 prepend set; +#X obj 1219 62 prepend set; +#X obj 1219 36 r P1Val; +#X obj 1299 62 prepend set; +#X obj 1379 62 prepend set; +#X obj 1459 62 prepend set; +#X obj 1539 62 prepend set; +#X obj 1619 62 prepend set; +#X obj 1699 62 prepend set; +#X obj 1779 62 prepend set; +#X obj 1299 36 r P2Val; +#X obj 1459 36 r D1Val; +#X obj 1539 36 r D2Val; +#X obj 1619 36 r D3Val; +#X obj 1699 36 r D4Val; +#X obj 1779 36 r D5Val; +#X text 27 -2 Associate LED blink time; +#X obj 1379 36 r D0Val; +#X obj 1320 478 route ZigBee_IO_Data_Sample_Rx_Indicator; +#X text 275 60 set sample rate; +#X floatatom 388 52 5 0 0 0 - - -; +#X obj 373 75 f; +#X obj 373 30 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1 +-1; +#X msg 1344 519 SAMPLE_FRAME; +#X floatatom 1320 563 5 0 0 0 - - -; +#X floatatom 1343 583 5 0 0 0 - - -; +#X symbolatom 1366 603 20 0 0 0 - - -; +#X floatatom 1412 645 5 0 0 0 - - -; +#X msg 248 60 0; +#X symbolatom 1389 623 10 0 0 0 - - -; +#X text 1220 562 frame_type (146); +#X obj 1320 541 unpack 0 0 s s 0; +#X text 1242 622 sender's 16-bit address; +#X text 1220 602 sender's 64-bit address; +#X text 1315 644 receive_options; +#X text 1270 582 data length; +#X obj 1187 310 print else; +#X text 874 245 Sample Frame; +#X obj 417 577 list trim; +#X obj 872 266 route D0 D1 D2 D3 D4 D5 D10 D11 D12 A0 A1 A2 A3 A7; +#X obj 866 296 cnv 15 300 50 empty empty Digital_Inputs 20 12 0 14 +-204786 -13381 0; +#X obj 866 347 cnv 15 400 90 empty empty Analog_Inputs 20 12 0 14 -232576 +-45076 0; +#X obj 869 380 nbx 5 14 -1e+37 1e+37 0 0 empty empty A0 40 8 0 10 -204800 +-13330 -159808 0 256; +#X obj 929 380 nbx 5 14 -1e+37 1e+37 0 0 empty empty A1 40 8 0 10 -204800 +-13330 -159808 0 256; +#X obj 989 380 nbx 5 14 -1e+37 1e+37 0 0 empty empty A2 40 8 0 10 -204800 +-13330 -159808 0 256; +#X obj 1049 380 nbx 5 14 -1e+37 1e+37 0 0 empty empty A3 40 8 0 10 +-204800 -13330 -159808 0 256; +#X obj 1109 380 nbx 5 14 -1e+37 1e+37 0 0 empty empty V+ 40 8 0 10 +-204800 -13330 -159808 0 256; +#X obj 872 322 nbx 2 14 -1e+37 1e+37 0 0 empty empty D0 8 20 0 10 -4034 +-1 -258113 0 256; +#X obj 912 322 nbx 2 14 -1e+37 1e+37 0 0 empty empty D1 8 20 0 10 -4034 +-1 -258113 0 256; +#X obj 942 322 nbx 2 14 -1e+37 1e+37 0 0 empty empty D2 8 20 0 10 -4034 +-1 -258113 0 256; +#X obj 972 322 nbx 2 14 -1e+37 1e+37 0 0 empty empty D3 8 20 0 10 -4034 +-1 -258113 0 256; +#X obj 1002 322 nbx 2 14 -1e+37 1e+37 0 0 empty empty D4 8 20 0 10 +-4034 -1 -258113 0 256; +#X obj 1032 322 nbx 2 14 -1e+37 1e+37 0 0 empty empty D5 8 20 0 10 +-4034 -1 -258113 0 256; +#X obj 1062 322 nbx 2 14 -1e+37 1e+37 0 0 empty empty P0 8 20 0 10 +-4034 -1 -258113 0 256; +#X obj 1092 322 nbx 2 14 -1e+37 1e+37 0 0 empty empty P1 8 20 0 10 +-4034 -1 -258113 0 256; +#X obj 1122 322 nbx 2 14 -1e+37 1e+37 0 0 empty empty P2 8 20 0 10 +-4034 -1 -258113 0 256; +#X msg 270 114 RAT 0x0013A200406BFE6C 0x9A17 2 V+ \$1; +#X obj 521 78 nbx 5 14 -1e+37 1e+37 0 0 empty empty Supply_Voltage_Threshold +0 -8 0 10 -4034 -13381 -1 0 256; +#X obj 869 419 nbx 5 14 -1e+37 1e+37 0 0 empty empty A0_mV 40 8 0 10 +-204800 -13330 -159808 0 256; +#X obj 869 399 * 1.17302; +#X obj 949 419 nbx 5 14 -1e+37 1e+37 0 0 empty empty A1_mV 40 8 0 10 +-204800 -13330 -159808 0 256; +#X obj 949 399 * 1.17302; +#X obj 1029 419 nbx 5 14 -1e+37 1e+37 0 0 empty empty A2_mV 40 8 0 +10 -204800 -13330 -159808 0 256; +#X obj 1029 399 * 1.17302; +#X obj 1109 419 nbx 5 14 -1e+37 1e+37 0 0 empty empty A3_mV 40 8 0 +10 -204800 -13330 -159808 0 256; +#X obj 1109 399 * 1.17302; +#X obj 1189 419 nbx 5 14 -1e+37 1e+37 0 0 empty empty V+_mV 40 8 0 +10 -204800 -13330 -159808 0 256; +#X obj 1189 399 * 1.17302; +#X msg 248 92 RAT 0x0013A200406BFE6C 0x9A17 2 IR \$1; +#X text 424 51 ms; +#X obj 506 97 f; +#X obj 506 48 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1 +-1; +#X connect 2 0 3 0; +#X connect 3 0 5 0; +#X connect 4 0 5 0; +#X connect 5 0 9 0; +#X connect 5 1 10 0; +#X connect 6 0 5 0; +#X connect 7 0 5 0; +#X connect 9 0 121 0; +#X connect 9 1 209 0; +#X connect 9 2 58 0; +#X connect 22 0 11 0; +#X connect 22 1 12 0; +#X connect 22 2 13 0; +#X connect 22 3 14 0; +#X connect 22 4 15 0; +#X connect 22 5 17 0; +#X connect 32 0 24 0; +#X connect 32 1 25 0; +#X connect 32 2 26 0; +#X connect 32 3 29 0; +#X connect 32 4 27 0; +#X connect 36 0 3 0; +#X connect 37 0 22 0; +#X connect 37 1 32 0; +#X connect 37 2 38 0; +#X connect 38 0 42 0; +#X connect 38 1 189 0; +#X connect 42 0 39 0; +#X connect 42 1 40 0; +#X connect 42 2 43 0; +#X connect 42 3 44 0; +#X connect 42 4 46 0; +#X connect 42 5 47 0; +#X connect 42 6 49 0; +#X connect 51 0 3 0; +#X connect 55 0 9 0; +#X connect 56 0 55 0; +#X connect 58 0 72 0; +#X connect 58 1 37 0; +#X connect 72 0 59 0; +#X connect 72 1 60 0; +#X connect 72 2 64 0; +#X connect 72 3 66 0; +#X connect 72 4 67 0; +#X connect 72 4 121 1; +#X connect 72 5 69 0; +#X connect 72 5 74 0; +#X connect 72 6 63 0; +#X connect 74 0 76 0; +#X connect 74 1 77 0; +#X connect 74 2 78 0; +#X connect 74 3 79 0; +#X connect 74 4 80 0; +#X connect 76 0 75 0; +#X connect 77 0 75 0; +#X connect 78 0 75 0; +#X connect 79 0 75 0; +#X connect 80 0 75 0; +#X connect 81 0 3 0; +#X connect 82 0 81 0; +#X connect 83 0 5 0; +#X connect 84 0 89 0; +#X connect 85 0 86 0; +#X connect 86 0 87 0; +#X connect 87 0 105 0; +#X connect 88 0 89 0; +#X connect 89 0 85 0; +#X connect 89 1 86 1; +#X connect 90 0 89 0; +#X connect 91 0 89 0; +#X connect 92 0 89 0; +#X connect 93 0 89 0; +#X connect 94 0 89 0; +#X connect 95 0 89 0; +#X connect 96 0 89 0; +#X connect 97 0 89 0; +#X connect 98 0 89 0; +#X connect 99 0 89 0; +#X connect 100 0 89 0; +#X connect 101 0 89 0; +#X connect 102 0 89 0; +#X connect 103 0 89 0; +#X connect 106 0 3 0; +#X connect 121 0 122 0; +#X connect 122 0 124 0; +#X connect 126 0 128 8; +#X connect 127 0 128 0; +#X connect 128 0 147 0; +#X connect 128 1 148 0; +#X connect 128 2 149 0; +#X connect 128 3 155 0; +#X connect 128 4 150 0; +#X connect 128 5 151 0; +#X connect 128 6 152 0; +#X connect 128 7 153 0; +#X connect 128 8 154 0; +#X connect 129 0 128 1; +#X connect 130 0 128 2; +#X connect 131 0 128 3; +#X connect 132 0 128 4; +#X connect 133 0 128 5; +#X connect 134 0 128 6; +#X connect 135 0 128 7; +#X connect 146 0 3 0; +#X connect 147 0 146 0; +#X connect 148 0 146 1; +#X connect 149 0 146 2; +#X connect 150 0 146 4; +#X connect 151 0 146 5; +#X connect 152 0 146 6; +#X connect 153 0 146 7; +#X connect 154 0 146 8; +#X connect 155 0 146 3; +#X connect 163 0 146 0; +#X connect 164 0 146 0; +#X connect 168 0 89 0; +#X connect 170 0 171 0; +#X connect 171 0 147 0; +#X connect 172 0 148 0; +#X connect 173 0 172 0; +#X connect 174 0 149 0; +#X connect 175 0 155 0; +#X connect 176 0 150 0; +#X connect 177 0 151 0; +#X connect 178 0 152 0; +#X connect 179 0 153 0; +#X connect 180 0 154 0; +#X connect 181 0 174 0; +#X connect 182 0 176 0; +#X connect 183 0 177 0; +#X connect 184 0 178 0; +#X connect 185 0 179 0; +#X connect 186 0 180 0; +#X connect 188 0 175 0; +#X connect 189 0 194 0; +#X connect 189 0 202 0; +#X connect 189 1 16 0; +#X connect 191 0 192 1; +#X connect 192 0 239 0; +#X connect 193 0 192 0; +#X connect 194 0 121 1; +#X connect 199 0 239 0; +#X connect 202 0 195 0; +#X connect 202 1 196 0; +#X connect 202 2 197 0; +#X connect 202 3 200 0; +#X connect 202 4 198 0; +#X connect 209 0 210 0; +#X connect 210 0 218 0; +#X connect 210 1 219 0; +#X connect 210 2 220 0; +#X connect 210 3 221 0; +#X connect 210 4 222 0; +#X connect 210 5 223 0; +#X connect 210 6 224 0; +#X connect 210 7 225 0; +#X connect 210 8 226 0; +#X connect 210 9 213 0; +#X connect 210 9 230 0; +#X connect 210 10 214 0; +#X connect 210 10 232 0; +#X connect 210 11 215 0; +#X connect 210 11 234 0; +#X connect 210 12 216 0; +#X connect 210 12 236 0; +#X connect 210 13 217 0; +#X connect 210 13 238 0; +#X connect 210 14 207 0; +#X connect 227 0 3 0; +#X connect 228 0 241 1; +#X connect 230 0 229 0; +#X connect 232 0 231 0; +#X connect 234 0 233 0; +#X connect 236 0 235 0; +#X connect 238 0 237 0; +#X connect 239 0 3 0; +#X connect 241 0 227 0; +#X connect 242 0 241 0; -- GitLab