diff options
Diffstat (limited to 'dmx512/src')
-rw-r--r-- | dmx512/src/Make.config.in | 31 | ||||
-rw-r--r-- | dmx512/src/Make.version | 1 | ||||
-rw-r--r-- | dmx512/src/Makefile | 76 | ||||
-rw-r--r-- | dmx512/src/configure.ac | 177 | ||||
-rw-r--r-- | dmx512/src/dmx4pd.h | 41 | ||||
-rw-r--r-- | dmx512/src/dmxin.c | 139 | ||||
-rw-r--r-- | dmx512/src/dmxout.c | 299 | ||||
-rw-r--r-- | dmx512/src/dmxout_b.c | 240 |
8 files changed, 1004 insertions, 0 deletions
diff --git a/dmx512/src/Make.config.in b/dmx512/src/Make.config.in new file mode 100644 index 0000000..3386e58 --- /dev/null +++ b/dmx512/src/Make.config.in @@ -0,0 +1,31 @@ +LIBNAME ?= @LIBNAME@ +VERSION ?= @VERSION@ + +PREFIX =@prefix@@PDLIBDIR@ + +INSTALL_BIN=$(PREFIX)/extra +INSTALL_DOC=$(PREFIX)/@REFERENCEPATH@$(LIBNAME) + +EXT = @EXT@ +VERSION ?= @VERSION@ +DEFS = @DFLAGS@ -DACONNECT_VERSION=\"$(VERSION)\" +IFLAGS = -I. @INCLUDES@ $(INCLUDES) + +CC = @CC@ +LD = @LD@ +STRIP = @STRIP@ @STRIPFLAGS@ + +AFLAGS = +LFLAGS = @LFLAGS@ +WFLAGS = + +MAKEDEP_FLAGS = @MAKEDEP_FLAGS@ + +TARNAME = $(LIBNAME)-$(VERSION).tgz +BINTARNAME = $(LIBNAME)-$(VERSION)-bin.tgz + + +DMX4PD_CFLAGS = $(DEFS) $(IFLAGS) $(WFLAGS) @CFLAGS@ + +LIBS = @LIBS@ + diff --git a/dmx512/src/Make.version b/dmx512/src/Make.version new file mode 100644 index 0000000..0bdb8b4 --- /dev/null +++ b/dmx512/src/Make.version @@ -0,0 +1 @@ +VERSION = $(shell svnversion | grep -e "[0-9]") diff --git a/dmx512/src/Makefile b/dmx512/src/Makefile new file mode 100644 index 0000000..36b92bc --- /dev/null +++ b/dmx512/src/Makefile @@ -0,0 +1,76 @@ +default: all + +include Make.version + + +Make.config: Make.config.in configure + ./configure + +-include Make.config + +#VERSIONDEFINE = _$(strip $(VERSION))_ +ifneq ($(strip $(VERSION)),) +VERSIONDEFINE = -DDMX4PD_VERSION="\"rev.$(VERSION)\"" +endif + +.SUFFIXES: .$(EXT) + +SOURCES=$(sort $(filter %.c, $(wildcard *.c))) +TARGETS = $(SOURCES:.c=.o) +OBJECTS = $(SOURCES:.c=.$(EXT)) + +all: $(OBJECTS) + +clean: + -rm -f *.o *.d + +binclean: clean + -rm -f *.$(EXT) *.dll *.pd_linux *.pd_darwin *.l_i386 *.l_ia64 *.d_ppc *.d_fat + +mrproper: distclean + -rm Make.config configure *.d.* + +distclean: clean binclean + -rm -f *~ _* config.* + -rm -rf autom4te.cache + +install: install-bin install-doc + +install-bin: + -install -d $(INSTALL_BIN) + -install -m 644 $(LIBNAME).$(EXT) $(INSTALL_BIN) + +install-doc: + -install -d $(INSTALL_BIN) + -install -m 644 *.pd $(INSTALL_BIN) + +dist: distclean + (cd ..;tar czvf $(TARNAME) $(LIBNAME)) + +distbin: distclean all clean + (cd ..; tar cvzf $(BINTARNAME) $(LIBNAME)) + +everything: clean all install distclean + + +$(TARGETS): %.o : %.c Make.config + $(CC) $(DMX4PD_CFLAGS) $(VERSIONDEFINE) -c -o $@ $*.c + +$(OBJECTS): %.$(EXT) : %.o + $(LD) $(LFLAGS) -o $@ $*.o $(LIBS) + $(STRIP) $(STRIPFLAGS) $@ + + +ifeq (,$(findstring clean, $(MAKECMDGOALS))) +## dependencies: as proposed by the GNU-make documentation +## see http://www.gnu.org/software/make/manual/html_node/make_47.html#SEC51 +-include $(SOURCES:.c=.d) +%.d: %.c + @set -e; rm -f $@; \ + $(CC) $(MAKEDEP_FLAGS) $(DMX4PD_CFLAGS) $< > $@.$$$$; \ + sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \ + rm -f $@.$$$$ + +configure: configure.ac + autoconf +endif diff --git a/dmx512/src/configure.ac b/dmx512/src/configure.ac new file mode 100644 index 0000000..eff616a --- /dev/null +++ b/dmx512/src/configure.ac @@ -0,0 +1,177 @@ +dnl Process this file with autoconf to produce a configure script. +AC_INIT(dmx4pd.h) + +LIBNAME=dmx4pd + +dnl Checks for programs. +AC_PROG_CC + +AC_SUBST(STK) +AC_SUBST(DFLAGS) +AC_SUBST(LFLAGS) +AC_SUBST(EXT) +AC_SUBST(LD) +AC_SUBST(STRIP) +AC_SUBST(STRIPFLAGS) +AC_SUBST(REFERENCEPATH) +AC_SUBST(PDLIBDIR) +AC_SUBST(INCLUDES) +AC_SUBST(LIBNAME) + +AC_SUBST(DMX4LINUX_LFLAGS) +AC_SUBST(DMX4LINUX_CFLAGS) + + +AC_ARG_WITH(pdversion, [ --with-pdversion=<ver> enforce a certain pd-version (e.g. 0.37)]) +AC_ARG_WITH(extension, [ --with-extension=<ext> enforce a certain extension for the dynamic library (e.g. dll)]) + + +dnl Checks for libraries. +dnl Replace `main' with a function in -lc: +AC_CHECK_LIB(c, main) +AC_CHECK_LIB(crtdll, fclose) + +dnl Replace `main' with a function in -lm: +AC_CHECK_LIB(m, main) +dnl Replace `main' with a function in -lpthread: +dnl AC_CHECK_LIB(pthread, main) +dnl Replace `main' with a function in -lstk: +dnl AC_CHECK_LIB(stk, main, STK=yes) + + +AC_CHECK_LIB(dmx4l, DMXsleep) +AC_CHECK_LIB(dmx4linux, DMXsleep) +#if test "x$ac_cv_lib_dmx4linux_DMXsleep" = "xyes"; then +# DMX4LINUX_LFLAGS="-ldmx4linux" +#fi + +if test "x$includedir" != "x"; then + for id in $includedir + do + if test -d $id; then INCLUDES="-I$id $INCLUDES"; fi + done +fi +if test "x$libdir" != "x"; then + for id in $libdir + do + if test -d $id; then LIBS="-L$id $LIBS"; fi + done +fi + +AC_CHECK_LIB(pd, nullfn) + +dnl Checks for header files. +AC_HEADER_STDC +AC_CHECK_HEADERS(stdlib.h stdio.h string.h math.h time.h sys/time.h) + +dnl Checks for typedefs, structures, and compiler characteristics. +AC_HEADER_TIME + +dnl Checks for library functions. +AC_FUNC_MMAP +AC_CHECK_FUNCS(select socket strerror) + +dnl check for "-mms-bitfields" cflag +dnl why is there no generic compiler-check for a given flag ? +dnl it would make things so easy: AC_CHECK_FLAG([-mms-bitfields],,) +AC_MSG_CHECKING("ms-bitfields") +cat > conftest.c << EOF +int main(){ + return 0; +} +EOF +if ${CC} ${INCLUDES} ${DFLAGS} -o conftest.o conftest.c ${CFLAGS} -mms-bitfields > /dev/null 2>&1 +then + echo "yes" + CFLAGS="${CFLAGS} -mms-bitfields" +else + echo "no" +fi + + +### make-depend flags +if test "x$ac_cv_c_compiler_gnu" = "xyes"; then + AC_SUBST(MAKEDEP_FLAGS, "-MM") +else + AC_SUBST(MAKEDEP_FLAGS, "-M") +fi + +dnl isn't there a better way to check for good linker/stripper ? + +dnl if we don't have $LD set, we set it to $(CC) +dnl LD=${LD:=$CC} +AC_CHECK_TOOL([LD], [ld], [${CC}]) + +dnl if we don't have $STRIP set, we set it to ${host}-strip or strip + +dnl if we don't have $STRIP set, we set it to ${host}-strip or strip +AC_CHECK_TOOL([STRIP], [strip], [true]) +AC_MSG_CHECKING([if strip is GNU strip]) +if $STRIP -V | grep GNU > /dev/null +then + AC_SUBST(STRIPFLAGS, "--strip-unneeded") + AC_MSG_RESULT([yes]) +else + AC_SUBST(STRIPFLAGS,"-x") + AC_MSG_RESULT([no]) +fi + +dnl +dnl OK, checks for machines are here now +dnl +if test `uname -s` = Linux; +then + LFLAGS="-export_dynamic -shared" + CFLAGS="-fPIC $CFLAGS" + EXT=pd_linux +fi + +dnl This should use '-bundle_loader /path/to/pd/bin/pd' instead of'-undefined suppress' +dnl then strip might do something +if test `uname -s` = Darwin; +then + LD=cc + LFLAGS="-bundle -undefined suppress -flat_namespace" + EXT=pd_darwin + STRIPFLAGS= +fi + +if test `uname | sed -e 's/^MINGW.*/NT/'` = NT; +then + LD=gcc + INCLUDES="-I@prefix@/src" + DFLAGS="-D__WIN32__ ${DFLAGS}" + LFLAGS="-shared @prefix@/bin/pd.dll" + EXT=dll +else + PDLIBDIR="/lib/pd" +fi + +if test `uname -s` = IRIX64; +then + LFLAGS="-n32 -DUNIX -DIRIX -DN32 -woff 1080,1064,1185 \ + -OPT:roundoff=3 -OPT:IEEE_arithmetic=3 -OPT:cray_ivdep=true \ + -shared -rdata_shared" + EXT=pd_irix6 + dnl DFLAGS="-DUNIX -DIRIX6 ${DFLAGS}" + STRIPFLAGS="--strip-unneeded" +fi + +if test `uname -s` = IRIX32; +then + LFLAGS="-o32 -DUNIX -DIRIX -O2 + -shared -rdata_shared" + EXT=pd_irix5 + dnl DFLAGS="-DUNIX -DIRIX5 ${DFLAGS}" + STRIPFLAGS="--strip-unneeded" +fi + +if test "x$with_extension" != "x" +then + EXT=$with_extension +fi + + +AC_OUTPUT(Make.config) + +rm -f conftest.* diff --git a/dmx512/src/dmx4pd.h b/dmx512/src/dmx4pd.h new file mode 100644 index 0000000..059c794 --- /dev/null +++ b/dmx512/src/dmx4pd.h @@ -0,0 +1,41 @@ + +/****************************************************** + * + * dmx4pd - header file + * + * copyleft (c) IOhannes m zm-bölnig-A + * + * 0603:forum::f-bür::umläute:2008-A + * + * institute of electronic music and acoustics (iem) + * + ****************************************************** + * + * license: GNU General Public License v.2 + * + ******************************************************/ + +#ifndef INCLUDE_DMX4PD_H__ +#define INCLUDE_DMX4PD_H__ + +#ifndef DMX4PD_VERSION +# define DMX4PD_VERSION __DATE__ +#endif + + + +#include "m_pd.h" +#include <dmx/dmx.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + + +#define DMX4PD_POSTBANNER \ + do { \ + post("DMX4PD ("DMX4PD_VERSION"): (c) 2008 IOhannes m zmölnig - iem @ kug"); \ + } while(0) + + +#endif /* INCLUDE_DMX4PD_H__ */ diff --git a/dmx512/src/dmxin.c b/dmx512/src/dmxin.c new file mode 100644 index 0000000..c009570 --- /dev/null +++ b/dmx512/src/dmxin.c @@ -0,0 +1,139 @@ +/****************************************************** + * + * dmxin - implementation file + * + * copyleft (c) IOhannes m zmölnig + * + * 0603:forum::für::umläute:2008 + * + * institute of electronic music and acoustics (iem) + * + ****************************************************** + * + * license: GNU General Public License v.2 + * + ******************************************************/ + + +#include "dmx4pd.h" + +#include <sys/select.h> +#include <sys/time.h> +#include <sys/types.h> +#include <unistd.h> + +static t_class *dmxin_class; + +typedef struct _dmxin +{ + t_object x_obj; + int x_device; + int x_port; + + dmx_t x_dmxbuffer[512]; + + + t_outlet*x_outlet1, *x_outlet2; +} t_dmxin; + +static void dmx_doread(t_dmxin*x) { + int dmxin=x->x_device; + fd_set readset; + post("dmxin_doread: %d", dmxin); + if(dmxin<=0)return; + + FD_ZERO(&readset); + FD_SET(dmxin, &readset); + FD_SET(0, &readset); + + int n=select(dmxin+1, &readset, NULL,NULL, NULL); + if(n>0 && FD_ISSET(dmxin, &readset)) { + dmx_t dmxbuffer[512]; + int i=0; + lseek (dmxin, 0, SEEK_SET); + n=read (dmxin, dmxbuffer, sizeof(dmxbuffer)); + for(i=0; i<512; i+=2) { + int c=dmxbuffer[i]; + if(c!=x->x_dmxbuffer[i]) { + x->x_dmxbuffer[i]=c; + post("read %03d @ %03d", c, i); + } + } + } +} +static void dmxin_bang(t_dmxin*x) +{ + dmx_doread(x); +} + +static void dmxin_close(t_dmxin*x) +{ + if(x->x_device>=0) { + close(x->x_device); + } + x->x_device=-1; +} + + +static void dmxin_open(t_dmxin*x, t_symbol*s_devname) +{ + int argc=2; + const char *args[2] = {"--dmxin", s_devname->s_name}; + const char**argv=args; + char*devname=""; + int fd; + + if(s_devname && s_devname->s_name) + devname=s_devname->s_name; + + // strncpy(args[0], "--dmx", MAXPDSTRING); + // strncpy(args[1], devname, MAXPDSTRING); + + fd = open (DMXINdev(&argc, argv), O_RDONLY); + + if(fd!=-1) { + dmxin_close(x); + x->x_device=fd; + } +} + + +static void *dmxin_new(void) +{ + int i=0; + t_dmxin *x = (t_dmxin *)pd_new(dmxin_class); + + x->x_device=0; + x->x_port=0; + + for(i=0; i<sizeof(x->x_dmxbuffer); i++) { + x->x_dmxbuffer[i]=0; + } + + + x->x_outlet1=outlet_new(&x->x_obj, &s_float); + x->x_outlet2=outlet_new(&x->x_obj, &s_float); + + + + dmxin_open(x, gensym("")); + return (x); +} +static void dmxin_free(t_dmxin*x) +{ + dmxin_close(x); +} + +void dmxin_setup(void) +{ + dmxin_class = class_new(gensym("dmxin"), (t_newmethod)dmxin_new, (t_method)dmxin_free, + sizeof(t_dmxin), + 0, + A_NULL); + + class_addbang(dmxin_class, dmxin_bang); + +#ifdef DMX4PD_POSTBANNER + DMX4PD_POSTBANNER; +#endif +} diff --git a/dmx512/src/dmxout.c b/dmx512/src/dmxout.c new file mode 100644 index 0000000..18358ce --- /dev/null +++ b/dmx512/src/dmxout.c @@ -0,0 +1,299 @@ +/****************************************************** + * + * dmxout - implementation file + * + * copyleft (c) IOhannes m zmölnig + * + * 0603:forum::für::umläute:2008 + * + * institute of electronic music and acoustics (iem) + * + ****************************************************** + * + * license: GNU General Public License v.2 + * + ******************************************************/ + +#include "dmx4pd.h" + +#include <unistd.h> +#include <string.h> +#include <stdio.h> + +#include <pthread.h> + + +static t_class *dmxout_class; +static t_class *dmxout_class2; + +#define NUM_DMXVALUES 512 + +static pthread_t g_thread_id; +static pthread_mutex_t *g_mutex; +static dmx_t g_values[NUM_DMXVALUES]; +static int g_device; +static int g_thread_running, g_thread_continue; + +typedef struct _dmxout +{ + t_object x_obj; + + t_inlet *x_portinlet; + t_float x_port; + int x_portrange; + + +} t_dmxout; + + +static void *dmxout_thread(void*you) +{ + pthread_mutex_t *mutex=g_mutex; + struct timeval timout; + + g_thread_running=1; + + while(g_thread_continue) { + timout.tv_sec = 0; + timout.tv_usec=100; + select(0,0,0,0,&timout); + + pthread_mutex_lock(g_mutex); + if(g_device>0) { + lseek (g_device, 0, SEEK_SET); /* set to the current channel */ + write (g_device, g_values, NUM_DMXVALUES); /* write the channel */ + } + pthread_mutex_unlock(g_mutex); + } + g_thread_running=0; + + return NULL; +} + +static void dmxout_close() +{ + if(g_device>=0) { + close(g_device); + } + g_device=-1; + + if(g_thread_running) { + /* terminate the current thread! */ + void*dummy=0; + int counter=0; + g_thread_continue=0; + pthread_join(g_thread_id, &dummy); + while(g_thread_running) { + counter++; + } + } + g_thread_id=0; + if(g_mutex) { + pthread_mutex_destroy(g_mutex); + freebytes(g_mutex, sizeof(pthread_mutex_t)); + g_mutex=NULL; + } +} + + +static void dmxout_open(t_symbol*s_devname) +{ + int argc=2; + const char *args[2] = {"--dmx", s_devname->s_name}; + const char**argv=args; + const char*devname=""; + int fd; + + dmxout_close(); + + if(s_devname && s_devname->s_name) + devname=s_devname->s_name; + + // strncpy(args[0], "--dmx", MAXPDSTRING); + // strncpy(args[1], devname, MAXPDSTRING); + verbose(2, "[dmxout]: trying to open '%s'", args[1]); + devname=DMXdev(&argc, argv); + if(!devname){ + error("couldn't find DMX device"); + return; + } + verbose(1, "[dmxout] opening %s", devname); + + fd = open (devname, O_WRONLY); + + if(fd!=-1) { + g_device=fd; + + g_thread_running=0; + g_thread_continue=0; + g_mutex=(pthread_mutex_t*) malloc(sizeof(pthread_mutex_t)); + if ( pthread_mutex_init(g_mutex, NULL) < 0 ) { + error("couldn't create mutex"); + } else { + g_thread_continue = 1; + pthread_create(&g_thread_id, 0, dmxout_thread, NULL); + } + } else { + error("failed to open DMX-device '%s'",devname); + } +} + +static void dmxout_doout(t_dmxout*x) { + if(g_device<=0) { + pd_error(x, "no DMX universe found"); + return; + } +} + + +static void dmxout_doout1(t_dmxout*x, short port, unsigned char value) +{ + g_values[port]=value; + dmxout_doout(x); +} + + +static void dmxout_float(t_dmxout*x, t_float f) +{ + unsigned char val=(unsigned char)f; + short port = (short)x->x_port; + if(f<0. || f>255.) { + pd_error(x, "value %f out of bounds [0..255]", f); + return; + } + if(x->x_port<0. || x->x_port>NUM_DMXVALUES) { + pd_error(x, "port %f out of bounds [0..%d]", x->x_port, NUM_DMXVALUES); + return; + } + + dmxout_doout1(x, port, val); +} + +static void dmxout_list(t_dmxout*x, t_symbol*s, int argc, t_atom*argv) +{ + int count=(argc<x->x_portrange)?argc:x->x_portrange; + int i=0; + int errors=0; + + int port=x->x_port; + if((port+count)>=NUM_DMXVALUES) { + if(count>NUM_DMXVALUES)count=NUM_DMXVALUES; + port=NUM_DMXVALUES-count; + } + + for(i=0; i<count; i++) { + t_float f=atom_getfloat(argv+i); + if(f<0. || f>255.) { + errors++; + if(f<0.)f=0.; + if(f>255)f=255; + } + g_values[port+i]=(unsigned char)f; + } + if(errors) { + pd_error(x, "%d valu%s out of bound [0..255]", errors, (1==errors)?"e":"es"); + } + + dmxout_doout(x); +} + +static void dmxout_port(t_dmxout*x, t_float f_baseport, t_floatarg f_portrange) +{ + short baseport =(short)f_baseport; + short portrange=(short)f_portrange; + + + if(baseport<0 || baseport>=NUM_DMXVALUES) { + pd_error(x, "port %f out of bounds [0..%d]", f_baseport, NUM_DMXVALUES); + baseport =0; + } + x->x_port = baseport; + + if(portrange<0) { + pd_error(x, "portrange %f<0! setting to 1", portrange); + portrange=1; + } else if (portrange==0) { + portrange=x->x_portrange; + } + + if (baseport+portrange>NUM_DMXVALUES) { + pd_error(x, "upper port exceeds %d! clamping", NUM_DMXVALUES); + portrange=NUM_DMXVALUES-baseport; + } + x->x_portrange=portrange; +} + +static void *dmxout_new(t_symbol*s, int argc, t_atom*argv) +{ + t_floatarg baseport=0.f, portrange=0.f; + t_dmxout *x = 0; + + switch(argc) { + case 2: + x=(t_dmxout *)pd_new(dmxout_class2); + x->x_portinlet=inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("port")); + baseport=atom_getfloat(argv); + portrange=atom_getfloat(argv+1); + dmxout_port(x, baseport, portrange); + break; + case 1: + baseport=atom_getfloat(argv); + case 0: + x=(t_dmxout *)pd_new(dmxout_class); + x->x_portinlet=floatinlet_new(&x->x_obj, &x->x_port); + x->x_port = baseport; + x->x_portrange = -1; + break; + default: + return 0; + } + return (x); +} + +static void *dmxout_free(t_dmxout*x) +{ + // dmxout_close(); +} + +static void dmxout_init(void) { + int i=0; + g_thread_id=0; + g_mutex=NULL; + for(i=0; i<NUM_DMXVALUES; i++) g_values[i]=0; + + g_device=-1; + g_thread_running=0; + g_thread_continue=0; + + dmxout_open(gensym("")); +} + + +void dmxout_setup(void) +{ + +#ifdef DMX4PD_POSTBANNER + DMX4PD_POSTBANNER; +#endif + + dmxout_class = class_new(gensym("dmxout"), (t_newmethod)dmxout_new, (t_method)dmxout_free, + sizeof(t_dmxout), + 0, + A_GIMME, A_NULL); + + class_addfloat(dmxout_class, dmxout_float); + + dmxout_class2 = class_new(gensym("dmxout"), (t_newmethod)dmxout_new, (t_method)dmxout_free, + sizeof(t_dmxout), + 0, + A_GIMME, A_NULL); + + class_addlist(dmxout_class2, dmxout_list); + + + class_addmethod(dmxout_class2, (t_method)dmxout_port, gensym("port"), + A_FLOAT, A_DEFFLOAT, A_NULL); + + + dmxout_init(); +} diff --git a/dmx512/src/dmxout_b.c b/dmx512/src/dmxout_b.c new file mode 100644 index 0000000..9623397 --- /dev/null +++ b/dmx512/src/dmxout_b.c @@ -0,0 +1,240 @@ +/****************************************************** + * + * dmxout_b - implementation file + * + * this is the "blocking" version + * + * copyleft (c) IOhannes m zmölnig + * + * 0603:forum::für::umläute:2008 + * + * institute of electronic music and acoustics (iem) + * + ****************************************************** + * + * license: GNU General Public License v.2 + * + ******************************************************/ + +#include "dmx4pd.h" + +#include <unistd.h> +#include <string.h> +#include <stdio.h> + +static t_class *dmxout_b_class; +static t_class *dmxout_b_class2; + +#define NUM_DMXVALUES 512 + +typedef struct _dmxout_b +{ + t_object x_obj; + + t_inlet *x_portinlet; + + int x_device; + t_float x_port; + int x_portrange; + + dmx_t x_values[NUM_DMXVALUES]; +} t_dmxout_b; + +static void dmxout_b_clearbuf(t_dmxout_b*x) +{ + int i=0; + for(i=0; i<NUM_DMXVALUES; i++) x->x_values[i]=0; +} + +static void dmxout_b_close(t_dmxout_b*x) +{ + if(x->x_device>=0) { + close(x->x_device); + } + x->x_device=-1; +} + + +static void dmxout_b_open(t_dmxout_b*x, t_symbol*s_devname) +{ + int argc=2; + const char *args[2] = {"--dmx", s_devname->s_name}; + const char**argv=args; + const char*devname=""; + int fd; + + dmxout_b_close(x); + + if(s_devname && s_devname->s_name) + devname=s_devname->s_name; + + verbose(2, "[dmxout_b]: trying to open '%s'", args[1]); + devname=DMXdev(&argc, argv); + if(!devname){ + pd_error(x, "couldn't find DMX device"); + return; + } + verbose(1, "[dmxout_b] opening %s", devname); + + fd = open (devname, O_WRONLY | O_NONBLOCK); + + if(fd!=-1) { + x->x_device=fd; + dmxout_b_clearbuf(x); + } else { + pd_error(x, "failed to open DMX-device '%s'",devname); + } +} + +static void dmxout_b_doout(t_dmxout_b*x) { + int device = x->x_device; + if(device<=0) { + pd_error(x, "no DMX universe found"); + return; + } + + lseek (device, 0, SEEK_SET); /* set to the current channel */ + write (device, x->x_values, NUM_DMXVALUES); /* write the channel */ +} + + +static void dmxout_b_doout1(t_dmxout_b*x, short port, unsigned char value) +{ + x->x_values[port]=value; + dmxout_b_doout(x); +} + + +static void dmxout_b_float(t_dmxout_b*x, t_float f) +{ + unsigned char val=(unsigned char)f; + short port = (short)x->x_port; + if(f<0. || f>255.) { + pd_error(x, "value %f out of bounds [0..255]", f); + return; + } + if(x->x_port<0. || x->x_port>NUM_DMXVALUES) { + pd_error(x, "port %f out of bounds [0..%d]", x->x_port, NUM_DMXVALUES); + return; + } + + dmxout_b_doout1(x, port, val); +} + +static void dmxout_b_list(t_dmxout_b*x, t_symbol*s, int argc, t_atom*argv) +{ + int count=(argc<x->x_portrange)?argc:x->x_portrange; + int i=0; + int errors=0; + + int port=x->x_port; + if((port+count)>=NUM_DMXVALUES) { + if(count>NUM_DMXVALUES)count=NUM_DMXVALUES; + port=NUM_DMXVALUES-count; + } + + for(i=0; i<count; i++) { + t_float f=atom_getfloat(argv+i); + if(f<0. || f>255.) { + errors++; + if(f<0.)f=0.; + if(f>255)f=255; + } + x->x_values[port+i]=(unsigned char)f; + } + if(errors) { + pd_error(x, "%d valu%s out of bound [0..255]", errors, (1==errors)?"e":"es"); + } + + dmxout_b_doout(x); +} + +static void dmxout_b_port(t_dmxout_b*x, t_float f_baseport, t_floatarg f_portrange) +{ + short baseport =(short)f_baseport; + short portrange=(short)f_portrange; + + + if(baseport<0 || baseport>=NUM_DMXVALUES) { + pd_error(x, "port %f out of bounds [0..%d]", f_baseport, NUM_DMXVALUES); + baseport =0; + } + x->x_port = baseport; + + if(portrange<0) { + pd_error(x, "portrange %f<0! setting to 1", portrange); + portrange=1; + } else if (portrange==0) { + portrange=x->x_portrange; + } + + if (baseport+portrange>NUM_DMXVALUES) { + pd_error(x, "upper port exceeds %d! clamping", NUM_DMXVALUES); + portrange=NUM_DMXVALUES-baseport; + } + x->x_portrange=portrange; +} + +static void *dmxout_b_new(t_symbol*s, int argc, t_atom*argv) +{ + t_floatarg baseport=0.f, portrange=0.f; + t_dmxout_b *x = 0; + + switch(argc) { + case 2: + x=(t_dmxout_b *)pd_new(dmxout_b_class2); + x->x_portinlet=inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("port")); + baseport=atom_getfloat(argv); + portrange=atom_getfloat(argv+1); + dmxout_b_port(x, baseport, portrange); + break; + case 1: + baseport=atom_getfloat(argv); + case 0: + x=(t_dmxout_b *)pd_new(dmxout_b_class); + x->x_portinlet=floatinlet_new(&x->x_obj, &x->x_port); + x->x_port = baseport; + x->x_portrange = -1; + break; + default: + return 0; + } + x->x_device=-1; + + dmxout_b_open(x, gensym("")); + return (x); +} + +static void *dmxout_b_free(t_dmxout_b*x) +{ + dmxout_b_close(x); +} + + +void dmxout_b_setup(void) +{ +#ifdef DMX4PD_POSTBANNER + DMX4PD_POSTBANNER; +#endif + + dmxout_b_class = class_new(gensym("dmxout_b"), (t_newmethod)dmxout_b_new, (t_method)dmxout_b_free, + sizeof(t_dmxout_b), + 0, + A_GIMME, A_NULL); + + class_addfloat(dmxout_b_class, dmxout_b_float); + class_addmethod(dmxout_b_class, (t_method)dmxout_b_open, gensym("open"), A_SYMBOL, A_NULL); + + dmxout_b_class2 = class_new(gensym("dmxout_b"), (t_newmethod)dmxout_b_new, (t_method)dmxout_b_free, + sizeof(t_dmxout_b), + 0, + A_GIMME, A_NULL); + + class_addlist(dmxout_b_class2, dmxout_b_list); + + + class_addmethod(dmxout_b_class2, (t_method)dmxout_b_port, gensym("port"), + A_FLOAT, A_DEFFLOAT, A_NULL); + + class_addmethod(dmxout_b_class2, (t_method)dmxout_b_open, gensym("open"), A_SYMBOL, A_NULL); +} |