aboutsummaryrefslogtreecommitdiff
path: root/dmx512/src
diff options
context:
space:
mode:
Diffstat (limited to 'dmx512/src')
-rw-r--r--dmx512/src/Make.config.in31
-rw-r--r--dmx512/src/Make.version1
-rw-r--r--dmx512/src/Makefile76
-rw-r--r--dmx512/src/configure.ac177
-rw-r--r--dmx512/src/dmx4pd.h41
-rw-r--r--dmx512/src/dmxin.c139
-rw-r--r--dmx512/src/dmxout.c299
-rw-r--r--dmx512/src/dmxout_b.c240
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);
+}