aboutsummaryrefslogtreecommitdiff
path: root/MIDIvice/src
diff options
context:
space:
mode:
Diffstat (limited to 'MIDIvice/src')
-rw-r--r--MIDIvice/src/MIDIvice.c46
-rw-r--r--MIDIvice/src/MIDIvice.h44
-rw-r--r--MIDIvice/src/Make.config.in31
-rw-r--r--MIDIvice/src/Makefile86
-rw-r--r--MIDIvice/src/configure.ac273
-rw-r--r--MIDIvice/src/motormix.c868
-rw-r--r--MIDIvice/src/motormix_buttons.txt374
7 files changed, 1722 insertions, 0 deletions
diff --git a/MIDIvice/src/MIDIvice.c b/MIDIvice/src/MIDIvice.c
new file mode 100644
index 0000000..0acdb1d
--- /dev/null
+++ b/MIDIvice/src/MIDIvice.c
@@ -0,0 +1,46 @@
+/* (c) copyleft 2002-2008 IOhannes m zmölnig
+ * forum::für::umläute
+ * Institute of Electronic Music and Acoustics (IEM)
+ * University of Music and Dramatic Arts Graz (KUG)
+ */
+
+/*
+ * MIDIvice - accessing complex MIDI devices
+ */
+
+#include "MIDIvice.h"
+void motormix_setup();
+
+typedef struct MIDIvice
+{
+ t_object t_ob;
+} t_MIDIvice;
+
+t_class *MIDIvice_class;
+
+static void MIDIvice_help(void)
+{
+ post("\nMIDIvice "VERSION);
+ post("supported devices:");
+ post("\tmotormix\t\tMotorMix(tm) by cm-labs(r)"
+ "\n");
+}
+
+void *MIDIvice_new(void)
+{
+ t_MIDIvice *x = (t_MIDIvice *)pd_new(MIDIvice_class);
+ return (void *)x;
+}
+
+
+void MIDIvice_setup(void)
+{
+ motormix_setup();
+
+ /* ************************************** */
+ post("\n\tMIDIvice "VERSION);
+ post("\tcopyleft forum::für::umläute @ IEM/KUG 2002-2008");
+
+ MIDIvice_class = class_new(gensym("MIDIvice"), MIDIvice_new, 0, sizeof(t_MIDIvice), 0, 0);
+ class_addmethod(MIDIvice_class, MIDIvice_help, gensym("help"), 0);
+}
diff --git a/MIDIvice/src/MIDIvice.h b/MIDIvice/src/MIDIvice.h
new file mode 100644
index 0000000..b3f3e93
--- /dev/null
+++ b/MIDIvice/src/MIDIvice.h
@@ -0,0 +1,44 @@
+/* ********************************************** */
+/* the MIDIvice external */
+/* externals for controlling MIDI-devices */
+/* ********************************************** */
+/* forum::für::umläute */
+/* ********************************************** */
+
+/* (c) copyleft 2002-2008 IOhannes m zmölnig
+ * forum::für::umläute
+ * Institute of Electronic Music and Acoustics (IEM)
+ * University of Music and Dramatic Arts Graz (KUG)
+ */
+
+/* the MIDIvice external is a runtime-library for miller s. puckette's realtime-computermusic-software "pure data"
+ * therefore you NEED "pure data" to make any use of the MIDIvice external
+ * (except if you want to use the code for other things)
+ * download "pure data" at
+
+ http://iem.kug.ac.at/pd
+ ftp://ftp.iem.at/pub/pd
+
+ *
+ * if you are looking for the latest release of the MIDIvice-external you should have another look at
+
+ ftp://iem.kug.ac.at/pd/Externals/MIDIvice
+
+ *
+ * MIDIvice is published under the GNU GeneralPublicLicense, that must be shipped with MIDIvice.
+ * if you are using Debian GNU/linux, the GNU-GPL can be found under /usr/share/common-licenses/GPL
+ * if you still haven't found a copy of the GNU-GPL, have a look at http://www.gnu.org
+ *
+ * "pure data" has it's own license, that comes shipped with "pure data".
+ *
+ * there are ABSOLUTELY NO WARRANTIES for anything
+ */
+
+#ifndef INCLUDE_MIDIVICE_H__
+#define INCLUDE_MIDIVICE_H__
+
+#include "m_pd.h"
+
+#define VERSION "0.1"
+
+#endif
diff --git a/MIDIvice/src/Make.config.in b/MIDIvice/src/Make.config.in
new file mode 100644
index 0000000..4bf19b8
--- /dev/null
+++ b/MIDIvice/src/Make.config.in
@@ -0,0 +1,31 @@
+LIBNAME=@LIBNAME@
+
+# when build as a library this holds a pre-processor define
+# (e.g. "-DBUILD_LIBRARY")
+# when build as single externals this is empty
+BUILDLIBRARY =@BUILDLIBRARY@
+
+PREFIX =@prefix@@PDLIBDIR@
+
+INSTALL_BIN=$(DESTDIR)$(PREFIX)/extra/$(LIBNAME)
+INSTALL_DOC=$(DESTDIR)$(PREFIX)/@REFERENCEPATH@$(LIBNAME)
+
+EXT = @EXT@
+DEFS = @DFLAGS@
+IFLAGS = -I. @INCLUDES@ $(INCLUDES)
+MAKEDEP_FLAGS = @MAKEDEP_FLAGS@
+
+CC = @CC@
+LD = @LD@
+STRIP = @STRIP@
+STRIPFLAGS= @STRIPFLAGS@
+
+AFLAGS =
+LFLAGS = @LFLAGS@
+WFLAGS =
+
+TARNAME = $(LIBNAME).tgz
+
+CONFIGUREFLAGS = @CONFIGUREFLAGS@
+CFLAGS = $(DEFS) $(IFLAGS) $(BUILDLIBRARY) -DPD $(WFLAGS) @CFLAGS@
+LIBS = @LIBS@
diff --git a/MIDIvice/src/Makefile b/MIDIvice/src/Makefile
new file mode 100644
index 0000000..4601f4c
--- /dev/null
+++ b/MIDIvice/src/Makefile
@@ -0,0 +1,86 @@
+default: all
+
+.PHONEY: default all everything dist \
+ clean realclean distclean \
+ install install-bin install-doc install-abs \
+ tests
+
+HELPERSOURCES=MIDIvice.c
+OBJECTSOURCES=$(sort $(filter-out $(HELPERSOURCES), $(filter %.c, $(wildcard *.c))))
+SOURCES=$(OBJECTSOURCES) $(HELPERSOURCES)
+
+
+configure: configure.ac
+ autoconf
+
+-include $(SOURCES:.c=.d)
+
+Make.config: Make.config.in configure
+ ./configure $(CONFIGUREFLAGS)
+
+-include Make.config
+
+
+## 2nd only generate depend-files when we have Make.config included
+## and thus MAKEDEP_FLAGS defined
+ifdef MAKEDEP_FLAGS
+## dependencies: as proposed by the GNU-make documentation
+## see http://www.gnu.org/software/make/manual/html_node/make_47.html#SEC51
+%.d: %.c
+ @set -e; rm -f $@; \
+ $(CPP) $(MAKEDEP_FLAGS) $(CFLAGS) $< > $@.$$$$; \
+ sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
+ rm -f $@.$$$$
+endif
+
+.SUFFIXES: .$(EXT)
+
+TARGETS = $(SOURCES:.c=.o)
+
+OBJECTS = $(OBJECTSOURCES:.c=.$(EXT))
+
+
+## if $(BUILDLIBRARY) is defined, we build everything as a single library
+## else we build separate externals
+ifneq "$(BUILDLIBRARY)" ""
+all: $(LIBNAME)
+ cp $(LIBNAME).$(EXT) ..
+else
+all: $(OBJECTS)
+endif
+
+$(OBJECTS): %.$(EXT) : %.o
+ $(LD) $(LFLAGS) -o $@ $*.o $(LIBS)
+ $(STRIP) $(STRIPFLAGS) $@
+
+
+$(LIBNAME): $(TARGETS)
+ $(LD) $(LFLAGS) -o $@.$(EXT) *.o $(LIBS)
+ $(STRIP) $(STRIPFLAGS) $(LIBNAME).$(EXT)
+
+$(TARGETS): %.o : %.c
+ $(CC) $(CFLAGS) -c -o $@ $*.c
+
+clean:
+ -rm -f *.$(EXT) *.o
+
+realclean: clean
+ -rm -f *~ _* config.*
+ -rm -f *.d *.d.*
+
+distclean: realclean
+ -rm -f Make.config
+ -rm -f *.exp *.lib *.ncb *.opt *.plg
+ -rm -rf autom4te.cache/
+
+install: install-bin install-doc
+
+install-bin:
+ -install -d $(INSTALL_BIN)
+ -install -m 644 *.$(EXT) $(INSTALL_BIN)
+
+install-doc:
+ -install -d $(INSTALL_DOC)
+ -install -m 644 *-help.pd $(INSTALL_DOC)
+
+everything: clean all install distclean
diff --git a/MIDIvice/src/configure.ac b/MIDIvice/src/configure.ac
new file mode 100644
index 0000000..7fe2f21
--- /dev/null
+++ b/MIDIvice/src/configure.ac
@@ -0,0 +1,273 @@
+dnl Process this file with autoconf to produce a configure script.
+AC_INIT(MIDIvice.c)
+
+LIBNAME=MIDIvice
+
+
+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(LIBRARY_VERSION)
+AC_SUBST(REFERENCEPATH)
+AC_SUBST(PDLIBDIR)
+AC_SUBST(INCLUDES)
+AC_SUBST(LIBNAME)
+AC_SUBST(CONFIGUREFLAGS)
+AC_SUBST(BUILDLIBRARY)
+
+## store the flags passed to us
+## is there no way to get the flags without quotes?
+#CONFIGUREFLAGS=${ac_configure_args}
+## and is this solution portable? time will show....
+CONFIGUREFLAGS=$(echo ${ac_configure_args} | sed "s/'//g")
+
+
+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)])
+AC_ARG_WITH(pdpath, [ --with-pd=</path/to/pd> where to look for pd-headers and and -libs])
+AC_ARG_ENABLE(PIC, [ --disable-PIC disable compilation with PIC-flag])
+AC_ARG_ENABLE(library,[ --disable-library split the library into single externals])
+
+if test "xno" != "x${enable_library}" ; then
+dnl LATER: find a more generic way to generate the .._LIBRARY define
+ BUILDLIBRARY="-DBUILD_LIBRARY"
+fi
+
+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)
+
+if test "x$with_pd" != "x"; then
+ if test -d "${with_pd}/src"; then
+ INCLUDES="-I${with_pd}/src ${INCLUDES}"
+ fi
+ if test -d "${with_pd}/bin"; then
+ LIBS="-L${with_pd}/bin ${LIBS}"
+ fi
+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)
+
+
+### 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 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
+
+
+
+
+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}
+if test "x$LD" = "x"
+then
+ if test "x$host" != "x"
+ then
+ LD=${host}-ld
+ if $(which ${LD} > /dev/null)
+ then
+ :
+ else
+ LD=""
+ fi
+ fi
+fi
+LD=${LD:=$CC}
+
+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 2>&1 | grep GNU > /dev/null
+then
+ AC_SUBST(STRIPFLAGS, "--strip-unneeded")
+ AC_MSG_RESULT([yes])
+else
+ AC_SUBST(STRIPFLAGS,"-x")
+ AC_MSG_RESULT([no])
+fi
+
+DFLAGS=""
+
+
+if test "x$enable_PIC" != "xno"; then
+AC_MSG_CHECKING("PIC")
+cat > conftest.c << EOF
+int main(){
+ return 0;
+}
+EOF
+if ${CC} ${INCLUDES} ${DFLAGS} -o conftest.o conftest.c ${CFLAGS} -fPIC > /dev/null 2>&1
+then
+ echo "yes"
+ CFLAGS="${CFLAGS} -fPIC"
+else
+ echo "no"
+fi
+fi
+
+
+dnl
+dnl OK, checks for machines are here now
+dnl
+if test `uname -s` = Linux;
+then
+ LFLAGS="-export_dynamic -shared"
+ CFLAGS="$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
+fi
+
+if test `uname | sed -e 's/^MINGW.*/NT/'` = NT;
+then
+ LD=gcc
+ INCLUDES="-I@prefix@/src"
+ DFLAGS="-D__WIN32__"
+ 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"
+fi
+
+if test `uname -s` = IRIX32;
+then
+ LFLAGS="-o32 -DUNIX -DIRIX -O2
+ -shared -rdata_shared"
+ EXT=pd_irix5
+ dnl DFLAGS="-DUNIX -DIRIX5"
+fi
+
+
+if test "x$with_extension" != "x"
+then
+ EXT=$with_extension
+fi
+
+
+dnl Checks for pd-version, to set the correct help-path
+AC_MSG_CHECKING("pd\>=0.37")
+
+if test "$with_pdversion" != ""
+then
+echo -n "($with_pdversion)... "
+ PD_VERSION="$with_pdversion"
+else
+if test "x$cross_compiling" = "xno"
+then
+
+cat > conftest.c << EOF
+#include <stdio.h>
+#include "m_pd.h"
+int main(){
+ printf("%d.%d\n", PD_MAJOR_VERSION, PD_MINOR_VERSION);
+ return 0;
+}
+EOF
+
+ if $CC $INCLUDES -o conftest.o conftest.c > /dev/null 2>&1
+ then
+ PD_VERSION=`./conftest.o`
+ else
+ PD_VERSION=""
+ fi
+ echo -n $PD_VERSION
+else
+dnl we are cross-compiling...
+ echo -n "(X)..."
+ PD_VERSION="0.38"
+fi
+fi
+
+let PD_MAJORVERSION=`echo $PD_VERSION | cut -d"." -f1`+0
+let PD_MINORVERSION=`echo $PD_VERSION | cut -d"." -f2`+0
+
+
+
+if test "$PD_MAJORVERSION" -gt 0 || test "$PD_MINORVERSION" -ge 37
+then
+ REFERENCEPATH=extra/
+ echo " yes"
+else
+ REFERENCEPATH=doc/5.reference/
+ echo " no"
+fi
+
+AC_OUTPUT(Make.config)
+
+rm -f conftest.*
diff --git a/MIDIvice/src/motormix.c b/MIDIvice/src/motormix.c
new file mode 100644
index 0000000..46355ee
--- /dev/null
+++ b/MIDIvice/src/motormix.c
@@ -0,0 +1,868 @@
+/* (c) copyleft 2002-2008 IOhannes m zmölnig
+ * forum::für::umläute
+ * Institute of Electronic Music and Acoustics (IEM)
+ * University of Music and Dramatic Arts Graz (KUG)
+ */
+
+/*
+ motormix by CM-labs
+*/
+
+#include "MIDIvice.h"
+#include <string.h>
+#include <ctype.h>
+
+#define LCD_TEXT 0x10
+#define LCD_GRAPH 0x11
+#define SEG7 0x12
+
+static int x_port = 0;
+static t_symbol *ctlin_sym;
+static t_symbol *notein_sym;
+
+void outmidi_noteon(int portno, int channel, int pitch, int velo);
+void outmidi_controlchange(int portno, int channel, int ctlno, int value);
+void sys_putmidibyte(int portno, int byte);
+
+static void outmidi_byte(unsigned char byte)
+{ sys_putmidibyte(x_port, byte); }
+
+
+
+/* ------------------------- LCDtext ------------------------------- */
+
+static t_class *LCDtext_class;
+typedef struct _LCDtext
+{
+ t_object x_obj;
+
+ int pos;
+ int length;
+ t_binbuf *bbuf;
+} t_LCDtext;
+
+
+static void LCD_header(unsigned char type)
+{
+ outmidi_byte(0xF0);
+ outmidi_byte(0x00);
+ outmidi_byte(0x01);
+ outmidi_byte(0x0F);
+ outmidi_byte(0x00);
+ outmidi_byte(0x11);
+ outmidi_byte(0x00);
+ outmidi_byte(type);
+}
+static void LCD_footer(void)
+{
+ outmidi_byte(0xF7);
+}
+
+static void LCDtext_text(t_LCDtext *x)
+{
+ char *c, *str=0;
+ int n, slen;
+ int pos = x->pos;
+ int len = x->length;
+ int rest=0;
+
+ if (!x->bbuf)return;
+
+ binbuf_gettext(x->bbuf, &str, &slen);
+ c=str;
+ if (len>slen){
+ n=slen;
+ rest=len-slen;
+ } else n=len?len:slen;
+
+ if (n>0x50-pos)n=0x50-pos;
+
+ LCD_header(LCD_TEXT);
+ outmidi_byte(pos);
+ while(n--)outmidi_byte(*c++);
+ while(rest--)outmidi_byte(' ');
+ LCD_footer();
+
+ freebytes(str, slen);
+}
+
+static void LCDtext_clear(t_LCDtext *x, t_float fmode)
+{
+ int mode = fmode;
+ int offset = (mode==2)?0x28:0x00;
+ int n = (mode>0)?0x28:0x50;
+
+ // post("offset=%d\tn=%d", offset, n);
+
+ LCD_header(LCD_TEXT);
+ outmidi_byte(offset);
+
+ while(n--)outmidi_byte(' ');
+
+ LCD_footer();
+}
+
+static void LCDtext_any(t_LCDtext *x, t_symbol *s, int argc, t_atom *argv)
+{
+ // t_atom a;
+ binbuf_clear(x->bbuf);
+
+ if ((s != &s_list)&&(s != &s_float)&&(s != &s_symbol)){
+ t_atom a;
+ SETSYMBOL(&a, s);
+ binbuf_add(x->bbuf, 1, &a);
+ }
+ binbuf_add(x->bbuf, argc, argv);
+
+ LCDtext_text(x);
+}
+
+static void LCDtext_pos(t_LCDtext *x, t_float pos, t_float len)
+{
+ if (pos<0 )pos=0;
+ if (pos>80)pos=80;
+ if (len<0 )len=0;
+
+ x->pos=pos;
+ x->length=len;
+}
+
+
+static void *LCDtext_new(t_floatarg f)
+{
+ t_LCDtext *x = (t_LCDtext *)pd_new(LCDtext_class);
+ int pos = f;
+
+ if (pos<0)pos=0;
+ if (pos>0x4f)pos=0x4f;
+ x->pos=pos;
+ // floatinlet_new(&x->x_obj, &x->pos);
+ inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym(""));
+
+ x->bbuf = binbuf_new();
+
+ return (x);
+}
+static void LCDtext_setup(void)
+{
+ LCDtext_class = class_new(gensym("motormix_LCDtext"), (t_newmethod)LCDtext_new,
+ 0, sizeof(t_LCDtext), 0, A_DEFFLOAT, 0);
+ class_addcreator((t_newmethod)LCDtext_new, gensym("mm_LCDtext"), A_DEFFLOAT, 0);
+
+ class_addmethod(LCDtext_class, (t_method)LCDtext_pos, gensym(""), A_DEFFLOAT, A_DEFFLOAT, 0);
+ class_addmethod(LCDtext_class, (t_method)LCDtext_clear, gensym("clear"), A_DEFFLOAT, 0);
+ class_addbang(LCDtext_class, (t_method)LCDtext_text);
+
+ class_addanything(LCDtext_class, LCDtext_any);
+ class_sethelpsymbol(LCDtext_class, gensym("MIDIvice/motormix"));
+}
+/* ------------------------- LCDgraph ------------------------------- */
+
+static t_class *LCDgraph_class;
+typedef struct _LCDgraph
+{
+ t_object x_obj;
+
+ t_float pos;
+ int type;
+} t_LCDgraph;
+
+static void LCDgraph_valpos(int pos, int val)
+{
+ if ((pos<1)||(pos>8))return;
+ if (val<0)val=0;
+ if (val>127)val=127;
+ outmidi_byte(pos-1);
+ outmidi_byte(val);
+}
+
+static void LCDgraph_float(t_LCDgraph *x, t_float f)
+{
+ if ((x->pos<1)||(x->pos>8))return;
+
+ LCD_header(LCD_GRAPH);
+ outmidi_byte(x->type);
+ LCDgraph_valpos(x->pos, f);
+ LCD_footer();
+}
+
+static void LCDgraph_clear(t_LCDgraph *x)
+{
+ int n = 0x28;
+ int pos=0x28;
+
+ LCD_header(LCD_TEXT);
+ outmidi_byte(pos);
+ while(n--)outmidi_byte(' ');
+ LCD_footer();
+}
+
+
+static void LCDgraph_pos(t_LCDgraph *x, t_float pos)
+{
+ x->pos=pos;
+}
+static void LCDgraph_typ(t_LCDgraph *x, t_float type)
+{
+ if (type<0 )type=0;
+ if (type>7)type=7;
+
+ x->type=type;
+}
+static void *LCDgraph_new(t_float ftype)
+{
+ t_LCDgraph *x = (t_LCDgraph *)pd_new(LCDgraph_class);
+
+ LCDgraph_typ(x, ftype);
+ floatinlet_new(&x->x_obj, &x->pos);
+ inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("type"));
+ x->pos=0;
+
+ return (x);
+}
+static void LCDgraph_setup(void)
+{
+ LCDgraph_class = class_new(gensym("motormix_LCDgraph"), (t_newmethod)LCDgraph_new,
+ 0, sizeof(t_LCDgraph), 0, A_DEFFLOAT, 0);
+ class_addcreator((t_newmethod)LCDgraph_new, gensym("mm_LCDgraph"), A_DEFFLOAT, 0);
+
+ class_addmethod(LCDgraph_class, (t_method)LCDgraph_typ, gensym("type"), A_DEFFLOAT, 0);
+ class_addmethod(LCDgraph_class, (t_method)LCDgraph_pos, gensym(""), A_DEFFLOAT, 0);
+ class_addmethod(LCDgraph_class, (t_method)LCDgraph_clear, gensym("clear"), 0);
+ class_addfloat (LCDgraph_class, (t_method)LCDgraph_float);
+
+ // class_addbang(LCDgraph_class, (t_method)LCDgraph_graph);
+ class_sethelpsymbol(LCDgraph_class, gensym("MIDIvice/motormix"));
+}
+
+/* ------------------------- seg7 ------------------------------- */
+
+static t_class *seg7_class;
+typedef struct _seg7
+{
+ t_object x_obj;
+
+ t_float point1, point2;
+ char c1, c2;
+} t_seg7;
+
+static void seg7_nibblebyte(char c, int point)
+{
+ char C = toupper(c);
+ char lo=C&0x0F;
+ char hi=(C>>4)&0x0F;
+ if (point)hi|=0x40;
+ // post("C=%c=%c", c, C);
+ // post("hi=%x\tlo=%x", hi, lo);
+
+ outmidi_byte(hi);
+ outmidi_byte(lo);
+}
+
+static void seg7_write(char c1, int pt1, char c2, int pt2)
+{
+ LCD_header(SEG7);
+
+ seg7_nibblebyte(c1, pt1);
+ seg7_nibblebyte(c2, pt2);
+
+ LCD_footer();
+}
+
+static void seg7_clear(t_seg7 *x, t_float fmode)
+{
+ int mode = fmode;
+
+ LCD_header(SEG7);
+ if (mode!=2)seg7_nibblebyte(' ', 0);
+ else seg7_nibblebyte(0, 0);
+ if (mode!=1)seg7_nibblebyte(' ', 0);
+ else seg7_nibblebyte(0, 0);
+
+ LCD_footer();
+}
+
+static void seg7_list(t_seg7 *x, t_symbol *s, int argc, t_atom* argv)
+{
+ char seg1, seg2;
+ int pt1=(x->point1 != 0);
+ int pt2=(x->point2 != 0);
+
+ seg1=(argv->a_type==A_SYMBOL)?
+ *atom_getsymbol(argv)->s_name:
+ (atom_getint(argv)%10+0x30);
+ argv++;
+ if (argc>1)seg2=(argv->a_type==A_SYMBOL)?*atom_getsymbol(argv)->s_name:(atom_getint(argv)%10+0x30);
+ else {
+ seg2=seg1;
+ seg1=' ';
+ }
+ // post("seg1=%c\tseg2=%c", seg1, seg2);
+
+ x->c1=seg1;
+ x->c2=seg2;
+
+ seg7_write(seg1, pt1, seg2, pt2);
+}
+static void seg7_symbol(t_seg7 *x, t_symbol *s)
+{
+ int pt1=(x->point1 != 0);
+ int pt2=(x->point2 != 0);
+ char c1=*s->s_name;
+ char c2=x->c2;
+
+ x->c1=c1;
+
+ // post("c1=%c\tc2=%c", c1, c2);
+
+ seg7_write(c1, pt1, c2, pt2);
+}
+static void seg7_symbol2(t_seg7 *x, t_symbol *s)
+{
+ x->c2=*s->s_name;
+}
+static void seg7_bang(t_seg7 *x)
+{
+ int pt1=(x->point1 != 0);
+ int pt2=(x->point2 != 0);
+ char c1=x->c1;
+ char c2=x->c2;
+
+ seg7_write(c1, pt1, c2, pt2);
+}
+
+static void *seg7_new(void)
+{
+ t_seg7 *x = (t_seg7 *)pd_new(seg7_class);
+
+ floatinlet_new(&x->x_obj, &x->point1);
+ inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("symbol"), gensym(""));
+ floatinlet_new(&x->x_obj, &x->point2);
+
+ x->point1=x->point2=0;
+ x->c1=x->c2=0;
+
+ return (x);
+}
+static void seg7_setup(void)
+{
+ seg7_class = class_new(gensym("motormix_7seg"), (t_newmethod)seg7_new,
+ 0, sizeof(t_seg7), 0, A_GIMME, 0);
+ class_addcreator((t_newmethod)seg7_new, gensym("mm_7seg"), A_GIMME, 0);
+ class_addbang(seg7_class, seg7_bang);
+ class_addlist(seg7_class, seg7_list);
+ class_addsymbol(seg7_class, seg7_symbol);
+ class_addmethod(seg7_class, (t_method)seg7_clear, gensym("clear"), A_DEFFLOAT, 0);
+ class_addmethod(seg7_class, (t_method)seg7_symbol2, gensym(""), A_DEFSYMBOL, 0);
+ class_sethelpsymbol(seg7_class, gensym("MIDIvice/motormix"));
+}
+
+/* ------------------------- LED ------------------------------- */
+
+static t_class *LED_class;
+typedef struct _LED
+{
+ t_object x_obj;
+
+ t_float LED;
+ t_float state;
+} t_LED;
+
+static void LED_float(t_LED *x, t_float f)
+{
+ int MSB, LSB;
+ int state = x->state;
+ int offset = 0;
+ int id = f;
+
+ if (id<0)return;
+ LSB=id%8;
+ MSB=id/8;
+
+ x->LED=id;
+
+
+ if (state>0)offset=0x40;
+ else if (state<0)offset=0x50;
+
+ // if (MSB<8)offset++;
+#if 0
+ post("LED: %x %x %x %x", 0x0C, MSB, 0x2C, LSB+offset);
+ // post("LED: %d %d %d %d\n", 0x0C, MSB, 0x2C, LSB+offset);
+#endif
+ outmidi_controlchange(x_port>>4, x_port&15, 0x0C, MSB);
+ outmidi_controlchange(x_port>>4, x_port&15, 0x2C, LSB+offset);
+}
+
+static void LED_symbol(t_LED *x, t_symbol *s)
+{
+ post("motormix_LED: no method for symbol");
+}
+
+static void LED_bang(t_LED *x)
+{
+ LED_float(x, x->LED);
+}
+
+static void *LED_new(void)
+{
+ t_LED *x = (t_LED *)pd_new(LED_class);
+
+ x->LED=-1;
+ floatinlet_new(&x->x_obj, &x->state);
+
+ x->state=0;
+
+ return (x);
+}
+static void LED_setup(void)
+{
+ LED_class = class_new(gensym("motormix_LED"), (t_newmethod)LED_new,
+ 0, sizeof(t_LED), 0, 0);
+ class_addcreator((t_newmethod)LED_new, gensym("mm_LED"), 0);
+
+ class_addsymbol(LED_class, LED_symbol);
+ class_addfloat (LED_class, LED_float);
+ class_addbang (LED_class, LED_bang);
+ class_sethelpsymbol(LED_class, gensym("MIDIvice/motormix"));
+}
+
+
+/* button */
+static t_class *button_class;
+typedef struct _button
+{
+ t_object x_obj;
+ int o_itsme; // the fader changed
+ int o_imtouched; // the fader was touched
+
+ t_outlet *o_value; // actual fader-value
+ t_outlet *o_touch; // 1=touched; 0=released
+
+ int activefader;
+ int fader;
+ unsigned char MSB, LSB;
+} t_button;
+
+static void button_touch(t_button *x, unsigned char value, unsigned char control)
+{
+ int pressed=0;
+ int MSB=x->MSB;
+ int LSB=0;
+
+ x->o_imtouched=0;
+
+ if (x->MSB<8){
+ if ((value==0x00) || (value==0x40))return;
+ }
+
+ LSB=value;
+
+ if (LSB>=0x40){
+ pressed=1;
+ LSB-=0x40;
+ }
+
+ outlet_float(x->o_touch, pressed);
+ outlet_float(x->o_value, MSB*8+LSB);
+}
+
+static void button_list(t_button *x, t_symbol *s, int argc, t_atom *argv)
+{
+ unsigned char ctl = atom_getfloatarg(0, argc, argv);
+ unsigned char val = atom_getfloatarg(1, argc, argv);
+ // int channel = atom_getfloatarg(2, argc, argv);
+
+ if (x->o_imtouched)button_touch(x, val, ctl);
+
+ if (ctl==0x0f){
+ x->o_imtouched=1;
+ x->MSB=val;
+ }
+}
+static void button_free(t_button *x)
+{
+ pd_unbind(&x->x_obj.ob_pd, ctlin_sym);
+}
+static void *button_new()
+{
+ t_button *x = (t_button *)pd_new(button_class);
+
+ x->o_value=outlet_new(&x->x_obj, &s_float);
+ x->o_touch=outlet_new(&x->x_obj, &s_float);
+
+ x->o_imtouched = 0;
+
+ pd_bind(&x->x_obj.ob_pd, ctlin_sym);
+
+ return (x);
+}
+static void button_setup(void)
+{
+ button_class = class_new(gensym("motormix_button"), (t_newmethod)button_new, (t_method)button_free,
+ sizeof(t_button), CLASS_NOINLET, A_DEFFLOAT, 0);
+ class_addcreator((t_newmethod)button_new, gensym("mm_button"), A_DEFFLOAT, 0);
+
+ class_addlist(button_class, button_list);
+ class_sethelpsymbol(button_class, gensym("MIDIvice/motormix"));
+}
+
+/* ------------------------- rotary ------------------------------- */
+
+
+static t_class *rotary_class;
+typedef struct _rotary
+{
+ t_object x_obj;
+
+ t_outlet *o_value; // actual rot-value
+ t_outlet *o_rot; // rot-number
+
+ int rot;
+} t_rotary;
+
+static void rotary_list(t_rotary *x, t_symbol *s, int argc, t_atom *argv)
+{
+ unsigned char ctl = atom_getfloatarg(0, argc, argv);
+ unsigned char val = atom_getfloatarg(1, argc, argv);
+ // int channel = atom_getfloatarg(2, argc, argv);
+
+ if ((ctl>=0x40) && (ctl<0x48)) {
+ if (x->rot) {
+ if (ctl+1-0x40==x->rot){
+ // int value = (val>=64)?val-64:-val;
+ outlet_float(x->o_value, (val>=64)?val-64:-val);
+ }
+ } else {
+ outlet_float(x->o_rot, (t_float)(ctl-0x40+1));
+ outlet_float(x->o_value, (val>=64)?val-64:-val);
+ }
+ }
+}
+static void rotary_free(t_rotary *x)
+{
+ pd_unbind(&x->x_obj.ob_pd, ctlin_sym);
+}
+static void *rotary_new(t_floatarg f)
+{
+ t_rotary *x = (t_rotary *)pd_new(rotary_class);
+
+ if ((f<0) || (f>=9)){
+ post("motormix_rotary: rot [%d] specified. only rotariess 1..8(&0) are valid", (int)f);
+ f=0;
+ }
+ x->rot = f;
+
+ x->o_value=outlet_new(&x->x_obj, &s_float);
+ if (!x->rot) x->o_rot=outlet_new(&x->x_obj, &s_float);
+
+ pd_bind(&x->x_obj.ob_pd, ctlin_sym);
+
+ return (x);
+}
+static void rotary_setup(void)
+{
+ rotary_class = class_new(gensym("motormix_rotary"), (t_newmethod)rotary_new, (t_method)rotary_free,
+ sizeof(t_rotary), CLASS_NOINLET, A_DEFFLOAT, 0);
+ class_addcreator((t_newmethod)rotary_new, gensym("mm_rotary"), A_DEFFLOAT, 0);
+
+ class_addlist(rotary_class, rotary_list);
+ class_sethelpsymbol(rotary_class, gensym("MIDIvice/motormix"));
+}
+
+/* ------------------------- encoder ------------------------------- */
+
+static t_class *encoder_class;
+typedef struct _encoder
+{
+ t_object x_obj;
+
+ t_outlet *o_value; // actual rot-value
+ t_outlet *o_push; // pushed
+} t_encoder;
+
+static void encoder_list(t_encoder *x, t_symbol *s, int argc, t_atom *argv)
+{
+ unsigned char ctl = atom_getfloatarg(0, argc, argv);
+ unsigned char val = atom_getfloatarg(1, argc, argv);
+ // int channel = atom_getfloatarg(2, argc, argv);
+
+ if (ctl==0x48) outlet_float(x->o_value, (val>=64)?val-64:-val);
+ else if (ctl==0x49)outlet_float(x->o_push, (t_float)(val==0x01));
+}
+static void encoder_free(t_encoder *x)
+{
+ pd_unbind(&x->x_obj.ob_pd, ctlin_sym);
+}
+static void *encoder_new(void)
+{
+ t_encoder *x = (t_encoder *)pd_new(encoder_class);
+
+ x->o_value=outlet_new(&x->x_obj, &s_float);
+ x->o_push =outlet_new(&x->x_obj, &s_float);
+
+ pd_bind(&x->x_obj.ob_pd, ctlin_sym);
+
+ return (x);
+}
+static void encoder_setup(void)
+{
+ encoder_class = class_new(gensym("motormix_encoder"), (t_newmethod)encoder_new, (t_method)encoder_free,
+ sizeof(t_encoder), CLASS_NOINLET, 0);
+ class_addcreator((t_newmethod)encoder_new, gensym("mm_encoder"), 0);
+
+ class_addlist(encoder_class, encoder_list);
+ class_sethelpsymbol(encoder_class, gensym("MIDIvice/motormix"));
+}
+
+
+/* ------------------------- faderIn ------------------------------- */
+
+static t_class *faderIn_class;
+typedef struct _faderIn
+{
+ t_object x_obj;
+ int o_itsme; // the fader changed
+ int o_imtouched; // the fader was touched
+
+ t_outlet *o_value; // actual fader-value
+ t_outlet *o_touch; // 1=touched; 0=released
+ t_outlet *o_fader; // fader-number
+
+ int activefader;
+ int fader;
+ unsigned char MSB, LSB;
+} t_faderIn;
+
+static void faderIn_parse(t_faderIn *x, unsigned char value, unsigned char control)
+{
+ unsigned int fader = (x->fader)?x->fader:x->activefader;
+ x->o_itsme=0;
+
+ if (fader+31==control){
+ x->LSB=value;
+ if (!x->fader)outlet_float(x->o_fader, x->activefader);
+ outlet_float(x->o_value, x->MSB+(1./128)*x->LSB);
+ }
+}
+static void faderIn_touch(t_faderIn *x, unsigned char value, unsigned char control)
+{
+ x->o_imtouched=0;
+
+ if (control==0x2F){
+ switch (value) {
+ case 0x00:
+ if (!x->fader)outlet_float(x->o_fader, x->activefader);
+ outlet_float(x->o_touch, 0.);
+ break;
+ case 0x40:
+ if (!x->fader)outlet_float(x->o_fader, x->activefader);
+ outlet_float(x->o_touch, 1.);
+ default:
+ break;
+ }
+ }
+}
+
+static void faderIn_list(t_faderIn *x, t_symbol *s, int argc, t_atom *argv)
+{
+ unsigned char ctl = atom_getfloatarg(0, argc, argv);
+ unsigned char val = atom_getfloatarg(1, argc, argv);
+ // int channel = atom_getfloatarg(2, argc, argv);
+
+ if (x->o_itsme) faderIn_parse(x, val, ctl);
+ if (x->o_imtouched)faderIn_touch(x, val, ctl);
+
+ if (ctl==0x0f){
+ if (x->fader) {
+ if (val+1==x->fader){ // touched me
+ x->o_imtouched=1;
+ }
+ } else {
+ if (val<=7){ // touched us
+ x->o_imtouched=1;
+ x->activefader=val+1;
+ }
+ }
+ } else if (ctl<0x08) {
+ if (x->fader) {
+ if (ctl+1==x->fader){
+ x->o_itsme=1;
+ x->MSB=val;
+ }
+ } else {
+ x->o_itsme=1;
+ x->activefader=ctl+1;
+ x->MSB=val;
+ }
+ }
+}
+static void faderIn_free(t_faderIn *x)
+{
+ pd_unbind(&x->x_obj.ob_pd, ctlin_sym);
+}
+static void *faderIn_new(t_floatarg f)
+{
+ t_faderIn *x = (t_faderIn *)pd_new(faderIn_class);
+
+ if ((f<0) || (f>=9)){
+ post("motormix_fader: fader [%d] specified. only faders 1..8(&0) are valid", (int)f);
+ f=0;
+ }
+ x->fader = f;
+
+ x->o_value=outlet_new(&x->x_obj, &s_float);
+ x->o_touch=outlet_new(&x->x_obj, &s_float);
+ if (!x->fader) x->o_fader=outlet_new(&x->x_obj, &s_float);
+
+ x->o_itsme = 0;
+ x->o_imtouched = 0;
+ x->activefader = 0;
+
+ pd_bind(&x->x_obj.ob_pd, ctlin_sym);
+
+ return (x);
+}
+static void faderIn_setup(void)
+{
+ faderIn_class = class_new(gensym("motormix_faderIn"), (t_newmethod)faderIn_new, (t_method)faderIn_free,
+ sizeof(t_faderIn), CLASS_NOINLET, A_DEFFLOAT, 0);
+ class_addcreator((t_newmethod)faderIn_new, gensym("mm_faderIn"), A_DEFFLOAT, 0);
+
+ class_addlist(faderIn_class, faderIn_list);
+ class_sethelpsymbol(faderIn_class, gensym("MIDIvice/motormix"));
+}
+
+/* ------------------------- faderOut ------------------------------- */
+
+static t_class *faderOut_class;
+typedef struct _faderOut
+{
+ t_object x_obj;
+
+ t_float fader;
+} t_faderOut;
+
+static void faderOut_float(t_faderOut *x, t_float f)
+{
+ int fader=x->fader;
+ unsigned char MSB, LSB;
+ if (f>=128)f=128;
+ else if (f<0)f=0;
+ if ((fader<1) || (fader>8))return;
+
+ MSB=f;
+ LSB=(f-MSB)*128;
+ outmidi_controlchange(x_port>>4, x_port&15, fader-1, MSB);
+ outmidi_controlchange(x_port>>4, x_port&15, fader-1+32, LSB);
+}
+
+static void *faderOut_new(t_floatarg f)
+{
+ t_faderOut *x = (t_faderOut *)pd_new(faderOut_class);
+
+ if ((f<0) || (f>=9)){
+ post("motormix_fader: fader [%d] specified. only faders 1..8(&0) are valid", (int)f);
+ f=0;
+ }
+ x->fader=f;
+ if (!x->fader)floatinlet_new(&x->x_obj, &x->fader);
+
+ return (x);
+}
+static void faderOut_setup(void)
+{
+ faderOut_class = class_new(gensym("motormix_faderOut"), (t_newmethod)faderOut_new,
+ 0, sizeof(t_faderOut), 0, A_DEFFLOAT, 0);
+ class_addcreator((t_newmethod)faderOut_new, gensym("mm_faderOut"), A_DEFFLOAT, 0);
+
+ class_addfloat(faderOut_class, faderOut_float);
+ class_sethelpsymbol(faderOut_class, gensym("MIDIvice/motormix"));
+}
+
+/* ------------------------- motormix ------------------------------- */
+
+static t_class *motormix_class;
+typedef struct _motormix
+{
+ t_object x_obj;
+} t_motormix;
+static void motormix_return(t_motormix *x, t_symbol *s, int argc, t_atom *argv)
+{
+ int p = atom_getfloatarg(0, argc, argv);
+ int v = atom_getfloatarg(1, argc, argv);
+
+ if ((p==0x00) && (v==0x7F))
+ outlet_bang(x->x_obj.ob_outlet);
+}
+
+static void motormix_bang(t_motormix *x)
+{ outmidi_noteon(x_port>>4, x_port&15,0,0); }
+
+static void motormix_help(t_motormix *x)
+{
+ post("MIDIvice - motormix\n===================");
+ post("support for MotorMix (tm) by cm-labs (r)");
+ post(" \tmotormix_faderIn"
+ "\n\tmotormix_rotary"
+ "\n\tmotormix_encoder"
+ "\n\tmotormix_button"
+ "\n\tmotormix_faderOut"
+ "\n\tmotormix_LED"
+ "\n\tmotormix_LCDtext"
+ "\n\tmotormix_LCDgraph"
+ "\n\tmotormix_7seg");
+ post("(l) forum::für::umläute @ IEM/KUG, Graz; 2002");
+}
+static void motormix_reset(t_motormix *x)
+{ /* this LOOKs like a reset; i don't know what it really is... */
+ LCD_header(SEG7);
+ LCD_footer();
+}
+static void motormix_free(t_motormix *x)
+{
+ pd_unbind(&x->x_obj.ob_pd, notein_sym);
+}
+static void *motormix_new(t_floatarg f)
+{
+ t_motormix *x = (t_motormix *)pd_new(motormix_class);
+ x_port=f;
+ outlet_new(&x->x_obj, &s_float);
+ pd_bind(&x->x_obj.ob_pd, notein_sym);
+ // outmidi_noteon(x_port>>4,x_port&15,0,0); // isn't this dangerous ???
+ return (x);
+}
+
+void motormix_setup(void)
+{
+ motormix_class = class_new(gensym("motormix"), (t_newmethod)motormix_new, (t_method)motormix_free,
+ sizeof(t_motormix), 0/*0CLASS_NOINLET*/, /*A_DEFFLOAT,*/ 0);
+
+ class_addcreator((t_newmethod)motormix_new, gensym("MotorMix"), /*A_DEFFLOAT,*/ 0);
+
+ class_addmethod(motormix_class, (t_method)motormix_help, gensym("help"), 0);
+ class_addbang(motormix_class, motormix_bang);
+ class_addmethod(motormix_class, (t_method)motormix_reset, gensym("reset"), 0);
+ class_addlist(motormix_class, motormix_return);
+
+ class_sethelpsymbol(motormix_class, gensym("MIDIvice/motormix"));
+
+ ctlin_sym = gensym("#ctlin");
+ notein_sym = gensym("#notein");
+
+ button_setup();
+ faderIn_setup();
+ faderOut_setup();
+ rotary_setup();
+ encoder_setup();
+ LED_setup();
+
+ LCDtext_setup();
+ LCDgraph_setup();
+ seg7_setup();
+
+ /* we have to send a motormix_ping once before it starts reacting.
+ * this seems to be a problem with pd, but i don't have hardware to test it right now
+ */
+ outmidi_noteon(x_port>>4,x_port&15,0,0);
+}
diff --git a/MIDIvice/src/motormix_buttons.txt b/MIDIvice/src/motormix_buttons.txt
new file mode 100644
index 0000000..47c4004
--- /dev/null
+++ b/MIDIvice/src/motormix_buttons.txt
@@ -0,0 +1,374 @@
+
+static int LED_sym2id(t_symbol *s)
+{
+ int id=-1;
+
+ if (s==gensym("1"))id=1; // +
+ else if (s==gensym("2"))id=2; // +
+ else if (s==gensym("3"))id=3; // +
+ else if (s==gensym("4"))id=4; // +
+ else if (s==gensym("5"))id=5; // +
+ else if (s==gensym("6"))id=6; // +
+ else if (s==gensym("7"))id=7; // +
+ else if (s==gensym("8"))id=8; // +
+ else if (s==gensym("a"))id=10;
+ else if (s==gensym("b"))id=11;
+ else if (s==gensym("c"))id=12;
+ else if (s==gensym("d"))id=13;
+ else if (s==gensym("e"))id=14;
+ else if (s==gensym("f"))id=15;
+ else if (s==gensym("g"))id=16;
+ else if (s==gensym("h"))id=17;
+ else if (s==gensym("i"))id=18;// +
+ else if (s==gensym("j"))id=19;// +
+ else if (s==gensym("k"))id=20;// +
+ else if (s==gensym("l"))id=21;// +
+ else if (s==gensym("m"))id=22;// +
+ else if (s==gensym("n"))id=23;// +
+ else if (s==gensym("o"))id=24;// +
+ else if (s==gensym("p"))id=25;// +
+ else if (s==gensym("q"))id=26;// +
+ else if (s==gensym("r"))id=27;// +
+ else if (s==gensym("s"))id=28;// +
+ else if (s==gensym("t"))id=29;// +
+ else if (s==gensym("u"))id=30;// +
+ else if (s==gensym("v"))id=31;// +
+ else if (s==gensym("w"))id=32;// +
+ else if (s==gensym("x"))id=33;// +
+ else if (s==gensym("y"))id=34;// +
+ else if (s==gensym("z"))id=35;// +
+ else if (s==gensym("0"))id=0;// +
+ else if (s==gensym("9"))id=9;// +
+ else if (s==gensym("*"))id=36;// +
+ else if (s==gensym("="))id=37;// +
+ else if (s==gensym("/"))id=38;// +
+ else if (s==gensym("."))id=39;// +
+ else if (s==gensym("shift")) id=40;
+ else if (s==gensym("undo")) id=41;
+ else if (s==gensym("default"))id=42;
+ else if (s==gensym("all")) id=43;
+ else if (s==gensym("window")) id=44;
+ else if (s==gensym("plug-in"))id=45;//...
+ else if (s==gensym("suspend"))id=46;
+ else if (s==gensym("auto")) id=47;
+
+ else if (s==gensym("escape")) id=48;//
+ else if (s==gensym("enter")) id=49;
+ else if (s==gensym("last")) id=40;
+ else if (s==gensym("next")) id=51;
+ else if (s==gensym("rewind")) id=52;
+ else if (s==gensym("f-fwd")) id=53;//
+ else if (s==gensym("stop")) id=54;
+ else if (s==gensym("play")) id=55;
+
+ else if (s==gensym("bank")) id=56;
+ else if (s==gensym("group")) id=57;
+ else if (s==gensym("record")) id=58;
+ else if (s==gensym("functA")) id=59;
+ else if (s==gensym("write")) id=50;
+ else if (s==gensym("functB")) id=61;
+ else if (s==gensym("burn")) id=62;
+ else if (s==gensym("functC")) id=63;
+ else if (s==gensym("fx")) id=64;//...
+ else if (s==gensym("fxbyps")) id=65;//...
+ else if (s==gensym("effect1"))id=66;//.
+ else if (s==gensym("eff-1")) id=67;//.
+ else if (s==gensym("mute")) id=68;//...
+ else if (s==gensym("s-mute")) id=69;//...
+ else if (s==gensym("effect2"))id=60;//.
+ else if (s==gensym("eff-2")) id=71;//.
+ else if (s==gensym("pre")) id=72;//...
+ else if (s==gensym("post")) id=73;//...
+ else if (s==gensym("pre/pst"))id=74;//...
+ else if (s==gensym("effect3"))id=75;//.
+ else if (s==gensym("eff-3")) id=76;//.
+ else if (s==gensym("sel")) id=77;//...
+ else if (s==gensym("select")) id=77;//...
+ else if (s==gensym("effect4"))id=78;//.
+ else if (s==gensym("eff-4")) id=79;//.
+
+
+ return id;
+}
+
+static void LED_id2rowcol(int id, int* row, int *col)
+{
+ *row=-1;
+ *col=-1;
+
+ if (id==1)*row=0,*col=0; //1
+ else if (id==2)*row=0,*col=1;
+ else if (id==3)*row=0,*col=2;
+ else if (id==4)*row=0,*col=3;
+ else if (id==5)*row=0,*col=4;
+ else if (id==6)*row=0,*col=5;
+ else if (id==7)*row=0,*col=6;
+ else if (id==8)*row=0,*col=7;
+
+ else if (id==10)*row=4,*col=0;//a
+ else if (id==11)*row=4,*col=1;
+ else if (id==12)*row=4,*col=2;
+ else if (id==13)*row=4,*col=3;
+ else if (id==14)*row=4,*col=4;
+ else if (id==15)*row=4,*col=5;
+ else if (id==16)*row=4,*col=6;
+ else if (id==17)*row=4,*col=7;
+ else if (id==18)*row=3,*col=0;//i
+ else if (id==19)*row=3,*col=1;
+ else if (id==20)*row=3,*col=2;
+ else if (id==21)*row=3,*col=3;
+ else if (id==22)*row=3,*col=4;
+ else if (id==23)*row=3,*col=5;
+ else if (id==24)*row=3,*col=6;
+ else if (id==25)*row=3,*col=7;
+ else if (id==26)*row=2,*col=0;//q
+ else if (id==27)*row=2,*col=1;
+ else if (id==28)*row=2,*col=2;
+ else if (id==29)*row=2,*col=3;
+ else if (id==30)*row=2,*col=4;
+ else if (id==31)*row=2,*col=5;
+ else if (id==32)*row=2,*col=6;
+ else if (id==33)*row=2,*col=7;
+ else if (id==34)*row=1,*col=0;//y
+ else if (id==35)*row=1,*col=1;
+ else if (id==0) *row=1,*col=2;
+ else if (id==9) *row=1,*col=3;
+ else if (id==36)*row=1,*col=4;
+ else if (id==37)*row=1,*col=5;
+ else if (id==38)*row=1,*col=6;
+ else if (id==39)*row=1,*col=7;
+
+ else if (id==40)*row=0,*col=8;//shift -- LEFT SIDE
+ else if (id==41)*row=1,*col=8;
+ else if (id==42)*row=2,*col=8;
+ else if (id==43)*row=3,*col=8;
+ else if (id==44)*row=4,*col=8;
+ else if (id==45)*row=5,*col=8;
+ else if (id==46)*row=6,*col=8;
+ else if (id==47)*row=7,*col=8;
+ else if (id==48)*row=0,*col=9;//escape -- RIGHT SIDE
+ else if (id==49)*row=1,*col=9;
+ else if (id==50)*row=2,*col=9;
+ else if (id==51)*row=3,*col=9;
+ else if (id==52)*row=4,*col=9;
+ else if (id==53)*row=5,*col=9;
+ else if (id==54)*row=6,*col=9;
+ else if (id==55)*row=7,*col=9;
+ else if (id==56)*row=0,*col=10;//left-arrow -- VIEW
+ else if (id==57)*row=1,*col=10;
+ else if (id==58)*row=2,*col=10;
+ else if (id==59)*row=3,*col=10;
+ else if (id==50)*row=4,*col=10;
+ else if (id==61)*row=5,*col=10;
+ else if (id==62)*row=6,*col=10;
+ else if (id==63)*row=7,*col=10;
+ else if (id==64)*row=0,*col=11;
+ else if (id==65)*row=0,*col=11;
+ else if (id==66)*row=1,*col=11;
+ else if (id==67)*row=1,*col=11;
+ else if (id==68)*row=2,*col=11;
+ else if (id==69)*row=2,*col=11;
+ else if (id==60)*row=3,*col=11;
+ else if (id==71)*row=3,*col=11;
+ else if (id==72)*row=4,*col=11;
+ else if (id==73)*row=4,*col=11;
+ else if (id==74)*row=4,*col=11;
+ else if (id==75)*row=5,*col=11;
+ else if (id==76)*row=5,*col=11;
+ else if (id==77)*row=6,*col=11;
+ else if (id==78)*row=7,*col=11;
+ else if (id==79)*row=7,*col=11;
+}
+
+
+static t_class *LED_class;
+typedef struct _LED
+{
+ t_object x_obj;
+
+ t_float LED;
+ t_float state;
+} t_LED;
+
+static void LED_float(t_LED *x, t_float f)
+{
+ int row, col;
+ int state = x->state;
+ int offset = 0;
+ int id = f;
+
+ LED_id2rowcol(id, &row, &col);
+
+ if (id<0)return;
+
+ if (state>0)offset=0x40;
+ else if (state<0)offset=0x50;
+
+
+ if (col<8)offset++;
+#if 0
+ post("LED: %x %x %x %x", 0x0C, col, 0x2C, row+offset);
+ post("LED: %d %d %d %d\n", 0x0C, col, 0x2C, row+offset);
+#endif
+ outmidi_controlchange(x_port>>4, x_port&15, 0x0C, col);
+ outmidi_controlchange(x_port>>4, x_port&15, 0x2C, row+offset);
+}
+
+static void LED_symbol(t_LED *x, t_symbol *s)
+{
+ LED_float(x, LED_sym2id(s));
+}
+
+static void LED_bang(t_LED *x)
+{
+
+}
+
+static void *LED_new(void)
+{
+ t_LED *x = (t_LED *)pd_new(LED_class);
+
+ x->LED=-1;
+ floatinlet_new(&x->x_obj, &x->state);
+
+ x->state=0;
+
+ return (x);
+}
+static void LED_setup(void)
+{
+ LED_class = class_new(gensym("motormix_LED"), (t_newmethod)LED_new,
+ 0, sizeof(t_LED), 0, 0);
+ class_addcreator((t_newmethod)LED_new, gensym("LED"), 0);
+
+ class_addsymbol(LED_class, LED_symbol);
+ class_addfloat (LED_class, LED_float);
+ class_addbang (LED_class, LED_bang);
+ class_sethelpsymbol(LED_class, gensym("zexy/motormix"));
+}
+
+/* button */
+static t_class *button_class;
+typedef struct _button
+{
+ t_object x_obj;
+ int o_itsme; // the fader changed
+ int o_imtouched; // the fader was touched
+
+ t_outlet *o_value; // actual fader-value
+ t_outlet *o_touch; // 1=touched; 0=released
+
+ int activefader;
+ int fader;
+ unsigned char MSB, LSB;
+} t_button;
+
+static void button_touch(t_button *x, unsigned char value, unsigned char control)
+{
+ int pressed=0;
+ int MSB=x->MSB;
+ int LSB=0;
+ int id=0;
+
+ x->o_imtouched=0;
+
+ if (x->MSB<8){
+ if ((value==0x00) || (value==0x40))return;
+ }
+
+ if (value>=0x40){
+ pressed=1;
+ value-=0x40;
+ }
+
+ LSB=value;
+
+ post("MSB=%d, LSB=%d", MSB, LSB);
+
+ switch (MSB) {
+ case 0x08: /* left side */
+ id=MSB+40;
+ break;
+ case 0x09: /* right side */
+ id=MSB+
+ break;
+ case 0x0A: /* VIEW */
+ break;
+ case 0x0B: /* fx */
+ break;
+ default:
+ if (MSB>0x08)return;
+ switch (LSB) {
+ case 0x01: /* 1..8 */
+ id=MSB+1;
+ break;
+ case 0x05: /* a..h */
+ id=MSB+10;
+ break;
+ case 0x04: /* i..p */
+ id=MSB+18;
+ break;
+ case 0x03: /* q..x */
+ id=MSB+26;
+ break;
+ case 0x02: /* y.. . */
+ switch (MSB){
+ case 0: case 1:
+ id=MSB+34;
+ break;
+ case 2:
+ id=0;
+ break;
+ case 3:
+ id=9;
+ break;
+ default:
+ id=MSB+32;
+ }
+ break;
+ default:
+ return;
+ }
+ }
+
+
+ outlet_float(x->o_touch, pressed);
+ outlet_float(x->o_value, id);
+}
+
+static void button_list(t_button *x, t_symbol *s, int argc, t_atom *argv)
+{
+ unsigned char ctl = atom_getfloatarg(0, argc, argv);
+ unsigned char val = atom_getfloatarg(1, argc, argv);
+ // int channel = atom_getfloatarg(2, argc, argv);
+
+ if (x->o_imtouched)button_touch(x, val, ctl);
+
+ if (ctl==0x0f){
+ x->o_imtouched=1;
+ x->MSB=val;
+ }
+}
+
+static void *button_new()
+{
+ t_button *x = (t_button *)pd_new(button_class);
+
+ x->o_value=outlet_new(&x->x_obj, &s_float);
+ x->o_touch=outlet_new(&x->x_obj, &s_float);
+
+ x->o_imtouched = 0;
+
+ pd_bind(&x->x_obj.ob_pd, ctlin_sym);
+
+ return (x);
+}
+static void button_setup(void)
+{
+ button_class = class_new(gensym("motormix_button"), (t_newmethod)button_new,
+ 0, sizeof(t_button), CLASS_NOINLET, A_DEFFLOAT, 0);
+ class_addcreator((t_newmethod)button_new, gensym("button"), A_DEFFLOAT, 0);
+
+ class_addlist(button_class, button_list);
+ class_sethelpsymbol(button_class, gensym("zexy/motormix"));
+}