diff options
author | Hans-Christoph Steiner <eighthave@users.sourceforge.net> | 2007-07-09 20:45:58 +0000 |
---|---|---|
committer | Hans-Christoph Steiner <eighthave@users.sourceforge.net> | 2007-07-09 20:45:58 +0000 |
commit | 17ec1deb74e2e934dc11fb4d9a2f8c6cef34c5a7 (patch) | |
tree | ce721cdc62bab6b69dbd023abfc3075d2609f64c |
This commit was generated by cvs2svn to compensate for changes in r7949,svn2git-root
which included commits to RCS files with non-trunk default branches.
svn path=/trunk/externals/moonlib/; revision=7950
-rw-r--r-- | .directory | 47 | ||||
-rw-r--r-- | Makefile | 18 | ||||
-rw-r--r-- | README.txt | 113 | ||||
-rw-r--r-- | XFS.txt | 1 | ||||
-rw-r--r-- | absolutepath.c | 140 | ||||
-rw-r--r-- | basedir.c | 72 | ||||
-rw-r--r-- | char2f.c | 53 | ||||
-rw-r--r-- | comma.c | 53 | ||||
-rw-r--r-- | dinlet~.c | 136 | ||||
-rw-r--r-- | dispatch.c | 194 | ||||
-rw-r--r-- | dripchar.c | 82 | ||||
-rw-r--r-- | f2char.c | 53 | ||||
-rw-r--r-- | gamme.c | 558 | ||||
-rw-r--r-- | help/absolutepath-help.pd | 13 | ||||
-rw-r--r-- | help/basedir-help.pd | 18 | ||||
-rw-r--r-- | help/char2f-help.pd | 18 | ||||
-rw-r--r-- | help/comma-help.pd | 40 | ||||
-rw-r--r-- | help/d/d0.gif | bin | 0 -> 231 bytes | |||
-rw-r--r-- | help/d/d1.gif | bin | 0 -> 232 bytes | |||
-rw-r--r-- | help/d/d10.gif | bin | 0 -> 239 bytes | |||
-rw-r--r-- | help/d/d11.gif | bin | 0 -> 238 bytes | |||
-rw-r--r-- | help/d/d12.gif | bin | 0 -> 236 bytes | |||
-rw-r--r-- | help/d/d13.gif | bin | 0 -> 237 bytes | |||
-rw-r--r-- | help/d/d14.gif | bin | 0 -> 237 bytes | |||
-rw-r--r-- | help/d/d15.gif | bin | 0 -> 239 bytes | |||
-rw-r--r-- | help/d/d16.gif | bin | 0 -> 238 bytes | |||
-rw-r--r-- | help/d/d17.gif | bin | 0 -> 234 bytes | |||
-rw-r--r-- | help/d/d18.gif | bin | 0 -> 232 bytes | |||
-rw-r--r-- | help/d/d19.gif | bin | 0 -> 239 bytes | |||
-rw-r--r-- | help/d/d2.gif | bin | 0 -> 237 bytes | |||
-rw-r--r-- | help/d/d20.gif | bin | 0 -> 240 bytes | |||
-rw-r--r-- | help/d/d21.gif | bin | 0 -> 236 bytes | |||
-rw-r--r-- | help/d/d22.gif | bin | 0 -> 236 bytes | |||
-rw-r--r-- | help/d/d23.gif | bin | 0 -> 236 bytes | |||
-rw-r--r-- | help/d/d24.gif | bin | 0 -> 236 bytes | |||
-rw-r--r-- | help/d/d25.gif | bin | 0 -> 234 bytes | |||
-rw-r--r-- | help/d/d26.gif | bin | 0 -> 234 bytes | |||
-rw-r--r-- | help/d/d27.gif | bin | 0 -> 236 bytes | |||
-rw-r--r-- | help/d/d28.gif | bin | 0 -> 235 bytes | |||
-rw-r--r-- | help/d/d29.gif | bin | 0 -> 234 bytes | |||
-rw-r--r-- | help/d/d3.gif | bin | 0 -> 234 bytes | |||
-rw-r--r-- | help/d/d30.gif | bin | 0 -> 233 bytes | |||
-rw-r--r-- | help/d/d31.gif | bin | 0 -> 233 bytes | |||
-rw-r--r-- | help/d/d32.gif | bin | 0 -> 238 bytes | |||
-rw-r--r-- | help/d/d33.gif | bin | 0 -> 233 bytes | |||
-rw-r--r-- | help/d/d34.gif | bin | 0 -> 236 bytes | |||
-rw-r--r-- | help/d/d35.gif | bin | 0 -> 233 bytes | |||
-rw-r--r-- | help/d/d36.gif | bin | 0 -> 235 bytes | |||
-rw-r--r-- | help/d/d37.gif | bin | 0 -> 236 bytes | |||
-rw-r--r-- | help/d/d38.gif | bin | 0 -> 237 bytes | |||
-rw-r--r-- | help/d/d39.gif | bin | 0 -> 236 bytes | |||
-rw-r--r-- | help/d/d4.gif | bin | 0 -> 231 bytes | |||
-rw-r--r-- | help/d/d40.gif | bin | 0 -> 237 bytes | |||
-rw-r--r-- | help/d/d41.gif | bin | 0 -> 235 bytes | |||
-rw-r--r-- | help/d/d42.gif | bin | 0 -> 238 bytes | |||
-rw-r--r-- | help/d/d43.gif | bin | 0 -> 236 bytes | |||
-rw-r--r-- | help/d/d44.gif | bin | 0 -> 230 bytes | |||
-rw-r--r-- | help/d/d45.gif | bin | 0 -> 235 bytes | |||
-rw-r--r-- | help/d/d46.gif | bin | 0 -> 236 bytes | |||
-rw-r--r-- | help/d/d47.gif | bin | 0 -> 235 bytes | |||
-rw-r--r-- | help/d/d48.gif | bin | 0 -> 240 bytes | |||
-rw-r--r-- | help/d/d49.gif | bin | 0 -> 236 bytes | |||
-rw-r--r-- | help/d/d5.gif | bin | 0 -> 238 bytes | |||
-rw-r--r-- | help/d/d50.gif | bin | 0 -> 237 bytes | |||
-rw-r--r-- | help/d/d51.gif | bin | 0 -> 236 bytes | |||
-rw-r--r-- | help/d/d52.gif | bin | 0 -> 234 bytes | |||
-rw-r--r-- | help/d/d53.gif | bin | 0 -> 239 bytes | |||
-rw-r--r-- | help/d/d54.gif | bin | 0 -> 238 bytes | |||
-rw-r--r-- | help/d/d55.gif | bin | 0 -> 240 bytes | |||
-rw-r--r-- | help/d/d56.gif | bin | 0 -> 235 bytes | |||
-rw-r--r-- | help/d/d57.gif | bin | 0 -> 236 bytes | |||
-rw-r--r-- | help/d/d58.gif | bin | 0 -> 236 bytes | |||
-rw-r--r-- | help/d/d59.gif | bin | 0 -> 236 bytes | |||
-rw-r--r-- | help/d/d6.gif | bin | 0 -> 236 bytes | |||
-rw-r--r-- | help/d/d60.gif | bin | 0 -> 235 bytes | |||
-rw-r--r-- | help/d/d61.gif | bin | 0 -> 236 bytes | |||
-rw-r--r-- | help/d/d62.gif | bin | 0 -> 235 bytes | |||
-rw-r--r-- | help/d/d63.gif | bin | 0 -> 229 bytes | |||
-rw-r--r-- | help/d/d7.gif | bin | 0 -> 237 bytes | |||
-rw-r--r-- | help/d/d8.gif | bin | 0 -> 240 bytes | |||
-rw-r--r-- | help/d/d9.gif | bin | 0 -> 237 bytes | |||
-rw-r--r-- | help/dinlet~-help.pd | 37 | ||||
-rw-r--r-- | help/dispatch-help.pd | 65 | ||||
-rw-r--r-- | help/dripchar-help.pd | 28 | ||||
-rw-r--r-- | help/f2char-help.pd | 18 | ||||
-rw-r--r-- | help/f2s-help.pd | 17 | ||||
-rw-r--r-- | help/gamme-help.pd | 171 | ||||
-rw-r--r-- | help/image-help.pd | 104 | ||||
-rw-r--r-- | help/joystik-help.pd | 44 | ||||
-rw-r--r-- | help/makecolor-help.pd | 18 | ||||
-rw-r--r-- | help/mknob-help.pd | 53 | ||||
-rw-r--r-- | help/panvol~-help.pd | 34 | ||||
-rw-r--r-- | help/pause.gif | bin | 0 -> 61 bytes | |||
-rw-r--r-- | help/play.gif | bin | 0 -> 58 bytes | |||
-rw-r--r-- | help/playy.gif | bin | 0 -> 58 bytes | |||
-rw-r--r-- | help/popen-help.pd | 68 | ||||
-rw-r--r-- | help/readsfv~-help.pd | 60 | ||||
-rw-r--r-- | help/rec.gif | bin | 0 -> 58 bytes | |||
-rw-r--r-- | help/relativepath-help.pd | 13 | ||||
-rw-r--r-- | help/s2f-help.pd | 18 | ||||
-rw-r--r-- | help/sarray-help.pd | 93 | ||||
-rw-r--r-- | help/saww.gif | bin | 0 -> 61 bytes | |||
-rw-r--r-- | help/sfread2~-help.pd | 60 | ||||
-rw-r--r-- | help/sin.gif | bin | 0 -> 58 bytes | |||
-rw-r--r-- | help/sinw.gif | bin | 0 -> 61 bytes | |||
-rw-r--r-- | help/slist-help.pd | 61 | ||||
-rw-r--r-- | help/squarew.gif | bin | 0 -> 61 bytes | |||
-rw-r--r-- | help/ssaw~-help.pd | 21 | ||||
-rw-r--r-- | help/tabdump2-help.pd | 31 | ||||
-rw-r--r-- | help/tabenv-help.pd | 25 | ||||
-rw-r--r-- | help/tabreadl-help.pd | 26 | ||||
-rw-r--r-- | help/tabsort-help.pd | 32 | ||||
-rw-r--r-- | help/tabsort2-help.pd | 84 | ||||
-rw-r--r-- | image.c | 306 | ||||
-rw-r--r-- | joystik.c | 191 | ||||
-rw-r--r-- | mknob.c | 870 | ||||
-rw-r--r-- | panvol~.c | 119 | ||||
-rw-r--r-- | popen.c | 211 | ||||
-rw-r--r-- | readsfv~.c | 1683 | ||||
-rw-r--r-- | relativepath.c | 146 | ||||
-rw-r--r-- | s2f.c | 53 | ||||
-rw-r--r-- | sarray.c | 264 | ||||
-rw-r--r-- | sfread2~.c | 410 | ||||
-rw-r--r-- | slist.c | 233 | ||||
-rw-r--r-- | ssaw~.c | 213 | ||||
-rw-r--r-- | tabdump2.c | 120 | ||||
-rw-r--r-- | tabenv.c | 294 | ||||
-rw-r--r-- | tabreadl.c | 84 | ||||
-rw-r--r-- | tabsort.c | 124 | ||||
-rw-r--r-- | tabsort2.c | 164 | ||||
-rw-r--r-- | wac.c | 253 |
131 files changed, 8528 insertions, 0 deletions
diff --git a/.directory b/.directory new file mode 100644 index 0000000..30a00cb --- /dev/null +++ b/.directory @@ -0,0 +1,47 @@ +[IconPosition::README] +X=456 +Y=60 + +[IconPosition::docs] +X=28 +Y=5 + +[IconPosition::externs] +X=113 +Y=5 + +[IconPosition::externs0.37] +X=190 +Y=5 + +[IconPosition::makefile] +X=287 +Y=60 + +[IconPosition::nilib_0.1.0] +X=281 +Y=5 + +[IconPosition::nilib_0.2.0] +X=368 +Y=5 + +[IconPosition::others_0.2] +X=453 +Y=5 + +[IconPosition::paths.txt] +X=370 +Y=60 + +[IconPosition::sublib_0.1.0] +X=16 +Y=60 + +[IconPosition::sublib_0.2.0] +X=103 +Y=60 + +[IconPosition::sublib_0.3.0] +X=190 +Y=60 diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..ae29994 --- /dev/null +++ b/Makefile @@ -0,0 +1,18 @@ +TARGET := $(shell pwd | sed 's|.*/\(.*\)$$|\1|') +EXTERNALS_ROOT := $(shell pwd | sed 's|^\(/.*externals\).*|\1|') + +default: + make -C $(EXTERNALS_ROOT) $(TARGET) + +install: + make -C $(EXTERNALS_ROOT) $(TARGET)_install + +clean: + make -C $(EXTERNALS_ROOT) $(TARGET)_clean + +test_locations: + make -C $(EXTERNALS_ROOT) test_locations + +etags: + etags *.[ch] $(EXTERNALS_ROOT)/../pd/src/*.[ch] /usr/include/*.h \ + /usr/include/*/*.h diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..e4e5d5a --- /dev/null +++ b/README.txt @@ -0,0 +1,113 @@ +Here are the libs I've written for Pd. +They can be splitted in three parts: + + 1. the nilib library, which is a kind of wrapper between Pd and Gtk, and its + objects: + nifs (a one-click file selector, with some special tricks...), niscope (a + simple oscilloscope), and nileon (a simple drum machine, but it's the + replication of an enormous mechanical one, named Leon Napakatbra, which was + built from a 8 meters diameter merry-go-round...). + There was also nimouse (giving mouse position/buttons) and nitab (the same + for wacom serial graphire tablet) but i don't use these anymore: it's too + dangerous to access a device file directly from pd. Beter use gtkmouse and + wac/wacusb programs with pdsend/pdreceive. + + 2. the sub library, which is a collection of gui control objects (subdial, + subslider, subbang and subtoggle) that are placed into a subpatch but are + visible in the parent window, into the subpatch's box. The idea was to build + easy-to-use complex subpatchs, or abstractions. I wrote it before + "graph-on-parent" was implemented in Pd, so it's a bit deprecated now, but + it has the advantage that subs values (positions of the buttons) are saved + into the parent patch... very useful in case of abstractions. + About of these questions, have a look to my AutoPreset abstractions, which + adds a manner to save the value of regular gui objects (hslider etc...) into + either a file or the parent patch, even those nested in abstractions (and + recursively in abstractions of abstractions...). It works also with tables, + symbols and symbol arrays. + + 3. some other objects, such as: + + tabenv : like env~, an enveloppe follower, but computing on a table, so + possibly much speeder than real-time env~'s computation. + tabsort and tabsort2 : returns the indices of the sorted table (tabsort2 + is bidimentionnal). + gamme : one octave of a piano keyboard used to filter/choose notes in a + selected scale. + absolutepath/relativepath : to use datas (sounds, texts, presets, images, + programs...) nested in the patch's directory (and in subdirs). + sarray and slist : to creates shared dynamic arrays or lists with symbols. + sfread2~ and readsfv~ : to pitch the direct-from-disk reading of sound files. + dinlet~ : an inlet~ with a default value (when nothing is connected to it). + mknob : a round knob ala iemgui vslider (with its "properties" window). + dispatch : creates one bus name for many buttons' buses: from the N pairs + (slider1-snd/slider1-rcv) ... (sliderN-snd/sliderN-rcv), creates only + one pair of buses named (slider-snd/slider-rcv) , in which datas are + prepended by the number of the "sub-bus". + joystik : an improvment of Joseph A. Sarlo's joystick. + image : an improvment of Guenter Geiger's one. Same name, but it's + compatible. Here you can share images through different objects, preload + a list of images, and animate this list. + + and some others... + +CAUTION: + + This stuff was written with Pd v0.34-4 to v0.37 on a PC under Linux. It + hasn't be tested under other conditions; nilib will only work under Linux + (but I think it will be OK on other machines than PC), because of use of + multithreading and GTK . + Anyway makefiles are only working for Linux for the moment... + Moreover I think sub library is potentially very sensible to possible + modifications of Pd sources. + + + +To install: + +sublib_0.1.0 is for Pd 0.33 +sublib_0.2.0 is for Pd 0.35 +sublib_0.3.0 is for Pd 0.37 + +nilib_0.1.0 is for Pd 0.35 +nilib_0.2.0 is for Pd 0.37 + +others_0.1.0 is for Pd 0.35 +others_0.2.0 is for Pd 0.37 + + + +Edit paths.txt to tune install paths and pure-data's location. +Edit this makefile if you want to select older versions of externals (if you + are using pd0.37 it should be ok). + +Then: + +make +make install + + + +If you keep externals locally inside moonlibs directory, then you should add it +to your pdrc file: + +-path moonlibs-0.2/externs +-helppath moonlibs-0.2/docs + + +CAUTION : + 1) (pd 0.35) You MUST fix a bug pd sources and recompile them in order to have + dinlet~ working !! + You have to replace the function obj_findsignalscalar() in file m_obj.c + by the one written in dinlet~.c . + + (dinlet~ is a signal inlet where you can choose the default float value it + outputs when no signal is connected into.) + + + 2) In order to have sfread~ working with big files in direct-from-disk + mode you have to hack pd sources: change + mlockall(MCL_FUTURE) + with + mlockall(MCL_CURRENT) + in s_linux.c (pd0.35) or s_inter.c (pd0.37). If not the whole file will be loaded in memory when + opening it. @@ -0,0 +1 @@ +xfs -port -1 -daemon -droppriv -user xfs diff --git a/absolutepath.c b/absolutepath.c new file mode 100644 index 0000000..3e75df6 --- /dev/null +++ b/absolutepath.c @@ -0,0 +1,140 @@ +/* +Copyright (C) 2002 Antoine Rousseau + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +/*#include <m_imp.h>*/ +#include "m_pd.h" +#include "g_canvas.h" + +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> +#include <libgen.h> +#include <string.h> + +extern t_canvas *canvas_list; /* list of all root canvases */ +extern int canvas_getdollarzero( void); + +struct _canvasenvironment +{ + t_symbol *ce_dir; /* directory patch lives in */ + int ce_argc; /* number of "$" arguments */ + t_atom *ce_argv; /* array of "$" arguments */ + int ce_dollarzero; /* value of "$0" */ +}; + +typedef struct _absolutepath +{ + t_object x_obj; + t_canvas *x_canvas; + int x_dolzero; + int x_realized; +}t_absolutepath; + +t_class *absolutepath_class; + +void absolutepath_setup(void); + +static t_glist *getcanvas(t_glist *can,int d0) +{ + t_canvas *retcan=0; + t_gobj *ob; + + if((can->gl_env)&&(can->gl_env->ce_dollarzero==d0)){ + return can; + } + + ob=can->gl_list; + while(ob&&(retcan==0)) { + if (pd_class(&ob->g_pd) == canvas_class) + retcan=getcanvas((t_glist *)ob,d0); + ob=ob->g_next; + } + + if((!retcan)&&(can->gl_next)) retcan=getcanvas((t_glist *)can->gl_next,d0); + return retcan; +} + + +static void absolutepath_symbol(t_absolutepath *x,t_symbol *sym) +{ + t_canvas *can=0; + char buf[MAXPDSTRING], *bufptr, + *instr=sym->s_name, + canname[MAXPDSTRING],totaldir[MAXPDSTRING], + *cnamedir, + *candir; + unsigned int n,i=0; + int fd; + + if(!x->x_realized) can=(t_canvas*)getcanvas(canvas_list,x->x_dolzero); + if(can) { + x->x_canvas = can; + x->x_realized = 1; + //post("found $0 canvas : %x %d ",x->x_canvas, x->x_canvas->gl_env->ce_dollarzero ); + } + + if(!instr) return; + + candir=canvas_getdir(x->x_canvas)->s_name; + if(!candir) candir=""; + + //post("input= %s candir= %s glname=%s",instr,candir,x->x_canvas->gl_name->s_name); + + strcpy(canname,x->x_canvas->gl_name->s_name); + cnamedir=dirname(canname); + + if (strcmp(cnamedir,".")) { + sprintf(totaldir,"%s/%s",candir,cnamedir); + fd=open_via_path(totaldir,instr ,"",buf, &bufptr, MAXPDSTRING, 1); + } + else + fd=open_via_path(candir, instr, "",buf, &bufptr, MAXPDSTRING, 1); + + if (fd>=0) { + close(fd); + buf[strlen(buf)]='/'; + outlet_symbol(x->x_obj.ob_outlet,gensym(buf)); + } + return; +} + + +static void *absolutepath_new(t_float dolzero) +{ + t_absolutepath *x = (t_absolutepath *)pd_new(absolutepath_class); + t_canvas *can=canvas_list; + int d0; + + outlet_new(&x->x_obj, 0); + x->x_canvas = canvas_getcurrent(); + x->x_dolzero = dolzero; + x->x_realized=dolzero?0:1; + + return (void *)x; +} + +void absolutepath_setup(void) +{ + absolutepath_class = class_new(gensym("absolutepath"),(t_newmethod)absolutepath_new, + 0, sizeof(t_absolutepath), 0,A_DEFFLOAT, 0); + + class_addsymbol(absolutepath_class, absolutepath_symbol); +} + diff --git a/basedir.c b/basedir.c new file mode 100644 index 0000000..ad2f4f6 --- /dev/null +++ b/basedir.c @@ -0,0 +1,72 @@ +/* +Copyright (C) 2002 Antoine Rousseau + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +/*#include <m_imp.h>*/ +#include "m_pd.h" + +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> +#include <libgen.h> +#include <string.h> + +typedef struct _basedir +{ + t_object x_obj; +}t_basedir; + +t_class *basedir_class; + +void basedir_setup(void); + +static void basedir_symbol(t_basedir *x,t_symbol *sym) +{ + static t_binbuf *binbuf=0; + t_atom at[2]; + char *b,*d; + int l; + + if(!sym->s_name) return; + + b=strdup(sym->s_name); + d=strdup(sym->s_name); + + SETSYMBOL(&at[0],gensym(basename(b))); + SETSYMBOL(&at[1],gensym(dirname(d))); + + outlet_list(x->x_obj.ob_outlet,0,2,at); +} + + +static void *basedir_new(void) +{ + t_basedir *x = (t_basedir *)pd_new(basedir_class); + outlet_new(&x->x_obj, 0); + return (void *)x; +} + +void basedir_setup(void) +{ + basedir_class = class_new(gensym("basedir"),(t_newmethod)basedir_new, + 0, sizeof(t_basedir), 0, 0); + + class_addsymbol(basedir_class, basedir_symbol); +} + diff --git a/char2f.c b/char2f.c new file mode 100644 index 0000000..ef8af99 --- /dev/null +++ b/char2f.c @@ -0,0 +1,53 @@ +/* +Copyright (C) 2002 Antoine Rousseau + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include "m_pd.h" + + +typedef struct _char2f +{ + t_object x_obj; +}t_char2f; + +t_class *char2f_class; + +void char2f_setup(void); + +static void char2f_symbol(t_char2f *x,t_symbol *sym) +{ + if(!sym->s_name) return; + + outlet_float(x->x_obj.ob_outlet,(float)sym->s_name[0]); +} + +static void *char2f_new(void) +{ + t_char2f *x = (t_char2f *)pd_new(char2f_class); + outlet_new(&x->x_obj, &s_float); + return (void *)x; +} + +void char2f_setup(void) +{ + char2f_class = class_new(gensym("char2f"),(t_newmethod)char2f_new, + 0, sizeof(t_char2f), 0, 0); + + class_addsymbol(char2f_class, char2f_symbol); +} + @@ -0,0 +1,53 @@ +/* +Copyright (C) 2002 Antoine Rousseau + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include "m_pd.h" + +static t_atom _commaatom_; + +typedef struct _comma +{ + t_object x_obj; +}t_comma; + +t_class *comma_class; + +void comma_setup(void); + +static void comma_bang(t_comma *x) +{ + outlet_list(x->x_obj.ob_outlet, &s_list, 1, &_commaatom_); +} + +static void *comma_new(void) +{ + t_comma *x = (t_comma *)pd_new(comma_class); + outlet_new(&x->x_obj,&s_symbol); + return (void *)x; +} + +void comma_setup(void) +{ + comma_class = class_new(gensym("comma"),(t_newmethod)comma_new, + 0, sizeof(t_comma), 0, 0); + + class_addbang(comma_class, comma_bang); + SETCOMMA(&_commaatom_); +} + diff --git a/dinlet~.c b/dinlet~.c new file mode 100644 index 0000000..dc7f260 --- /dev/null +++ b/dinlet~.c @@ -0,0 +1,136 @@ +/* +Copyright (C) 2002 Antoine Rousseau + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +/* this file is made from parts of m_object.c and g_io.c +* it defines a signal inlet named dinlet~ which is the same as inlet~ +* exepts you can give a default float value for the case none signal +* is connected to this inlet~. */ + +/***********************************************************************/ +/* CAUTION : + You MUST fix a bug pd sources and recompile them in order to have + dinlet~ working !! + + this function must be fixed in pd/m_obj.c: */ +#if 0 +t_sample *obj_findsignalscalar(t_object *x, int m) +{ + int n = 0,mbak=m; + t_inlet *i; + post("my obj_findsignalscalar"); + if (x->ob_pd->c_firstin && x->ob_pd->c_floatsignalin) + { + if (!m--) + return (x->ob_pd->c_floatsignalin > 0 ? + (t_sample *)(((char *)x) + x->ob_pd->c_floatsignalin) : 0); + n++; + } + for (i = x->ob_inlet; i; i = i->i_next, m--) + if (i->i_symfrom == &s_signal) + { + /*if (m == 0)*/ + if(n==mbak) + return (&i->i_un.iu_floatsignalvalue); + n++; + } + return (0); +} +#endif +/***********************************************************************/ + +#include "m_pd.h" +#include "m_imp.h" +#include "g_canvas.h" +#include <string.h> + +/******************** from m_obj.c: **************************/ +/* only because inlet_float() is not public... */ +union inletunion +{ + t_symbol *iu_symto; + t_gpointer *iu_pointerslot; + t_float *iu_floatslot; + t_symbol **iu_symslot; + t_sample iu_floatsignalvalue; +}; + +struct _inlet +{ + t_pd i_pd; + struct _inlet *i_next; + t_object *i_owner; + t_pd *i_dest; + t_symbol *i_symfrom; + union inletunion i_un; +}; + +#define i_symto i_un.iu_symto + +static void dinlet_float(t_inlet *x, t_float f) +{ + if (x->i_symfrom == &s_float) + pd_vmess(x->i_dest, x->i_symto, "f", (t_floatarg)f); + else if (x->i_symfrom == &s_signal) + x->i_un.iu_floatsignalvalue = f; + else if (!x->i_symfrom) + pd_float(x->i_dest, f); + /*else inlet_wrong(x, &s_float);*/ +} +/**************** from g_io.c : *********************************/ + +void signal_setborrowed(t_signal *sig, t_signal *sig2); +void signal_makereusable(t_signal *sig); + +/* ------------------------- vinlet -------------------------- */ +t_class *vinlet_class; + +typedef struct _vinlet +{ + t_object x_obj; + t_canvas *x_canvas; + t_inlet *x_inlet; + int x_bufsize; + t_float *x_buf; /* signal buffer; zero if not a signal */ + t_float *x_endbuf; + t_float *x_fill; + t_float *x_read; + int x_hop; + /* if not reblocking, the next slot communicates the parent's inlet + signal from the prolog to the DSP routine: */ + t_signal *x_directsignal; +} t_vinlet; + + +static void *dinlet_newsig(t_floatarg f) +{ + t_vinlet *x = (t_vinlet *)pd_new(vinlet_class); + x->x_canvas = canvas_getcurrent(); + x->x_inlet = canvas_addinlet(x->x_canvas, &x->x_obj.ob_pd, &s_signal,0); + x->x_endbuf = x->x_buf = (t_float *)getbytes(0); + x->x_bufsize = 0; + x->x_directsignal = 0; + x->x_inlet->i_un.iu_floatsignalvalue=f; + outlet_new(&x->x_obj, &s_signal); + return (x); +} + +void dinlet_tilde_setup(void) +{ + class_addcreator((t_newmethod)dinlet_newsig, gensym("dinlet~"), A_DEFFLOAT,0); +} diff --git a/dispatch.c b/dispatch.c new file mode 100644 index 0000000..f8a937a --- /dev/null +++ b/dispatch.c @@ -0,0 +1,194 @@ +/* +Copyright (C) 2003 Antoine Rousseau + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +/* a shared symbol array, ala "value" .*/ + +#include "m_pd.h" +#include <stdlib.h> +#include <string.h> +#include <stdio.h> + +static t_class *dispatch_class, *dispsnd_class; +static t_symbol *s__; + +typedef struct _dispatch t_dispatch; + +typedef struct dispsnd +{ + t_pd d_pd; + t_symbol *d_eachsnd; + t_symbol *d_allsnd; + t_int d_num; +} t_dispsnd; + +struct _dispatch +{ + t_object x_obj; + t_symbol *x_sym; + int x_from; + int x_to; + + t_dispsnd **x_snds; + + t_symbol *x_allrcv; + t_symbol **x_eachrcvs; +}; + +/*--------------------- dispsnd ------------------------------------*/ + +static void dispsnd_ff(t_dispsnd *x) +{ + pd_unbind((t_pd*)x, x->d_eachsnd); +} + +static void *dispsnd_new(t_symbol *eachsnd,t_symbol *allsnd,int num) +{ + t_dispsnd *x = (t_dispsnd *)pd_new(dispsnd_class); + + //post("new dispsnd: num=%d rcv=%s snd=%s",num,eachsnd->s_name,allsnd->s_name); + x->d_eachsnd=eachsnd; + x->d_allsnd=allsnd; + x->d_num=num; + + pd_bind((t_pd*)x, x->d_eachsnd); + + return (x); +} + +static void dispsnd_float(t_dispsnd *x, t_float f) +{ + t_atom out[2]; + + if (x->d_allsnd->s_thing) { + SETFLOAT(&out[0],x->d_num); + SETFLOAT(&out[1],f); + + typedmess(x->d_allsnd->s_thing, &s_list, 2, out); + } +} + +static void dispsnd_anything(t_dispsnd *x, t_symbol *s, int argc, t_atom *argv) +{ + t_atom *out; + + if (x->d_allsnd->s_thing) { + out = (t_atom*)getbytes(sizeof(t_atom)*(argc+2)); + memcpy(&out[2], argv, argc*sizeof(t_atom)); + SETFLOAT(&out[0],x->d_num); + SETSYMBOL(&out[1],s); + + typedmess(x->d_allsnd->s_thing, &s_list, argc+2, out); + + freebytes(out, sizeof(t_atom)*(argc+2)); + } +} + + + +/*--------------------- dispatch ------------------------------------*/ + +static void *dispatch_new(t_symbol *s,t_float from,t_float to) +{ + int i,len; + t_dispatch *x = (t_dispatch *)pd_new(dispatch_class); + char str[512]; + t_symbol *allsnd,*eachsnd; + + x->x_snds=0; + x->x_sym = s; + x->x_from = from; + x->x_to = to; + len=x->x_to-x->x_from+1; + + if(len>0){ + sprintf(str,"%s-snd",x->x_sym->s_name); + allsnd=gensym(str); + + sprintf(str,"%s-rcv",x->x_sym->s_name); + x->x_allrcv=gensym(str); + pd_bind((t_pd*)x, x->x_allrcv); + + x->x_snds=getbytes(len*sizeof(t_dispsnd *)); + x->x_eachrcvs=getbytes(len*sizeof(t_symbol *)); + + for(i=0;i<len;i++){ + sprintf(str,"%s%d-snd",x->x_sym->s_name,i+x->x_from); + eachsnd=gensym(str); + x->x_snds[i]=dispsnd_new(eachsnd,allsnd,i+x->x_from); + + sprintf(str,"%s%d-rcv",x->x_sym->s_name,i+x->x_from); + x->x_eachrcvs[i]=gensym(str); + } + } + return (x); +} + +static void dispatch_ff(t_dispatch *x) +{ + int i,len=x->x_to-x->x_from+1; + + if(len<=0) return; + + pd_unbind((t_pd*)x, x->x_allrcv); + + for(i=0;i<len;i++) pd_free((t_pd*)x->x_snds[i]); + + freebytes(x->x_snds,len*sizeof(t_dispsnd *)); + freebytes(x->x_eachrcvs,len*sizeof(t_symbol *)); +} + + +static void dispatch_list(t_dispatch *x, t_symbol *s, int argc, t_atom *argv) +{ + int num; + + if((!argc)|(argv[0].a_type!=A_FLOAT)) { + error("dispatch: bad list format"); + return; + } + + num=atom_getint(&argv[0]); + + if((num<x->x_from)|(num>x->x_to)) { + //error("dispatch: bad num"); + return; + } + + if (x->x_eachrcvs[num-x->x_from]->s_thing) + pd_forwardmess(x->x_eachrcvs[num-x->x_from]->s_thing, argc-1, argv+1); +} + + + + +/*--------------------------------------------------------------*/ + +void dispatch_setup(void) +{ + dispatch_class = class_new(gensym("dispatch"), (t_newmethod)dispatch_new, + (t_method)dispatch_ff, + sizeof(t_dispatch), 0, A_SYMBOL, A_FLOAT, A_FLOAT,0); + + class_addlist(dispatch_class, dispatch_list); + dispsnd_class = class_new(gensym("dispatch"), 0, (t_method)dispsnd_ff, + sizeof(t_dispsnd), CLASS_PD, 0); + class_addanything(dispsnd_class, dispsnd_anything); + class_addfloat(dispsnd_class, dispsnd_float); +} + diff --git a/dripchar.c b/dripchar.c new file mode 100644 index 0000000..184e204 --- /dev/null +++ b/dripchar.c @@ -0,0 +1,82 @@ +/* +Copyright (C) 2002 Antoine Rousseau + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +/*#include <m_imp.h>*/ +#include "m_pd.h" + +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> + +typedef struct _dripchar +{ + t_object x_obj; +}t_dripchar; + +t_class *dripchar_class; + +void dripchar_setup(void); + +static void dripchar_symbol(t_dripchar *x,t_symbol *sym) +{ + static t_binbuf *binbuf=0; + t_atom at; + char *c,s[2]={0}; + int l; + + if(!binbuf) binbuf=binbuf_new(); + /*post("dripchar_symbol");*/ + if(!sym->s_name) return; + + c=sym->s_name; + while(*c) { + s[0]=*c++; + SETSYMBOL(&at,gensym(s)); + binbuf_add(binbuf,1,&at); + } + + + outlet_list(x->x_obj.ob_outlet,0, + binbuf_getnatom(binbuf),binbuf_getvec(binbuf)); + binbuf_clear(binbuf); +} + +static void dripchar_float(t_dripchar *x,t_floatarg f) +{ + post("dripchar_float"); + /*outlet_symbol(x->x_obj.ob_outlet,*/ +} + +static void *dripchar_new(void) +{ + t_dripchar *x = (t_dripchar *)pd_new(dripchar_class); + outlet_new(&x->x_obj, 0); + return (void *)x; +} + +void dripchar_setup(void) +{ + dripchar_class = class_new(gensym("dripchar"),(t_newmethod)dripchar_new, + 0, sizeof(t_dripchar), 0, 0); + + class_addsymbol(dripchar_class, dripchar_symbol); + class_addfloat(dripchar_class, dripchar_float); +} + diff --git a/f2char.c b/f2char.c new file mode 100644 index 0000000..e14c5cf --- /dev/null +++ b/f2char.c @@ -0,0 +1,53 @@ +/* +Copyright (C) 2002 Antoine Rousseau + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include "m_pd.h" + +typedef struct _f2char +{ + t_object x_obj; +}t_f2char; + +t_class *f2char_class; + +void f2char_setup(void); + +static void f2char_float(t_f2char *x,t_floatarg f) +{ + char s[2]={0}; + + s[0]=(char)f; + outlet_symbol(x->x_obj.ob_outlet,gensym(s)); +} + +static void *f2char_new(void) +{ + t_f2char *x = (t_f2char *)pd_new(f2char_class); + outlet_new(&x->x_obj,&s_symbol); + return (void *)x; +} + +void f2char_setup(void) +{ + f2char_class = class_new(gensym("f2char"),(t_newmethod)f2char_new, + 0, sizeof(t_f2char), 0, 0); + + class_addfloat(f2char_class, f2char_float); +} + @@ -0,0 +1,558 @@ +/* +Copyright (C) 2002 Antoine Rousseau + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ +#include <math.h> +#include <stdlib.h> +#include <m_pd.h> +#include "g_canvas.h" + +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif + +/* ------------------------ gamme ----------------------------- */ +#define BACKGROUND "-fill grey" +#define BACKGROUNDCOLOR "grey" + +#ifndef PD_VERSION_MINOR +#define PD_VERSION_MINOR 32 +#endif + +#define IS_A_POINTER(atom,index) ((atom+index)->a_type == A_POINTER) +#define IS_A_FLOAT(atom,index) ((atom+index)->a_type == A_FLOAT) +#define IS_A_SYMBOL(atom,index) ((atom+index)->a_type == A_SYMBOL) + + +#define DEFAULTSIZE 15 +#define DEFAULTWIDTH 90 +#define DEFAULTHEIGHT 40 + +#define DEFAULTCOLOR "black" +#define BLACKCOLOR "black" +#define WHITECOLOR "white" +#define SELBLACKCOLOR "gold" +#define SELWHITECOLOR "yellow" + + +static t_class *gamme_class; + +static char *NoteNames[]= + { "C","C#","D","D#","E","F","F#","G","G#","A","A#","B" }; +static char NoteColPos[]= + { 1,-1,2,-2,3,4,-4,5,-5,6,-6,7 }; +static char Whites[]={0,2,4,5,7,9,11}; +static char Blacks[]={1,3,6,8,10}; +static char BlacksWhites[]={1,3,6,8,10,0,2,4,5,7,9,11}; +static char WhitesBlacks[]={0,2,4,5,7,9,11,1,3,6,8,10}; + +#define ISWHITE(x) (NoteColPos[x]>0) +#define ISBLACK(x) (!ISWHITE(x)) + +#define te_xpos te_xpix +#define te_ypos te_ypix + +typedef struct _gamme +{ + t_object x_obj; + t_outlet *x_out_n; /*gives the number of selected notes when change occurs*/ + t_outlet *x_out_note; /*gives the number and new value of the changed notes when change occurs*/ + t_glist * x_glist; + int x_width; + int x_height; + char x_n; + char x_notes[12]; + char x_on_notes[12]; +} t_gamme; + +/* widget helper functions */ + + +#define INTERSPACE 0.02 +#define NOTEWIDTH ((1-INTERSPACE*6.0)/7.0) +#define BLACK1st ((NOTEWIDTH+INTERSPACE)/2.0) +#define BLACKH 0.6 +static void note_get_rel_rect(int x, float *xp1, float *yp1, float *xp2, float *yp2) +{ + int cp=NoteColPos[x]; + + *xp1=(abs(cp)-1)*(NOTEWIDTH+INTERSPACE) + (cp<0)*BLACK1st; + *xp2=*xp1+NOTEWIDTH; + + *yp1=0; + *yp2=cp<0?BLACKH:1; +} + +static int get_touched_note(float x, float y) +{ + int i,j; + float xp1,xp2,yp1,yp2; + + for(j=0;j<12;j++) { + i=BlacksWhites[j]; + note_get_rel_rect(i,&xp1,&yp1,&xp2,&yp2); + if((x>=xp1)&&(x<=xp2)&&(y>=yp1)&&(y<=yp2)) + return i; + } + /*post("gamme::get_touched_note note not found: x=%f y=%f",x,y);*/ + return -1; +} + +static void draw_inlets(t_gamme *x, t_glist *glist, int firsttime, int nin, int nout) +{ + int n = nout; + int nplus, i; + int xpos=text_xpix(&x->x_obj, glist); + int ypos=text_ypix(&x->x_obj, glist); + + nplus = (n == 1 ? 1 : n-1); + for (i = 0; i < n; i++) + { + int onset = xpos + (x->x_width - IOWIDTH) * i / nplus; + if (firsttime) + sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %xo%d\n", + glist_getcanvas(glist), + onset, ypos + x->x_height - 1, + onset + IOWIDTH, ypos + x->x_height, + x, i); + else + sys_vgui(".x%x.c coords %xo%d %d %d %d %d\n", + glist_getcanvas(glist), x, i, + onset, ypos + x->x_height - 1, + onset + IOWIDTH, ypos + x->x_height); + } + n = nin; + nplus = (n == 1 ? 1 : n-1); + for (i = 0; i < n; i++) + { + int onset = xpos + (x->x_width - IOWIDTH) * i / nplus; + if (firsttime) + sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %xi%d\n", + glist_getcanvas(glist), + onset, ypos, + onset + IOWIDTH, ypos + 1, + x, i); + else + sys_vgui(".x%x.c coords %xi%d %d %d %d %d\n", + glist_getcanvas(glist), x, i, + onset, ypos, + onset + IOWIDTH, ypos + 1); + + } +} + +void gamme_drawme(t_gamme *x, t_glist *glist, int firsttime) +{ + int i,j; + float x1,y1,x2,y2; + int xi1,yi1,xi2,yi2; + char *color; + int xpos=text_xpix(&x->x_obj, glist); + int ypos=text_ypix(&x->x_obj, glist); + + if (firsttime) { + sys_vgui(".x%x.c create rectangle \ +%d %d %d %d -tags %xS "BACKGROUND"\n", + glist_getcanvas(glist), + xpos, ypos, + xpos + x->x_width, ypos + x->x_height, + x); + + } + else { + sys_vgui(".x%x.c coords %xS \ +%d %d %d %d\n", + glist_getcanvas(glist), x, + xpos, ypos, + xpos + x->x_width, ypos + x->x_height); + } + + for(j=0;j<12;j++){ + i=WhitesBlacks[j]; + note_get_rel_rect(i,&x1,&y1,&x2,&y2); + xi1=xpos + x->x_width*x1; + xi2=xpos + x->x_width*x2; + yi1=ypos + x->x_height*y1; + yi2=ypos + x->x_height*y2; + + if (firsttime) { + color=x->x_notes[i]? (ISWHITE(i)?SELWHITECOLOR:SELBLACKCOLOR): + (ISWHITE(i)?WHITECOLOR:BLACKCOLOR); + sys_vgui(".x%x.c create rectangle \ +%d %d %d %d -tags %x%s -fill %s\n", + glist_getcanvas(glist),xi1,yi1,xi2,yi2, + x,NoteNames[i],color); + } + else { + sys_vgui(".x%x.c coords %x%s \ +%d %d %d %d\n", + glist_getcanvas(glist),x,NoteNames[i],xi1,yi1,xi2,yi2); + } + } + + draw_inlets(x, glist, firsttime, 1,3); + +} + +void gamme_erase(t_gamme* x,t_glist* glist) +{ + int n; + t_canvas *canvas=glist_getcanvas(glist); + + sys_vgui(".x%x.c delete %xS\n",canvas, x); + + for(n=0;n<12;n++) + sys_vgui(".x%x.c delete %x%s\n",canvas,x,NoteNames[n]); + + n = 1; + while (n--) { + sys_vgui(".x%x.c delete %xi%d\n",canvas,x,n); + } + n = 3; + while (n--) { + sys_vgui(".x%x.c delete %xo%d\n",canvas,x,n); + } +} + + + +/* ------------------------ gamme widgetbehaviour----------------------------- */ + + +static void gamme_getrect(t_gobj *z, t_glist *glist, + int *xp1, int *yp1, int *xp2, int *yp2) +{ + t_gamme *x = (t_gamme *)z; + int width, height; + t_gamme* s = (t_gamme*)z; + + + width = s->x_width; + height = s->x_height; + *xp1 = text_xpix(&x->x_obj, glist); + *yp1 = text_ypix(&x->x_obj, glist); + *xp2 = *xp1 + width; + *yp2 = *yp1 + height; +} + +static void gamme_displace(t_gobj *z, t_glist *glist, + int dx, int dy) +{ + t_gamme *x = (t_gamme *)z; + x->x_obj.te_xpos += dx; + x->x_obj.te_ypos += dy; + gamme_drawme(x, glist, 0); + canvas_fixlinesfor(glist_getcanvas(glist),(t_text*) x); +} + +static void gamme_select(t_gobj *z, t_glist *glist, int state) +{ + t_gamme *x = (t_gamme *)z; + sys_vgui(".x%x.c itemconfigure %xS -fill %s\n", glist, + x, (state? "blue" : BACKGROUNDCOLOR)); +} + + +static void gamme_activate(t_gobj *z, t_glist *glist, int state) +{ +/* t_text *x = (t_text *)z; + t_rtext *y = glist_findrtext(glist, x); + if (z->g_pd != gatom_class) rtext_activate(y, state);*/ +} + +static void gamme_delete(t_gobj *z, t_glist *glist) +{ + t_text *x = (t_text *)z; + canvas_deletelinesfor(glist, x); +} + + +static void gamme_vis(t_gobj *z, t_glist *glist, int vis) +{ + t_gamme* s = (t_gamme*)z; + if (vis) + gamme_drawme(s, glist, 1); + else + gamme_erase(s,glist); +} + +/* can we use the normal text save function ?? */ + +static void gamme_save(t_gobj *z, t_binbuf *b) +{ + t_gamme *x = (t_gamme *)z; + char *c=x->x_notes; + + binbuf_addv(b, "ssiisiiiiiiiiiiiiii", gensym("#X"),gensym("obj"), + (t_int)x->x_obj.te_xpos, (t_int)x->x_obj.te_ypos, + gensym("gamme"),x->x_width,x->x_height, + c[0],c[1],c[2],c[3],c[4],c[5],c[6],c[7],c[8],c[9],c[10],c[11]); + binbuf_addv(b, ";"); +} + +void gamme_getn(t_gamme *x) +{ + outlet_float(x->x_out_n,x->x_n); +} + +void gamme_out_changed(t_gamme *x,int note) +{ + t_atom ats[2]; + SETFLOAT(&ats[0],note); + SETFLOAT(&ats[1],x->x_notes[note]); + + outlet_list(x->x_out_note,0,2,ats); +} + +inline float my_mod(float x,int n) +{ + float y=fmod(x,n); + return y<0?y+n:y; +} + +#define my_div(x,y) (floor(x/y)) +#define tonotei(x) (my_mod(rint(x),12U)) + +void gamme_set(t_gamme *x,t_floatarg note,t_floatarg on) +{ + unsigned int i,notei=tonotei(note),changed=0; + char *color; + t_canvas *canvas=glist_getcanvas(x->x_glist); + + + if(x->x_notes[notei]!=on) changed=1; + if(on<0) x->x_notes[notei]=!(x->x_notes[notei]); + else x->x_notes[notei]=on; + if(changed) gamme_out_changed(x,notei); + + color=x->x_notes[notei]?(ISWHITE(notei)?SELWHITECOLOR:SELBLACKCOLOR): + (ISWHITE(notei)?WHITECOLOR:BLACKCOLOR); + + if(glist_isvisible(x->x_glist)) + sys_vgui(".x%x.c itemconfigure %x%s -fill %s\n", canvas, + x, NoteNames[notei],color); + + x->x_n=0; + for(i=0;i<12;i++) if(x->x_notes[i]) x->x_on_notes[(int)(x->x_n++)]=i; + gamme_getn(x); +} + +#define getnote(n) \ + (my_div(n,(int)x->x_n)*12+x->x_on_notes[(int)my_mod(n,x->x_n)]) +void gamme_get(t_gamme *x,t_floatarg ref_octave,t_floatarg note) +{ + int no0,no1,ni0,ni1,n0,n1,n; + float xn,xx,nn; + + if(!x->x_n) return; + no0=floor(note); + no1=ceil(note); + xx=note-no0; + + nn=getnote((float)no0)*(1-xx)+getnote((float)(no0+1))*xx+ref_octave*12; + n=getnote((float)no0)+ref_octave*12; + outlet_float(x->x_obj.ob_outlet,nn); +} + +static void gamme_click(t_gamme *x, t_floatarg xpos, t_floatarg ypos, + t_floatarg shift, t_floatarg ctrl, t_floatarg alt) +{ + int note; + int x0=text_xpix(&x->x_obj, x->x_glist); + int y0=text_ypix(&x->x_obj, x->x_glist); + + note=get_touched_note( + (xpos-x0)/x->x_width, + (ypos-y0)/x->x_height); + + if(note>=0) gamme_set(x,note,!x->x_notes[note]); +} + +static int gamme_newclick(t_gobj *z, struct _glist *glist, + int xpix, int ypix, int shift, int alt, int dbl, int doit) +{ + t_gamme* x = (t_gamme *)z; + + if(doit) + { + gamme_click( x, (t_floatarg)xpix, (t_floatarg)ypix, (t_floatarg)shift, + 0, (t_floatarg)alt); + } + return (1); +} + +void gamme_float(t_gamme *x,t_floatarg f) +{ + unsigned int notei=tonotei(f); + + /*post("notei=%d",notei);*/ + if(x->x_notes[notei]) + outlet_float(x->x_obj.ob_outlet,f); +} + +void gamme_round(t_gamme *x,t_floatarg f,t_floatarg round) +{ + unsigned int notei=tonotei(f); + int imin=floor(f),imax=ceil(f); + float norm; + + if(!x->x_n) return; + + while(!x->x_notes[(int)my_mod((imin),12U)]) imin--; + while(!x->x_notes[(int)my_mod((imax),12U)]) imax++; + + /*post("min: %d max: %d",imin,imax);*/ + + if((imin!=imax)&&round) { + round*=round; + norm=(f-imin)/(imax-imin)*2-1; + norm=norm/sqrt(1+round*norm*norm)*sqrt(1+round)/2+.5; + f=norm*(imax-imin)+imin; + } + outlet_float(x->x_obj.ob_outlet,f); +} + +void gamme_setall(t_gamme *x,t_symbol *s, int argc, t_atom *argv) +{ + int i=0,err=0; + + if(argc==12) + { + for(i=0;i<12;i++) err+=!IS_A_FLOAT(argv,i); + if(!err) for(i=0;i<12;i++) gamme_set(x,i,atom_getfloat(&argv[i])); + } +} + +void gamme_getall(t_gamme *x) +{ + int i=0; + + for(i=0;i<12;i++) gamme_out_changed(x,i); + gamme_getn(x); +} + +extern int sys_noloadbang; +static void gamme_loadbang(t_gamme *x) +{ + int i; + + if(sys_noloadbang) return; + for(i=0;i<12;i++) gamme_out_changed(x,i); + gamme_getn(x); +} + +void gamme_size(t_gamme* x,t_floatarg w,t_floatarg h) { + x->x_width = w; + x->x_height = h; + gamme_drawme(x, x->x_glist, 0); +} + +t_widgetbehavior gamme_widgetbehavior; + +static void gamme_setwidget(void) +{ + gamme_widgetbehavior.w_getrectfn = gamme_getrect; + gamme_widgetbehavior.w_displacefn = gamme_displace; + gamme_widgetbehavior.w_selectfn = gamme_select; + gamme_widgetbehavior.w_activatefn = gamme_activate; + gamme_widgetbehavior.w_deletefn = gamme_delete; + gamme_widgetbehavior.w_visfn = gamme_vis; + gamme_widgetbehavior.w_clickfn = gamme_newclick; + //gamme_widgetbehavior.w_propertiesfn = NULL; + //gamme_widgetbehavior.w_savefn = gamme_save; +} + + +static void *gamme_new(t_symbol *s, int argc, t_atom *argv) +{ + int i=0,err=0; + + t_gamme *x = (t_gamme *)pd_new(gamme_class); + + x->x_glist = (t_glist*) canvas_getcurrent(); + x->x_width = DEFAULTWIDTH; + x->x_height = DEFAULTHEIGHT; + outlet_new(&x->x_obj, &s_float); + x->x_out_n=outlet_new(&x->x_obj, &s_float); + x->x_out_note=outlet_new(&x->x_obj, &s_float); + + x->x_n=0; + for(i=0;i<12;i++) x->x_notes[i]=0; + for(i=0;i<12;i++) x->x_on_notes[i]=0; + + if((argc>1)&&IS_A_FLOAT(argv,0)&&IS_A_FLOAT(argv,1)) + { + if(atom_getfloat(&argv[0])) x->x_width = atom_getfloat(&argv[0]); + if(atom_getfloat(&argv[1])) x->x_height = atom_getfloat(&argv[1]); + + if(argc==14) + { + for(i=0;i<12;i++) err+=(!IS_A_FLOAT(argv,i+2)); + if(!err) { + for(i=0;i<12;i++) if(x->x_notes[i]=atom_getfloat(&argv[i+2])) + x->x_on_notes[(int)(x->x_n++)]=i; + /*gamme_set(x,i,atom_getfloat(&argv[i+2]));gamme_getn(x);*/ + } + else post("gamme_new : error in creation arguments"); + } + /*if(argc==14) gamme_setall(x,s,argc-2,&argv[2]);*/ + } + + return (x); +} + +void gamme_setup(void) +{ + post("gamme_setup"); + gamme_class = class_new(gensym("gamme"), (t_newmethod)gamme_new, 0, + sizeof(t_gamme),0, A_GIMME,0); + + class_addfloat(gamme_class,gamme_float); + + class_addmethod(gamme_class, (t_method)gamme_click, gensym("click"), + A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); + + class_addmethod(gamme_class, (t_method)gamme_size, gensym("size"), + A_FLOAT, A_FLOAT, 0); + + class_addmethod(gamme_class, (t_method)gamme_set, gensym("set"), + A_FLOAT, A_FLOAT, 0); + + class_addmethod(gamme_class, (t_method)gamme_get, gensym("get"), + A_FLOAT, A_FLOAT, 0); + + class_addmethod(gamme_class, (t_method)gamme_round, gensym("round"), + A_FLOAT, A_FLOAT, 0); + + class_addmethod(gamme_class, (t_method)gamme_setall, gensym("setall"), + A_GIMME, 0); + + class_addmethod(gamme_class, (t_method)gamme_getall, gensym("getall"), 0); + + class_addmethod(gamme_class, (t_method)gamme_getn, gensym("getn"), 0); + + /*class_addmethod(gamme_class, (t_method)gamme_loadbang, gensym("loadbang"), 0);*/ + + + gamme_setwidget(); + class_setwidget(gamme_class,&gamme_widgetbehavior); + class_setsavefn(gamme_class, gamme_save); + +} + + diff --git a/help/absolutepath-help.pd b/help/absolutepath-help.pd new file mode 100644 index 0000000..b056f4a --- /dev/null +++ b/help/absolutepath-help.pd @@ -0,0 +1,13 @@ +#N canvas 14 323 660 379 10; +#X text 17 352 (c) Antoine Rousseau 2004; +#X obj 33 108 absolutepath; +#X symbolatom 33 131 0 0 0; +#X msg 33 51 symbol absolutepath.pd; +#X obj 33 220 relativepath; +#X symbolatom 33 245 0 0 0; +#X text 14 6 absolutepath / relativepath : use filenames relatively +to the patch's path.; +#X connect 1 0 2 0; +#X connect 2 0 4 0; +#X connect 3 0 1 0; +#X connect 4 0 5 0; diff --git a/help/basedir-help.pd b/help/basedir-help.pd new file mode 100644 index 0000000..cbf9c9e --- /dev/null +++ b/help/basedir-help.pd @@ -0,0 +1,18 @@ +#N canvas 136 196 430 247 10; +#X obj 0 0 cnv 8 100 60 empty empty basedir 20 20 1 18 -262144 -1109 +0; +#X text 7 221 (c) Moonix: Antoine Rousseau 2003; +#X text 135 12 basename/dirname functions; +#X obj 124 102 basedir; +#X obj 124 136 unpack s s; +#X symbolatom 124 158 0 0 0; +#X symbolatom 189 158 0 0 0; +#X msg 124 62 symbol /usr/local/bin/pd; +#X obj 124 42 loadbang; +#X text 108 175 basename; +#X text 212 175 dirname; +#X connect 3 0 4 0; +#X connect 4 0 5 0; +#X connect 4 1 6 0; +#X connect 7 0 3 0; +#X connect 8 0 7 0; diff --git a/help/char2f-help.pd b/help/char2f-help.pd new file mode 100644 index 0000000..f133288 --- /dev/null +++ b/help/char2f-help.pd @@ -0,0 +1,18 @@ +#N canvas 134 318 430 247 10; +#X obj 0 0 cnv 8 100 60 empty empty char2f_f2char 10 20 1 18 -262144 +-1109 0; +#X text 7 221 (c) Moonix: Antoine Rousseau 2003; +#X text 160 14 ascii utilities; +#X obj 131 115 char2f; +#X floatatom 131 136 5 0 0; +#X msg 131 69 symbol A; +#X obj 131 173 f2char; +#X symbolatom 131 194 2 0 0; +#X obj 131 49 loadbang; +#X msg 216 70 symbol a; +#X connect 3 0 4 0; +#X connect 4 0 6 0; +#X connect 5 0 3 0; +#X connect 6 0 7 0; +#X connect 8 0 5 0; +#X connect 9 0 3 0; diff --git a/help/comma-help.pd b/help/comma-help.pd new file mode 100644 index 0000000..b8a8e63 --- /dev/null +++ b/help/comma-help.pd @@ -0,0 +1,40 @@ +#N canvas 172 316 715 428 10; +#X obj 0 0 cnv 8 100 60 empty empty comma 10 20 1 18 -262144 -1109 +0; +#X text 109 12 how to write " \, " in a message...; +#X text 2 388 (c) Moonix: Antoine Rousseau 2004; +#X msg 71 101 foo 1 \, bar 2; +#X floatatom 70 340 5 0 0 0 - - -; +#X floatatom 113 341 5 0 0 0 - - -; +#X obj 70 318 route foo bar; +#X text 59 85 build a message like this:; +#X text 106 118 | notice the comma...; +#X text 106 116 ^; +#X obj 437 192 drip; +#X obj 396 192 comma; +#X msg 417 222 add2 \$1; +#X msg 372 110 foo 10; +#X obj 407 171 t b a; +#X msg 331 82 set; +#X msg 427 110 bar 20; +#X msg 417 249 foo 10 \, bar 20 \,; +#X obj 517 171 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X text 39 72 0: what we want to do is to; +#X text 299 64 1: reset the message; +#X text 375 92 2: add parts; +#X text 467 153 (or click the message directly); +#X text 453 142 3: send the message; +#X connect 3 0 6 0; +#X connect 6 0 4 0; +#X connect 6 1 5 0; +#X connect 10 0 12 0; +#X connect 11 0 12 0; +#X connect 12 0 17 0; +#X connect 13 0 14 0; +#X connect 14 0 11 0; +#X connect 14 1 10 0; +#X connect 15 0 17 0; +#X connect 16 0 14 0; +#X connect 17 0 6 0; +#X connect 18 0 17 0; diff --git a/help/d/d0.gif b/help/d/d0.gif Binary files differnew file mode 100644 index 0000000..89fd454 --- /dev/null +++ b/help/d/d0.gif diff --git a/help/d/d1.gif b/help/d/d1.gif Binary files differnew file mode 100644 index 0000000..3bdd5b6 --- /dev/null +++ b/help/d/d1.gif diff --git a/help/d/d10.gif b/help/d/d10.gif Binary files differnew file mode 100644 index 0000000..13941b5 --- /dev/null +++ b/help/d/d10.gif diff --git a/help/d/d11.gif b/help/d/d11.gif Binary files differnew file mode 100644 index 0000000..05489a9 --- /dev/null +++ b/help/d/d11.gif diff --git a/help/d/d12.gif b/help/d/d12.gif Binary files differnew file mode 100644 index 0000000..b6f2e79 --- /dev/null +++ b/help/d/d12.gif diff --git a/help/d/d13.gif b/help/d/d13.gif Binary files differnew file mode 100644 index 0000000..95ac806 --- /dev/null +++ b/help/d/d13.gif diff --git a/help/d/d14.gif b/help/d/d14.gif Binary files differnew file mode 100644 index 0000000..c820bcb --- /dev/null +++ b/help/d/d14.gif diff --git a/help/d/d15.gif b/help/d/d15.gif Binary files differnew file mode 100644 index 0000000..aadd006 --- /dev/null +++ b/help/d/d15.gif diff --git a/help/d/d16.gif b/help/d/d16.gif Binary files differnew file mode 100644 index 0000000..b6b7429 --- /dev/null +++ b/help/d/d16.gif diff --git a/help/d/d17.gif b/help/d/d17.gif Binary files differnew file mode 100644 index 0000000..dbc581a --- /dev/null +++ b/help/d/d17.gif diff --git a/help/d/d18.gif b/help/d/d18.gif Binary files differnew file mode 100644 index 0000000..d2699d0 --- /dev/null +++ b/help/d/d18.gif diff --git a/help/d/d19.gif b/help/d/d19.gif Binary files differnew file mode 100644 index 0000000..082ad9a --- /dev/null +++ b/help/d/d19.gif diff --git a/help/d/d2.gif b/help/d/d2.gif Binary files differnew file mode 100644 index 0000000..c1cd34f --- /dev/null +++ b/help/d/d2.gif diff --git a/help/d/d20.gif b/help/d/d20.gif Binary files differnew file mode 100644 index 0000000..2bf3398 --- /dev/null +++ b/help/d/d20.gif diff --git a/help/d/d21.gif b/help/d/d21.gif Binary files differnew file mode 100644 index 0000000..e1b9463 --- /dev/null +++ b/help/d/d21.gif diff --git a/help/d/d22.gif b/help/d/d22.gif Binary files differnew file mode 100644 index 0000000..b33a110 --- /dev/null +++ b/help/d/d22.gif diff --git a/help/d/d23.gif b/help/d/d23.gif Binary files differnew file mode 100644 index 0000000..cef38bf --- /dev/null +++ b/help/d/d23.gif diff --git a/help/d/d24.gif b/help/d/d24.gif Binary files differnew file mode 100644 index 0000000..629442d --- /dev/null +++ b/help/d/d24.gif diff --git a/help/d/d25.gif b/help/d/d25.gif Binary files differnew file mode 100644 index 0000000..87b766a --- /dev/null +++ b/help/d/d25.gif diff --git a/help/d/d26.gif b/help/d/d26.gif Binary files differnew file mode 100644 index 0000000..3a45164 --- /dev/null +++ b/help/d/d26.gif diff --git a/help/d/d27.gif b/help/d/d27.gif Binary files differnew file mode 100644 index 0000000..257f589 --- /dev/null +++ b/help/d/d27.gif diff --git a/help/d/d28.gif b/help/d/d28.gif Binary files differnew file mode 100644 index 0000000..0de8ba8 --- /dev/null +++ b/help/d/d28.gif diff --git a/help/d/d29.gif b/help/d/d29.gif Binary files differnew file mode 100644 index 0000000..588f65c --- /dev/null +++ b/help/d/d29.gif diff --git a/help/d/d3.gif b/help/d/d3.gif Binary files differnew file mode 100644 index 0000000..1d6528b --- /dev/null +++ b/help/d/d3.gif diff --git a/help/d/d30.gif b/help/d/d30.gif Binary files differnew file mode 100644 index 0000000..1962cb8 --- /dev/null +++ b/help/d/d30.gif diff --git a/help/d/d31.gif b/help/d/d31.gif Binary files differnew file mode 100644 index 0000000..4b5dd54 --- /dev/null +++ b/help/d/d31.gif diff --git a/help/d/d32.gif b/help/d/d32.gif Binary files differnew file mode 100644 index 0000000..37391dc --- /dev/null +++ b/help/d/d32.gif diff --git a/help/d/d33.gif b/help/d/d33.gif Binary files differnew file mode 100644 index 0000000..5ce47b2 --- /dev/null +++ b/help/d/d33.gif diff --git a/help/d/d34.gif b/help/d/d34.gif Binary files differnew file mode 100644 index 0000000..29f5804 --- /dev/null +++ b/help/d/d34.gif diff --git a/help/d/d35.gif b/help/d/d35.gif Binary files differnew file mode 100644 index 0000000..0f2ac0f --- /dev/null +++ b/help/d/d35.gif diff --git a/help/d/d36.gif b/help/d/d36.gif Binary files differnew file mode 100644 index 0000000..2c59cf6 --- /dev/null +++ b/help/d/d36.gif diff --git a/help/d/d37.gif b/help/d/d37.gif Binary files differnew file mode 100644 index 0000000..290e514 --- /dev/null +++ b/help/d/d37.gif diff --git a/help/d/d38.gif b/help/d/d38.gif Binary files differnew file mode 100644 index 0000000..246422c --- /dev/null +++ b/help/d/d38.gif diff --git a/help/d/d39.gif b/help/d/d39.gif Binary files differnew file mode 100644 index 0000000..c09316e --- /dev/null +++ b/help/d/d39.gif diff --git a/help/d/d4.gif b/help/d/d4.gif Binary files differnew file mode 100644 index 0000000..16c157c --- /dev/null +++ b/help/d/d4.gif diff --git a/help/d/d40.gif b/help/d/d40.gif Binary files differnew file mode 100644 index 0000000..15a4f98 --- /dev/null +++ b/help/d/d40.gif diff --git a/help/d/d41.gif b/help/d/d41.gif Binary files differnew file mode 100644 index 0000000..a618a8a --- /dev/null +++ b/help/d/d41.gif diff --git a/help/d/d42.gif b/help/d/d42.gif Binary files differnew file mode 100644 index 0000000..0a2f7ab --- /dev/null +++ b/help/d/d42.gif diff --git a/help/d/d43.gif b/help/d/d43.gif Binary files differnew file mode 100644 index 0000000..9a52db3 --- /dev/null +++ b/help/d/d43.gif diff --git a/help/d/d44.gif b/help/d/d44.gif Binary files differnew file mode 100644 index 0000000..b649b7c --- /dev/null +++ b/help/d/d44.gif diff --git a/help/d/d45.gif b/help/d/d45.gif Binary files differnew file mode 100644 index 0000000..6926b51 --- /dev/null +++ b/help/d/d45.gif diff --git a/help/d/d46.gif b/help/d/d46.gif Binary files differnew file mode 100644 index 0000000..ef6966c --- /dev/null +++ b/help/d/d46.gif diff --git a/help/d/d47.gif b/help/d/d47.gif Binary files differnew file mode 100644 index 0000000..f22a248 --- /dev/null +++ b/help/d/d47.gif diff --git a/help/d/d48.gif b/help/d/d48.gif Binary files differnew file mode 100644 index 0000000..b76e2e2 --- /dev/null +++ b/help/d/d48.gif diff --git a/help/d/d49.gif b/help/d/d49.gif Binary files differnew file mode 100644 index 0000000..4db26a3 --- /dev/null +++ b/help/d/d49.gif diff --git a/help/d/d5.gif b/help/d/d5.gif Binary files differnew file mode 100644 index 0000000..5245f49 --- /dev/null +++ b/help/d/d5.gif diff --git a/help/d/d50.gif b/help/d/d50.gif Binary files differnew file mode 100644 index 0000000..acae768 --- /dev/null +++ b/help/d/d50.gif diff --git a/help/d/d51.gif b/help/d/d51.gif Binary files differnew file mode 100644 index 0000000..345177e --- /dev/null +++ b/help/d/d51.gif diff --git a/help/d/d52.gif b/help/d/d52.gif Binary files differnew file mode 100644 index 0000000..371ee22 --- /dev/null +++ b/help/d/d52.gif diff --git a/help/d/d53.gif b/help/d/d53.gif Binary files differnew file mode 100644 index 0000000..0aaeed8 --- /dev/null +++ b/help/d/d53.gif diff --git a/help/d/d54.gif b/help/d/d54.gif Binary files differnew file mode 100644 index 0000000..4eae9e5 --- /dev/null +++ b/help/d/d54.gif diff --git a/help/d/d55.gif b/help/d/d55.gif Binary files differnew file mode 100644 index 0000000..f7579f0 --- /dev/null +++ b/help/d/d55.gif diff --git a/help/d/d56.gif b/help/d/d56.gif Binary files differnew file mode 100644 index 0000000..56157aa --- /dev/null +++ b/help/d/d56.gif diff --git a/help/d/d57.gif b/help/d/d57.gif Binary files differnew file mode 100644 index 0000000..eba1418 --- /dev/null +++ b/help/d/d57.gif diff --git a/help/d/d58.gif b/help/d/d58.gif Binary files differnew file mode 100644 index 0000000..9952fb4 --- /dev/null +++ b/help/d/d58.gif diff --git a/help/d/d59.gif b/help/d/d59.gif Binary files differnew file mode 100644 index 0000000..ec69b2c --- /dev/null +++ b/help/d/d59.gif diff --git a/help/d/d6.gif b/help/d/d6.gif Binary files differnew file mode 100644 index 0000000..fd27e6d --- /dev/null +++ b/help/d/d6.gif diff --git a/help/d/d60.gif b/help/d/d60.gif Binary files differnew file mode 100644 index 0000000..8cfd531 --- /dev/null +++ b/help/d/d60.gif diff --git a/help/d/d61.gif b/help/d/d61.gif Binary files differnew file mode 100644 index 0000000..937089a --- /dev/null +++ b/help/d/d61.gif diff --git a/help/d/d62.gif b/help/d/d62.gif Binary files differnew file mode 100644 index 0000000..1ac6be2 --- /dev/null +++ b/help/d/d62.gif diff --git a/help/d/d63.gif b/help/d/d63.gif Binary files differnew file mode 100644 index 0000000..3642bb1 --- /dev/null +++ b/help/d/d63.gif diff --git a/help/d/d7.gif b/help/d/d7.gif Binary files differnew file mode 100644 index 0000000..dd74b47 --- /dev/null +++ b/help/d/d7.gif diff --git a/help/d/d8.gif b/help/d/d8.gif Binary files differnew file mode 100644 index 0000000..59251c0 --- /dev/null +++ b/help/d/d8.gif diff --git a/help/d/d9.gif b/help/d/d9.gif Binary files differnew file mode 100644 index 0000000..782e7b9 --- /dev/null +++ b/help/d/d9.gif diff --git a/help/dinlet~-help.pd b/help/dinlet~-help.pd new file mode 100644 index 0000000..8033afe --- /dev/null +++ b/help/dinlet~-help.pd @@ -0,0 +1,37 @@ +#N canvas 196 161 422 282 10; +#X text 6 248 (c) Antoine Rousseau 2001; +#X obj 9 5 dinlet~; +#X text 66 6 A signal inlet with a default value.; +#N canvas 178 154 300 161 --- 0; +#X obj 108 70 unsig~ 50; +#X obj 108 96 outlet; +#X obj 196 71 unsig~ 50; +#X obj 196 97 outlet; +#X obj 108 43 dinlet~ 1; +#X obj 196 44 dinlet~ 2; +#X obj 29 70 unsig~ 50; +#X obj 29 96 outlet; +#X obj 29 43 inlet~; +#X connect 0 0 1 0; +#X connect 2 0 3 0; +#X connect 4 0 0 0; +#X connect 5 0 2 0; +#X connect 6 0 7 0; +#X connect 8 0 6 0; +#X restore 112 100 pd ---; +#X floatatom 130 158 5 0 0; +#X floatatom 33 159 5 0 0; +#X floatatom 242 157 5 0 0; +#X obj 129 56 sig~ 5; +#X text 3 180 normal inlet~; +#X text 129 177 dinlet~ with; +#X text 128 192 default 1; +#X text 242 177 dinlet~ with; +#X text 241 192 default 2; +#X text 199 61 try connect and deconnect; +#X text 198 77 sig~ object to each of; +#X text 198 93 the subpatch inlets.; +#X connect 3 0 5 0; +#X connect 3 1 4 0; +#X connect 3 2 6 0; +#X connect 7 0 3 2; diff --git a/help/dispatch-help.pd b/help/dispatch-help.pd new file mode 100644 index 0000000..16231ef --- /dev/null +++ b/help/dispatch-help.pd @@ -0,0 +1,65 @@ +#N canvas 479 347 565 404 10; +#X obj 0 0 cnv 8 100 60 empty empty dispatch 10 20 1 18 -262144 -1109 +0; +#X obj 40 131 r foo1-rcv; +#X obj 40 151 print foo1; +#X obj 121 131 r foo2-rcv; +#X obj 121 151 print foo2; +#X obj 198 132 r foo3-rcv; +#X obj 198 152 print foo3; +#X obj 293 78 dispatch foo 1 3; +#X text 291 60 args: name min-index max-index; +#X msg 310 102 2 truc; +#X text 132 12 link several pairs of send/receive addresses to; +#X msg 39 82 f1snd; +#X msg 119 83 f2snd; +#X msg 197 83 f3snd; +#X obj 39 102 s foo1-snd; +#X obj 119 103 s foo2-snd; +#X obj 197 103 s foo3-snd; +#X obj 310 154 r foo-snd; +#X obj 310 122 s foo-rcv; +#X obj 310 175 print foo-snd; +#X text 406 162 one "send" from all; +#X text 382 110 one "receive" to all; +#X obj 35 208 cnv 15 300 150 empty empty empty 20 12 0 14 -261681 -66577 +0; +#X obj 77 223 tgl 15 0 \$0-bar1-snd \$0-bar1-rcv bar1 0 -6 1 8 -262144 +-1 -1 0 1; +#X obj 104 223 tgl 15 0 \$0-bar2-snd \$0-bar2-rcv bar2 0 -6 1 8 -262144 +-1 -1 0 1; +#X obj 132 223 tgl 15 0 \$0-bar3-snd \$0-bar3-rcv bar3 0 -6 1 8 -262144 +-1 -1 0 1; +#X obj 49 223 tgl 15 0 \$0-bar0-snd \$0-bar0-rcv bar0 0 -6 1 8 -262144 +-1 -1 0 1; +#X obj 173 321 s \$0-bar-rcv; +#X obj 49 276 r \$0-bar-snd; +#X obj 173 276 hdl 15 0 0 4 empty empty empty 0 -6 0 8 -262144 -1 -1 +1; +#X obj 185 221 dispatch \$0-bar 0 3; +#X msg 173 297 \$1 bang; +#X obj 49 298 unpack f f; +#X floatatom 49 319 2 0 0 0 - - -; +#X floatatom 114 320 2 0 0 0 - - -; +#X text 5 383 (c) Moonix: Antoine Rousseau 2004; +#X text 362 238 Warning: you HAVE to name; +#X text 343 254 your boutton buses like this:; +#X text 362 241 _______; +#X text 351 280 (notice the -snd and -rcv); +#X text 351 268 skeletonX-snd skeletonX-rcv; +#X text 134 24 a single one \, in which datas are prepended by the +number; +#X text 134 37 of the receiver/sender.; +#X connect 1 0 2 0; +#X connect 3 0 4 0; +#X connect 5 0 6 0; +#X connect 9 0 18 0; +#X connect 11 0 14 0; +#X connect 12 0 15 0; +#X connect 13 0 16 0; +#X connect 17 0 19 0; +#X connect 28 0 32 0; +#X connect 29 0 31 0; +#X connect 31 0 27 0; +#X connect 32 0 33 0; +#X connect 32 1 34 0; diff --git a/help/dripchar-help.pd b/help/dripchar-help.pd new file mode 100644 index 0000000..6318f36 --- /dev/null +++ b/help/dripchar-help.pd @@ -0,0 +1,28 @@ +#N canvas 117 153 430 247 10; +#X obj 0 0 cnv 8 100 60 empty empty dripchar 10 20 1 18 -262144 -1109 +0; +#X text 7 221 (c) Moonix: Antoine Rousseau 2003; +#X obj 131 49 loadbang; +#X obj 131 95 dripchar; +#X msg 131 69 symbol Antoine; +#X text 132 12 drip characters from a symbol to a list; +#X obj 131 117 unpack s s s s s s s; +#X symbolatom 131 142 1 0 0; +#X symbolatom 153 142 1 0 0; +#X symbolatom 176 142 1 0 0; +#X symbolatom 198 142 1 0 0; +#X symbolatom 221 142 1 0 0; +#X symbolatom 243 142 1 0 0; +#X symbolatom 266 142 1 0 0; +#X msg 245 69 symbol moonix_; +#X connect 2 0 4 0; +#X connect 3 0 6 0; +#X connect 4 0 3 0; +#X connect 6 0 7 0; +#X connect 6 1 8 0; +#X connect 6 2 9 0; +#X connect 6 3 10 0; +#X connect 6 4 11 0; +#X connect 6 5 12 0; +#X connect 6 6 13 0; +#X connect 14 0 3 0; diff --git a/help/f2char-help.pd b/help/f2char-help.pd new file mode 100644 index 0000000..f133288 --- /dev/null +++ b/help/f2char-help.pd @@ -0,0 +1,18 @@ +#N canvas 134 318 430 247 10; +#X obj 0 0 cnv 8 100 60 empty empty char2f_f2char 10 20 1 18 -262144 +-1109 0; +#X text 7 221 (c) Moonix: Antoine Rousseau 2003; +#X text 160 14 ascii utilities; +#X obj 131 115 char2f; +#X floatatom 131 136 5 0 0; +#X msg 131 69 symbol A; +#X obj 131 173 f2char; +#X symbolatom 131 194 2 0 0; +#X obj 131 49 loadbang; +#X msg 216 70 symbol a; +#X connect 3 0 4 0; +#X connect 4 0 6 0; +#X connect 5 0 3 0; +#X connect 6 0 7 0; +#X connect 8 0 5 0; +#X connect 9 0 3 0; diff --git a/help/f2s-help.pd b/help/f2s-help.pd new file mode 100644 index 0000000..005754a --- /dev/null +++ b/help/f2s-help.pd @@ -0,0 +1,17 @@ +#N canvas -5 264 527 298 10; +#X text 27 268 (c) Antoine Rousseau 2001; +#X obj 44 31 f2s; +#X text 80 32 A float-to-symbol converter \, with scientific-mode writing. +; +#X floatatom 196 85 5 0 300; +#X obj 163 136 f2s; +#X obj 196 106 dbtorms; +#X symbolatom 163 158 4 0 0; +#X floatatom 207 158 0 0 0; +#X text 244 85 Touch this; +#X text 57 196 The idea: many decades in an always 4 characters long +symbol...; +#X connect 3 0 5 0; +#X connect 4 0 6 0; +#X connect 5 0 4 0; +#X connect 5 0 7 0; diff --git a/help/gamme-help.pd b/help/gamme-help.pd new file mode 100644 index 0000000..8f87eb0 --- /dev/null +++ b/help/gamme-help.pd @@ -0,0 +1,171 @@ +#N canvas 246 348 520 515 10; +#X text 10 491 (c) Antoine Rousseau 2001; +#X text 85 3 gamme: a musical scale selector.; +#X obj 113 187 gamme 90 40 1 0 0 0 1 0 0 1 0 0 0 0; +#X floatatom 51 244 6 0 0 0 - - -; +#X floatatom 134 71 4 0 0 0 - - -; +#X floatatom 33 78 4 0 0 0 - - -; +#X floatatom 154 244 4 0 0 0 - - -; +#X msg 280 256 set \$1 \$2; +#X obj 280 288 gamme 90 40 1 0 0 0 1 0 0 1 0 0 0 0; +#X msg 401 177 getall; +#X floatatom 322 336 4 0 0 0 - - -; +#X floatatom 282 72 6 0 0 0 - - -; +#X msg 282 138 round \$1 \$2; +#X obj 282 116 pack f f; +#X floatatom 363 71 4 0 200 0 - - -; +#X obj 281 227 print changed; +#X obj 134 119 pack f f; +#X floatatom 190 71 4 0 0 0 - - -; +#X obj 156 99 t b f; +#X msg 134 141 get \$1 \$2; +#X text 126 53 octave; +#X text 188 53 note; +#X text 271 56 semitone; +#X text 344 55 rounding strength; +#X obj 303 93 t b f; +#X text 19 59 semitone; +#X text 152 33 ARPEGE; +#X text 28 39 FILTER; +#X text 324 36 ROUNDING; +#X text 51 263 Result; +#X text 139 261 Number of; +#X text 127 273 selected notes; +#X text 377 238 in the key set.; +#X text 383 225 Last change; +#X text 371 158 get all the key set.; +#N canvas 483 118 375 520 audio 0; +#X obj 4 356 gamme 90 40 1 0 1 0 1 0 0 1 0 1 0 0; +#X obj 28 464 *~; +#X obj 4 419 mtof; +#X obj 4 442 osc~; +#N canvas 394 93 600 400 env 0; +#X obj 19 122 inlet; +#X obj 105 121 inlet; +#X msg 19 143 bang; +#X obj 89 280 line~; +#X obj 114 329 outlet~; +#X obj 114 307 *~; +#X obj 130 280 +~ 1; +#X obj 130 258 *~ 0.6; +#X obj 130 237 osc~ 12; +#X msg 89 228 0 \$1; +#X obj 89 206 200; +#X obj 48 206 0.2; +#X obj 64 121 inlet; +#X text 18 101 trig; +#X text 62 101 vol; +#X text 103 102 sustain; +#X text 133 219 lfo...; +#X msg 48 228 \$1 2; +#X obj 89 183 delay 2; +#X connect 0 0 2 0; +#X connect 1 0 10 1; +#X connect 2 0 11 0; +#X connect 2 0 18 0; +#X connect 3 0 5 0; +#X connect 5 0 4 0; +#X connect 6 0 5 1; +#X connect 7 0 6 0; +#X connect 8 0 7 0; +#X connect 9 0 3 0; +#X connect 10 0 9 0; +#X connect 11 0 17 0; +#X connect 12 0 11 1; +#X connect 17 0 3 0; +#X connect 18 0 10 0; +#X restore 44 441 pd env; +#X floatatom 51 236 5 0 0 0 - - -; +#X obj 17 499 dac~; +#X obj 62 421 pow 4; +#X obj 4 189 metro 180; +#X obj 4 211 i; +#X obj 4 162 tgl 20 0 empty empty play 0 -8 1 10 -262144 -1 -1 1 1 +; +#X obj 29 211 + 1; +#X obj 4 286 spigot; +#X obj 49 286 == 0; +#X obj 54 211 mod 16; +#X obj 91 287 spigot; +#X obj 136 287 == 1; +#X msg 91 309 get 4 \$1; +#X obj 233 251 unpack f; +#X obj 188 279 spigot; +#X msg 188 345 round \$1 \$2; +#X obj 188 323 pack f f; +#X obj 233 279 == 2; +#X obj 4 306 + 60; +#X obj 188 301 + 60.05; +#X obj 191 375 hsl 50 10 0 500 0 1 empty empty Sustain -2 -6 1 10 -262144 +-1 -1 1700 1; +#X obj 52 165 hsl 50 10 5 500 0 1 empty empty Metro(ms) -2 -6 1 10 +-262144 -1 -1 1200 1; +#X obj 318 165 vsl 10 40 0 100 0 1 empty empty Round 0 -8 1 10 -262144 +-1 -1 600 1; +#X obj 191 486 hsl 60 15 0 1 0 1 empty empty Volume -2 -6 1 10 -258699 +-1 -1 4300 1; +#X obj 149 88 cnv 15 90 47 empty empty filter/arpeg/round 2 8 1 10 +-233017 -1 0; +#X obj 149 162 hdl 30 0 1 3 empty empty empty 20 8 0 8 -262144 -1 -1 +0; +#X obj 13 328 inlet; +#X connect 0 0 4 0; +#X connect 0 0 2 0; +#X connect 1 0 6 0; +#X connect 1 0 6 1; +#X connect 2 0 3 0; +#X connect 3 0 1 0; +#X connect 4 0 1 1; +#X connect 5 0 15 0; +#X connect 5 0 12 0; +#X connect 5 0 19 0; +#X connect 7 0 4 1; +#X connect 8 0 9 0; +#X connect 9 0 5 0; +#X connect 9 0 11 0; +#X connect 10 0 8 0; +#X connect 11 0 14 0; +#X connect 12 0 23 0; +#X connect 13 0 12 1; +#X connect 14 0 9 1; +#X connect 15 0 17 0; +#X connect 16 0 15 1; +#X connect 17 0 0 0; +#X connect 18 0 16 0; +#X connect 18 0 22 0; +#X connect 18 0 13 0; +#X connect 19 0 24 0; +#X connect 20 0 0 0; +#X connect 21 0 20 0; +#X connect 22 0 19 1; +#X connect 23 0 0 0; +#X connect 24 0 21 0; +#X connect 25 0 4 2; +#X connect 26 0 8 1; +#X connect 27 0 21 1; +#X connect 28 0 7 0; +#X connect 30 0 18 0; +#X connect 31 0 0 0; +#X coords 0 0 1 1 210 110 1; +#X restore 33 325 pd audio demo; +#X connect 2 0 3 0; +#X connect 2 1 6 0; +#X connect 2 2 7 0; +#X connect 2 2 15 0; +#X connect 4 0 16 0; +#X connect 5 0 2 0; +#X connect 7 0 8 0; +#X connect 7 0 35 0; +#X connect 8 1 10 0; +#X connect 9 0 2 0; +#X connect 11 0 13 0; +#X connect 12 0 2 0; +#X connect 13 0 12 0; +#X connect 14 0 24 0; +#X connect 16 0 19 0; +#X connect 17 0 18 0; +#X connect 18 0 16 0; +#X connect 18 1 16 1; +#X connect 19 0 2 0; +#X connect 24 0 13 0; +#X connect 24 1 13 1; diff --git a/help/image-help.pd b/help/image-help.pd new file mode 100644 index 0000000..12a5e9f --- /dev/null +++ b/help/image-help.pd @@ -0,0 +1,104 @@ +#N canvas 150 138 585 548 10; +#X obj 0 0 cnv 8 100 60 empty empty image 20 20 1 18 -262144 -1109 +0; +#X text 14 510 (c) moonix: Antoine Rousseau 2004; +#X text 118 15 image viewer; +#X text 79 33 usage: image image_symbol [type]; +#X text 97 48 if type=0 (or absent) \, image_symbol is a file.; +#X text 444 63 see "load" and "set"; +#X text 98 63 if type=1 \, image_symbol means a pre-loaded image \; +; +#X text 248 510 \, but it's a hack of Gunter Geiger's image...; +#X obj 112 134 cnv 15 80 40 empty empty empty 20 12 0 14 -1 -66577 +0; +#X obj 122 148 image play.gif 0; +#X obj 348 216 cnv 15 20 20 empty empty empty 20 12 0 14 -1 -66577 +0; +#X obj 372 197 t a; +#X msg 424 105 open play.gif; +#X msg 425 125 open playy.gif; +#X msg 424 144 open rec.gif; +#X msg 424 162 open pause.gif; +#X msg 424 180 open sinw.gif; +#X msg 425 198 open squarew.gif; +#X msg 425 215 open saww.gif; +#X obj 360 227 image play.gif 0; +#X obj 136 148 image rec.gif 0; +#X obj 152 148 image pause.gif 0; +#X obj 185 144 image sinw.gif 0; +#X obj 185 156 image squarew.gif 0; +#X obj 185 168 image saww.gif 0; +#N canvas 183 192 77 40 /SUBPATCH/ 0; +#X obj 87 205 t a; +#X msg 127 127 open sinw.gif; +#X msg 146 150 open squarew.gif; +#X msg 165 171 open saww.gif; +#X obj -1 0 tgl 40 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1; +#X obj 0 1 cnv 15 40 40 empty empty empty 20 12 0 14 -1 -66577 0; +#X obj 26 20 image sinw.gif 0; +#X obj 127 84 i; +#X obj 153 85 + 1; +#X obj 179 85 mod 3; +#X obj 127 105 sel 0 1 2; +#X obj 127 63 b; +#X connect 1 0 0 0; +#X connect 2 0 0 0; +#X connect 3 0 0 0; +#X connect 4 0 11 0; +#X connect 7 0 8 0; +#X connect 7 0 10 0; +#X connect 8 0 9 0; +#X connect 9 0 7 1; +#X connect 10 0 1 0; +#X connect 10 1 2 0; +#X connect 10 2 3 0; +#X connect 11 0 7 0; +#X coords 0 0 1 1 40 40 1; +#X restore 246 133 pd; +#X text 241 118 click !; +#X obj 65 348 t f f; +#X obj 65 410 pack s s; +#X msg 65 430 load \$1 \$2; +#X msg 295 397 set \$1; +#X obj 298 304 hsl 128 15 0 63 0 0 empty empty empty -2 -6 0 8 -262144 +-1 -1 0 1; +#X obj 295 326 i; +#X obj 202 446 image d15 1; +#X obj 295 349 change; +#X obj 65 370 makesymbol d%s; +#X obj 95 390 makesymbol d/d%s.gif; +#X obj 295 376 makesymbol d%s; +#X text 6 253 For animations \, it's beter to preload images:; +#X obj 402 377 loadbang; +#X msg 402 397 open rec.gif; +#X text 95 274 1: load img_sym file; +#X text 291 287 2: set img_sym; +#X text 270 443 rem: when a img_symbol is loaded \, it; +#X text 305 455 can be used in any image object.; +#X text 17 94 ONLY GIF FILES ACCEPTED !! (because of Tk...); +#X msg 62 276 64; +#X obj 63 299 until; +#X obj 64 325 float; +#X obj 101 325 + 1; +#X connect 12 0 11 0; +#X connect 13 0 11 0; +#X connect 14 0 11 0; +#X connect 15 0 11 0; +#X connect 16 0 11 0; +#X connect 17 0 11 0; +#X connect 18 0 11 0; +#X connect 27 0 35 0; +#X connect 27 1 36 0; +#X connect 28 0 29 0; +#X connect 31 0 32 0; +#X connect 32 0 34 0; +#X connect 34 0 37 0; +#X connect 35 0 28 0; +#X connect 36 0 28 1; +#X connect 37 0 30 0; +#X connect 39 0 40 0; +#X connect 46 0 47 0; +#X connect 47 0 48 0; +#X connect 48 0 27 0; +#X connect 48 0 49 0; +#X connect 49 0 48 1; diff --git a/help/joystik-help.pd b/help/joystik-help.pd new file mode 100644 index 0000000..7915d33 --- /dev/null +++ b/help/joystik-help.pd @@ -0,0 +1,44 @@ +#N canvas 42 155 422 423 10; +#X obj 173 137 tgl 20 1 empty empty empty 20 8 0 8 -262144 -1 -1 1 +1; +#X text 103 121 in order to work.; +#X text 25 391 (c) Antoine Rousseau 2001; +#X obj 233 236 route 0 1; +#X obj 307 235 route 0 1; +#X obj 307 267 tgl 15 0 empty empty empty 8 -8 0 10 -262144 -1 -1 0 +1; +#X obj 336 268 tgl 15 0 empty empty empty 8 -8 0 10 -262144 -1 -1 0 +1; +#X floatatom 225 265 4 0 0; +#X floatatom 262 265 4 0 0; +#X obj 45 206 joystik; +#X obj 24 236 route 0 1; +#X obj 112 238 route 0 1; +#X obj 112 270 tgl 15 0 empty empty empty 8 -8 0 10 -262144 -1 -1 0 +1; +#X obj 141 270 tgl 15 0 empty empty empty 8 -8 0 10 -262144 -1 -1 0 +1; +#X floatatom 17 267 4 0 0; +#X floatatom 53 267 4 0 0; +#X obj 21 19 joystik; +#X text 104 109 joystiks must be switched on; +#X text 36 290 Axis; +#X text 112 291 Buttons; +#X text 78 20 A joystik reporter.; +#X text 28 55 args: [joystick number [is_usb]]; +#X obj 233 207 joystik 1 0; +#X text 22 345 CAUTION: usb untested !; +#X connect 0 0 9 0; +#X connect 0 0 22 0; +#X connect 3 0 7 0; +#X connect 3 1 8 0; +#X connect 4 0 5 0; +#X connect 4 1 6 0; +#X connect 9 0 10 0; +#X connect 9 1 11 0; +#X connect 10 0 14 0; +#X connect 10 1 15 0; +#X connect 11 0 12 0; +#X connect 11 1 13 0; +#X connect 22 0 3 0; +#X connect 22 1 4 0; diff --git a/help/makecolor-help.pd b/help/makecolor-help.pd new file mode 100644 index 0000000..ac52e81 --- /dev/null +++ b/help/makecolor-help.pd @@ -0,0 +1,18 @@ +#N canvas 36 264 527 298 10; +#X text 27 268 (c) Antoine Rousseau 2001; +#X obj 18 27 makecolor; +#X text 91 22 A color-symbol builder \, transforming RGB values in +one hexa symbol.; +#X obj 161 149 makecolor; +#X symbolatom 161 186 10 0 0; +#X floatatom 144 85 5 0 0; +#X floatatom 190 85 5 0 0; +#X floatatom 235 86 5 0 0; +#X obj 161 127 b; +#X connect 3 0 4 0; +#X connect 5 0 3 0; +#X connect 6 0 3 1; +#X connect 6 0 8 0; +#X connect 7 0 3 2; +#X connect 7 0 8 0; +#X connect 8 0 3 0; diff --git a/help/mknob-help.pd b/help/mknob-help.pd new file mode 100644 index 0000000..90f4fb2 --- /dev/null +++ b/help/mknob-help.pd @@ -0,0 +1,53 @@ +#N canvas 19 167 677 325 10; +#X obj 0 0 cnv 8 100 60 empty empty mknob 20 20 1 18 -262144 -1109 +0; +#X floatatom 55 149 5 0 0 0 - - -; +#X floatatom 55 68 5 0 0 0 - - -; +#X text 104 208 Just an adaptation of musil's slider.; +#X obj 138 224 hsl 128 15 0 127 0 0 empty empty empty -2 -6 0 8 -262144 +-1 -1 0 1; +#X text 103 222 See:; +#X msg 3 107 set \$1; +#X floatatom 190 114 5 0 0 0 - - -; +#X obj 190 95 r foo-snd; +#X floatatom 190 60 5 0 0 0 - - -; +#X obj 190 76 s foo-rcv; +#X text 135 12 gui-round-knob; +#X text 2 302 (c) moonix: Antoine Rousseau 2003; +#X obj 149 57 mknob 25 100 0 100 0 0 foo-snd foo-rcv empty -2 -6 192 +8 -225271 -1 -1 0 1; +#X obj 55 85 mknob 30 100 0 127 0 0 empty empty empty -2 -6 0 8 -241291 +-24198 -1 0 1; +#X obj 55 126 mknob 15 100 127 0 0 0 empty empty empty -2 -6 0 8 -258699 +-24198 -1 0 1; +#X text 306 40 "mouse" parameter sets mouse; +#X text 309 50 excursion for full range.; +#X text 309 62 Set it with "size" parameter:; +#X obj 398 201 mknob 25 -1 0 127 0 0 empty empty empty -2 -6 0 8 -262144 +-1 -1 0 1; +#X msg 369 96 size 25 300; +#X msg 398 119 size 25 10; +#X text 452 96 low sensibility; +#X text 474 120 high sens; +#X text 494 142 default; +#X msg 413 141 size 25 100; +#X text 497 164 angular control; +#X msg 427 165 size 25 0; +#X text 518 187 full angular control; +#X msg 443 188 size 25 -1; +#X text 273 253 Note: there is in the sources a patch named mknob.pd.tk.diff +to add (in pd.tk) mknob in the Pd "Put" menu \, and to give the hotkey +"Alt-k" to it. It will only work for Pd0.37 \, but it can help to do +the modif by hand for another version.; +#X connect 2 0 14 0; +#X connect 6 0 14 0; +#X connect 8 0 7 0; +#X connect 9 0 10 0; +#X connect 14 0 15 0; +#X connect 15 0 6 0; +#X connect 15 0 1 0; +#X connect 20 0 19 0; +#X connect 21 0 19 0; +#X connect 25 0 19 0; +#X connect 27 0 19 0; +#X connect 29 0 19 0; diff --git a/help/panvol~-help.pd b/help/panvol~-help.pd new file mode 100644 index 0000000..f7ad351 --- /dev/null +++ b/help/panvol~-help.pd @@ -0,0 +1,34 @@ +#N canvas 117 381 340 290 10; +#X obj 0 0 cnv 8 100 60 empty empty panvol~ 10 20 1 18 -262144 -1109 +0; +#X text 3 269 (c) Moonix: Antoine Rousseau 2003; +#X text 132 12 pan & volume; +#X obj 138 69 hsl 60 10 -45 45 0 0 empty empty pan -2 -6 0 8 -262144 +-1 -1 2950 1; +#X obj 238 61 vsl 10 60 0 1 0 0 empty empty vol 0 -8 0 8 -262144 -1 +-1 5900 1; +#X floatatom 135 85 5 0 0; +#X floatatom 238 127 5 0 0; +#X obj 113 141 panvol~; +#X obj 94 190 unsig~ 100; +#X floatatom 94 210 5 0 0; +#X obj 60 85 osc~ 440; +#X obj 173 190 unsig~ 100; +#X floatatom 173 210 5 0 0; +#X obj 94 170 envrms~; +#X obj 173 170 envrms~; +#X obj 60 104 *~ 2; +#X msg 174 49 0; +#X connect 3 0 5 0; +#X connect 4 0 6 0; +#X connect 5 0 7 1; +#X connect 6 0 7 2; +#X connect 7 0 13 0; +#X connect 7 1 14 0; +#X connect 8 0 9 0; +#X connect 10 0 15 0; +#X connect 11 0 12 0; +#X connect 13 0 8 0; +#X connect 14 0 11 0; +#X connect 15 0 7 0; +#X connect 16 0 3 0; diff --git a/help/pause.gif b/help/pause.gif Binary files differnew file mode 100644 index 0000000..684f755 --- /dev/null +++ b/help/pause.gif diff --git a/help/play.gif b/help/play.gif Binary files differnew file mode 100644 index 0000000..10ae809 --- /dev/null +++ b/help/play.gif diff --git a/help/playy.gif b/help/playy.gif Binary files differnew file mode 100644 index 0000000..c710c7e --- /dev/null +++ b/help/playy.gif diff --git a/help/popen-help.pd b/help/popen-help.pd new file mode 100644 index 0000000..e37d8e9 --- /dev/null +++ b/help/popen-help.pd @@ -0,0 +1,68 @@ +#N canvas 0 195 644 383 10; +#X obj 0 0 cnv 8 100 60 empty empty popen 10 20 1 18 -262144 -1109 +0; +#X text 13 362 (c) Moonix: Antoine Rousseau 2003; +#X msg 31 74 open process; +#X text 12 57 open: popen for writing; +#X msg 240 76 ropen process; +#X text 221 59 ropen: popen for reading; +#X msg 466 76 close; +#X text 428 60 close (quit) current process; +#X text 108 13 processus in/out (linux only); +#X text 108 26 DANGEROUS: deadlocks are easy!!!!; +#N canvas 0 0 850 359 example 0; +#X obj 458 194 popen; +#X msg 516 167 close; +#X obj 82 311 popen; +#X msg 151 261 close; +#X msg 76 190 list cat to where you want; +#X msg 24 145 open cat > /tmp/tmp_fifo; +#X msg 431 138 ropen cat /tmp/tmp_fifo; +#X obj 38 89 system; +#X msg 38 67 mkfifo /tmp/tmp_fifo; +#X obj 76 258 symbol \;; +#X obj 76 236 t b a; +#X symbolatom 433 284 0 0 0 0 - - -; +#X text 10 17 example: fifo read/write. RESPECT THE NUMBERS for commands +!; +#X text 430 120 3: open for reading; +#X msg 92 213 list Caution not to lock your computer...; +#X text 517 183 6: close reading process; +#X obj 433 260 l2s; +#X obj 458 227 print ropen; +#X text 76 173 4: write to fifo (as many times you want); +#X text 36 46 1: create the fifo (if not done); +#X text 147 244 5: close writing process FIRST; +#X text 23 125 2: open the fifo for writing FIRST; +#X text 503 248 Caution: popen/ropen waits for a " \; "; +#X text 565 260 to send its buffer (pd style).; +#X connect 0 0 17 0; +#X connect 0 0 16 0; +#X connect 1 0 0 0; +#X connect 3 0 2 0; +#X connect 4 0 10 0; +#X connect 5 0 2 0; +#X connect 6 0 0 0; +#X connect 8 0 7 0; +#X connect 9 0 2 0; +#X connect 10 0 9 0; +#X connect 10 1 2 0; +#X connect 14 0 10 0; +#X connect 16 0 11 0; +#X restore 19 161 pd example; +#X obj 31 109 popen; +#X text 20 191 Remarks:; +#X text 46 204 The danger here comes from the fact processes lauched +by; +#X text 47 215 popen runs concurrently with pd: if they are blocking +\, pd; +#X text 46 228 is blocking too. Very dangerous if pd has real-time +priority: it blocks all the sytem. You have to switch off the computer... +; +#X text 47 267 It's much safer to use netsend/netreceive in conjonction +with pdsend/pdreceive.; +#X obj 206 333 system; +#X text 46 297 You can use "at now" to lauch programs totally independantly +from Pd:; +#X msg 206 313 echo xclock -display 0:0 | at now; +#X connect 19 0 17 0; diff --git a/help/readsfv~-help.pd b/help/readsfv~-help.pd new file mode 100644 index 0000000..5870912 --- /dev/null +++ b/help/readsfv~-help.pd @@ -0,0 +1,60 @@ +#N canvas 117 77 546 422 10; +#X obj 0 0 cnv 8 100 60 empty empty readsfv~ 10 20 1 18 -262144 -1109 +0; +#X text 4 400 (c) Moonix: Antoine Rousseau 2003; +#X obj 124 367 dac~; +#X obj 132 331 readsfv~; +#X obj 132 188 delay 20; +#X msg 132 207 start; +#X msg 193 207 1; +#X obj 132 158 bng 15 250 50 0 empty empty play -25 4 0 8 -24198 -1 +-1; +#X obj 183 351 s replay; +#X obj 132 60 r replay; +#X obj 159 284 symbol; +#X msg 159 304 open \$1; +#X msg 229 283 symbol /usr/local/lib/pd/doc/sound/bell.aiff; +#X msg 229 262 symbol ../../sound/bell.aiff; +#X msg 47 298 speed \$1; +#X obj 266 239 openpanel; +#X obj 266 220 bng 15 250 50 0 empty empty open 0 -6 1 8 -195568 -1 +-1; +#X obj 132 126 spigot; +#X obj 169 109 tgl 15 1 empty empty loop 0 -6 1 8 -241291 -1 -1 1 1 +; +#X obj 47 58 vsl 15 128 0.08 8 1 0 empty empty speed 0 -8 1 8 -260818 +-1 -1 6965 1; +#X obj 1 57 init 1; +#X obj 47 278 f; +#X text 171 207 (or; +#X text 220 207 ); +#X obj 57 253 b; +#X obj 113 106 del 100; +#X text 129 8 read a big soundfile in direct-to-disk mode; +#X text 131 20 at variable speed.; +#X text 230 104 read manual of; +#X text 390 103 for more details...; +#X obj 335 102 readsf~; +#X connect 3 0 2 0; +#X connect 3 0 2 1; +#X connect 3 1 8 0; +#X connect 4 0 5 0; +#X connect 5 0 3 0; +#X connect 5 0 24 0; +#X connect 7 0 4 0; +#X connect 7 0 10 0; +#X connect 9 0 25 0; +#X connect 10 0 11 0; +#X connect 11 0 3 0; +#X connect 12 0 10 1; +#X connect 13 0 10 1; +#X connect 14 0 3 0; +#X connect 15 0 10 1; +#X connect 16 0 15 0; +#X connect 17 0 7 0; +#X connect 18 0 17 1; +#X connect 19 0 21 0; +#X connect 20 0 19 0; +#X connect 21 0 14 0; +#X connect 24 0 21 0; +#X connect 25 0 17 0; diff --git a/help/rec.gif b/help/rec.gif Binary files differnew file mode 100644 index 0000000..d49b027 --- /dev/null +++ b/help/rec.gif diff --git a/help/relativepath-help.pd b/help/relativepath-help.pd new file mode 100644 index 0000000..b056f4a --- /dev/null +++ b/help/relativepath-help.pd @@ -0,0 +1,13 @@ +#N canvas 14 323 660 379 10; +#X text 17 352 (c) Antoine Rousseau 2004; +#X obj 33 108 absolutepath; +#X symbolatom 33 131 0 0 0; +#X msg 33 51 symbol absolutepath.pd; +#X obj 33 220 relativepath; +#X symbolatom 33 245 0 0 0; +#X text 14 6 absolutepath / relativepath : use filenames relatively +to the patch's path.; +#X connect 1 0 2 0; +#X connect 2 0 4 0; +#X connect 3 0 1 0; +#X connect 4 0 5 0; diff --git a/help/s2f-help.pd b/help/s2f-help.pd new file mode 100644 index 0000000..2192924 --- /dev/null +++ b/help/s2f-help.pd @@ -0,0 +1,18 @@ +#N canvas 106 74 492 266 10; +#X obj 0 0 cnv 8 100 60 empty empty s2f 10 20 1 18 -262144 -1109 0 +; +#X text 1 244 (c) Moonix: Antoine Rousseau 2003; +#X text 129 8 symbol to float converter; +#X obj 197 159 s2f; +#X floatatom 197 184 0 0 0; +#X symbolatom 197 142 0 0 0; +#X obj 345 105 makesymbol %s; +#X msg 48 84 symbol 0.0003125foo; +#X msg 197 85 symbol 54.123e-3bar; +#X msg 345 85 13.25; +#X connect 3 0 4 0; +#X connect 5 0 3 0; +#X connect 6 0 5 0; +#X connect 7 0 5 0; +#X connect 8 0 5 0; +#X connect 9 0 6 0; diff --git a/help/sarray-help.pd b/help/sarray-help.pd new file mode 100644 index 0000000..157d245 --- /dev/null +++ b/help/sarray-help.pd @@ -0,0 +1,93 @@ +#N canvas 158 412 745 484 10; +#X obj 0 0 cnv 8 100 60 empty empty sarray 10 20 1 18 -262144 -1109 +0; +#X text 2 467 (c) Moonix: Antoine Rousseau 2003; +#X msg 74 275 1; +#X msg 103 275 2; +#X msg 131 275 3; +#X symbolatom 139 356 10 0 0; +#X msg 533 269 reset; +#X text 109 12 shared array of symbols; +#X obj 47 146 sarray foo 8; +#X text 23 48 1) set the length; +#X msg 47 71 setlen 10; +#X text 236 43 2) set the nth element; +#X msg 266 85 set 2 two; +#X msg 274 106 set 3 three; +#X obj 258 169 sarray foo; +#X msg 129 110 print; +#X msg 44 299 get \$1; +#X obj 44 320 sarray foo; +#X obj 44 339 route bang; +#X msg 159 275 4; +#X obj 44 359 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X msg 44 275 0; +#X text 12 256 3) get the nth symbol (first:0); +#X obj 533 289 sarray foo; +#X text 1 376 (bang when empty); +#X text 298 252 4) dump the whole array; +#X obj 299 379 sarray foo; +#X msg 299 272 dump; +#X obj 299 400 print dump; +#X msg 334 325 dump _null_; +#X msg 334 345 dump *?!; +#X text 315 298 specify a default symbol; +#X text 329 309 for empty elements; +#X obj 472 175 sarray foo; +#X text 494 85 specify a default symbol; +#X text 494 97 for empty elements; +#X msg 294 147 print; +#X msg 428 146 print; +#X text 531 251 6) clear the sarray; +#X msg 578 269 print; +#X text 6 165 args: sarray name [length]; +#X text 258 193 args: set [empty_symbol] first_index sym1 [sym2 [sym3...]]] +; +#X text 286 425 args: dump [empty_symbol]; +#X msg 258 61 set 0 zero; +#X text 453 43 3) set many elements; +#X text 533 134 ...erase one element; +#X msg 281 127 set 4 four; +#X msg 57 93 setlen 4; +#X msg 534 149 set _niet_ 3 _niet_; +#X msg 499 113 set _ 0 zero un _ trois _ cinq; +#X msg 472 60 set 0 zero ein zwei drei; +#X text 528 328 7) switch to another array; +#X obj 523 370 sarray foo2 4; +#X msg 523 351 set 0 zero2 one2 two2 three2; +#X obj 528 442 sarray; +#X msg 528 402 print; +#X msg 577 403 setarray foo; +#X msg 577 422 setarray foo2; +#X connect 2 0 16 0; +#X connect 3 0 16 0; +#X connect 4 0 16 0; +#X connect 6 0 23 0; +#X connect 10 0 8 0; +#X connect 12 0 14 0; +#X connect 13 0 14 0; +#X connect 15 0 8 0; +#X connect 16 0 17 0; +#X connect 17 0 18 0; +#X connect 18 0 20 0; +#X connect 18 1 5 0; +#X connect 19 0 16 0; +#X connect 21 0 16 0; +#X connect 26 0 28 0; +#X connect 27 0 26 0; +#X connect 29 0 26 0; +#X connect 30 0 26 0; +#X connect 36 0 14 0; +#X connect 37 0 33 0; +#X connect 39 0 23 0; +#X connect 43 0 14 0; +#X connect 46 0 14 0; +#X connect 47 0 8 0; +#X connect 48 0 33 0; +#X connect 49 0 33 0; +#X connect 50 0 33 0; +#X connect 53 0 52 0; +#X connect 55 0 54 0; +#X connect 56 0 54 0; +#X connect 57 0 54 0; diff --git a/help/saww.gif b/help/saww.gif Binary files differnew file mode 100644 index 0000000..32997ad --- /dev/null +++ b/help/saww.gif diff --git a/help/sfread2~-help.pd b/help/sfread2~-help.pd new file mode 100644 index 0000000..ad8ae16 --- /dev/null +++ b/help/sfread2~-help.pd @@ -0,0 +1,60 @@ +#N canvas 38 250 582 490 10; +#X obj 0 0 cnv 8 100 60 empty empty sfread2~ 10 20 1 18 -262144 -1109 +0; +#X text 2 459 (c) Moonix: Antoine Rousseau 2003; +#X text 66 390 Change "mlockall(MCL_FUTURE)" with "mlockall(MCL_CURRENT) +; +#X obj 155 262 sfread2~ 2; +#X msg 155 202 open \$1; +#X obj 19 151 bng 15 250 50 0 empty empty play 20 8 1 8 -24198 -1 -1 +; +#X msg 278 225 loop \$1; +#X obj 278 207 tgl 15 1 empty empty loop 20 8 0 8 -241291 -1 -1 1 1 +; +#X obj 57 103 tgl 15 1 empty empty interpolation 20 8 1 8 -257472 -1 +-1 1 1; +#X msg 57 121 interp \$1; +#X obj 458 181 vsl 15 128 -8 8 0 0 empty empty speed 0 -8 1 8 -260818 +-1 -1 7144 1; +#X text 135 12 soundfile reader at variable speed (possibly negative) +\, whith 4-point interpolation and loop.; +#X obj 154 296 dac~; +#X obj 155 92 openpanel; +#X obj 155 72 bng 15 250 50 0 empty empty open 0 -6 1 8 -166441 -1 +-1; +#X obj 18 179 bng 15 250 50 0 empty empty stop 20 8 1 8 -1 -1 -1; +#X msg 18 196 0; +#X obj 148 339 sfread~; +#X text 43 341 read manual of; +#X text 202 339 for more details...; +#X text 235 159 resets sound to position; +#X text 234 148 start position in samples; +#X msg 238 174 index 20000; +#X obj 497 177 loadbang; +#X msg 497 196 1; +#X msg 261 99 symbol /usr/local/lib/pd/doc/sound/voice.wav; +#X msg 261 78 symbol ../../sound/voice.wav; +#X text 66 414 If not \, the whole file will be loaded in memory when +opened (use of C function mmap()).; +#X text 66 401 in s_linux.c... SORRY \, I mean in s_inter.c (since +0.37...); +#X text 59 378 CAUTION: you should hack pd sources to have d-t-d working. +; +#X connect 3 0 12 0; +#X connect 3 1 12 1; +#X connect 4 0 3 0; +#X connect 5 0 3 0; +#X connect 6 0 3 0; +#X connect 7 0 6 0; +#X connect 8 0 9 0; +#X connect 9 0 3 0; +#X connect 10 0 3 1; +#X connect 13 0 4 0; +#X connect 14 0 13 0; +#X connect 15 0 16 0; +#X connect 16 0 3 0; +#X connect 22 0 3 0; +#X connect 23 0 24 0; +#X connect 24 0 10 0; +#X connect 25 0 4 0; +#X connect 26 0 4 0; diff --git a/help/sin.gif b/help/sin.gif Binary files differnew file mode 100644 index 0000000..c84ad79 --- /dev/null +++ b/help/sin.gif diff --git a/help/sinw.gif b/help/sinw.gif Binary files differnew file mode 100644 index 0000000..8bedc66 --- /dev/null +++ b/help/sinw.gif diff --git a/help/slist-help.pd b/help/slist-help.pd new file mode 100644 index 0000000..f499120 --- /dev/null +++ b/help/slist-help.pd @@ -0,0 +1,61 @@ +#N canvas 459 312 690 375 10; +#X obj 0 0 cnv 8 100 60 empty empty slist 10 20 1 18 -262144 -1109 +0; +#X text 3 354 (c) Moonix: Antoine Rousseau 2003; +#X text 109 12 shared list of symbols \, with a "find" feature; +#X obj 80 107 slist foo; +#X obj 261 100 slist foo; +#X text 24 55 1) fill the slist; +#X msg 261 79 len; +#X text 260 58 2) get the slist length; +#X floatatom 319 121 5 0 0; +#X obj 480 106 slist foo; +#X msg 451 79 1; +#X msg 480 79 2; +#X msg 508 79 3; +#X symbolatom 509 127 10 0 0; +#X obj 157 218 slist foo; +#X text 448 59 3) get the nth symbol (first:1); +#X msg 21 189 find boo; +#X msg 225 189 find bar; +#X floatatom 157 242 5 0 0; +#X msg 91 189 find bee; +#X msg 157 189 find baa; +#X obj 548 212 slist foo; +#X text 21 168 4) find the index of a symbol (0 = not found); +#X msg 548 192 reset; +#X msg 144 77 add baa; +#X msg 26 77 add boo \, add bee; +#X obj 378 223 slist foo; +#X text 364 169 5) print to console; +#X text 546 171 6) clear the slist; +#X msg 378 203 print; +#X text 383 184 (debug); +#X obj 256 318 slist foo2; +#X text 256 271 7) switch to another slist; +#X obj 476 345 slist; +#X msg 503 296 setlist foo; +#X msg 503 318 setlist foo2; +#X msg 460 296 print; +#X msg 256 297 add boo2 \, add bee2 \, add baa2; +#X msg 212 297 print; +#X connect 4 2 8 0; +#X connect 6 0 4 0; +#X connect 9 1 13 0; +#X connect 10 0 9 0; +#X connect 11 0 9 0; +#X connect 12 0 9 0; +#X connect 14 0 18 0; +#X connect 16 0 14 0; +#X connect 17 0 14 0; +#X connect 19 0 14 0; +#X connect 20 0 14 0; +#X connect 23 0 21 0; +#X connect 24 0 3 0; +#X connect 25 0 3 0; +#X connect 29 0 26 0; +#X connect 34 0 33 0; +#X connect 35 0 33 0; +#X connect 36 0 33 0; +#X connect 37 0 31 0; +#X connect 38 0 31 0; diff --git a/help/squarew.gif b/help/squarew.gif Binary files differnew file mode 100644 index 0000000..3e689c7 --- /dev/null +++ b/help/squarew.gif diff --git a/help/ssaw~-help.pd b/help/ssaw~-help.pd new file mode 100644 index 0000000..25903d1 --- /dev/null +++ b/help/ssaw~-help.pd @@ -0,0 +1,21 @@ +#N canvas 106 74 492 266 10; +#X obj 0 0 cnv 8 100 60 empty empty ssaw 10 20 1 18 -262144 -1109 0 +; +#X text 8 243 (c) Moonix: Antoine Rousseau 2004; +#X obj 162 103 ssaw~ 440; +#X obj 163 149 *~; +#X obj 162 77 mtof; +#X floatatom 161 57 5 0 0 0 - - -; +#X floatatom 207 77 0 0 0 0 - - -; +#X obj 197 128 hsl 128 15 0 1 0 0 empty empty empty -2 -6 0 8 -262144 +-1 -1 0 1; +#X obj 159 193 dac~; +#X text 124 19 sweet sawtooth generator; +#X text 121 32 (not to much aliasing below 10kHz); +#X connect 2 0 3 0; +#X connect 3 0 8 0; +#X connect 3 0 8 1; +#X connect 4 0 6 0; +#X connect 4 0 2 0; +#X connect 5 0 4 0; +#X connect 7 0 3 1; diff --git a/help/tabdump2-help.pd b/help/tabdump2-help.pd new file mode 100644 index 0000000..b69458c --- /dev/null +++ b/help/tabdump2-help.pd @@ -0,0 +1,31 @@ +#N canvas 21 53 496 358 10; +#X obj 13 21 tabdump2; +#X obj 187 37 tabdump; +#X text 22 332 (c) Antoine Rousseau 2004; +#X text 104 21 dump the contents of a table as a list; +#X text 104 37 like zexy's; +#X text 244 38 but with min/max dumping limits.; +#N canvas 0 0 450 300 graph5 0; +#X array \$0-array 10 float 0; +#X coords 0 1 9 0 100 80 1; +#X restore 330 71 graph; +#X obj 17 132 s \$0-array; +#X msg 17 112 0 0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9; +#X obj 17 92 loadbang; +#X obj 34 243 tabdump2 \$0-array; +#X obj 34 269 l2s; +#X symbolatom 34 293 0 0 0 0 - - -; +#X obj 258 204 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X msg 22 204 dump 0 5; +#X msg 95 203 dump 5 10; +#X text 18 177 dump N M: from N to (M-1); +#X msg 174 203 dump 5 6; +#X connect 8 0 7 0; +#X connect 9 0 8 0; +#X connect 10 0 11 0; +#X connect 11 0 12 0; +#X connect 13 0 10 0; +#X connect 14 0 10 0; +#X connect 15 0 10 0; +#X connect 17 0 10 0; diff --git a/help/tabenv-help.pd b/help/tabenv-help.pd new file mode 100644 index 0000000..cb719d0 --- /dev/null +++ b/help/tabenv-help.pd @@ -0,0 +1,25 @@ +#N canvas 205 155 534 360 10; +#X text 22 332 (c) Antoine Rousseau 2001; +#X obj 21 19 tabenv; +#X text 78 21 A envelope follower for table (not in real-time).; +#X text 35 65 args: arrayname [computation_num_points [output_period]] +; +#X text 147 151 change the array; +#X msg 64 181 reset; +#X msg 64 152 set Array1; +#X obj 64 255 tabenv Array0; +#X floatatom 64 283 5 0 0; +#X msg 64 209 0 44100; +#X text 125 209 compute 1 sec from the beginning; +#X text 126 181 reset the computation buffers; +#X obj 258 86 env~; +#X text 294 85 ); +#X text 217 86 (like; +#X text 151 84 ); +#X text 47 86 (like; +#X obj 90 86 tabplay~; +#X text 79 38 (in fact it's a mix between tabplay and env~); +#X connect 5 0 7 0; +#X connect 6 0 7 0; +#X connect 7 0 8 0; +#X connect 9 0 7 0; diff --git a/help/tabreadl-help.pd b/help/tabreadl-help.pd new file mode 100644 index 0000000..feebabe --- /dev/null +++ b/help/tabreadl-help.pd @@ -0,0 +1,26 @@ +#N canvas 502 181 672 415 10; +#X obj 10 11 tabreadl; +#X text 22 332 (c) Antoine Rousseau 2004; +#X floatatom 15 173 0 0 0; +#X floatatom 15 278 0 0 0; +#N canvas 0 0 450 300 graph1 0; +#X array \$0-array 10 float 0; +#X coords 0 0 10 10 250 200 1; +#X restore 362 179 graph; +#X text 60 276 output = array99[index]; +#X text 34 50 click here to initialize; +#X text 159 236 creation argument; +#X text 155 254 gives array name; +#X text 137 204 change array name; +#X msg 25 204 set \$0-array99; +#X msg 33 65 resize 10 \, bounds 0 0 10 10 \, xlabel -0.5 0 1 2 3 4 +5 6 7 8 9 10 \, ylabel -1 0 1 2 3 4 5 6 7 8 9 10 \, 0 1 4 2 8 5 6 1 +4 2 8; +#X obj 34 139 s \$0-array; +#X text 110 8 - linear interpolating read from a table; +#X text 46 174 index(float); +#X obj 15 245 tabreadl \$0-array; +#X connect 2 0 15 0; +#X connect 10 0 15 0; +#X connect 11 0 12 0; +#X connect 15 0 3 0; diff --git a/help/tabsort-help.pd b/help/tabsort-help.pd new file mode 100644 index 0000000..805f12a --- /dev/null +++ b/help/tabsort-help.pd @@ -0,0 +1,32 @@ +#N canvas 118 208 534 360 10; +#X text 22 332 (c) Antoine Rousseau 2001; +#X floatatom 39 303 5 0 0 0 - - -; +#X obj 21 19 tabsort; +#X text 20 58 args: source_table dest_table; +#N canvas 0 0 450 300 graph29 0; +#X array source 10 float 1; +#A 0 -0.0571429 -0.985715 -0.942858 -0.857143 -0.757143 -0.542857 -0.171429 +0.528571 0.842858 0.914287; +#X coords 0 1 9 -1 200 140 1; +#X restore 51 92 graph; +#N canvas 0 0 450 300 graph29 0; +#X array dest 10 float 1; +#A 0 9 8 7 0 6 5 4 3 2 1; +#X coords 0 10 9 0 200 140 1; +#X restore 304 89 graph; +#X obj 39 282 tabsort source dest; +#X msg 39 262 10; +#X text 79 12 write to dest_table the indices of source_table's elements +sorted by decreasing order (biggest first); +#X text 38 248 sort the n first elements; +#X obj 304 264 tabread dest; +#X obj 304 285 tabread source; +#X floatatom 304 246 5 0 0 0 - - -; +#X floatatom 304 305 5 0 0 0 - - -; +#X text 347 244 try it!; +#X text 300 321 it should decrease with input; +#X connect 6 0 1 0; +#X connect 7 0 6 0; +#X connect 10 0 11 0; +#X connect 11 0 13 0; +#X connect 12 0 10 0; diff --git a/help/tabsort2-help.pd b/help/tabsort2-help.pd new file mode 100644 index 0000000..4f4e29a --- /dev/null +++ b/help/tabsort2-help.pd @@ -0,0 +1,84 @@ +#N canvas 133 15 811 538 10; +#X floatatom 62 381 5 0 0 0 - - -; +#N canvas 0 0 450 300 graph29 0; +#X array source1 100 float 1; +#A 0 -0.0428565 -0.0571422 0.085715 0.228572 0.442858 0.657144 0.871429 +1.08572 1.22857 1.51429 1.72857 1.94286 2.22857 2.37143 2.58571 2.72857 +2.87143 2.94286 3.15714 3.3 3.3 3.44286 3.58571 3.65714 3.72857 3.8 +3.94286 4.01429 4.08571 4.22857 4.3 4.13929 3.97857 3.81786 3.51429 +3.22857 2.8 2.37143 2.3 2.3 2.3 2.37143 2.44286 2.51429 2.51429 2.58572 +2.55 2.37143 2.22857 1.94286 1.72857 1.58572 1.44286 1.44286 1.37144 +1.37144 1.37144 1.44286 1.44286 1.44286 1.44286 1.51429 1.51429 1.58572 +1.65714 1.65714 1.70476 1.75238 1.8 1.87143 2.01429 2.15714 2.22857 +4.58572 4.94286 5.22857 5.44286 5.58572 5.58572 5.39524 5.20477 5.01429 +4.82381 4.63334 4.44286 4.25238 4.06191 3.8 3.72857 3.65715 3.65715 +3.58572 3.58572 4.15715 4.51429 4.58572 4.72858 4.87143 5.08572 5.44286 +; +#X coords 0 10 99 0 200 140 1; +#X restore 60 133 graph; +#N canvas 0 0 450 300 graph29 0; +#X array dest 100 float 0; +#X coords 0 100 99 0 200 140 1; +#X restore 547 129 graph; +#X obj 10 8 tabsort2; +#X text 75 9 2 dimensionnal sort.; +#X text 24 99 args: source_table1 source_table2 dest_table; +#X text 248 8 write to dest_table the indices of the first N source_table1's +elements sorted by decreasing order (biggest first) \, then sort the +"columns" of sqrt(N) indices decreasingly according to their values +in source_table2 (is it clear?).; +#N canvas 0 0 450 300 graph29 0; +#X array source2 100 float 1; +#A 0 7.71429 7.64286 7.64286 7.57143 7.5 7.35714 7.21428 6.92857 6.57143 +6 5.71428 5.57143 5.21428 4.5 4.35714 4.28571 4.28571 4.28571 4.28571 +4.28571 4.42857 4.57143 4.64285 4.78571 4.92857 5.14285 5.35714 5.71428 +6 6.21428 6.42857 6.57143 6.64286 6.64286 6.64286 6.64286 6.57143 6.57143 +6.42857 6.35714 6.28571 6.14286 5.92857 5.78571 5.64286 5.42857 7.85714 +7.92857 8.42857 8.71428 8.92857 8.92857 8.92857 8.92857 8.85714 8.78571 +8.78571 8.78571 8.5 8.28571 8.07143 7.5 7.28571 6.85714 6.57143 5.78571 +5.5 5.21428 4.78571 4.64286 4.64286 4.78571 4.92857 5.07143 5.21428 +5.42857 5.57143 5.71428 5.92857 6.28571 6.5 6.85714 7.14286 7.35714 +7.64286 7.71429 7.78572 7.85714 7.85714 7.85714 7.71429 7.64286 7.5 +7.35714 7.14286 7.07143 7 6.85714 4.5 -0.342857; +#X coords 0 10 99 0 200 140 1; +#X restore 311 131 graph; +#X msg 62 340 100; +#X obj 62 360 tabsort2 source1 source2 dest; +#X obj 500 416 tabread dest; +#X obj 452 362 * 10; +#X obj 500 391 +; +#X floatatom 451 346 5 0 9 0 - - -; +#X obj 528 361 t b f; +#X floatatom 528 344 5 0 9 0 - - -; +#X floatatom 407 485 0 0 0 0 - - -; +#X obj 407 465 tabread source1; +#X obj 557 467 tabread source2; +#X floatatom 557 487 0 0 0 0 - - -; +#X floatatom 527 393 5 0 0 0 - - -; +#X text 433 328 x(columns); +#X text 521 327 y(lines); +#X text 403 504 decrease with x; +#X text 555 505 decrease with y; +#X text 49 305 1) Sort it:; +#X text 381 304 2) Try it:; +#X text 8 520 (c) Antoine Rousseau 2002; +#X floatatom 603 441 5 0 0 0 - - -; +#X text 604 416 index of sources; +#X text 606 426 elements; +#X text 28 396 output=sqrt(N)=the width/height; +#X text 28 410 of the destination "square".; +#X text 61 326 sort the N first elements; +#X connect 8 0 9 0; +#X connect 9 0 0 0; +#X connect 10 0 17 0; +#X connect 10 0 18 0; +#X connect 10 0 28 0; +#X connect 11 0 12 0; +#X connect 12 0 10 0; +#X connect 12 0 20 0; +#X connect 13 0 11 0; +#X connect 14 0 12 0; +#X connect 14 1 12 1; +#X connect 15 0 14 0; +#X connect 17 0 16 0; +#X connect 18 0 19 0; @@ -0,0 +1,306 @@ +#include <m_pd.h> +#include "g_canvas.h" +#include <unistd.h> +#include <string.h> +#include <stdio.h> + +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif + +/* ------------------------ image ----------------------------- */ + +static t_class *image_class; + +typedef struct _image +{ + t_object x_obj; + t_glist * x_glist; + int x_width; + int x_height; + t_symbol* x_image; + int x_type; //0=file 1=tk_image + t_int x_localimage; //localimage "img%x" done +} t_image; + +/* widget helper functions */ + +const char* image_get_filename(t_image *x,char *file) +{ + static char fname[MAXPDSTRING]; + char *bufptr; + int fd; + + fd=open_via_path(canvas_getdir(glist_getcanvas(x->x_glist))->s_name, + file, "",fname, &bufptr, MAXPDSTRING, 1); + if(fd>0){ + fname[strlen(fname)]='/'; + //post("image file: %s",fname); + close(fd); + return fname; + } + else return 0; +} + +void image_drawme(t_image *x, t_glist *glist, int firsttime) +{ + if (firsttime) { + if(x->x_type) { + sys_vgui(".x%x.c create image %d %d -tags %xS\n", + glist_getcanvas(glist), + text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist),x); + sys_vgui(".x%x.c itemconfigure %xS -image %s\n", + glist_getcanvas(glist),x,x->x_image->s_name); + } + else { + const char *fname=image_get_filename(x,x->x_image->s_name); + if(!x->x_localimage) { + sys_vgui("image create photo img%x\n",x); + x->x_localimage=1; + } + if(fname) sys_vgui("img%x configure -file %s\n",x,fname); + sys_vgui(".x%x.c create image %d %d -image img%x -tags %xS\n", + glist_getcanvas(glist), + text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist),x,x); + } + /* TODO callback from gui + sys_vgui("image_size logo"); + */ + } + else { + sys_vgui(".x%x.c coords %xS \ +%d %d\n", + glist_getcanvas(glist), x, + text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist)); + } + +} + + +void image_erase(t_image* x,t_glist* glist) +{ + int n; + sys_vgui(".x%x.c delete %xS\n", + glist_getcanvas(glist), x); + +} + + + +/* ------------------------ image widgetbehaviour----------------------------- */ + + +static void image_getrect(t_gobj *z, t_glist *glist, + int *xp1, int *yp1, int *xp2, int *yp2) +{ + int width, height; + t_image* x = (t_image*)z; + + + width = x->x_width; + height = x->x_height; + *xp1 = text_xpix(&x->x_obj, glist); + *yp1 = text_ypix(&x->x_obj, glist); + *xp2 = text_xpix(&x->x_obj, glist) + width; + *yp2 = text_ypix(&x->x_obj, glist) + height; +} + +static void image_displace(t_gobj *z, t_glist *glist, + int dx, int dy) +{ + t_image *x = (t_image *)z; + x->x_obj.te_xpix += dx; + x->x_obj.te_ypix += dy; + sys_vgui(".x%x.c coords %xSEL %d %d %d %d\n", + glist_getcanvas(glist), x, + text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist), + text_xpix(&x->x_obj, glist) + x->x_width, text_ypix(&x->x_obj, glist) + x->x_height); + + image_drawme(x, glist, 0); + canvas_fixlinesfor(glist_getcanvas(glist),(t_text*) x); +} + +static void image_select(t_gobj *z, t_glist *glist, int state) +{ + t_image *x = (t_image *)z; + if (state) { + sys_vgui(".x%x.c create rectangle \ +%d %d %d %d -tags %xSEL -outline blue\n", + glist_getcanvas(glist), + text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist), + text_xpix(&x->x_obj, glist) + x->x_width, text_ypix(&x->x_obj, glist) + x->x_height, + x); + } + else { + sys_vgui(".x%x.c delete %xSEL\n", + glist_getcanvas(glist), x); + } + + + +} + + +static void image_activate(t_gobj *z, t_glist *glist, int state) +{ +/* t_text *x = (t_text *)z; + t_rtext *y = glist_findrtext(glist, x); + if (z->g_pd != gatom_class) rtext_activate(y, state);*/ +} + +static void image_delete(t_gobj *z, t_glist *glist) +{ + t_text *x = (t_text *)z; + //canvas_deletelinesfor(glist_getcanvas(glist), x); + canvas_deletelinesfor(glist, x); +} + + +static void image_vis(t_gobj *z, t_glist *glist, int vis) +{ + t_image* s = (t_image*)z; + if (vis) + image_drawme(s, glist, 1); + else + image_erase(s,glist); +} + +/* can we use the normal text save function ?? */ + +static void image_save(t_gobj *z, t_binbuf *b) +{ + t_image *x = (t_image *)z; + binbuf_addv(b, "ssiissi", gensym("#X"),gensym("obj"), + x->x_obj.te_xpix, x->x_obj.te_ypix, + gensym("image"),x->x_image,x->x_type); + binbuf_addv(b, ";"); +} + + +t_widgetbehavior image_widgetbehavior; + +void image_size(t_image* x,t_floatarg w,t_floatarg h) { + x->x_width = w; + x->x_height = h; +} + +void image_color(t_image* x,t_symbol* col) +{ +/* outlet_bang(x->x_obj.ob_outlet); only bang if there was a bang .. + so color black does the same as bang, but doesn't forward the bang +*/ +} + +void image_open(t_gobj *z,t_symbol* file) +{ + t_image* x = (t_image*)z; + const char *fname; + int oldtype=x->x_type; + + + fname=image_get_filename(x,file->s_name); + if(fname){ + x->x_image=file; + x->x_type=0; + if(glist_isvisible(x->x_glist)) { + if(!x->x_localimage) { + sys_vgui("image create photo img%x\n",x); + x->x_localimage=1; + } + sys_vgui("img%x blank\n",x); + sys_vgui("img%x configure -file %s\n",x,fname); + if(oldtype) sys_vgui(".x%x.c itemconfigure %xS -image img%x\n", + glist_getcanvas(x->x_glist),x,x); + } + } +} + +void image_load(t_gobj *z,t_symbol* image,t_symbol* file) +{ + t_image* x = (t_image*)z; + const char *fname; + + fname=image_get_filename(x,file->s_name); + if(fname){ + sys_vgui("image create photo %s -file %s\n",image->s_name,fname); + } +} + +void image_set(t_gobj *z,t_symbol* image) +{ + t_image* x = (t_image*)z; + + x->x_image=image; + x->x_type=1; + + if(glist_isvisible(x->x_glist)) { + sys_vgui(".x%x.c itemconfigure %xS -image %s\n", + glist_getcanvas(x->x_glist),x,x->x_image->s_name); + } +} + + +static void image_setwidget(void) +{ + image_widgetbehavior.w_getrectfn = image_getrect; + image_widgetbehavior.w_displacefn = image_displace; + image_widgetbehavior.w_selectfn = image_select; + image_widgetbehavior.w_activatefn = image_activate; + image_widgetbehavior.w_deletefn = image_delete; + image_widgetbehavior.w_visfn = image_vis; +#if (PD_VERSION_MINOR > 31) + image_widgetbehavior.w_clickfn = NULL; + image_widgetbehavior.w_propertiesfn = NULL; +#endif +#if PD_MINOR_VERSION < 37 + image_widgetbehavior.w_savefn = image_save; +#endif +} + + +static void *image_new(t_symbol* image,int type) +{ + t_image *x = (t_image *)pd_new(image_class); + + x->x_glist = (t_glist*) canvas_getcurrent(); + + x->x_width = 15; + x->x_height = 15; + x->x_type=type; + x->x_localimage=0; + x->x_image = image; + + outlet_new(&x->x_obj, &s_float); + return (x); +} + +void image_setup(void) +{ + image_class = class_new(gensym("image"), (t_newmethod)image_new, 0, + sizeof(t_image),0, A_DEFSYM,A_DEFFLOAT,0); + +/* + class_addmethod(image_class, (t_method)image_size, gensym("size"), + A_FLOAT, A_FLOAT, 0); + + class_addmethod(image_class, (t_method)image_color, gensym("color"), + A_SYMBOL, 0); +*/ + + class_addmethod(image_class, (t_method)image_open, gensym("open"), + A_SYMBOL, 0); + class_addmethod(image_class, (t_method)image_set, gensym("set"), + A_SYMBOL, 0); + class_addmethod(image_class, (t_method)image_load, gensym("load"), + A_SYMBOL, A_SYMBOL, 0); + + image_setwidget(); + class_setwidget(image_class,&image_widgetbehavior); +#if PD_MINOR_VERSION >= 37 + class_setsavefn(image_class,&image_save); +#endif + +} + + diff --git a/joystik.c b/joystik.c new file mode 100644 index 0000000..2c09093 --- /dev/null +++ b/joystik.c @@ -0,0 +1,191 @@ +/* +'pd_joystik' (An external library for Miller Puckette's 'PD' software +adding PC and/or USB joystik control capabilities) + +Copyright (C) 2001 Antoine Rousseau (from the initial file of Joseph A. Sarlo) + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include <m_pd.h> +#include <s_stuff.h> + +#include <unistd.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <stdio.h> +#include <errno.h> +#include <linux/joystick.h> +#include <glib.h> + +/*0=normal joystick: /dev/jsXX 1=usb joystick: /dev/input/jsXX */ + +static GList *(joy_lists)[2][16]={{0},{0}}; +static int fds[2][16]; + +typedef struct _joystik +{ + t_object t_ob; + t_outlet *x_axis_out; + t_outlet *x_button_out; + guchar x_connected; + guchar x_usb; /*0:normal 1:usb*/ + gushort x_number; /*0 to 15*/ +}t_joystik; + +t_class *joystik_class; + +void joystik_setup(void); +static void joystik_read(GList *l,int fd); + +static void fd_open(int usb,int n) +{ + char filename[128]; + int *fd=&fds[(int)usb][(int)n]; + GList *l=joy_lists[(int)usb][(int)n]; + + if(usb) sprintf(filename,"/dev/input/js%d",n); + else sprintf(filename,"/dev/js%d",n); + + if(*fd<=0){ + *fd = open (filename, O_RDONLY | O_NONBLOCK); + if(*fd<0){ + post("open (%s, O_RDONLY | O_NONBLOCK)",filename); + perror("open"); + return; + } + } + sys_addpollfn(*fd,(t_fdpollfn)joystik_read,(void*)l); + /*post("joystick: adding poll");*/ +} + +static void fd_close(int usb,int n) +{ + int *fd=&fds[(int)usb][(int)n]; + + sys_rmpollfn(*fd); + close(*fd); + *fd=-1; + /*post("joystick: removing poll");*/ +} + +static void joystik_connect(t_joystik *x) +{ + GList *l=joy_lists[x->x_usb][x->x_number]; + + if(g_list_find(l,(void*)x)) return; + + g_list_append(l,(void*)x); + + if(g_list_length(l)==2){ + fd_open(x->x_usb,x->x_number); + } +} +static void joystik_deconnect(t_joystik *x) +{ + GList *l=joy_lists[x->x_usb][x->x_number]; + + if(!g_list_find(l,(void*)x)) return; + + g_list_remove(l,(void*)x); + + if(g_list_length(l)==1){ + fd_close(x->x_usb,x->x_number); + } +} + +static void joystik_float(t_joystik *x,t_floatarg connect) +{ + connect=(connect!=0); + + if(x->x_connected==connect) return; + + if(connect) joystik_connect(x); + else joystik_deconnect(x); + + x->x_connected=connect; +} + +static void *joystik_new(t_float num, t_float usb) +{ + t_joystik *x = (t_joystik *)pd_new(joystik_class); + int n=num; + GList **l=0; + + if((n<0)||(n>16)) { + post("ERROR in joystik_new : device number out of range"); + return (void*)x; + } + + usb=(usb!=0); + x->x_axis_out = outlet_new(&x->t_ob, &s_list); + x->x_button_out = outlet_new(&x->t_ob, &s_list); + + x->x_connected=0; + x->x_usb=usb; + x->x_number=n; + + l=&joy_lists[(int)usb][(int)n]; + + if(!*l) *l=g_list_alloc(); + + return (void *)x; +} + +void joystik_setup(void) +{ + joystik_class = class_new(gensym("joystik"),(t_newmethod)joystik_new, + (t_method)joystik_deconnect, sizeof(t_joystik), 0, A_DEFFLOAT, A_DEFFLOAT, 0); + class_addfloat(joystik_class, joystik_float); + + +} + +static void joystik_read(GList *l,int fd) +{ + #define AMP 32767.0 + int rt; + struct js_event e; + t_atom ats[2]; + GList *ltmp; + + while (read (fd, &e, sizeof(struct js_event)) > -1) + { + SETFLOAT(&ats[0],e.number); + if (e.type == JS_EVENT_AXIS) + { + SETFLOAT(&ats[1],e.value/AMP); + ltmp=l; + while(ltmp->next){ + ltmp=ltmp->next; + outlet_list(((t_joystik*)ltmp->data)->x_axis_out,0,2,ats); + } + } + else if (e.type == JS_EVENT_BUTTON) + { + SETFLOAT(&ats[1],e.value); + ltmp=l; + while(ltmp->next){ + ltmp=ltmp->next; + outlet_list(((t_joystik*)ltmp->data)->x_button_out,0,2,ats); + } + } + } +} + @@ -0,0 +1,870 @@ +/* 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. */ + +/* mknob.c written by Antoine Rousseau from g_vslider.c.*/ +/* g_7_guis.c written by Thomas Musil (c) IEM KUG Graz Austria 2000-2001 */ +/* thanks to Miller Puckette, Guenther Geiger and Krzystof Czaja */ + + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <ctype.h> +#include "m_pd.h" +#include "g_canvas.h" +#include "t_tk.h" +#include "g_all_guis.h" +#include <math.h> + +#ifdef NT +#include <io.h> +#else +#include <unistd.h> +#endif + + +#define MKNOB_TANGLE 100 +#define MKNOB_DEFAULTH 100 +#define MKNOB_DEFAULTSIZE 25 +#define MKNOB_MINSIZE 12 +#define MKNOB_THICK 3 +/* ------------ mknob ----------------------- */ +typedef struct _mknob +{ + t_iemgui x_gui; + int x_pos; + int x_val; + int x_center; + int x_thick; + int x_lin0_log1; + int x_steady; + double x_min; + double x_max; + int x_H; + double x_k; +} t_mknob; + +t_widgetbehavior mknob_widgetbehavior; +static t_class *mknob_class; + +/* widget helper functions */ +static void mknob_update_knob(t_mknob *x, t_glist *glist) +{ + t_canvas *canvas=glist_getcanvas(glist); +// float val=(x->x_val + 50.0)/100.0/MKNOB_TANGLE; + float val=(x->x_val + 50.0)/100.0/x->x_H; + float angle, + radius=x->x_gui.x_w/2.0, + miniradius=MKNOB_THICK; + int x0,y0,x1,y1,xc,yc,xp,yp,xpc,ypc; + x0=text_xpix(&x->x_gui.x_obj, glist); + y0=text_ypix(&x->x_gui.x_obj, glist); + x1=x0+x->x_gui.x_w; + y1=y0+x->x_gui.x_w; + xc=(x0+x1)/2; + yc=(y0+y1)/2; + + if(x->x_gui.x_h<0) + angle=val*(M_PI*2)+M_PI/2.0; + else + angle=val*(M_PI*1.5)+3.0*M_PI/4.0; + + xp=xc+radius*cos(angle); + yp=yc+radius*sin(angle); + xpc=miniradius*cos(angle-M_PI/2); + ypc=miniradius*sin(angle-M_PI/2); + + sys_vgui(".x%x.c coords %xKNOB %d %d %d %d %d %d\n", + canvas,x,xp,yp,xc+xpc,yc+ypc,xc-xpc,yc-ypc); +} + +static void mknob_draw_update(t_mknob *x, t_glist *glist) +{ + if (glist_isvisible(glist)) + { + mknob_update_knob(x,glist); + + /*if(x->x_val == x->x_center) + { + if(!x->x_thick) + { + sys_vgui(".x%x.c itemconfigure %xKNOB -width 7\n", canvas, x); + x->x_thick = 1; + } + } + else + { + if(x->x_thick) + { + sys_vgui(".x%x.c itemconfigure %xKNOB -width 3\n", canvas, x); + x->x_thick = 0; + } + }*/ + } +} + +static void mknob_draw_new(t_mknob *x, t_glist *glist) +{ + int xpos=text_xpix(&x->x_gui.x_obj, glist); + int ypos=text_ypix(&x->x_gui.x_obj, glist); + int r = xpos + (x->x_val + 50)/100; + int xc=xpos+x->x_gui.x_w/2; + int yc=ypos+x->x_gui.x_w/2; + t_canvas *canvas=glist_getcanvas(glist); + + sys_vgui(".x%x.c create oval %d %d %d %d -fill #%6.6x -tags %xBASE\n", + canvas,xpos,ypos,xpos + x->x_gui.x_w, ypos + x->x_gui.x_w, + x->x_gui.x_bcol,x); + sys_vgui(".x%x.c create polygon %d %d %d %d %d %d -fill #%6.6x -tags %xKNOB\n", + glist_getcanvas(glist), + xc,ypos,xc-4,yc,xc+4,yc,x->x_gui.x_fcol,x); + mknob_update_knob(x,glist); + sys_vgui(".x%x.c create text %d %d -text {%s} -anchor w \ + -font {%s %d bold} -fill #%6.6x -tags %xLABEL\n", + canvas, xpos+x->x_gui.x_ldx, + ypos+x->x_gui.x_ldy, + strcmp(x->x_gui.x_lab->s_name, "empty")?x->x_gui.x_lab->s_name:"", + x->x_gui.x_font, x->x_gui.x_fontsize, x->x_gui.x_lcol, x); + /*if(!x->x_gui.x_fsf.x_snd_able) + sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %xOUT%d\n", + canvas, xpos+ x->x_gui.x_w/2-3, ypos + x->x_gui.x_w-1, + xpos+ x->x_gui.x_w/2+4, ypos + x->x_gui.x_w, x, 0); + if(!x->x_gui.x_fsf.x_rcv_able) + sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %xIN%d\n", + canvas, xpos+ x->x_gui.x_w/2-3, ypos, + xpos+ x->x_gui.x_w/2+4, ypos+1, x, 0);*/ +} + +static void mknob_draw_move(t_mknob *x, t_glist *glist) +{ + int xpos=text_xpix(&x->x_gui.x_obj, glist); + int ypos=text_ypix(&x->x_gui.x_obj, glist); + int r = xpos + (x->x_val + 50)/100; + t_canvas *canvas=glist_getcanvas(glist); + + sys_vgui(".x%x.c coords %xBASE %d %d %d %d\n", + canvas, x, + xpos, ypos, + xpos + x->x_gui.x_w, ypos + x->x_gui.x_w); + mknob_update_knob(x,glist); + sys_vgui(".x%x.c coords %xLABEL %d %d\n", + canvas, x, xpos+x->x_gui.x_ldx, ypos+x->x_gui.x_ldy); + /*if(!x->x_gui.x_fsf.x_snd_able) + sys_vgui(".x%x.c coords %xOUT%d %d %d %d %d\n", + canvas, x, 0, + xpos+ x->x_gui.x_w/2-3, ypos + x->x_gui.x_w-1, + xpos+ x->x_gui.x_w/2+4, ypos + x->x_gui.x_w); + if(!x->x_gui.x_fsf.x_rcv_able) + sys_vgui(".x%x.c coords %xIN%d %d %d %d %d\n", + canvas, x, 0, + xpos+ x->x_gui.x_w/2-3, ypos, + xpos+ x->x_gui.x_w/2+4, ypos+1);*/ +} + +static void mknob_draw_erase(t_mknob* x,t_glist* glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + + sys_vgui(".x%x.c delete %xBASE\n", canvas, x); + sys_vgui(".x%x.c delete %xKNOB\n", canvas, x); + sys_vgui(".x%x.c delete %xLABEL\n", canvas, x); + /*if(!x->x_gui.x_fsf.x_snd_able) + sys_vgui(".x%x.c delete %xOUT%d\n", canvas, x, 0); + if(!x->x_gui.x_fsf.x_rcv_able) + sys_vgui(".x%x.c delete %xIN%d\n", canvas, x, 0);*/ +} + +static void mknob_draw_config(t_mknob* x,t_glist* glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + + sys_vgui(".x%x.c itemconfigure %xLABEL -font {%s %d bold} -fill #%6.6x -text {%s} \n", + canvas, x, x->x_gui.x_font, x->x_gui.x_fontsize, + x->x_gui.x_fsf.x_selected?IEM_GUI_COLOR_SELECTED:x->x_gui.x_lcol, + strcmp(x->x_gui.x_lab->s_name, "empty")?x->x_gui.x_lab->s_name:""); + sys_vgui(".x%x.c itemconfigure %xKNOB -fill #%6.6x\n", canvas, x, x->x_gui.x_fcol); + sys_vgui(".x%x.c itemconfigure %xBASE -fill #%6.6x\n", canvas, x, x->x_gui.x_bcol); +} + +static void mknob_draw_io(t_mknob* x,t_glist* glist, int old_snd_rcv_flags) +{ + int xpos=text_xpix(&x->x_gui.x_obj, glist); + int ypos=text_ypix(&x->x_gui.x_obj, glist); + t_canvas *canvas=glist_getcanvas(glist); + + /*if((old_snd_rcv_flags & IEM_GUI_OLD_SND_FLAG) && !x->x_gui.x_fsf.x_snd_able) + sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %xOUT%d\n", + canvas, xpos+ x->x_gui.x_w/2-3, ypos + x->x_gui.x_w-1, + xpos+ x->x_gui.x_w/2+4, ypos + x->x_gui.x_w, x, 0); + if(!(old_snd_rcv_flags & IEM_GUI_OLD_SND_FLAG) && x->x_gui.x_fsf.x_snd_able) + sys_vgui(".x%x.c delete %xOUT%d\n", canvas, x, 0); + if((old_snd_rcv_flags & IEM_GUI_OLD_RCV_FLAG) && !x->x_gui.x_fsf.x_rcv_able) + sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %xIN%d\n", + canvas, xpos+ x->x_gui.x_w/2-3, ypos, + xpos+ x->x_gui.x_w/2+4, ypos+1, x, 0); + if(!(old_snd_rcv_flags & IEM_GUI_OLD_RCV_FLAG) && x->x_gui.x_fsf.x_rcv_able) + sys_vgui(".x%x.c delete %xIN%d\n", canvas, x, 0);*/ +} + +static void mknob_draw_select(t_mknob* x,t_glist* glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + + if(x->x_gui.x_fsf.x_selected) + { + //pd_bind(&x->x_gui.x_obj.ob_pd, iemgui_key_sym); + sys_vgui(".x%x.c itemconfigure %xBASE -outline #%6.6x\n", canvas, x, IEM_GUI_COLOR_SELECTED); + sys_vgui(".x%x.c itemconfigure %xLABEL -fill #%6.6x\n", canvas, x, IEM_GUI_COLOR_SELECTED); + } + else + { + //pd_unbind(&x->x_gui.x_obj.ob_pd, iemgui_key_sym); + sys_vgui(".x%x.c itemconfigure %xBASE -outline #%6.6x\n", canvas, x, IEM_GUI_COLOR_NORMAL); + sys_vgui(".x%x.c itemconfigure %xLABEL -fill #%6.6x\n", canvas, x, x->x_gui.x_lcol); + } +} + +void mknob_draw(t_mknob *x, t_glist *glist, int mode) +{ + if(mode == IEM_GUI_DRAW_MODE_UPDATE) + mknob_draw_update(x, glist); + else if(mode == IEM_GUI_DRAW_MODE_MOVE) + mknob_draw_move(x, glist); + else if(mode == IEM_GUI_DRAW_MODE_NEW) + mknob_draw_new(x, glist); + else if(mode == IEM_GUI_DRAW_MODE_SELECT) + mknob_draw_select(x, glist); + else if(mode == IEM_GUI_DRAW_MODE_ERASE) + mknob_draw_erase(x, glist); + else if(mode == IEM_GUI_DRAW_MODE_CONFIG) + mknob_draw_config(x, glist); + /*else if(mode >= IEM_GUI_DRAW_MODE_IO) + mknob_draw_io(x, glist, mode - IEM_GUI_DRAW_MODE_IO);*/ +} + +/* ------------------------ mknob widgetbehaviour----------------------------- */ + + +static void mknob_getrect(t_gobj *z, t_glist *glist, + int *xp1, int *yp1, int *xp2, int *yp2) +{ + t_mknob* x = (t_mknob*)z; + + *xp1 = text_xpix(&x->x_gui.x_obj, glist); + *yp1 = text_ypix(&x->x_gui.x_obj, glist); + *xp2 = *xp1 + x->x_gui.x_w; + *yp2 = *yp1 + x->x_gui.x_w; +} + +static void mknob_save(t_gobj *z, t_binbuf *b) +{ + t_mknob *x = (t_mknob *)z; + int bflcol[3], *ip1, *ip2; + t_symbol *srl[3]; + + iemgui_save(&x->x_gui, srl, bflcol); + ip1 = (int *)(&x->x_gui.x_isa); + ip2 = (int *)(&x->x_gui.x_fsf); + binbuf_addv(b, "ssiisiiffiisssiiiiiiiii", gensym("#X"),gensym("obj"), + (t_int)x->x_gui.x_obj.te_xpix, (t_int)x->x_gui.x_obj.te_ypix, + gensym("mknob"), x->x_gui.x_w, x->x_gui.x_h, + (float)x->x_min, (float)x->x_max, + x->x_lin0_log1, (*ip1)&IEM_INIT_ARGS_ALL, + srl[0], srl[1], srl[2], + x->x_gui.x_ldx, x->x_gui.x_ldy, + (*ip2)&IEM_FSTYLE_FLAGS_ALL, x->x_gui.x_fontsize, + bflcol[0], bflcol[1], bflcol[2], + x->x_val, x->x_steady); + binbuf_addv(b, ";"); +} + +void mknob_check_wh(t_mknob *x, int w, int h) +{ + int H; + + if(w < MKNOB_MINSIZE) w = MKNOB_MINSIZE; + x->x_gui.x_w = w; + + if(h < -1) h=-1; + if((h>0)&&(h<20)) h=20; + x->x_gui.x_h = h; + + H=x->x_gui.x_h; + if(H<0) H=360; + if(H==0) H=270; + x->x_H=H; + + if(x->x_lin0_log1) + x->x_k = log(x->x_max/x->x_min)/(double)(x->x_H - 1); + else + x->x_k = (x->x_max - x->x_min)/(double)(x->x_H - 1); + + /*x->x_center = (x->x_gui.x_w-1)*50; + if(x->x_val > (x->x_gui.x_w*100 - 100)) + { + x->x_pos = x->x_gui.x_w*100 - 100; + x->x_val = x->x_pos; + } + if(x->x_lin0_log1) + x->x_k = log(x->x_max/x->x_min)/(double)(x->x_gui.x_w - 1); + else + x->x_k = (x->x_max - x->x_min)/(double)(x->x_gui.x_w - 1);*/ +} + +void mknob_check_minmax(t_mknob *x, double min, double max) +{ + int H; + + if(x->x_lin0_log1) + { + if((min == 0.0)&&(max == 0.0)) + max = 1.0; + if(max > 0.0) + { + if(min <= 0.0) + min = 0.01*max; + } + else + { + if(min > 0.0) + max = 0.01*min; + } + } + x->x_min = min; + x->x_max = max; + if(x->x_min > x->x_max) /* bugfix */ + x->x_gui.x_isa.x_reverse = 1; + else + x->x_gui.x_isa.x_reverse = 0; + + if(x->x_lin0_log1) + x->x_k = log(x->x_max/x->x_min)/(double)(x->x_H - 1); + else + x->x_k = (x->x_max - x->x_min)/(double)(x->x_H - 1); + /*if(x->x_lin0_log1) + x->x_k = log(x->x_max/x->x_min)/(double)(MKNOB_TANGLE - 1); + else + x->x_k = (x->x_max - x->x_min)/(double)(MKNOB_TANGLE - 1);*/ +} + +static void mknob_properties(t_gobj *z, t_glist *owner) +{ + t_mknob *x = (t_mknob *)z; + char buf[800]; + t_symbol *srl[3]; + + iemgui_properties(&x->x_gui, srl); + sprintf(buf, "pdtk_iemgui_dialog %%s mknob \ + --------dimension(pix):-------- %d %d width: %d %d mouse: \ + -----------output-range:----------- %g left: %g right: %g \ + %d lin log %d %d empty %d \ + %s %s \ + %s %d %d \ + %d %d \ + %d %d %d\n", + x->x_gui.x_w, MKNOB_MINSIZE, x->x_gui.x_h, -1, + x->x_min, x->x_max, 0.0,/*no_schedule*/ + x->x_lin0_log1, x->x_gui.x_isa.x_loadinit, x->x_steady, -1,/*no multi, but iem-characteristic*/ + srl[0]->s_name, srl[1]->s_name, + srl[2]->s_name, x->x_gui.x_ldx, x->x_gui.x_ldy, + x->x_gui.x_fsf.x_font_style, x->x_gui.x_fontsize, + 0xffffff & x->x_gui.x_bcol, 0xffffff & x->x_gui.x_fcol, 0xffffff & x->x_gui.x_lcol); + gfxstub_new(&x->x_gui.x_obj.ob_pd, x, buf); +} + +static void mknob_set(t_mknob *x, t_floatarg f) /* bugfix */ +{ + double g; + + if(x->x_gui.x_isa.x_reverse) /* bugfix */ + { + if(f > x->x_min) + f = x->x_min; + if(f < x->x_max) + f = x->x_max; + } + else + { + if(f > x->x_max) + f = x->x_max; + if(f < x->x_min) + f = x->x_min; + } + if(x->x_lin0_log1) + g = log(f/x->x_min)/x->x_k; + else + g = (f - x->x_min) / x->x_k; + x->x_val = (int)(100.0*g + 0.49999); + x->x_pos = x->x_val; + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE); +} + +static void mknob_bang(t_mknob *x) +{ + double out; + + if(x->x_lin0_log1) + out = x->x_min*exp(x->x_k*(double)(x->x_val)*0.01); + else + out = (double)(x->x_val)*0.01*x->x_k + x->x_min; + if((out < 1.0e-10)&&(out > -1.0e-10)) + out = 0.0; + outlet_float(x->x_gui.x_obj.ob_outlet, out); + if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing) + pd_float(x->x_gui.x_snd->s_thing, out); +} + +static void mknob_dialog(t_mknob *x, t_symbol *s, int argc, t_atom *argv) +{ + t_symbol *srl[3]; + int w = (int)atom_getintarg(0, argc, argv); + int h = (int)atom_getintarg(1, argc, argv); + double min = (double)atom_getfloatarg(2, argc, argv); + double max = (double)atom_getfloatarg(3, argc, argv); + int lilo = (int)atom_getintarg(4, argc, argv); + int steady = (int)atom_getintarg(17, argc, argv); + int sr_flags; + + if(lilo != 0) lilo = 1; + x->x_lin0_log1 = lilo; + if(steady) + x->x_steady = 1; + else + x->x_steady = 0; + sr_flags = iemgui_dialog(&x->x_gui, srl, argc, argv); + //x->x_gui.x_h = iemgui_clip_size(h); + //x->x_gui.x_w = iemgui_clip_size(w); + mknob_check_wh(x, w, h); + mknob_check_minmax(x, min, max); + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_CONFIG); + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_IO + sr_flags); + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_MOVE); + canvas_fixlinesfor(glist_getcanvas(x->x_gui.x_glist), (t_text*)x); +} + +static int xm0,ym0,xm,ym; + +static void mknob_motion(t_mknob *x, t_floatarg dx, t_floatarg dy) +{ + int old = x->x_val; + float d=-dy; + + if (abs(dx)>abs(dy)) d=dx; + + if(x->x_gui.x_fsf.x_finemoved) + x->x_pos += (int)d; + else + x->x_pos += 100*(int)d; + x->x_val = x->x_pos; + if(x->x_val > (100*x->x_H - 100)) + { + x->x_val = 100*x->x_H - 100; + x->x_pos += 50; + x->x_pos -= x->x_pos%100; + } + if(x->x_val < 0) + { + x->x_val = 0; + x->x_pos -= 50; + x->x_pos -= x->x_pos%100; + } + if(old != x->x_val) + { + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE); + mknob_bang(x); + } +} + +static void mknob_motion_circular(t_mknob *x, t_floatarg dx, t_floatarg dy) +{ + int xc=text_xpix(&x->x_gui.x_obj, x->x_gui.x_glist)+x->x_gui.x_w/2; + int yc=text_ypix(&x->x_gui.x_obj, x->x_gui.x_glist)+x->x_gui.x_w/2; + int old = x->x_val; + float alpha; + + xm+=dx; + ym+=dy; + + alpha=atan2(xm-xc,ym-yc)*180.0/M_PI; + + x->x_pos=(int)(31500-alpha*100.0)%36000; + if(x->x_pos>31500) x->x_pos=0; + else if(x->x_pos>(27000-100)) x->x_pos=(27000-100); + + x->x_val=x->x_pos; + + if(old != x->x_val) + { + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE); + mknob_bang(x); + } +} + +static void mknob_motion_fullcircular(t_mknob *x, t_floatarg dx, t_floatarg dy) +{ + int xc=text_xpix(&x->x_gui.x_obj, x->x_gui.x_glist)+x->x_gui.x_w/2; + int yc=text_ypix(&x->x_gui.x_obj, x->x_gui.x_glist)+x->x_gui.x_w/2; + int old = x->x_val; + float alpha; + + xm+=dx; + ym+=dy; + + alpha=atan2(xm-xc,ym-yc)*180.0/M_PI; + + x->x_pos=(int)(36000-alpha*100.0)%36000; + /*if(x->x_pos>31500) x->x_pos=0; + else if(x->x_pos>(27000-100)) x->x_pos=(27000-100);*/ + + if(x->x_pos>(36000-100)) x->x_pos=(36000-100); + x->x_val=x->x_pos; + + if(old != x->x_val) + { + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE); + mknob_bang(x); + } +} + +static void mknob_click(t_mknob *x, t_floatarg xpos, t_floatarg ypos, + t_floatarg shift, t_floatarg ctrl, t_floatarg alt) +{ + xm0=xm=xpos; + ym0=ym=ypos; + //if(!x->x_steady) + //x->x_val = (int)(100.0 * (xpos - text_xpix(&x->x_gui.x_obj, x->x_gui.x_glist))); + if(x->x_val > (100*x->x_H - 100)) + x->x_val = 100*x->x_H - 100; + if(x->x_val < 0) + x->x_val = 0; + x->x_pos = x->x_val; + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE); + mknob_bang(x); + + if(x->x_gui.x_h<0) + glist_grab(x->x_gui.x_glist, &x->x_gui.x_obj.te_g, + (t_glistmotionfn)mknob_motion_fullcircular, 0, xpos, ypos); + else if(x->x_gui.x_h==0) + glist_grab(x->x_gui.x_glist, &x->x_gui.x_obj.te_g, + (t_glistmotionfn)mknob_motion_circular, 0, xpos, ypos); + else + glist_grab(x->x_gui.x_glist, &x->x_gui.x_obj.te_g, + (t_glistmotionfn)mknob_motion, 0, xpos, ypos); + +} + +static int mknob_newclick(t_gobj *z, struct _glist *glist, + int xpix, int ypix, int shift, int alt, int dbl, int doit) +{ + t_mknob* x = (t_mknob *)z; + + if(doit) + { + mknob_click( x, (t_floatarg)xpix, (t_floatarg)ypix, (t_floatarg)shift, + 0, (t_floatarg)alt); + if(shift) + x->x_gui.x_fsf.x_finemoved = 1; + else + x->x_gui.x_fsf.x_finemoved = 0; + } + return (1); +} + +static void mknob_size(t_mknob *x, t_symbol *s, int ac, t_atom *av) +{ + int w=(int)atom_getintarg(0, ac, av), + h=x->x_gui.x_h; + + if(ac > 1) h=(int)atom_getintarg(1, ac, av); + + mknob_check_wh(x, w, h); + iemgui_size((void *)x, &x->x_gui); +} + +static void mknob_delta(t_mknob *x, t_symbol *s, int ac, t_atom *av) +{iemgui_delta((void *)x, &x->x_gui, s, ac, av);} + +static void mknob_pos(t_mknob *x, t_symbol *s, int ac, t_atom *av) +{iemgui_pos((void *)x, &x->x_gui, s, ac, av);} + +static void mknob_range(t_mknob *x, t_symbol *s, int ac, t_atom *av) +{ + mknob_check_minmax(x, (double)atom_getfloatarg(0, ac, av), + (double)atom_getfloatarg(1, ac, av)); +} + +static void mknob_color(t_mknob *x, t_symbol *s, int ac, t_atom *av) +{iemgui_color((void *)x, &x->x_gui, s, ac, av);} + +static void mknob_send(t_mknob *x, t_symbol *s) +{iemgui_send(x, &x->x_gui, s);} + +static void mknob_receive(t_mknob *x, t_symbol *s) +{iemgui_receive(x, &x->x_gui, s);} + +static void mknob_label(t_mknob *x, t_symbol *s) +{iemgui_label((void *)x, &x->x_gui, s);} + +static void mknob_label_pos(t_mknob *x, t_symbol *s, int ac, t_atom *av) +{iemgui_label_pos((void *)x, &x->x_gui, s, ac, av);} + +static void mknob_label_font(t_mknob *x, t_symbol *s, int ac, t_atom *av) +{iemgui_label_font((void *)x, &x->x_gui, s, ac, av);} + +static void mknob_log(t_mknob *x) +{ + x->x_lin0_log1 = 1; + mknob_check_minmax(x, x->x_min, x->x_max); +} + +static void mknob_lin(t_mknob *x) +{ + x->x_lin0_log1 = 0; + x->x_k = (x->x_max - x->x_min)/(double)(x->x_gui.x_w - 1); +} + +static void mknob_init(t_mknob *x, t_floatarg f) +{ + x->x_gui.x_isa.x_loadinit = (f==0.0)?0:1; +} + +static void mknob_steady(t_mknob *x, t_floatarg f) +{ + x->x_steady = (f==0.0)?0:1; +} + +static void mknob_float(t_mknob *x, t_floatarg f) +{ + double out; + + mknob_set(x, f); + if(x->x_lin0_log1) + out = x->x_min*exp(x->x_k*(double)(x->x_val)*0.01); + else + out = (double)(x->x_val)*0.01*x->x_k + x->x_min; + if((out < 1.0e-10)&&(out > -1.0e-10)) + out = 0.0; + if(x->x_gui.x_fsf.x_put_in2out) + { + outlet_float(x->x_gui.x_obj.ob_outlet, out); + if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing) + pd_float(x->x_gui.x_snd->s_thing, out); + } +} + +static void mknob_loadbang(t_mknob *x) +{ + if(!sys_noloadbang && x->x_gui.x_isa.x_loadinit) + { + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE); + mknob_bang(x); + } +} + +/*static void mknob_list(t_mknob *x, t_symbol *s, int ac, t_atom *av) +{ + int l=iemgui_list((void *)x, &x->x_gui, s, ac, av); + + if(l < 0) + { + if(IS_A_FLOAT(av,0)) + mknob_float(x, atom_getfloatarg(0, ac, av)); + } + else if(l > 0) + { + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_MOVE); + canvas_fixlinesfor(glist_getcanvas(x->x_gui.x_glist), (t_text*)x); + } +}*/ + +static void *mknob_new(t_symbol *s, int argc, t_atom *argv) +{ + t_mknob *x = (t_mknob *)pd_new(mknob_class); + int bflcol[]={-262144, -1, -1}; + //t_symbol *srl[3]; + int w=MKNOB_DEFAULTSIZE, h=MKNOB_DEFAULTH; + int fs=8 ,lilo=0, ldx=-2, ldy=-6, f=0, v=0, steady=1; + //int iinit=0, ifstyle=0; + double min=0.0, max=(double)(IEM_SL_DEFAULTSIZE-1); + //t_iem_init_symargs *init=(t_iem_init_symargs *)(&iinit); + //t_iem_fstyle_flags *fstyle=(t_iem_fstyle_flags *)(&ifstyle); + char str[144]; + + /*srl[0] = gensym("empty"); + srl[1] = gensym("empty"); + srl[2] = gensym("empty");*/ + + if(((argc == 17)||(argc == 18))&&IS_A_FLOAT(argv,0)&&IS_A_FLOAT(argv,1) + &&IS_A_FLOAT(argv,2)&&IS_A_FLOAT(argv,3) + &&IS_A_FLOAT(argv,4)&&IS_A_FLOAT(argv,5) + &&(IS_A_SYMBOL(argv,6)||IS_A_FLOAT(argv,6)) + &&(IS_A_SYMBOL(argv,7)||IS_A_FLOAT(argv,7)) + &&(IS_A_SYMBOL(argv,8)||IS_A_FLOAT(argv,8)) + &&IS_A_FLOAT(argv,9)&&IS_A_FLOAT(argv,10) + &&IS_A_FLOAT(argv,11)&&IS_A_FLOAT(argv,12)&&IS_A_FLOAT(argv,13) + &&IS_A_FLOAT(argv,14)&&IS_A_FLOAT(argv,15)&&IS_A_FLOAT(argv,16)) + { + w = (int)atom_getintarg(0, argc, argv); + h = (int)atom_getintarg(1, argc, argv); + min = (double)atom_getfloatarg(2, argc, argv); + max = (double)atom_getfloatarg(3, argc, argv); + lilo = (int)atom_getintarg(4, argc, argv); + iem_inttosymargs(&x->x_gui.x_isa, atom_getintarg(5, argc, argv)); + iemgui_new_getnames(&x->x_gui, 6, argv); + ldx = (int)atom_getintarg(9, argc, argv); + ldy = (int)atom_getintarg(10, argc, argv); + iem_inttofstyle(&x->x_gui.x_fsf, atom_getintarg(11, argc, argv)); + fs = (int)atom_getintarg(12, argc, argv); + bflcol[0] = (int)atom_getintarg(13, argc, argv); + bflcol[1] = (int)atom_getintarg(14, argc, argv); + bflcol[2] = (int)atom_getintarg(15, argc, argv); + v = (int)atom_getintarg(16, argc, argv); + /*iinit = (int)atom_getintarg(5, argc, argv); + if(IS_A_SYMBOL(argv,6)) + srl[0] = atom_getsymbolarg(6, argc, argv); + else if(IS_A_FLOAT(argv,6)) + { + sprintf(str, "%d", (int)atom_getintarg(6, argc, argv)); + srl[0] = gensym(str); + } + if(IS_A_SYMBOL(argv,7)) + srl[1] = atom_getsymbolarg(7, argc, argv); + else if(IS_A_FLOAT(argv,7)) + { + sprintf(str, "%d", (int)atom_getintarg(7, argc, argv)); + srl[1] = gensym(str); + } + if(IS_A_SYMBOL(argv,8)) + srl[2] = atom_getsymbolarg(8, argc, argv); + else if(IS_A_FLOAT(argv,8)) + { + sprintf(str, "%d", (int)atom_getintarg(8, argc, argv)); + srl[2] = gensym(str); + }*/ + //ifstyle = (int)atom_getintarg(11, argc, argv); + } + else iemgui_new_getnames(&x->x_gui, 6, 0); + + if((argc == 18)&&IS_A_FLOAT(argv,17)) + steady = (int)atom_getintarg(17, argc, argv); + + /*iinit &= IEM_INIT_ARGS_ALL; + ifstyle &= IEM_FSTYLE_FLAGS_ALL; + fstyle->x_snd_able = 1; + fstyle->x_rcv_able = 1;*/ + x->x_gui.x_draw = (t_iemfunptr)mknob_draw; + x->x_gui.x_fsf.x_snd_able = 1; + x->x_gui.x_fsf.x_rcv_able = 1; + x->x_gui.x_glist = (t_glist *)canvas_getcurrent(); + //x->x_gui.x_isa = *init; + if(x->x_gui.x_isa.x_loadinit) + x->x_val = v; + else + x->x_val = 0; + x->x_pos = x->x_val; + if(lilo != 0) lilo = 1; + x->x_lin0_log1 = lilo; + if(steady != 0) steady = 1; + x->x_steady = steady; + if(!strcmp(x->x_gui.x_snd->s_name, "empty")) x->x_gui.x_fsf.x_snd_able = 0; + if(!strcmp(x->x_gui.x_rcv->s_name, "empty")) x->x_gui.x_fsf.x_rcv_able = 0; + //if(!strcmp(srl[0]->s_name, "empty")) fstyle->x_snd_able = 0; + //if(!strcmp(srl[1]->s_name, "empty")) fstyle->x_rcv_able = 0; + //x->x_gui.x_unique_num = 0; + if(x->x_gui.x_fsf.x_font_style == 1) strcpy(x->x_gui.x_font, "helvetica"); + else if(x->x_gui.x_fsf.x_font_style == 2) strcpy(x->x_gui.x_font, "times"); + else { x->x_gui.x_fsf.x_font_style = 0; + /*if(fstyle->x_font_style == 1) strcpy(x->x_gui.x_font, "helvetica"); + else if(fstyle->x_font_style == 2) strcpy(x->x_gui.x_font, "times"); + else { fstyle->x_font_style = 0;*/ + strcpy(x->x_gui.x_font, "courier"); } + //x->x_gui.x_fsf = *fstyle; + //iemgui_first_dollararg2sym(&x->x_gui, srl); + //if(x->x_gui.x_fsf.x_rcv_able) pd_bind(&x->x_gui.x_obj.ob_pd, srl[1]); + /*x->x_gui.x_snd = srl[0]; + x->x_gui.x_rcv = srl[1]; + x->x_gui.x_lab = srl[2];*/ + if(x->x_gui.x_fsf.x_rcv_able) pd_bind(&x->x_gui.x_obj.ob_pd, x->x_gui.x_rcv); + x->x_gui.x_ldx = ldx; + x->x_gui.x_ldy = ldy; + if(fs < 4) + fs = 4; + x->x_gui.x_fontsize = fs; + //x->x_gui.x_h = iemgui_clip_size(h); + //x->x_gui.x_w = iemgui_clip_size(w); + mknob_check_wh(x, w, h); + //mknob_check_width(x, w); + mknob_check_minmax(x, min, max); + iemgui_all_colfromload(&x->x_gui, bflcol); + x->x_thick = 0; + iemgui_verify_snd_ne_rcv(&x->x_gui); + outlet_new(&x->x_gui.x_obj, &s_float); + return (x); +} + +static void mknob_free(t_mknob *x) +{ + /*if(x->x_gui.x_fsf.x_selected) + pd_unbind(&x->x_gui.x_obj.ob_pd, iemgui_key_sym);*/ + if(x->x_gui.x_fsf.x_rcv_able) + pd_unbind(&x->x_gui.x_obj.ob_pd, x->x_gui.x_rcv); + gfxstub_deleteforkey(x); +} + +extern void canvas_iemguis(t_glist *gl, t_symbol *guiobjname); + +void canvas_mknob(t_glist *gl, t_symbol *s, int argc, t_atom *argv) +{ + canvas_iemguis(gl, gensym("mknob")); +} + +void mknob_setup(void) +{ + mknob_class = class_new(gensym("mknob"), (t_newmethod)mknob_new, + (t_method)mknob_free, sizeof(t_mknob), 0, A_GIMME, 0); +#ifndef GGEE_mknob_COMPATIBLE +// class_addcreator((t_newmethod)mknob_new, gensym("mknob"), A_GIMME, 0); +#endif + class_addbang(mknob_class,mknob_bang); + class_addfloat(mknob_class,mknob_float); + //class_addlist(mknob_class, mknob_list); + class_addmethod(mknob_class, (t_method)mknob_click, gensym("click"), + A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); + class_addmethod(mknob_class, (t_method)mknob_motion, gensym("motion"), + A_FLOAT, A_FLOAT, 0); + class_addmethod(mknob_class, (t_method)mknob_dialog, gensym("dialog"), A_GIMME, 0); + class_addmethod(mknob_class, (t_method)mknob_loadbang, gensym("loadbang"), 0); + class_addmethod(mknob_class, (t_method)mknob_set, gensym("set"), A_FLOAT, 0); + class_addmethod(mknob_class, (t_method)mknob_size, gensym("size"), A_GIMME, 0); + class_addmethod(mknob_class, (t_method)mknob_delta, gensym("delta"), A_GIMME, 0); + class_addmethod(mknob_class, (t_method)mknob_pos, gensym("pos"), A_GIMME, 0); + class_addmethod(mknob_class, (t_method)mknob_range, gensym("range"), A_GIMME, 0); + class_addmethod(mknob_class, (t_method)mknob_color, gensym("color"), A_GIMME, 0); + class_addmethod(mknob_class, (t_method)mknob_send, gensym("send"), A_DEFSYM, 0); + class_addmethod(mknob_class, (t_method)mknob_receive, gensym("receive"), A_DEFSYM, 0); + class_addmethod(mknob_class, (t_method)mknob_label, gensym("label"), A_DEFSYM, 0); + class_addmethod(mknob_class, (t_method)mknob_label_pos, gensym("label_pos"), A_GIMME, 0); + class_addmethod(mknob_class, (t_method)mknob_label_font, gensym("label_font"), A_GIMME, 0); + class_addmethod(mknob_class, (t_method)mknob_log, gensym("log"), 0); + class_addmethod(mknob_class, (t_method)mknob_lin, gensym("lin"), 0); + class_addmethod(mknob_class, (t_method)mknob_init, gensym("init"), A_FLOAT, 0); + class_addmethod(mknob_class, (t_method)mknob_steady, gensym("steady"), A_FLOAT, 0); + /*if(!iemgui_key_sym) + iemgui_key_sym = gensym("#keyname");*/ + mknob_widgetbehavior.w_getrectfn = mknob_getrect; + mknob_widgetbehavior.w_displacefn = iemgui_displace; + mknob_widgetbehavior.w_selectfn = iemgui_select; + mknob_widgetbehavior.w_activatefn = NULL; + mknob_widgetbehavior.w_deletefn = iemgui_delete; + mknob_widgetbehavior.w_visfn = iemgui_vis; + mknob_widgetbehavior.w_clickfn = mknob_newclick; + //mknob_widgetbehavior.w_propertiesfn = mknob_properties; + //mknob_widgetbehavior.w_savefn = mknob_save; + class_setwidget(mknob_class, &mknob_widgetbehavior); + + class_setsavefn(mknob_class, mknob_save); + class_setpropertiesfn(mknob_class, mknob_properties); + class_addmethod(canvas_class, (t_method)canvas_mknob, gensym("mknob"), + A_GIMME, A_NULL); +} diff --git a/panvol~.c b/panvol~.c new file mode 100644 index 0000000..2e302c6 --- /dev/null +++ b/panvol~.c @@ -0,0 +1,119 @@ +/*************************************************************************** + * File: pan~.c + * Auth: Iain Mott [iain.mott@bigpond.com] + * Maintainer: Iain Mott [iain.mott@bigpond.com] + * Version: Part of motex_1.1.2 + * Date: January 2001 + * + * Description: Pd signal external. Equal-power stereo panning + * Angle input specified in degrees. -45 left, 0 centre, 45 right. + * See supporting Pd patch: pan~.pd + * + * Copyright (C) 2001 by Iain Mott [iain.mott@bigpond.com] + * + * 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, 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, which should be included with this + * program, for more details. + * + ****************************************************************************/ + +/* I've only add a global volume... Antoine Rousseau 2003*/ + +#include "m_pd.h" +#include <math.h> + +static t_class *pan_class; +#define RADCONST 0.017453293 +#define ROOT2DIV2 0.707106781 + +typedef struct _pan +{ + t_object x_obj; + float x_f; + float pan; + float left; + float right; + float vol; +} t_pan; + +static void *pan_new(t_symbol *s, int argc, t_atom *argv) +{ + t_pan *x = (t_pan *)pd_new(pan_class); + outlet_new(&x->x_obj, gensym("signal")); + outlet_new(&x->x_obj, gensym("signal")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("panf")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("volf")); + + x->x_f = 0; + x->left = ROOT2DIV2; + x->right = ROOT2DIV2; + x->vol = 1; + return (x); +} + +static t_int *pan_perform(t_int *w) +{ + float *in1 = (t_float *)(w[1]); + float *out1 = (t_float *)(w[2]); + float *out2 = (t_float *)(w[3]); + int n = (int)(w[4]); + t_pan *x = (t_pan *)(w[5]); + float left=x->left*x->vol; + float right=x->right*x->vol; + float value; + + while (n--) + { + value = *in1++; + *out1++ = value * left; + *out2++ = value * right; + } + return (w+6); +} + +static void pan_dsp(t_pan *x, t_signal **sp) +{ + int n = sp[0]->s_n; + float *in1 = sp[0]->s_vec; + float *out1 = sp[1]->s_vec; + float *out2 = sp[2]->s_vec; + + dsp_add(pan_perform, 5, + in1, out1, out2, n, x); +} + +static void pan_f(t_pan *x, t_floatarg f) +{ + double angle; + f = f < -45 ? -45 : f; + f = f > 45 ? 45 : f; + angle = f * RADCONST; // convert degrees to radians + x->right = ROOT2DIV2 * (cos(angle) + sin(angle)); + x->left = ROOT2DIV2 * (cos(angle) - sin(angle)); +/* post("left = %f : right = %f", x->left, x->right); */ +} + +static void vol_f(t_pan *x, t_floatarg f) +{ + f = f < 0 ? 0 : f; + x->vol=f; +} + +void panvol_tilde_setup(void) +{ + pan_class = class_new(gensym("panvol~"), (t_newmethod)pan_new, 0, + sizeof(t_pan), 0, A_GIMME, 0); + + class_addmethod(pan_class, nullfn, gensym("signal"), 0); + + class_addmethod(pan_class, (t_method)pan_dsp, gensym("dsp"), 0); + class_addmethod(pan_class, (t_method)pan_f, gensym("panf"), A_FLOAT, 0); + class_addmethod(pan_class, (t_method)vol_f, gensym("volf"), A_FLOAT, 0); +} @@ -0,0 +1,211 @@ +/* +Copyright (C) 2002 Antoine Rousseau + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include "m_pd.h" +#include "s_stuff.h" +#include <stdio.h> +#include <sys/types.h> +#include <unistd.h> +#include <string.h> +#define BUFSIZE 4096 + +typedef struct popen +{ + t_object x_obj; + FILE *x_file; + char x_data[BUFSIZE]; + int x_count; + int x_ropened; + t_outlet *x_msgout; +} t_popen; + +t_class *popen_class; +static t_binbuf *inbinbuf; + + +static void *popen_new(t_symbol *s, int argc, t_atom *argv) +{ + t_popen *x; + + x = (t_popen *)pd_new(popen_class); + + x->x_file = NULL; + x->x_count=0; + x->x_msgout = outlet_new(&x->x_obj, &s_anything); + x->x_ropened=0; + return (x); +} + +static void popen_close(t_popen *x) +{ + if(x->x_ropened) { + sys_rmpollfn(fileno(x->x_file)); + //fflush(x->x_file); + } + if(x->x_file) pclose(x->x_file); + x->x_file=0; + x->x_ropened=0; +} + +static void popen_ff(t_popen *x) +{ + +} + +static void popen_open(t_popen *x, t_symbol *s,int argc, t_atom *argv) +{ + char cmd[512],*text; + int cmd_len; + + t_binbuf *bb=binbuf_new(); + + popen_close(x); + + //post("argc=%d",argc); + //post("argv[0]=%s",atom_getsymbol(&argv[0])->s_name); + + binbuf_add(bb,argc,argv); + binbuf_gettext(bb, &text,&cmd_len); + binbuf_free(bb); + + strncpy(cmd,text,cmd_len); + cmd[cmd_len]=0; + //post("cmd=%s",cmd); + + x->x_file=popen(cmd,"w"); + +} + +static void popen_list(t_popen *x, t_symbol *s, + int argc, t_atom *argv) +{ + t_binbuf *bb; + char *buf; + int l; + + if(!x->x_file) return; + + bb=binbuf_new(); + binbuf_add(bb,argc,argv); + //binbuf_print(bb); + binbuf_gettext(bb, &buf,&l); + buf[l]=0; + + //printf("popen list: %s\n",buf); + fprintf(x->x_file,"%s\n",buf);fflush(x->x_file); + + freebytes(buf,l); + binbuf_free(bb); +} + +static void popen_out(t_popen *x, t_binbuf *b) +{ + t_atom messbuf[1024]; + int msg, natom = binbuf_getnatom(b); + t_atom *at = binbuf_getvec(b); + for (msg = 0; msg < natom;) + { + int emsg; + for (emsg = msg; emsg < natom && at[emsg].a_type != A_COMMA + && at[emsg].a_type != A_SEMI; emsg++) + ; + if (emsg > msg) + { + int i; + for (i = msg; i < emsg; i++) + if (at[i].a_type == A_DOLLAR || at[i].a_type == A_DOLLSYM) + { + pd_error(x, "popen: got dollar sign in message"); + goto nodice; + } + if (at[msg].a_type == A_FLOAT) + { + if (emsg > msg + 1) + outlet_list(x->x_msgout, 0, emsg-msg, at + msg); + else outlet_float(x->x_msgout, at[msg].a_w.w_float); + } + else if (at[msg].a_type == A_SYMBOL) + outlet_anything(x->x_msgout, at[msg].a_w.w_symbol, + emsg-msg-1, at + msg + 1); + } + nodice: + msg = emsg + 1; + } +} + +static void popen_read(t_popen *x,int fd) +{ + int len,i=0; + unsigned char b; + unsigned char buffer[BUFSIZE]; + + if((len=read(fd,buffer,BUFSIZE))> 0){ + + for(i=0;i<len;i++){ + if(x->x_count>=BUFSIZE) x->x_count=0; + x->x_data[x->x_count++]=buffer[i]; + if(buffer[i]==';') { + binbuf_text(inbinbuf, x->x_data, x->x_count); + x->x_count=0; + popen_out(x,inbinbuf); + } + } + } +} + +static void popen_ropen(t_popen *x, t_symbol *s,int argc, t_atom *argv) +{ + char cmd[512],*text; + int cmd_len; + + t_binbuf *bb=binbuf_new(); + + popen_close(x); + + //post("argc=%d",argc); + //post("argv[0]=%s",atom_getsymbol(&argv[0])->s_name); + + binbuf_add(bb,argc,argv); + binbuf_gettext(bb, &text,&cmd_len); + binbuf_free(bb); + + strncpy(cmd,text,cmd_len); + cmd[cmd_len]=0; + //post("cmd=%s",cmd); + + x->x_file=popen(cmd,"r"); + sys_addpollfn(fileno(x->x_file),(t_fdpollfn)popen_read,(void*)x); + x->x_ropened=1; +} + +void popen_setup(void ) +{ + inbinbuf = binbuf_new(); + popen_class = class_new(gensym("popen"), (t_newmethod)popen_new, + (t_method)popen_close,sizeof(t_popen), 0, A_GIMME, 0); + class_addmethod(popen_class, (t_method)popen_close, + gensym("close"), 0); + class_addmethod(popen_class, (t_method)popen_open, + gensym("open"), A_GIMME, 0); + class_addmethod(popen_class, (t_method)popen_ropen, + gensym("ropen"), A_GIMME, 0); + class_addlist(popen_class, popen_list); + +} + diff --git a/readsfv~.c b/readsfv~.c new file mode 100644 index 0000000..6707cf1 --- /dev/null +++ b/readsfv~.c @@ -0,0 +1,1683 @@ +/* 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. */ + +/* this file contains, first, a collection of soundfile access routines, a +sort of soundfile library. Second, the "soundfiler" object is defined which +uses the routines to read or write soundfiles, synchronously, from garrays. +These operations are not to be done in "real time" as they may have to wait +for disk accesses (even the write routine.) Finally, the realtime objects +readsf~ and writesf~ are defined which confine disk operations to a separate +thread so that they can be used in real time. The real-time disk access +objects are available for linux only so far, although they could be compiled +for Windows if someone were willing to find a Pthreads package for it. */ + +/* this is a partial copy of d_soundfile, with some hacking: + 1: a fix in soundfiler to compute the normalization factor only on + the samples we want to write on the disk... + 2: a version of readsf~ that works with a (positive) speed parameter. + + Antoine Rousseau +*/ + +#ifdef UNIX +#include <unistd.h> +#include <fcntl.h> +#endif +#include <pthread.h> +#ifdef NT +#include <io.h> +#endif +#include <stdio.h> +#include <string.h> +#include <errno.h> + +#include "m_pd.h" + +#define MAXSFCHANS 4 + + +/***************** soundfile header structures ************************/ + +typedef unsigned short uint16; +typedef unsigned long uint32; + +#define FORMAT_WAVE 0 +#define FORMAT_AIFF 1 +#define FORMAT_NEXT 2 + +/* the NeXTStep sound header structure; can be big or little endian */ + +typedef struct _nextstep +{ + char ns_fileid[4]; /* magic number '.snd' if file is big-endian */ + uint32 ns_onset; /* byte offset of first sample */ + uint32 ns_length; /* length of sound in bytes */ + uint32 ns_format; /* format; see below */ + uint32 ns_sr; /* sample rate */ + uint32 ns_nchans; /* number of channels */ + char ns_info[4]; /* comment */ +} t_nextstep; + +#define NS_FORMAT_LINEAR_16 3 +#define NS_FORMAT_LINEAR_24 4 +#define NS_FORMAT_FLOAT 6 +#define SCALE (1./(1024. * 1024. * 1024. * 2.)) + +/* the WAVE header. All Wave files are little endian. We assume + the "fmt" chunk comes first which is usually the case but perhaps not + always; same for AIFF and the "COMM" chunk. */ + +typedef unsigned word; +typedef unsigned long dword; + +typedef struct _wave +{ + char w_fileid[4]; /* chunk id 'RIFF' */ + uint32 w_chunksize; /* chunk size */ + char w_waveid[4]; /* wave chunk id 'WAVE' */ + char w_fmtid[4]; /* format chunk id 'fmt ' */ + uint32 w_fmtchunksize; /* format chunk size */ + uint16 w_fmttag; /* format tag, 1 for PCM */ + uint16 w_nchannels; /* number of channels */ + uint32 w_samplespersec; /* sample rate in hz */ + uint32 w_navgbytespersec; /* average bytes per second */ + uint16 w_nblockalign; /* number of bytes per sample */ + uint16 w_nbitspersample; /* number of bits in a sample */ + char w_datachunkid[4]; /* data chunk id 'data' */ + uint32 w_datachunksize; /* length of data chunk */ +} t_wave; + +typedef struct _fmt /* format chunk */ +{ + uint16 f_fmttag; /* format tag, 1 for PCM */ + uint16 f_nchannels; /* number of channels */ + uint32 f_samplespersec; /* sample rate in hz */ + uint32 f_navgbytespersec; /* average bytes per second */ + uint16 f_nblockalign; /* number of bytes per frame */ + uint16 f_nbitspersample; /* number of bits in a sample */ +} t_fmt; + +typedef struct _wavechunk /* ... and the last two items */ +{ + char wc_id[4]; /* data chunk id, e.g., 'data' or 'fmt ' */ + uint32 wc_size; /* length of data chunk */ +} t_wavechunk; + +/* the AIFF header. I'm assuming AIFC is compatible but don't really know + that. */ + +typedef struct _datachunk +{ + char dc_id[4]; /* data chunk id 'SSND' */ + uint32 dc_size; /* length of data chunk */ +} t_datachunk; + +//#define CHUNKHDRSIZE sizeof(t_datachunk) + +typedef struct _comm +{ + uint16 c_nchannels; /* number of channels */ + uint16 c_nframeshi; /* # of sample frames (hi) */ + uint16 c_nframeslo; /* # of sample frames (lo) */ + uint16 c_bitspersamp; /* bits per sample */ + unsigned char c_samprate[10]; /* sample rate, 80-bit float! */ +} t_comm; + + /* this version is more convenient for writing them out: */ +typedef struct _aiff +{ + char a_fileid[4]; /* chunk id 'FORM' */ + uint32 a_chunksize; /* chunk size */ + char a_aiffid[4]; /* aiff chunk id 'AIFF' */ + char a_fmtid[4]; /* format chunk id 'COMM' */ + uint32 a_fmtchunksize; /* format chunk size, 18 */ + uint16 a_nchannels; /* number of channels */ + uint16 a_nframeshi; /* # of sample frames (hi) */ + uint16 a_nframeslo; /* # of sample frames (lo) */ + uint16 a_bitspersamp; /* bits per sample */ + unsigned char a_samprate[10]; /* sample rate, 80-bit float! */ +} t_aiff; + +#define AIFFHDRSIZE 38 /* probably not what sizeof() gives */ + + +#define AIFFPLUS (AIFFHDRSIZE + 8) /* header size including first chunk hdr */ + +#define WHDR1 sizeof(t_nextstep) +#define WHDR2 (sizeof(t_wave) > WHDR1 ? sizeof (t_wave) : WHDR1) +#define WRITEHDRSIZE (AIFFPLUS > WHDR2 ? AIFFPLUS : WHDR2) + +#define READHDRSIZE (16 > WHDR2 ? 16 : WHDR2) + +#define OBUFSIZE MAXPDSTRING /* assume MAXPDSTRING is bigger than headers */ + +#ifdef NT +#include <fcntl.h> +#define BINCREATE _O_WRONLY | _O_CREAT | _O_BINARY | _O_TRUNC | +#else +#define BINCREATE O_WRONLY|O_CREAT|O_TRUNC +#endif + +/* this routine returns 1 if the high order byte comes at the lower +address on our architecture (big-endianness.). It's 1 for Motorola, +0 for Intel: */ + +extern int garray_ambigendian(void); + +/* byte swappers */ + +static uint32 swap4(uint32 n, int doit) +{ + if (doit) + return (((n & 0xff) << 24) | ((n & 0xff00) << 8) | + ((n & 0xff0000) >> 8) | ((n & 0xff000000) >> 24)); + else return (n); +} + +static uint16 swap2(uint32 n, int doit) +{ + if (doit) + return (((n & 0xff) << 8) | ((n & 0xff00) >> 8)); + else return (n); +} + +static void swapstring(char *foo, int doit) +{ + if (doit) + { + char a = foo[0], b = foo[1], c = foo[2], d = foo[3]; + foo[0] = d; foo[1] = c; foo[2] = b; foo[3] = a; + } +} + +/******************** soundfile access routines **********************/ + +void readsf_banana( void); /* debugging */ + +/* This routine opens a file, looks for either a nextstep or "wave" header, +* seeks to end of it, and fills in bytes per sample and number of channels. +* Only 2- and 3-byte fixed-point samples and 4-byte floating point samples +* are supported. If "headersize" is nonzero, the +* caller should supply the number of channels, endinanness, and bytes per +* sample; the header is ignored. Otherwise, the routine tries to read the +* header and fill in the properties. +*/ + +extern int open_soundfile(const char *dirname, const char *filename, int headersize, + int *p_bytespersamp, int *p_bigendian, int *p_nchannels, long *p_bytelimit, + long skipframes); + + +static void soundfile_xferin(int sfchannels, int nvecs, float **vecs, + long itemsread, unsigned char *buf, int nitems, int bytespersamp, + int bigendian) +{ + int i, j; + unsigned char *sp, *sp2; + float *fp; + int nchannels = (sfchannels < nvecs ? sfchannels : nvecs); + int bytesperframe = bytespersamp * sfchannels; + for (i = 0, sp = buf; i < nchannels; i++, sp += bytespersamp) + { + if (bytespersamp == 2) + { + if (bigendian) + { + for (j = 0, sp2 = sp, fp=vecs[i] + itemsread; + j < nitems; j++, sp2 += bytesperframe, fp++) + *fp = SCALE * ((sp2[0] << 24) | (sp2[1] << 16)); + } + else + { + for (j = 0, sp2 = sp, fp=vecs[i] + itemsread; + j < nitems; j++, sp2 += bytesperframe, fp++) + *fp = SCALE * ((sp2[1] << 24) | (sp2[0] << 16)); + } + } + else if (bytespersamp == 3) + { + if (bigendian) + { + for (j = 0, sp2 = sp, fp=vecs[i] + itemsread; + j < nitems; j++, sp2 += bytesperframe, fp++) + *fp = SCALE * ((sp2[0] << 24) | (sp2[1] << 16) + | (sp2[2] << 8)); + } + else + { + for (j = 0, sp2 = sp, fp=vecs[i] + itemsread; + j < nitems; j++, sp2 += bytesperframe, fp++) + *fp = SCALE * ((sp2[2] << 24) | (sp2[1] << 16) + | (sp2[0] << 8)); + } + } + else if (bytespersamp == 4) + { + if (bigendian) + { + for (j = 0, sp2 = sp, fp=vecs[i] + itemsread; + j < nitems; j++, sp2 += bytesperframe, fp++) + *(long *)fp = ((sp2[0] << 24) | (sp2[1] << 16) + | (sp2[2] << 8) | sp2[3]); + } + else + { + for (j = 0, sp2 = sp, fp=vecs[i] + itemsread; + j < nitems; j++, sp2 += bytesperframe, fp++) + *(long *)fp = ((sp2[3] << 24) | (sp2[2] << 16) + | (sp2[1] << 8) | sp2[0]); + } + } + } + /* zero out other outputs */ + for (i = sfchannels; i < nvecs; i++) + for (j = nitems, fp = vecs[i]; j--; ) + *fp++ = 0; + +} + +static void interpolate(int nvec,float **invec,int nin, + float **outvec,int nout) +{ + + float r=nin/(float)nout; + int i,j; + + + for(i=0;i<nout;i++) + for(j=0;j<nvec;j++) + outvec[j][i]=invec[j][(int)(i*r)]; + +} + /* soundfiler2_write ... + + usage: write [flags] filename table ... + flags: + -nframes <frames> + -skip <frames> + -bytes <bytes per sample> + -normalize + -nextstep + -wave + -big + -little + */ + + /* the routine which actually does the work should LATER also be called + from garray_write16. */ + + + /* Parse arguments for writing. The "obj" argument is only for flagging + errors. For streaming to a file the "normalize", "onset" and "nframes" + arguments shouldn't be set but the calling routine flags this. */ + +static int soundfiler2_writeargparse(void *obj, int *p_argc, t_atom **p_argv, + t_symbol **p_filesym, + int *p_filetype, int *p_bytespersamp, int *p_swap, int *p_bigendian, + int *p_normalize, long *p_onset, long *p_nframes,float *p_amp) +{ + int argc = *p_argc; + t_atom *argv = *p_argv; + int bytespersamp = 2, bigendian = 0, + endianness = -1, swap, filetype = FORMAT_WAVE, normalize = 0; + long onset = 0, nframes = 0x7fffffff; + float amp=1; + t_symbol *filesym; + while (argc > 0 && argv->a_type == A_SYMBOL && + *argv->a_w.w_symbol->s_name == '-') + { + char *flag = argv->a_w.w_symbol->s_name + 1; + if (!strcmp(flag, "skip")) + { + if (argc < 2 || argv[1].a_type != A_FLOAT || + ((onset = argv[1].a_w.w_float) < 0)) + goto usage; + argc -= 2; argv += 2; + } + else if (!strcmp(flag, "nframes")) + { + if (argc < 2 || argv[1].a_type != A_FLOAT || + ((nframes = argv[1].a_w.w_float) < 0)) + goto usage; + argc -= 2; argv += 2; + } + else if (!strcmp(flag, "bytes")) + { + if (argc < 2 || argv[1].a_type != A_FLOAT || + ((bytespersamp = argv[1].a_w.w_float) < 2) || + bytespersamp > 4) + goto usage; + argc -= 2; argv += 2; + } + else if (!strcmp(flag, "normalize")) + { + normalize = 1; + argc -= 1; argv += 1; + } + else if (!strcmp(flag, "amp")) + { + if (argc < 2 || argv[1].a_type != A_FLOAT) + goto usage; + amp = argv[1].a_w.w_float; + argc -= 2; argv += 2; + } + else if (!strcmp(flag, "wave")) + { + filetype = FORMAT_WAVE; + argc -= 1; argv += 1; + } + else if (!strcmp(flag, "nextstep")) + { + filetype = FORMAT_NEXT; + argc -= 1; argv += 1; + } + else if (!strcmp(flag, "aiff")) + { + filetype = FORMAT_AIFF; + argc -= 1; argv += 1; + } + else if (!strcmp(flag, "big")) + { + endianness = 1; + argc -= 1; argv += 1; + } + else if (!strcmp(flag, "little")) + { + endianness = 1; + argc -= 1; argv += 1; + } + else goto usage; + } + /* only NextStep handles floating point samples */ + if (bytespersamp == 4) + filetype = FORMAT_NEXT; + + /* for WAVE force little endian; for nextstep use machine native */ + if (filetype == FORMAT_WAVE) + { + bigendian = 0; + if (endianness == 1) + pd_error(obj, "WAVE file forced to little endian"); + } + else if (filetype == FORMAT_AIFF) + { + bigendian = 1; + if (endianness == 0) + pd_error(obj, "AIFF file forced to big endian"); + } + else if (endianness == -1) + { + bigendian = garray_ambigendian(); + } + swap = (bigendian != garray_ambigendian()); + if (!argc || argv->a_type != A_SYMBOL) + goto usage; + filesym = argv->a_w.w_symbol; + argc--; argv++; + + *p_argc = argc; + *p_argv = argv; + *p_filesym = filesym; + *p_filetype = filetype; + *p_bytespersamp = bytespersamp; + *p_swap = swap; + *p_normalize = normalize; + *p_onset = onset; + *p_nframes = nframes; + *p_bigendian = bigendian; + *p_amp = amp; + return (0); +usage: + return (-1); +} + +static int create_soundfile2(t_canvas *canvas, const char *filename, + int filetype, int nframes, int bytespersamp, + int bigendian, int nchannels, int swap) +{ + char filenamebuf[MAXPDSTRING], buf2[MAXPDSTRING]; + char headerbuf[WRITEHDRSIZE]; + t_wave *wavehdr = (t_wave *)headerbuf; + t_nextstep *nexthdr = (t_nextstep *)headerbuf; + t_aiff *aiffhdr = (t_aiff *)headerbuf; + int fd, headersize = 0; + + strncpy(filenamebuf, filename, MAXPDSTRING-10); + filenamebuf[MAXPDSTRING-10] = 0; + + if (filetype == FORMAT_NEXT) + { + if (strcmp(filenamebuf + strlen(filenamebuf)-4, ".snd")) + strcat(filenamebuf, ".snd"); + if (bigendian) + strncpy(nexthdr->ns_fileid, ".snd", 4); + else strncpy(nexthdr->ns_fileid, "dns.", 4); + nexthdr->ns_onset = swap4(sizeof(*nexthdr), swap); + nexthdr->ns_length = 0; + nexthdr->ns_format = swap4((bytespersamp == 3 ? NS_FORMAT_LINEAR_24 : + (bytespersamp == 4 ? NS_FORMAT_FLOAT : NS_FORMAT_LINEAR_16)), swap);; + nexthdr->ns_sr = swap4(44100, swap); /* lie */ + nexthdr->ns_nchans = swap4(nchannels, swap); + strcpy(nexthdr->ns_info, "Pd "); + swapstring(nexthdr->ns_info, swap); + headersize = sizeof(t_nextstep); + } + else if (filetype == FORMAT_AIFF) + { + long datasize = nframes * nchannels * bytespersamp; + long longtmp; + static unsigned char dogdoo[] = + {0x40, 0x0e, 0xac, 0x44, 0, 0, 0, 0, 0, 0, 'S', 'S', 'N', 'D'}; + if (strcmp(filenamebuf + strlen(filenamebuf)-4, ".aif") && + strcmp(filenamebuf + strlen(filenamebuf)-5, ".aiff")) + strcat(filenamebuf, ".aif"); + strncpy(aiffhdr->a_fileid, "FORM", 4); + aiffhdr->a_chunksize = swap4(datasize + sizeof(*aiffhdr) + 4, swap); + strncpy(aiffhdr->a_aiffid, "AIFF", 4); + strncpy(aiffhdr->a_fmtid, "COMM", 4); + aiffhdr->a_fmtchunksize = swap4(18, swap); + aiffhdr->a_nchannels = swap2(nchannels, swap); + longtmp = swap4(nframes, swap); + memcpy(&aiffhdr->a_nframeshi, &longtmp, 4); + aiffhdr->a_bitspersamp = swap2(8 * bytespersamp, swap); + memcpy(aiffhdr->a_samprate, dogdoo, sizeof(dogdoo)); + longtmp = swap4(datasize, swap); + memcpy(aiffhdr->a_samprate + sizeof(dogdoo), &longtmp, 4); + headersize = AIFFPLUS; + } + else /* WAVE format */ + { + long datasize = nframes * nchannels * bytespersamp; + if (strcmp(filenamebuf + strlen(filenamebuf)-4, ".wav")) + strcat(filenamebuf, ".wav"); + strncpy(wavehdr->w_fileid, "RIFF", 4); + wavehdr->w_chunksize = swap4(datasize + sizeof(*wavehdr) - 8, swap); + strncpy(wavehdr->w_waveid, "WAVE", 4); + strncpy(wavehdr->w_fmtid, "fmt ", 4); + wavehdr->w_fmtchunksize = swap4(16, swap); + wavehdr->w_fmttag = swap2(1, swap); + wavehdr->w_nchannels = swap2(nchannels, swap); + wavehdr->w_samplespersec = swap4(44100, swap); + wavehdr->w_navgbytespersec = swap4(44100 * nchannels * bytespersamp, swap); + wavehdr->w_nblockalign = swap2(bytespersamp, swap); + wavehdr->w_nbitspersample = swap2(8 * bytespersamp, swap); + strncpy(wavehdr->w_datachunkid, "data", 4); + wavehdr->w_datachunksize = swap4(datasize, swap); + headersize = sizeof(t_wave); + } + + canvas_makefilename(canvas, filenamebuf, buf2, MAXPDSTRING); + sys_bashfilename(buf2, buf2); + if ((fd = open(buf2, BINCREATE, 0666)) < 0) + return (-1); + + if (write(fd, headerbuf, headersize) < headersize) + { + close (fd); + return (-1); + } + return (fd); +} + +static void soundfile_finishwrite(void *obj, char *filename, int fd, + int filetype, long nframes, long itemswritten, int bytesperframe, int swap) +{ + if (itemswritten < nframes) + { + if (nframes < 0x7fffffff) + pd_error(obj, "soundfiler2_write: %d out of %d bytes written", + itemswritten, nframes); + /* try to fix size fields in header */ + if (filetype == FORMAT_WAVE) + { + long datasize = itemswritten * bytesperframe, mofo; + + if (lseek(fd, + ((char *)(&((t_wave *)0)->w_chunksize)) - (char *)0, + SEEK_SET) == 0) + goto baddonewrite; + mofo = swap4(datasize + sizeof(t_wave) - 8, swap); + if (write(fd, (char *)(&mofo), 4) < 4) + goto baddonewrite; + if (lseek(fd, + ((char *)(&((t_wave *)0)->w_datachunksize)) - (char *)0, + SEEK_SET) == 0) + goto baddonewrite; + mofo = swap4(datasize, swap); + if (write(fd, (char *)(&mofo), 4) < 4) + goto baddonewrite; + } + if (filetype == FORMAT_AIFF) + { + long mofo; + if (lseek(fd, + ((char *)(&((t_aiff *)0)->a_nframeshi)) - (char *)0, + SEEK_SET) == 0) + goto baddonewrite; + mofo = swap4(nframes, swap); + if (write(fd, (char *)(&mofo), 4) < 4) + goto baddonewrite; + } + } + return; +baddonewrite: + post("%s: %s", filename, strerror(errno)); +} + +static void soundfile_xferout(int nchannels, float **vecs, + unsigned char *buf, int nitems, long onset, int bytespersamp, + int bigendian, float normalfactor) +{ + int i, j; + unsigned char *sp, *sp2; + float *fp; + int bytesperframe = bytespersamp * nchannels; + long xx; + for (i = 0, sp = buf; i < nchannels; i++, sp += bytespersamp) + { + if (bytespersamp == 2) + { + float ff = normalfactor * 32768.; + if (bigendian) + { + for (j = 0, sp2 = sp, fp = vecs[i] + onset; + j < nitems; j++, sp2 += bytesperframe, fp++) + { + int xx = 32768. + (*fp * ff); + xx -= 32768; + if (xx < -32767) + xx = -32767; + if (xx > 32767) + xx = 32767; + sp2[0] = (xx >> 8); + sp2[1] = xx; + } + } + else + { + for (j = 0, sp2 = sp, fp=vecs[i] + onset; + j < nitems; j++, sp2 += bytesperframe, fp++) + { + int xx = 32768. + (*fp * ff); + xx -= 32768; + if (xx < -32767) + xx = -32767; + if (xx > 32767) + xx = 32767; + sp2[1] = (xx >> 8); + sp2[0] = xx; + } + } + } + else if (bytespersamp == 3) + { + float ff = normalfactor * 8388608.; + if (bigendian) + { + for (j = 0, sp2 = sp, fp=vecs[i] + onset; + j < nitems; j++, sp2 += bytesperframe, fp++) + { + int xx = 8388608. + (*fp * ff); + xx -= 8388608; + if (xx < -8388607) + xx = -8388607; + if (xx > 8388607) + xx = 8388607; + sp2[0] = (xx >> 16); + sp2[1] = (xx >> 8); + sp2[2] = xx; + } + } + else + { + for (j = 0, sp2 = sp, fp=vecs[i] + onset; + j < nitems; j++, sp2 += bytesperframe, fp++) + { + int xx = 8388608. + (*fp * ff); + xx -= 8388608; + if (xx < -8388607) + xx = -8388607; + if (xx > 8388607) + xx = 8388607; + sp2[2] = (xx >> 16); + sp2[1] = (xx >> 8); + sp2[0] = xx; + } + } + } + else if (bytespersamp == 4) + { + if (bigendian) + { + for (j = 0, sp2 = sp, fp=vecs[i] + onset; + j < nitems; j++, sp2 += bytesperframe, fp++) + { + float f2 = *fp * normalfactor; + xx = *(long *)&f2; + sp2[0] = (xx >> 24); sp2[1] = (xx >> 24); + sp2[2] = (xx >> 24); sp2[3] = xx; + } + } + else + { + for (j = 0, sp2 = sp, fp=vecs[i] + onset; + j < nitems; j++, sp2 += bytesperframe, fp++) + { + float f2 = *fp * normalfactor; + xx = *(long *)&f2; + sp2[3] = (xx >> 24); sp2[2] = (xx >> 24); + sp2[1] = (xx >> 24); sp2[0] = xx; + } + } + } + } +} + + +/* ------- soundfiler - reads and writes soundfiles to/from "garrays" ---- */ +#define DEFMAXSIZE 4000000 /* default maximum 16 MB per channel */ +#define SAMPBUFSIZE 1024 + + +static t_class *soundfiler2_class; + +typedef struct _soundfiler2 +{ + t_object x_obj; + t_canvas *x_canvas; +} t_soundfiler2; + +static t_soundfiler2 *soundfiler2_new(void) +{ + t_soundfiler2 *x = (t_soundfiler2 *)pd_new(soundfiler2_class); + x->x_canvas = canvas_getcurrent(); + outlet_new(&x->x_obj, &s_float); + return (x); +} + + /* soundfiler2_read ... + + usage: read [flags] filename table ... + flags: + -skip <frames> ... frames to skip in file + -nframes <frames> + -onset <frames> ... onset in table to read into (NOT DONE YET) + -raw <headersize channels bytes endian> + -resize + -maxsize <max-size> + */ + +static void soundfiler2_read(t_soundfiler2 *x, t_symbol *s, + int argc, t_atom *argv) +{ + int headersize = -1, channels = 0, bytespersamp = 0, bigendian = 0, + resize = 0, i, j; + long skipframes = 0, nframes = 0, finalsize = 0, itemsleft, + maxsize = DEFMAXSIZE, itemsread = 0, bytelimit = 0x7fffffff; + int fd = -1; + char endianness, *filename; + t_garray *garrays[MAXSFCHANS]; + t_float *vecs[MAXSFCHANS]; + char sampbuf[SAMPBUFSIZE]; + int bufframes, nitems; + FILE *fp; + while (argc > 0 && argv->a_type == A_SYMBOL && + *argv->a_w.w_symbol->s_name == '-') + { + char *flag = argv->a_w.w_symbol->s_name + 1; + if (!strcmp(flag, "skip")) + { + if (argc < 2 || argv[1].a_type != A_FLOAT || + ((skipframes = argv[1].a_w.w_float) < 0)) + goto usage; + argc -= 2; argv += 2; + } + else if (!strcmp(flag, "nframes")) + { + if (argc < 2 || argv[1].a_type != A_FLOAT || + ((nframes = argv[1].a_w.w_float) < 0)) + goto usage; + argc -= 2; argv += 2; + } + else if (!strcmp(flag, "raw")) + { + if (argc < 5 || + argv[1].a_type != A_FLOAT || + ((headersize = argv[1].a_w.w_float) < 0) || + argv[2].a_type != A_FLOAT || + ((channels = argv[2].a_w.w_float) < 1) || + (channels > MAXSFCHANS) || + argv[3].a_type != A_FLOAT || + ((bytespersamp = argv[3].a_w.w_float) < 2) || + (bytespersamp > 4) || + argv[4].a_type != A_SYMBOL || + ((endianness = argv[4].a_w.w_symbol->s_name[0]) != 'b' + && endianness != 'l' && endianness != 'n')) + goto usage; + if (endianness == 'b') + bigendian = 1; + else if (endianness == 'l') + bigendian = 0; + else + bigendian = garray_ambigendian(); + argc -= 5; argv += 5; + } + else if (!strcmp(flag, "resize")) + { + resize = 1; + argc -= 1; argv += 1; + } + else if (!strcmp(flag, "maxsize")) + { + if (argc < 2 || argv[1].a_type != A_FLOAT || + ((maxsize = argv[1].a_w.w_float) < 0)) + goto usage; + resize = 1; /* maxsize implies resize. */ + argc -= 2; argv += 2; + } + else goto usage; + } + if (argc < 2 || argc > MAXSFCHANS + 1 || argv[0].a_type != A_SYMBOL) + goto usage; + filename = argv[0].a_w.w_symbol->s_name; + argc--; argv++; + + for (i = 0; i < argc; i++) + { + int vecsize; + if (argv[i].a_type != A_SYMBOL) + goto usage; + if (!(garrays[i] = + (t_garray *)pd_findbyclass(argv[i].a_w.w_symbol, garray_class))) + { + pd_error(x, "%s: no such table", argv[i].a_w.w_symbol->s_name); + goto done; + } + else if (!garray_getfloatarray(garrays[i], &vecsize, &vecs[i])) + error("%s: bad template for tabwrite", + argv[i].a_w.w_symbol->s_name); + if (finalsize && finalsize != vecsize && !resize) + { + post("soundfiler2_read: arrays have different lengths; resizing..."); + resize = 1; + } + finalsize = vecsize; + } + fd = open_soundfile(canvas_getdir(x->x_canvas)->s_name, filename, + headersize, &bytespersamp, &bigendian, &channels, &bytelimit, + skipframes); + + if (fd < 0) + { + pd_error(x, "soundfiler2_read: %s: %s", filename, (errno == EIO ? + "unknown or bad header format" : strerror(errno))); + goto done; + } + + if (resize) + { + /* figure out what to resize to */ + long poswas, eofis, framesinfile; + + poswas = lseek(fd, 0, SEEK_CUR); + eofis = lseek(fd, 0, SEEK_END); + if (poswas < 0 || eofis < 0) + { + pd_error(x, "lseek failed"); + goto done; + } + lseek(fd, poswas, SEEK_SET); + framesinfile = (eofis - poswas) / (channels * bytespersamp); + if (framesinfile > maxsize) + { + pd_error(x, "soundfiler2_read: truncated to %d elements", maxsize); + framesinfile = maxsize; + } + if (framesinfile > bytelimit / bytespersamp) + framesinfile = bytelimit / bytespersamp; + finalsize = framesinfile; + for (i = 0; i < argc; i++) + { + int vecsize; + + garray_resize(garrays[i], finalsize); + /* for sanity's sake let's clear the save-in-patch flag here */ + garray_setsaveit(garrays[i], 0); + garray_getfloatarray(garrays[i], &vecsize, &vecs[i]); + /* if the resize failed, garray_resize reported the error */ + if (vecsize != framesinfile) + { + pd_error(x, "resize failed"); + goto done; + } + } + } + if (!finalsize) finalsize = 0x7fffffff; + if (finalsize > bytelimit / bytespersamp) + finalsize = bytelimit / bytespersamp; + fp = fdopen(fd, "rb"); + bufframes = SAMPBUFSIZE / (channels * bytespersamp); + + for (itemsread = 0; itemsread < finalsize; ) + { + int thisread = finalsize - itemsread; + thisread = (thisread > bufframes ? bufframes : thisread); + nitems = fread(sampbuf, channels * bytespersamp, thisread, fp); + if (nitems <= 0) break; + soundfile_xferin(channels, argc, vecs, itemsread, + (unsigned char *)sampbuf, nitems, bytespersamp, bigendian); + itemsread += nitems; + } + /* zero out remaining elements of vectors */ + + for (i = 0; i < argc; i++) + { + int nzero, vecsize; + garray_getfloatarray(garrays[i], &vecsize, &vecs[i]); + for (j = itemsread; j < vecsize; j++) + vecs[i][j] = 0; + } + /* zero out vectors in excess of number of channels */ + for (i = channels; i < argc; i++) + { + int vecsize; + float *foo; + garray_getfloatarray(garrays[i], &vecsize, &foo); + for (j = 0; j < vecsize; j++) + foo[j] = 0; + } + /* do all graphics updates */ + for (i = 0; i < argc; i++) + garray_redraw(garrays[i]); + fclose(fp); + fd = -1; + goto done; +usage: + pd_error(x, "usage: read [flags] filename tablename..."); + post("flags: -skip <n> -nframes <n> -resize -maxsize <n> ..."); + post("-raw <headerbytes> <channels> <bytespersamp> <endian (b, l, or n)>."); +done: + if (fd >= 0) + close (fd); + outlet_float(x->x_obj.ob_outlet, (float)itemsread); +} + + /* this is broken out from soundfiler2_write below so garray_write can + call it too... not done yet though. */ + +static long soundfiler2_dowrite(void *obj, t_canvas *canvas, + int argc, t_atom *argv) +{ + int headersize, bytespersamp, bigendian, + endianness, swap, filetype, normalize, i, j, nchannels; + long onset, nframes, itemsleft, + maxsize = DEFMAXSIZE, itemswritten = 0; + t_garray *garrays[MAXSFCHANS]; + t_float *vecs[MAXSFCHANS]; + char sampbuf[SAMPBUFSIZE]; + int bufframes, nitems; + int fd = -1; + float normfactor, biggest = 0,ftmp,amp; + t_symbol *filesym; + + if (soundfiler2_writeargparse(obj, &argc, &argv, &filesym, &filetype, + &bytespersamp, &swap, &bigendian, &normalize, &onset, &nframes,&)) + goto usage; + nchannels = argc; + if (nchannels < 1 || nchannels > MAXSFCHANS) + goto usage; + + for (i = 0; i < nchannels; i++) + { + int vecsize; + + if (argv[i].a_type != A_SYMBOL) goto usage; + + if (!(garrays[i] = + (t_garray *)pd_findbyclass(argv[i].a_w.w_symbol, garray_class))) + { + pd_error(obj, "%s: no such table", argv[i].a_w.w_symbol->s_name); + goto fail; + } + else if (!garray_getfloatarray(garrays[i], &vecsize, &vecs[i])) + error("%s: bad template for tabwrite",argv[i].a_w.w_symbol->s_name); + if (nframes > vecsize - onset) + nframes = vecsize - onset; + + for (j = 0; j < nframes; j++) /* FIXED (Antoine Rousseau)*/ + { + ftmp=vecs[i][j+onset]; + if (ftmp > biggest) biggest = ftmp; + else if (-ftmp > biggest) biggest = -ftmp; + } + } + + if (nframes <= 0) + { + pd_error(obj, "soundfiler2_write: no samples at onset %ld", onset); + goto fail; + } + + if ((fd = create_soundfile2(canvas, filesym->s_name, filetype, + nframes, bytespersamp, bigendian, nchannels, + swap)) < 0) + { + post("%s: %s\n", filesym->s_name, strerror(errno)); + goto fail; + } + if (!normalize) + { + if ((bytespersamp != 4) && (biggest > 1)) + { + //post("%s: normalizing max amplitude %f to 1", filesym->s_name, biggest); + normalize = 1; + } + //else post("%s: biggest amplitude = %f", filesym->s_name, biggest); + } + if (normalize) + normfactor = (biggest > 0 ? 32767./(32768. * biggest) : 1); + else normfactor = amp; + + /*post("%s: biggest amplitude = %f , normfactor = %f", + filesym->s_name, biggest,normfactor);*/ + + bufframes = SAMPBUFSIZE / (nchannels * bytespersamp); + + for (itemswritten = 0; itemswritten < nframes; ) + { + int thiswrite = nframes - itemswritten, nitems, nbytes; + thiswrite = (thiswrite > bufframes ? bufframes : thiswrite); + soundfile_xferout(argc, vecs, (unsigned char *)sampbuf, thiswrite, + onset, bytespersamp, bigendian, normfactor); + nbytes = write(fd, sampbuf, nchannels * bytespersamp * thiswrite); + if (nbytes < nchannels * bytespersamp * thiswrite) + { + post("%s: %s", filesym->s_name, strerror(errno)); + if (nbytes > 0) + itemswritten += nbytes / (nchannels * bytespersamp); + break; + } + itemswritten += thiswrite; + onset += thiswrite; + } + if (fd >= 0) + { + soundfile_finishwrite(obj, filesym->s_name, fd, + filetype, nframes, itemswritten, nchannels * bytespersamp, swap); + close (fd); + } + return ((float)itemswritten); +usage: + pd_error(obj, "usage: write [flags] filename tablename..."); + post("flags: -skip <n> -nframes <n> -bytes <n> -wave -aiff -nextstep ..."); + post("-big -little -normalize -amp <n>"); + post("(defaults to a 16-bit wave file)."); +fail: + if (fd >= 0) + close (fd); + return (0); +} + +static void soundfiler2_write(t_soundfiler2 *x, t_symbol *s, + int argc, t_atom *argv) +{ + long bozo = soundfiler2_dowrite(x, x->x_canvas, + argc, argv); + outlet_float(x->x_obj.ob_outlet, (float)bozo); +} + +void soundfiler2_setup(void) +{ + soundfiler2_class = class_new(gensym("soundfiler2"), (t_newmethod)soundfiler2_new, + 0, sizeof(t_soundfiler2), 0, 0); + class_addmethod(soundfiler2_class, (t_method)soundfiler2_read, gensym("read"), + A_GIMME, 0); + class_addmethod(soundfiler2_class, (t_method)soundfiler2_write, + gensym("write"), A_GIMME, 0); +} + +/************************* readsf object ******************************/ + +/* READSF uses the Posix threads package; for the moment we're Linux +only although this should be portable to the other platforms. + +Each instance of readsf~ owns a "child" thread for doing the UNIX (NT?) file +reading. The parent thread signals the child each time: + (1) a file wants opening or closing; + (2) we've eaten another 1/16 of the shared buffer (so that the + child thread should check if it's time to read some more.) +The child signals the parent whenever a read has completed. Signalling +is done by setting "conditions" and putting data in mutex-controlled common +areas. +*/ + +#ifdef __linux__ + +#define MAXBYTESPERSAMPLE 4 +#define MAXVECSIZE 128 + +#define READSIZE 65536 +#define WRITESIZE 65536 +#define DEFBUFPERCHAN 262144 +#define MINBUFSIZE (4 * READSIZE) +#define MAXBUFSIZE 16777216 /* arbitrary; just don't want to hang malloc */ + +#define REQUEST_NOTHING 0 +#define REQUEST_OPEN 1 +#define REQUEST_CLOSE 2 +#define REQUEST_QUIT 3 +#define REQUEST_BUSY 4 + +#define STATE_IDLE 0 +#define STATE_STARTUP 1 +#define STATE_STREAM 2 + +static t_class *readsfv_class; + +static t_sample *(tmpvec[MAXSFCHANS]); + +typedef struct _readsf +{ + t_object x_obj; + t_canvas *x_canvas; + t_clock *x_clock; + char *x_buf; /* soundfile buffer */ + int x_bufsize; /* buffer size in bytes */ + int x_noutlets; /* number of audio outlets */ + t_sample *(x_outvec[MAXSFCHANS]); /* audio vectors */ + int x_vecsize; /* vector size for transfers */ + t_outlet *x_bangout; /* bang-on-done outlet */ + int x_state; /* opened, running, or idle */ + /* parameters to communicate with subthread */ + int x_requestcode; /* pending request from parent to I/O thread */ + char *x_filename; /* file to open (string is permanently allocated) */ + int x_fileerror; /* slot for "errno" return */ + int x_skipheaderbytes; /* size of header we'll skip */ + int x_bytespersample; /* bytes per sample (2 or 3) */ + int x_bigendian; /* true if file is big-endian */ + int x_sfchannels; /* number of channels in soundfile */ + long x_onsetframes; /* number of sample frames to skip */ + long x_bytelimit; /* max number of data bytes to read */ + int x_fd; /* filedesc */ + int x_fifosize; /* buffer size appropriately rounded down */ + int x_fifohead; /* index of next byte to get from file */ + int x_fifotail; /* index of next byte the ugen will read */ + int x_eof; /* true if fifohead has stopped changing */ + int x_sigcountdown; /* counter for signalling child for more data */ + int x_sigperiod; /* number of ticks per signal */ + int x_filetype; /* writesf~ only; type of file to create */ + int x_itemswritten; /* writesf~ only; items writen */ + int x_swap; /* writesf~ only; true if byte swapping */ + float x_f; /* writesf~ only; scalar for signal inlet */ + /*----HACK------*/ + float x_speed; /*speed of reading*/ + float x_frac; /*fractionnal part of sample to play next buffer*/ + + pthread_mutex_t x_mutex; + pthread_cond_t x_requestcondition; + pthread_cond_t x_answercondition; + pthread_t x_childthread; +} t_readsf; + + +/************** the child thread which performs file I/O ***********/ + +#if 0 +static void pute(char *s) /* debug routine */ +{ + write(2, s, strlen(s)); +} +#else +#define pute(x) +#endif + +#if 1 +#define sfread_cond_wait pthread_cond_wait +#define sfread_cond_signal pthread_cond_signal +#else +#include <sys/time.h> /* debugging version... */ +#include <sys/types.h> +static void readsf_fakewait(pthread_mutex_t *b) +{ + struct timeval timout; + timout.tv_sec = 0; + timout.tv_usec = 1000000; + pthread_mutex_unlock(b); + select(0, 0, 0, 0, &timout); + pthread_mutex_lock(b); +} + +static void readsf_banana( void) +{ + struct timeval timout; + timout.tv_sec = 0; + timout.tv_usec = 200000; + pute("banana1\n"); + select(0, 0, 0, 0, &timout); + pute("banana2\n"); +} + + +#define sfread_cond_wait(a,b) readsf_fakewait(b) +#define sfread_cond_signal(a) +#endif + +static void *readsf_child_main(void *zz) +{ + t_readsf *x = zz; + pute("1\n"); + pthread_mutex_lock(&x->x_mutex); + while (1) + { + int fd, fifohead; + char *buf; + pute("0\n"); + if (x->x_requestcode == REQUEST_NOTHING) + { + pute("wait 2\n"); + sfread_cond_signal(&x->x_answercondition); + sfread_cond_wait(&x->x_requestcondition, &x->x_mutex); + pute("3\n"); + } + else if (x->x_requestcode == REQUEST_OPEN) + { + char boo[80]; + int sysrtn, wantbytes; + + /* copy file stuff out of the data structure so we can + relinquish the mutex while we're in open_soundfile(). */ + long onsetframes = x->x_onsetframes; + long bytelimit = 0x7fffffff; + int skipheaderbytes = x->x_skipheaderbytes; + int bytespersample = x->x_bytespersample; + int sfchannels = x->x_sfchannels; + int bigendian = x->x_bigendian; + char *filename = x->x_filename; + char *dirname = canvas_getdir(x->x_canvas)->s_name; + /* alter the request code so that an ensuing "open" will get + noticed. */ + pute("4\n"); + x->x_requestcode = REQUEST_BUSY; + x->x_fileerror = 0; + + /* if there's already a file open, close it */ + if (x->x_fd >= 0) + { + fd = x->x_fd; + pthread_mutex_unlock(&x->x_mutex); + close (fd); + pthread_mutex_lock(&x->x_mutex); + x->x_fd = -1; + if (x->x_requestcode != REQUEST_BUSY) + goto lost; + } + /* open the soundfile with the mutex unlocked */ + pthread_mutex_unlock(&x->x_mutex); + fd = open_soundfile(dirname, filename, + skipheaderbytes, &bytespersample, &bigendian, + &sfchannels, &bytelimit, onsetframes); + pthread_mutex_lock(&x->x_mutex); + + pute("5\n"); + /* copy back into the instance structure. */ + x->x_bytespersample = bytespersample; + x->x_sfchannels = sfchannels; + x->x_bigendian = bigendian; + x->x_fd = fd; + x->x_bytelimit = bytelimit; + if (fd < 0) + { + x->x_fileerror = errno; + x->x_eof = 1; + pute("open failed\n"); + pute(filename); + pute(dirname); + goto lost; + } + /* check if another request has been made; if so, field it */ + if (x->x_requestcode != REQUEST_BUSY) + goto lost; + pute("6\n"); + x->x_fifohead = 0; + /* set fifosize from bufsize. fifosize must be a + multiple of the number of bytes eaten for each DSP + tick. We pessimistically assume MAXVECSIZE samples + per tick since that could change. There could be a + problem here if the vector size increases while a + soundfile is being played... */ + x->x_fifosize = x->x_bufsize - (x->x_bufsize % + (x->x_bytespersample * x->x_sfchannels * MAXVECSIZE)); + /* arrange for the "request" condition to be signalled 16 + times per buffer */ + sprintf(boo, "fifosize %d\n", + x->x_fifosize); + pute(boo); + x->x_sigcountdown = x->x_sigperiod = + (x->x_fifosize / + (16 * x->x_bytespersample * x->x_sfchannels * + x->x_vecsize)); + /* in a loop, wait for the fifo to get hungry and feed it */ + + while (x->x_requestcode == REQUEST_BUSY) + { + int fifosize = x->x_fifosize; + pute("77\n"); + if (x->x_eof) + break; + if (x->x_fifohead >= x->x_fifotail) + { + /* if the head is >= the tail, we can immediately read + to the end of the fifo. Unless, that is, we would + read all the way to the end of the buffer and the + "tail" is zero; this would fill the buffer completely + which isn't allowed because you can't tell a completely + full buffer from an empty one. */ + if (x->x_fifotail || (fifosize - x->x_fifohead > READSIZE)) + { + wantbytes = fifosize - x->x_fifohead; + if (wantbytes > READSIZE) + wantbytes = READSIZE; + if (wantbytes > x->x_bytelimit) + wantbytes = x->x_bytelimit; + sprintf(boo, "head %d, tail %d, size %d\n", + x->x_fifohead, x->x_fifotail, wantbytes); + pute(boo); + } + else + { + pute("wait 7a ...\n"); + sfread_cond_signal(&x->x_answercondition); + pute("signalled\n"); + sfread_cond_wait(&x->x_requestcondition, + &x->x_mutex); + pute("7a done\n"); + continue; + } + } + else + { + /* otherwise check if there are at least READSIZE + bytes to read. If not, wait and loop back. */ + wantbytes = x->x_fifotail - x->x_fifohead - 1; + if (wantbytes < READSIZE) + { + pute("wait 7...\n"); + sfread_cond_signal(&x->x_answercondition); + sfread_cond_wait(&x->x_requestcondition, + &x->x_mutex); + pute("7 done\n"); + continue; + } + else wantbytes = READSIZE; + } + pute("8\n"); + fd = x->x_fd; + buf = x->x_buf; + fifohead = x->x_fifohead; + pthread_mutex_unlock(&x->x_mutex); + sysrtn = read(fd, buf + fifohead, wantbytes); + pthread_mutex_lock(&x->x_mutex); + if (x->x_requestcode != REQUEST_BUSY) + break; + if (sysrtn < 0) + { + pute("fileerror\n"); + x->x_fileerror = errno; + break; + } + else if (sysrtn == 0) + { + x->x_eof = 1; + break; + } + else + { + x->x_fifohead += sysrtn; + x->x_bytelimit -= sysrtn; + if (x->x_bytelimit <= 0) + { + x->x_eof = 1; + break; + } + if (x->x_fifohead == fifosize) + x->x_fifohead = 0; + } + sprintf(boo, "after: head %d, tail %d\n", + x->x_fifohead, x->x_fifotail); + pute(boo); + /* signal parent in case it's waiting for data */ + sfread_cond_signal(&x->x_answercondition); + } + lost: + + if (x->x_requestcode == REQUEST_BUSY) + x->x_requestcode = REQUEST_NOTHING; + /* fell out of read loop: close file if necessary, + set EOF and signal once more */ + if (x->x_fd >= 0) + { + fd = x->x_fd; + pthread_mutex_unlock(&x->x_mutex); + close (fd); + pthread_mutex_lock(&x->x_mutex); + x->x_fd = -1; + } + sfread_cond_signal(&x->x_answercondition); + + } + else if (x->x_requestcode == REQUEST_CLOSE) + { + if (x->x_fd >= 0) + { + fd = x->x_fd; + pthread_mutex_unlock(&x->x_mutex); + close (fd); + pthread_mutex_lock(&x->x_mutex); + x->x_fd = -1; + } + if (x->x_requestcode == REQUEST_CLOSE) + x->x_requestcode = REQUEST_NOTHING; + sfread_cond_signal(&x->x_answercondition); + } + else if (x->x_requestcode == REQUEST_QUIT) + { + if (x->x_fd >= 0) + { + fd = x->x_fd; + pthread_mutex_unlock(&x->x_mutex); + close (fd); + pthread_mutex_lock(&x->x_mutex); + x->x_fd = -1; + } + x->x_requestcode = REQUEST_NOTHING; + sfread_cond_signal(&x->x_answercondition); + break; + } + else + { + pute("13\n"); + } + } + pute("thread exit\n"); + pthread_mutex_unlock(&x->x_mutex); + return (0); +} + +/******** the object proper runs in the calling (parent) thread ****/ + +static void readsf_tick(t_readsf *x); + +static void *readsf_new(t_floatarg fnchannels, t_floatarg fbufsize) +{ + t_readsf *x; + int nchannels = fnchannels, bufsize = fbufsize, i; + char *buf; + + if (nchannels < 1) + nchannels = 1; + else if (nchannels > MAXSFCHANS) + nchannels = MAXSFCHANS; + if (bufsize <= 0) bufsize = DEFBUFPERCHAN * nchannels; + else if (bufsize < MINBUFSIZE) + bufsize = MINBUFSIZE; + else if (bufsize > MAXBUFSIZE) + bufsize = MAXBUFSIZE; + buf = getbytes(bufsize); + if (!buf) return (0); + + x = (t_readsf *)pd_new(readsfv_class); + + for (i = 0; i < nchannels; i++) + outlet_new(&x->x_obj, gensym("signal")); + x->x_noutlets = nchannels; + x->x_bangout = outlet_new(&x->x_obj, &s_bang); + pthread_mutex_init(&x->x_mutex, 0); + pthread_cond_init(&x->x_requestcondition, 0); + pthread_cond_init(&x->x_answercondition, 0); + x->x_vecsize = MAXVECSIZE; + x->x_state = STATE_IDLE; + x->x_clock = clock_new(x, (t_method)readsf_tick); + x->x_canvas = canvas_getcurrent(); + x->x_bytespersample = 2; + x->x_sfchannels = 1; + x->x_fd = -1; + x->x_buf = buf; + x->x_bufsize = bufsize; + x->x_fifosize = x->x_fifohead = x->x_fifotail = x->x_requestcode = 0; + pthread_create(&x->x_childthread, 0, readsf_child_main, x); + return (x); +} + +static void readsf_tick(t_readsf *x) +{ + outlet_bang(x->x_bangout); +} + +static t_int *readsf_perform(t_int *w) +{ + t_readsf *x = (t_readsf *)(w[1]); + int vecsize = x->x_vecsize, noutlets = x->x_noutlets, i, j, + bytespersample = x->x_bytespersample, + bigendian = x->x_bigendian,wantsamples; + float *fp,tmp,speed=x->x_speed; + if (x->x_state == STATE_STREAM) + { + int wantbytes, nchannels, sfchannels = x->x_sfchannels; + pthread_mutex_lock(&x->x_mutex); + tmp=vecsize *speed+x->x_frac; + wantsamples=(int)tmp; + x->x_frac=tmp-wantsamples; + + if(!speed) goto idle; + + wantbytes = sfchannels * wantsamples * bytespersample; + + while ( + !x->x_eof && x->x_fifohead >= x->x_fifotail && + x->x_fifohead < x->x_fifotail + wantbytes-1) + { + pute("wait...\n"); + sfread_cond_signal(&x->x_requestcondition); + sfread_cond_wait(&x->x_answercondition, &x->x_mutex); + pute("done\n"); + } + if (x->x_eof && x->x_fifohead >= x->x_fifotail && + x->x_fifohead < x->x_fifotail + wantbytes-1) + { + if (x->x_fileerror) + { + pd_error(x, "dsp: %s: %s", x->x_filename, + (x->x_fileerror == EIO ? + "unknown or bad header format" : + strerror(x->x_fileerror))); + } + clock_delay(x->x_clock, 0); + x->x_state = STATE_IDLE; + sfread_cond_signal(&x->x_requestcondition); + pthread_mutex_unlock(&x->x_mutex); + goto idle; + } + + if(speed==1) + soundfile_xferin(sfchannels, noutlets, x->x_outvec, 0, + (unsigned char *)(x->x_buf + x->x_fifotail), vecsize, + bytespersample, bigendian); + else { + soundfile_xferin(sfchannels, noutlets, tmpvec, 0, + (unsigned char *)(x->x_buf + x->x_fifotail), wantsamples, + bytespersample, bigendian); + interpolate(noutlets,tmpvec,wantsamples,x->x_outvec,vecsize); + } + + x->x_fifotail += wantbytes; + if (x->x_fifotail >= x->x_fifosize) + x->x_fifotail = 0; + if ((--x->x_sigcountdown) <= 0) + { + sfread_cond_signal(&x->x_requestcondition); + x->x_sigcountdown = x->x_sigperiod; + } + pthread_mutex_unlock(&x->x_mutex); + } + else + { + idle: + for (i = 0; i < noutlets; i++) + for (j = vecsize, fp = x->x_outvec[i]; j--; ) + *fp++ = 0; + } + return (w+2); +} + +static void readsf_start(t_readsf *x) +{ + /* start making output. If we're in the "startup" state change + to the "running" state. */ + if (x->x_state == STATE_STARTUP) + x->x_state = STATE_STREAM; + else pd_error(x, "readsf: start requested with no prior 'open'"); +} + +static void readsf_stop(t_readsf *x) +{ + /* LATER rethink whether you need the mutex just to set a variable? */ + pthread_mutex_lock(&x->x_mutex); + x->x_state = STATE_IDLE; + x->x_requestcode = REQUEST_CLOSE; + sfread_cond_signal(&x->x_requestcondition); + pthread_mutex_unlock(&x->x_mutex); +} + +static void readsf_float(t_readsf *x, t_floatarg f) +{ + if (f != 0) + readsf_start(x); + else readsf_stop(x); +} + +static void readsf_speed(t_readsf *x, t_floatarg f) +{ + if((f>=0)&&(f<=8)) + x->x_speed=f; +} + + /* open method. Called as: + open filename [skipframes headersize channels bytespersamp endianness] + (if headersize is zero, header is taken to be automatically + detected; thus, use the special "-1" to mean a truly headerless file.) + */ + +static void readsf_open(t_readsf *x, t_symbol *s, int argc, t_atom *argv) +{ + t_symbol *filesym = atom_getsymbolarg(0, argc, argv); + t_float onsetframes = atom_getfloatarg(1, argc, argv); + t_float headerbytes = atom_getfloatarg(2, argc, argv); + t_float channels = atom_getfloatarg(3, argc, argv); + t_float bytespersamp = atom_getfloatarg(4, argc, argv); + t_symbol *endian = atom_getsymbolarg(5, argc, argv); + if (!*filesym->s_name) + return; + pthread_mutex_lock(&x->x_mutex); + x->x_requestcode = REQUEST_OPEN; + x->x_filename = filesym->s_name; + x->x_fifotail = 0; + x->x_fifohead = 0; + if (*endian->s_name == 'b') + x->x_bigendian = 1; + else if (*endian->s_name == 'l') + x->x_bigendian = 0; + else if (*endian->s_name) + pd_error(x, "endianness neither 'b' nor 'l'"); + else x->x_bigendian = garray_ambigendian(); + x->x_onsetframes = (onsetframes > 0 ? onsetframes : 0); + x->x_skipheaderbytes = (headerbytes > 0 ? headerbytes : + (headerbytes == 0 ? -1 : 0)); + x->x_sfchannels = (channels >= 1 ? channels : 1); + x->x_bytespersample = (bytespersamp > 2 ? bytespersamp : 2); + x->x_eof = 0; + x->x_fileerror = 0; + x->x_state = STATE_STARTUP; + x->x_speed=1; + x->x_frac=0; + sfread_cond_signal(&x->x_requestcondition); + pthread_mutex_unlock(&x->x_mutex); +} + +static void readsf_dsp(t_readsf *x, t_signal **sp) +{ + int i, noutlets = x->x_noutlets; + pthread_mutex_lock(&x->x_mutex); + x->x_vecsize = sp[0]->s_n; + + x->x_sigperiod = (x->x_fifosize / + (x->x_bytespersample * x->x_sfchannels * x->x_vecsize)); + for (i = 0; i < noutlets; i++) + x->x_outvec[i] = sp[i]->s_vec; + pthread_mutex_unlock(&x->x_mutex); + dsp_add(readsf_perform, 1, x); +} + +static void readsf_print(t_readsf *x) +{ + post("state %d", x->x_state); + post("fifo head %d", x->x_fifohead); + post("fifo tail %d", x->x_fifotail); + post("fifo size %d", x->x_fifosize); + post("fd %d", x->x_fd); + post("eof %d", x->x_eof); +} + +static void readsf_free(t_readsf *x) +{ + /* request QUIT and wait for acknowledge */ + void *threadrtn; + pthread_mutex_lock(&x->x_mutex); + x->x_requestcode = REQUEST_QUIT; + post("stopping readsf thread..."); + sfread_cond_signal(&x->x_requestcondition); + while (x->x_requestcode != REQUEST_NOTHING) + { + post("signalling..."); + sfread_cond_signal(&x->x_requestcondition); + sfread_cond_wait(&x->x_answercondition, &x->x_mutex); + } + pthread_mutex_unlock(&x->x_mutex); + if (pthread_join(x->x_childthread, &threadrtn)) + error("readsf_free: join failed"); + post("... done."); + + pthread_cond_destroy(&x->x_requestcondition); + pthread_cond_destroy(&x->x_answercondition); + pthread_mutex_destroy(&x->x_mutex); + freebytes(x->x_buf, x->x_bufsize); + clock_free(x->x_clock); +} + +#endif /* __linux__ */ + +void readsfv_tilde_setup(void) +{ +#ifdef __linux__ + int i; + + readsfv_class = class_new(gensym("readsfv~"), (t_newmethod)readsf_new, + (t_method)readsf_free, sizeof(t_readsf), 0, A_DEFFLOAT, A_DEFFLOAT, 0); + + class_addfloat(readsfv_class, (t_method)readsf_float); + class_addmethod(readsfv_class, (t_method)readsf_speed, gensym("speed"), A_FLOAT,0); + class_addmethod(readsfv_class, (t_method)readsf_start, gensym("start"), 0); + class_addmethod(readsfv_class, (t_method)readsf_stop, gensym("stop"), 0); + class_addmethod(readsfv_class, (t_method)readsf_dsp, gensym("dsp"), 0); + class_addmethod(readsfv_class, (t_method)readsf_open, gensym("open"), + A_GIMME, 0); + class_addmethod(readsfv_class, (t_method)readsf_print, gensym("print"), 0); + + for(i=0;i<MAXSFCHANS;i++) + tmpvec[i]=getbytes(sizeof(t_sample)*8*1024); +#endif /* __linux__ */ +} + + + + diff --git a/relativepath.c b/relativepath.c new file mode 100644 index 0000000..f599222 --- /dev/null +++ b/relativepath.c @@ -0,0 +1,146 @@ +/* +Copyright (C) 2002 Antoine Rousseau + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +/*#include <m_imp.h>*/ +#include "m_pd.h" +#include "g_canvas.h" + +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> +#include <libgen.h> +#include <string.h> + +extern t_canvas *canvas_list; /* list of all root canvases */ +extern int canvas_getdollarzero( void); + +struct _canvasenvironment +{ + t_symbol *ce_dir; /* directory patch lives in */ + int ce_argc; /* number of "$" arguments */ + t_atom *ce_argv; /* array of "$" arguments */ + int ce_dollarzero; /* value of "$0" */ +}; + +typedef struct _relativepath +{ + t_object x_obj; + t_canvas *x_canvas; + int x_dolzero; + int x_realized; +}t_relativepath; + +t_class *relativepath_class; + +void relativepath_setup(void); + +static t_glist *getcanvas(t_glist *can,int d0) +{ + t_canvas *retcan=0; + t_gobj *ob; + + if((can->gl_env)&&(can->gl_env->ce_dollarzero==d0)){ + return can; + } + + ob=can->gl_list; + while(ob&&(retcan==0)) { + if (pd_class(&ob->g_pd) == canvas_class) + retcan=getcanvas((t_glist *)ob,d0); + ob=ob->g_next; + } + + if((!retcan)&&(can->gl_next)) retcan=getcanvas((t_glist *)can->gl_next,d0); + return retcan; +} + +static void relativepath_symbol(t_relativepath *x,t_symbol *sym) +{ + t_canvas *can=0; + t_symbol *s=sym; + char *instr=sym->s_name,*outstr=instr, + *candir, + canname[MAXPDSTRING],totaldir[MAXPDSTRING], + *cnamedir; + unsigned int n,i=0; + + if(!x->x_realized) can=(t_canvas*)getcanvas(canvas_list,x->x_dolzero); + if(can) { + x->x_canvas = can; + x->x_realized = 1; + //post("found $0 canvas : %x %d ",x->x_canvas, x->x_canvas->gl_env->ce_dollarzero ); + } + + if(!instr) return; + + candir=canvas_getdir(x->x_canvas)->s_name; + if(!candir) candir=""; + + strcpy(canname,x->x_canvas->gl_name->s_name); + //post("canname=%s",canname); + cnamedir=dirname(canname); + + if (strcmp(cnamedir,".")) { + sprintf(totaldir,"%s/%s",candir,cnamedir); + } + else + strcpy(totaldir,candir); + + //post("dir=%s",totaldir); + + n=strlen(totaldir); + if(strlen(instr)<=n) goto end; + + while(i<n) { + if(instr[i]!=totaldir[i]) goto end; + i++; + } + + if(instr[n]=='/'){ + outstr=strdup(instr+n+1); + s=gensym(outstr); + } + +end: + outlet_symbol(x->x_obj.ob_outlet,s); +} + + +static void *relativepath_new(t_float dolzero) +{ + t_relativepath *x = (t_relativepath *)pd_new(relativepath_class); + int d0; + + outlet_new(&x->x_obj, 0); + x->x_canvas = canvas_getcurrent(); + x->x_dolzero = dolzero; + x->x_realized=dolzero?0:1; + + return (void *)x; +} + +void relativepath_setup(void) +{ + relativepath_class = class_new(gensym("relativepath"),(t_newmethod)relativepath_new, + 0, sizeof(t_relativepath), 0,A_DEFFLOAT,0); + + class_addsymbol(relativepath_class, relativepath_symbol); +} + @@ -0,0 +1,53 @@ +/* +Copyright (C) 2002 Antoine Rousseau + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include "m_pd.h" +#include <stdlib.h> + +typedef struct _s2f +{ + t_object x_obj; +}t_s2f; + +t_class *s2f_class; + +void s2f_setup(void); + +static void s2f_symbol(t_s2f *x,t_symbol *sym) +{ + if(!sym->s_name) return; + + outlet_float(x->x_obj.ob_outlet,(float)strtod(sym->s_name,0)); +} + +static void *s2f_new(void) +{ + t_s2f *x = (t_s2f *)pd_new(s2f_class); + outlet_new(&x->x_obj, &s_float); + return (void *)x; +} + +void s2f_setup(void) +{ + s2f_class = class_new(gensym("s2f"),(t_newmethod)s2f_new, + 0, sizeof(t_s2f), 0, 0); + + class_addsymbol(s2f_class, s2f_symbol); +} + diff --git a/sarray.c b/sarray.c new file mode 100644 index 0000000..d44f7ce --- /dev/null +++ b/sarray.c @@ -0,0 +1,264 @@ +/* +Copyright (C) 2003 Antoine Rousseau + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +/* a shared symbol array, ala "value" .*/ + +#include "m_pd.h" +#include <stdlib.h> +#include <string.h> + +static t_class *sarray_class, *scommon_class; +static t_symbol *s__; + +typedef struct scommon +{ + t_pd c_pd; + t_symbol *c_sym; + int c_refcount; + int c_len; + t_symbol **c_array; +} t_scommon; + +typedef struct _sarray +{ + t_object x_obj; + t_symbol *x_sym; + t_scommon *x_c; + //t_outlet *x_symout; + //t_outlet *x_lenout; +} t_sarray; + +/*static int scommon_find(t_scommon *x, t_symbol *s) +{ + t_sitem *si=x->first; + t_int i=1; + + while(si) { + if(!strcmp(si->s->s_name,s->s_name)) return i; + si=si->next; + i++; + } + return 0; +}*/ + +static t_symbol *scommon_get(t_scommon *x, t_float f) +{ + int i=(int)f; + + if(i<0) i=0; + if(i>=x->c_len) i=x->c_len-1; + return x->c_array[i]; +} + +static void scommon_set(t_scommon *x, t_float f, t_symbol *s) +{ + int i=(int)f; + + if((i<0)||(i>=x->c_len)) return; + x->c_array[i]=s; + //x->c_array[i]=gensym(strdup(s->s_name)); + //x->c_array[i]=gensym("ok"); +} + +static void scommon_setlen(t_scommon *x, t_float flen) +{ + int i,oldlen=x->c_len,len=flen; + + if(len<1) len=1; + x->c_len=len; + + x->c_array=realloc(x->c_array,sizeof(t_symbol *)*len); + + if(len>oldlen) for(i=oldlen;i<len;i++) x->c_array[i]=&s_; +} + +static void scommon_reset(t_scommon *x) +{ + int i; + + for(i=0;i<x->c_len;i++) x->c_array[i]=&s_; +} + +static t_atom *scommon_dump(t_scommon *x,t_symbol *s) +{ + int i; + t_atom *atombuf; + + atombuf = (t_atom *)getbytes(sizeof(t_atom)*x->c_len); + + for(i=0;i<x->c_len;i++) { + if(x->c_array[i]==&s_) SETSYMBOL(&atombuf[i],s); + else SETSYMBOL(&atombuf[i],x->c_array[i]); + } + + return atombuf; +} + +static void scommon_ff(t_scommon *x) +{ + //scommon_reset(x); + pd_unbind((t_pd*)x, x->c_sym); +} + +static void *scommon_new(t_symbol *s) +{ + t_scommon *x = (t_scommon *)pd_new(scommon_class); + + x->c_refcount = 0; + x->c_sym=s; + pd_bind((t_pd*)x, s); + + x->c_len=1; + x->c_array=malloc(sizeof(t_symbol *)*1); + scommon_reset(x); + + return (x); +} + + + /* get a pointer to a named symbol list (a "scommon" object), + which is created if necessary. */ +t_scommon *sarray_scget(t_symbol *s) +{ + t_scommon *c = (t_scommon *)pd_findbyclass(s, scommon_class); + + if (!c) c = (t_scommon *)scommon_new(s); + c->c_refcount++; + return (c); +} + + /* release a variable. This only frees the "scommon" resource when the + last interested party releases it. */ +void sarray_release(t_scommon *c) +{ + if (!--c->c_refcount) scommon_ff(c); +} + + +static void *sarray_new(t_symbol *s,t_float len) +{ + t_sarray *x = (t_sarray *)pd_new(sarray_class); + + x->x_sym = s; + x->x_c = sarray_scget(s); + if(len) scommon_setlen(x->x_c,len); + + outlet_new(&x->x_obj, &s_anything); + //x->x_symout=outlet_new(&x->x_obj, &s_anything); + //x->x_lenout=outlet_new(&x->x_obj, &s_float); + return (x); +} + +static void sarray_ff(t_sarray *x) +{ + sarray_release(x->x_c); +} + +static void sarray_print(t_sarray *x) +{ + int i; + + for(i=0;i<x->x_c->c_len;i++){ + post("item %d: %s",i,x->x_c->c_array[i]->s_name); + } +} + +static void sarray_reset(t_sarray *x) +{ + scommon_reset(x->x_c); +} + +static void sarray_set(t_sarray *x, t_symbol *sfoo,int argc, t_atom *argv) +{ + int i,j=0; + t_symbol *snull=&s_,*s; + + /*if((argc<2)||(argv[0].a_type!=A_FLOAT)) + { + error("Bad arguments for message 'set' to object 'sarray'"); + return ; + }*/ + if(argv[0].a_type==A_SYMBOL) { + snull=atom_getsymbol(&argv[0]); + j=1; + } + + if(argv[j].a_type!=A_FLOAT){ + error("Bad arguments for message 'set' to object 'sarray'"); + return ; + } + + i=atom_getfloat(&argv[j++]); + + while((j<argc)&&(argv[j].a_type==A_SYMBOL)){ + s=atom_getsymbol(&argv[j++]); + if(s==snull) s=&s_; + scommon_set(x->x_c,i++,s); + } +} + +static void sarray_get(t_sarray *x,t_float i) +{ + t_symbol *s=scommon_get(x->x_c,i); + + if(s==&s_) outlet_bang(x->x_obj.ob_outlet); + else outlet_symbol(x->x_obj.ob_outlet,scommon_get(x->x_c,i)); +} + +static void sarray_dump(t_sarray *x,t_symbol *s) +{ + t_atom *l=scommon_dump(x->x_c,s); + + outlet_list(x->x_obj.ob_outlet, &s_list, x->x_c->c_len, l); + free(l); +} + +static void sarray_setarray(t_sarray *x,t_symbol *s) +{ + sarray_release(x->x_c); + x->x_c = sarray_scget(s); + x->x_sym = s; +} + +static void sarray_setlen(t_sarray *x,t_float len) +{ + scommon_setlen(x->x_c,len); +} + + +void sarray_setup(void) +{ + s__=gensym("_"); + sarray_class = class_new(gensym("sarray"), (t_newmethod)sarray_new, + (t_method)sarray_ff, + sizeof(t_sarray), 0, A_DEFSYM, A_DEFFLOAT,0); + + //class_addbang(sarray_class, sarray_bang); + //class_addfloat(sarray_class, sarray_float); + class_addmethod(sarray_class,(t_method)sarray_set, gensym("set"),A_GIMME,0); + class_addmethod(sarray_class,(t_method)sarray_get, gensym("get"),A_FLOAT,0); + class_addmethod(sarray_class,(t_method)sarray_reset, gensym("reset"),0); + class_addmethod(sarray_class,(t_method)sarray_print, gensym("print"),0); + class_addmethod(sarray_class,(t_method)sarray_setlen, gensym("setlen"),A_FLOAT,0); + class_addmethod(sarray_class,(t_method)sarray_dump, gensym("dump"),A_DEFSYM,0); + class_addmethod(sarray_class,(t_method)sarray_setarray, gensym("setarray"),A_SYMBOL,0); + scommon_class = class_new(gensym("sarray"), 0, 0, + sizeof(t_scommon), CLASS_PD, 0); +} + diff --git a/sfread2~.c b/sfread2~.c new file mode 100644 index 0000000..aceb39e --- /dev/null +++ b/sfread2~.c @@ -0,0 +1,410 @@ +#include <m_pd.h> +//#include <m_imp.h> +#include "g_canvas.h" +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif + +#include <stdio.h> +#include <string.h> +#ifndef NT +#include <unistd.h> +#include <sys/mman.h> +#else +#include <io.h> +#endif + + +#include <fcntl.h> +#include <sys/stat.h> + +/* ------------------------ sfread~ ----------------------------- */ + +#ifdef NT +#define BINREADMODE "rb" +#else +#define BINREADMODE "r" +#endif + +static t_class *sfread_class; + + +typedef struct _sfread +{ + t_object x_obj; + void* x_mapaddr; + int x_fd; + + t_int x_play; + t_int x_outchannels; + t_int x_loop; + double x_index; //samples + t_float x_speed; //1=sample rate + t_int x_interp; + + t_int x_size; // bytes + t_int x_fchannels; // file channels + t_int x_len; // samples + t_int x_skip; //bytes + t_clock *x_clock; + + + t_glist * x_glist; + t_outlet *x_stateout; + t_outlet *x_sizeout; +} t_sfread; + +#define MAX_CHANS 4 + + + +//1 -> 2 + +//1 -> 4 + +//2 -> 4 + + +static t_int *sfread_perform(t_int *w) +{ + t_sfread* x = (t_sfread*)(w[1]); + short *fp, *buf = x->x_mapaddr+x->x_skip; +/* t_float *in = (t_float *)(w[2]); will we need this (indexing) ?*/ + int c = x->x_outchannels; + int fc = x->x_fchannels,fc2=2*fc; + double findex = x->x_index; + t_float speed = x->x_speed; + float frac, a, b, cc, d, cminusb; + int i,n,index,rindex; + int end = x->x_len -3;/* -3 is for safe interpolation*/ + t_float* out[MAX_CHANS]; + t_int in_off[MAX_CHANS]; + t_int loground=(fc==1?0:fc==2?1:2); + + if(!x->x_mapaddr) return(w+c+4); + + for (i=0;i<c;i++){ + out[i] = (t_float *)(w[3+i]); + in_off[i]=i%fc; + } + n = (int)(w[3+c]); + + /* loop */ + + if (findex > end) + findex = end; + + if (findex + n*speed > end) { // playing forward end + if (!x->x_loop) { + x->x_play=0; + findex = 0; + clock_delay(x->x_clock, 0); + } + } + + if (findex + n*speed < 1) { // playing backwards end + if (!x->x_loop) { + x->x_play=0; + findex = end; + clock_delay(x->x_clock, 0); + } + + } + + + if (x->x_play && x->x_mapaddr) { + + if (speed != 1) { /* different speed */ + if (x->x_interp) while (n--) { + index=findex; + rindex=index<<loground; + frac = findex - index; + for (i=0;i<c;i++) { + fp=buf + rindex +in_off[i]; + a = fp[-fc]; + b = fp[0]; + cc = fp[fc]; + d = fp[fc2]; + cminusb = cc-b; + *out[i]++ = 3.052689e-05* + (b + frac * (cminusb - 0.5f * (frac-1.) * + ((a - d + 3.0f * cminusb) * frac + (b - a - cminusb)))); + //*out[i]++ = *(buf+rindex+in_off[i])*3.052689e-05; + } + findex=findex+speed; + if (findex > end) { + if (x->x_loop) findex = 1; + else break; + } + if (findex < 1) { + if (x->x_loop) findex = end; + else break; + } + } + else while (n--) { + rindex=((int)findex)<<loground; + for (i=0;i<c;i++) { + *out[i]++ = *(buf+rindex+in_off[i])*3.052689e-05; + } + findex+=speed; + if (findex > end) { + if (x->x_loop) findex = 1; + else break; + } + if (findex < 1) { + if (x->x_loop) findex = end; + else break; + } + } + /* Fill with zero in case of end */ + n++; + while (n--) + for (i=0;i<c;i++) + *out[i]++ = 0; + //offset = aoff; + } + else { /* speed == 1 */ + int end2=end*fc; + rindex=((int)findex)<<loground; + while (n--) { + for (i=0;i<c;i++) { + *out[i]++ = *(buf+rindex+in_off[i])*3.052689e-05; + } + rindex+=fc; + if (rindex > end2) { + if (x->x_loop) rindex = 1; + else break; + } + } + + /* Fill with zero in case of end */ + n++; + while (n--) + for (i=0;i<c;i++) + *out[i]++ = 0.; + findex=rindex>>loground; + } + + } + else { + while (n--) { + for (i=0;i<c;i++) + *out[i]++ = 0.; + } + } + x->x_index = findex; + return (w+c+4); +} + + +static void sfread_loop(t_sfread *x, t_floatarg f) +{ + x->x_loop = f; +} + +static void sfread_interp(t_sfread *x, t_floatarg f) +{ + x->x_interp = (f!=0); +} + +static void sfread_index(t_sfread *x, t_floatarg f) +{ + x->x_index = f; +} + + +static void sfread_size(t_sfread* x) +{ + outlet_float(x->x_sizeout,x->x_len); +} + +static void sfread_state(t_sfread* x) +{ + outlet_float(x->x_stateout, x->x_play); +} + +static void sfread_float(t_sfread *x, t_floatarg f) +{ + int t = f; + if (t && x->x_mapaddr) { + x->x_play=1; + } + else { + x->x_play=0; + } + sfread_state(x); +} + + +static void sfread_bang(t_sfread* x) +{ + x->x_index = x->x_speed>0?1:x->x_len-3; + sfread_float(x,1.0); +} + + +static void sfread_dsp(t_sfread *x, t_signal **sp) +{ +/* post("sfread: dsp"); */ + switch (x->x_outchannels) { + case 1: + dsp_add(sfread_perform, 4, x, sp[0]->s_vec, + sp[1]->s_vec, sp[0]->s_n); + break; + case 2: + dsp_add(sfread_perform, 5, x, sp[0]->s_vec, + sp[1]->s_vec,sp[2]->s_vec, sp[0]->s_n); + break; + case 4: + dsp_add(sfread_perform, 6, x, sp[0]->s_vec, + sp[1]->s_vec,sp[2]->s_vec, + sp[3]->s_vec,sp[4]->s_vec, + sp[0]->s_n); + break; + } +} + + +extern int open_soundfile(const char *dirname, const char *filename, int headersize, + int *p_bytespersamp, int *p_bigendian, int *p_nchannels, long *p_bytelimit, + long skipframes); /* in pd/src/d_soundfile.c */ + + +static void sfread_open(t_sfread *x,t_symbol *filename) +{ + struct stat fstate; + char fname[MAXPDSTRING]; + int bytespersamp=0,bigendian=0,channels=0; + long bytelimit= 0x7fffffff,skipframes = 0; + + if (filename == &s_) { + post("sfread: open without filename"); + return; + } + + canvas_makefilename(glist_getcanvas(x->x_glist), filename->s_name, + fname, MAXPDSTRING); + + + /* close the old file */ + + if (x->x_mapaddr) munmap(x->x_mapaddr,x->x_size); + if (x->x_fd >= 0) close(x->x_fd); + + /*if ((x->x_fd = open(fname,O_RDONLY)) < 0)*/ + //post("fname: %s",fname); + + if ((x->x_fd = open_soundfile("",fname, -1,&bytespersamp,&bigendian, + &channels, &bytelimit,0)) < 0) + { + error("can't open %s",fname); + x->x_play = 0; + x->x_mapaddr = NULL; + return; + } + + if( ((x->x_fchannels!=1)&&(x->x_fchannels!=2)&&(x->x_fchannels!=4)) || + (bytespersamp!=2) ) + { + error("file %s error: not a 1 or 2 or 4 channels soundfile, or not a 16 bits soundfile",fname); + post("channels:%d bytes:%d ",x->x_fchannels,bytespersamp); + x->x_play = 0; + x->x_mapaddr = NULL; + return; + } + + x->x_fchannels=channels; + + /* get the size */ + + fstat(x->x_fd,&fstate); + x->x_size = (int)fstate.st_size; + x->x_skip=x->x_size-bytelimit; + x->x_len = (bytelimit)/(bytespersamp*x->x_fchannels); + + //post("bytelimit=%d x->x_size-x->x_skip=%d x->x_size=%d x->x_skip=%d",bytelimit,x->x_size-x->x_skip,x->x_size,x->x_skip); + + /* map the file into memory */ + + if (!(x->x_mapaddr = mmap(NULL,x->x_size,PROT_READ,MAP_PRIVATE,x->x_fd,0))) + { + error("can't mmap %s",fname); + return; + } + sfread_size(x); +} + +static void *sfread_new(t_floatarg chan,t_floatarg interp) +{ + t_sfread *x = (t_sfread *)pd_new(sfread_class); + t_int c = chan; + + x->x_glist = (t_glist*) canvas_getcurrent(); + + if (c<1 || c > MAX_CHANS) c = 1; + floatinlet_new(&x->x_obj, &x->x_speed); + + + x->x_fd = -1; + x->x_mapaddr = NULL; + + x->x_size = 0; + x->x_len = 0; + x->x_loop = 0; + x->x_outchannels = c; + x->x_fchannels = 1; + x->x_mapaddr=NULL; + x->x_index = 1; + x->x_skip = 0; + x->x_speed = 1.0; + x->x_play = 0; + x->x_interp = (interp!=0); + x->x_clock = clock_new(x, (t_method)sfread_state); + + while (c--) { + outlet_new(&x->x_obj, gensym("signal")); + } + + x->x_stateout = outlet_new(&x->x_obj, &s_float); + x->x_sizeout = outlet_new(&x->x_obj, &s_float); + +/* post("sfread: x_channels = %d, x_speed = %f",x->x_channels,x->x_speed);*/ + + return (x); +} + +static void sfread_free(t_sfread *x) +{ + clock_free(x->x_clock); +} + +void sfread2_tilde_setup(void) +{ + /* sfread */ + + sfread_class = class_new(gensym("sfread2~"), (t_newmethod)sfread_new, + (t_method)sfread_free,sizeof(t_sfread), 0,A_DEFFLOAT,A_DEFFLOAT,0); + + class_addmethod(sfread_class, nullfn, gensym("signal"), 0); + class_addmethod(sfread_class, (t_method) sfread_dsp, gensym("dsp"), 0); + class_addmethod(sfread_class, (t_method) sfread_open, gensym("open"), A_SYMBOL,A_NULL); + class_addmethod(sfread_class, (t_method) sfread_size, gensym("size"), 0); + class_addmethod(sfread_class, (t_method) sfread_state, gensym("state"), 0); + class_addfloat(sfread_class, sfread_float); + class_addbang(sfread_class,sfread_bang); + class_addmethod(sfread_class,(t_method)sfread_loop,gensym("loop"),A_FLOAT,A_NULL); + class_addmethod(sfread_class,(t_method)sfread_interp,gensym("interp"),A_FLOAT,A_NULL); + class_addmethod(sfread_class,(t_method)sfread_index,gensym("index"),A_FLOAT,A_NULL); + + + // Impossible with pd-0.35 because it leaves super-user mode. + //if(munlockall()) perror("munlockall()"); + //if(mlockall(MCL_CURRENT)) perror("mlockall(MCL_CURRENT)"); +} + + + + + + @@ -0,0 +1,233 @@ +/* +Copyright (C) 2003 Antoine Rousseau + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +/* a shared symbol list, ala "value" .*/ + +#include <m_pd.h> +#include <stdlib.h> +#include <string.h> + +static t_class *slist_class, *scommon_class; + +typedef struct _sitem t_sitem; + +struct _sitem +{ + t_sitem *next; + t_symbol *s; +}; + +typedef struct scommon +{ + t_pd c_pd; + t_symbol *c_sym; + int c_refcount; + t_sitem *first; +} t_scommon; + +typedef struct _slist +{ + t_object x_obj; + t_symbol *x_sym; + t_scommon *x_c; + t_outlet *x_symout; + t_outlet *x_lenout; +} t_slist; + + +static void sitem_delete(t_sitem **x) +{ + t_sitem *next=(*x)->next; + + //freebytes((*x)->name,strlen((*x)->name)+1); + freebytes(*x,sizeof(t_sitem)); + (*x)=next; +} + +static void sitem_add(t_sitem **x,t_symbol *s) +{ + t_int l; + t_sitem *newone=getbytes(sizeof(t_sitem)); + + //newone->name=getbytes(l=(strlen(s->s_name)+1)); + //strncpy(newone->name,s->s_name,l); + newone->s=s; + newone->next=0; + + while(*x) x=&((*x)->next); + + *x=newone; +} + +static void *scommon_new(t_symbol *s) +{ + t_scommon *x = (t_scommon *)pd_new(scommon_class); + + x->c_refcount = 0; + x->c_sym=s; + pd_bind((t_pd*)x, s); + + x->first=0; + + return (x); +} + +static int scommon_find(t_scommon *x, t_symbol *s) +{ + t_sitem *si=x->first; + t_int i=1; + + while(si) { + if(!strcmp(si->s->s_name,s->s_name)) return i; + si=si->next; + i++; + } + return 0; +} + +static void scommon_add(t_scommon *x, t_symbol *s) +{ + sitem_add(&x->first,s); +} + +static void scommon_reset(t_scommon *x) +{ + while(x->first) sitem_delete(&x->first); +} + +static void scommon_ff(t_scommon *x) +{ + scommon_reset(x); + pd_unbind((t_pd*)x, x->c_sym); +} + + + /* get a pointer to a named symbol list (a "scommon" object), + which is created if necessary. */ +t_scommon *slist_get(t_symbol *s) +{ + t_scommon *c = (t_scommon *)pd_findbyclass(s, scommon_class); + + if (!c) c = (t_scommon *)scommon_new(s); + c->c_refcount++; + return (c); +} + + /* release a variable. This only frees the "scommon" resource when the + last interested party releases it. */ +void slist_release(t_scommon *c) +{ + if (!--c->c_refcount) scommon_ff(c); +} + + +static void *slist_new(t_symbol *s) +{ + t_slist *x = (t_slist *)pd_new(slist_class); + x->x_sym = s; + x->x_c = slist_get(s); + outlet_new(&x->x_obj, &s_float); + x->x_symout=outlet_new(&x->x_obj, &s_symbol); + x->x_lenout=outlet_new(&x->x_obj, &s_float); + return (x); +} + +static void slist_ff(t_slist *x) +{ + slist_release(x->x_c); +} + +static void slist_print(t_slist *x) +{ + t_sitem *t=x->x_c->first; + int i=0; + + while(t){ + post("item %d: %s",++i,t->s->s_name); + t=t->next; + } +} + +static void slist_reset(t_slist *x) +{ + scommon_reset(x->x_c); +} + +static void slist_add(t_slist *x,t_symbol *s) +{ + scommon_add(x->x_c,s); +} + +static void slist_find(t_slist *x,t_symbol *s) +{ + outlet_float(x->x_obj.ob_outlet,scommon_find(x->x_c,s)); +} + +static void slist_setlist(t_slist *x,t_symbol *s) +{ + slist_release(x->x_c); + x->x_c = slist_get(s); +} + +static void slist_float(t_slist *x, t_float f) +{ + t_sitem *t=x->x_c->first; + int i=0; + + if(!f) return; + + while(t&&((++i)!=f)){ + t=t->next; + } + + if(t) outlet_symbol(x->x_symout,t->s); +} + +static void slist_len(t_slist *x) +{ + t_sitem *t=x->x_c->first; + int i=0; + + while(t){ + t=t->next; + i++; + } + + outlet_float(x->x_lenout,i); +} + + +void slist_setup(void) +{ + slist_class = class_new(gensym("slist"), (t_newmethod)slist_new, + (t_method)slist_ff, + sizeof(t_slist), 0, A_DEFSYM, 0); + + //class_addbang(slist_class, slist_bang); + class_addfloat(slist_class, slist_float); + class_addmethod(slist_class,(t_method)slist_add, gensym("add"),A_SYMBOL,0); + class_addmethod(slist_class,(t_method)slist_find, gensym("find"),A_SYMBOL,0); + class_addmethod(slist_class,(t_method)slist_setlist, gensym("setlist"),A_SYMBOL,0); + class_addmethod(slist_class,(t_method)slist_reset, gensym("reset"),0); + class_addmethod(slist_class,(t_method)slist_print, gensym("print"),0); + class_addmethod(slist_class,(t_method)slist_len, gensym("len"),0); + scommon_class = class_new(gensym("slist"), 0, 0, + sizeof(t_scommon), CLASS_PD, 0); +} + @@ -0,0 +1,213 @@ +/* +Copyright (C) 2004 Antoine Rousseau +all material Copyright (c) 1997-1999 Miller Puckette. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +/* a "sweet" saw generator, as described in pddoc/3.audio/K05.bandlimited .*/ + +#include "m_pd.h" +#include "math.h" +#include <stdlib.h> + +#define UNITBIT32 1572864. /* 3*2^19; bit 32 has place value 1 */ + + /* machine-dependent definitions. These ifdefs really + should have been by CPU type and not by operating system! */ +#ifdef IRIX + /* big-endian. Most significant byte is at low address in memory */ +#define HIOFFSET 0 /* word offset to find MSB */ +#define LOWOFFSET 1 /* word offset to find LSB */ +#define int32 long /* a data type that has 32 bits */ +#else +#ifdef MSW + /* little-endian; most significant byte is at highest address */ +#define HIOFFSET 1 +#define LOWOFFSET 0 +#define int32 long +#else +#ifdef __FreeBSD__ +#include <machine/endian.h> +#if BYTE_ORDER == LITTLE_ENDIAN +#define HIOFFSET 1 +#define LOWOFFSET 0 +#else +#define HIOFFSET 0 /* word offset to find MSB */ +#define LOWOFFSET 1 /* word offset to find LSB */ +#endif /* BYTE_ORDER */ +#include <sys/types.h> +#define int32 int32_t +#endif +#ifdef __linux__ + +#include <endian.h> + +#if !defined(__BYTE_ORDER) || !defined(__LITTLE_ENDIAN) +#error No byte order defined +#endif + +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define HIOFFSET 1 +#define LOWOFFSET 0 +#else +#define HIOFFSET 0 /* word offset to find MSB */ +#define LOWOFFSET 1 /* word offset to find LSB */ +#endif /* __BYTE_ORDER */ + +#include <sys/types.h> +#define int32 int32_t + +#else +#ifdef MACOSX +#define HIOFFSET 0 /* word offset to find MSB */ +#define LOWOFFSET 1 /* word offset to find LSB */ +#define int32 int /* a data type that has 32 bits */ + +#endif /* MACOSX */ +#endif /* __linux__ */ +#endif /* MSW */ +#endif /* SGI */ + +union tabfudge +{ + double tf_d; + int32 tf_i[2]; +}; + + +/* -------------------------- ssaw~ ------------------------------ */ +static t_class *ssaw_class, *scalarssaw_class; +static float ssaw_array[1002]; +#define SAW_ARRAY_LEN 1002 + +typedef struct _ssaw +{ + t_object x_obj; + //from phasor~: + double x_phase; + float x_conv; + float x_f; /* scalar frequency */ + float x_band; /* band limit (Hertz)*/ +} t_ssaw; + +static void *ssaw_new(t_floatarg f) +{ + t_ssaw *x = (t_ssaw *)pd_new(ssaw_class); + x->x_f = f; + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("ft1")); + x->x_phase = 0; + x->x_conv = 0; + x->x_band = 22000; + outlet_new(&x->x_obj, gensym("signal")); + return (x); +} + +static t_int *ssaw_perform(t_int *w) +{ + t_ssaw *x = (t_ssaw *)(w[1]); + t_float *in = (t_float *)(w[2]); + t_float *out = (t_float *)(w[3]); + int i,n = (int)(w[4]); + double dphase = x->x_phase + UNITBIT32; + union tabfudge tf; + int normhipart; + float conv = x->x_conv; + float band=x->x_band*.33; + float *buf = ssaw_array; + + tf.tf_d = UNITBIT32; + normhipart = tf.tf_i[HIOFFSET]; + tf.tf_d = dphase; + + for (i = 0; i < n; i++) + //while (n--) + { + float phase,band2,findex /*= *in++*/; + int index /*= findex*/; + float frac, a, b, c, d, cminusb, *fp; + + tf.tf_i[HIOFFSET] = normhipart; + band2=abs(*in); + if(band2>999999) band2=999999; else if(band2<1) band2=1; + band2=band/band2; + dphase += *in++ * conv; + /**out++*/phase = (tf.tf_d - UNITBIT32)-0.5; + tf.tf_d = dphase; + + findex=phase*band2; + if(findex>0.5) findex=0.5; else if(findex<-0.5) findex=-0.5; + + /*findex=findex*1000+501; + index=findex;*/ + /*if (index < 1) + index = 1, frac = 0; + else if (index > maxindex) + index = maxindex, frac = 1; + else*/ frac = findex - index; + /*fp = buf + index; + a = fp[-1]; + b = fp[0]; + c = fp[1]; + d = fp[2]; + cminusb = c-b; + *out++ = 0.5+ phase - ( + b + frac * ( cminusb - 0.1666667f * (1.-frac) * ( + (d - a - 3.0f * cminusb) * frac + (d + 2.0f*a - 3.0f*b))) + );*/ + *out++ = 0.5+ phase - buf[(int)(findex*1000+501)]; + } + + tf.tf_i[HIOFFSET] = normhipart; + x->x_phase = tf.tf_d - UNITBIT32; + return (w+5); +} + +static void ssaw_dsp(t_ssaw *x, t_signal **sp) +{ + x->x_conv = 1./sp[0]->s_sr; + dsp_add(ssaw_perform, 4, x, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n); +} + +static void ssaw_ft1(t_ssaw *x, t_float f) +{ + x->x_phase = f; +} + +static void ssaw_initarray(void) +{ + int i; + float j; + + for(i=0;i<1002;i++){ + j=(i-1)*M_PI/1000.0; //period 2000 sample, 1 sample back phase + ssaw_array[i]= 0.57692* + (-1*cos(j) + 0.333333*cos(j*3.0) -0.2* cos(j*5.0)); + } +} + +void ssaw_tilde_setup(void) +{ + ssaw_class = class_new(gensym("ssaw~"), (t_newmethod)ssaw_new, 0, + sizeof(t_ssaw), 0, A_DEFFLOAT, 0); + CLASS_MAINSIGNALIN(ssaw_class, t_ssaw, x_f); + class_addmethod(ssaw_class, (t_method)ssaw_dsp, gensym("dsp"), 0); + class_addmethod(ssaw_class, (t_method)ssaw_ft1, + gensym("ft1"), A_FLOAT, 0); + ssaw_initarray(); + +} + diff --git a/tabdump2.c b/tabdump2.c new file mode 100644 index 0000000..9c779e9 --- /dev/null +++ b/tabdump2.c @@ -0,0 +1,120 @@ +/* +Copyright (C) 2004 Antoine Rousseau + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +/* + tabdump2 -- from tabdump (from zexy) but with min/max dumping limits. +*/ + +#include <m_pd.h> + +static t_class *tabdump_class; + +typedef struct _tabdump +{ + t_object x_obj; + t_symbol *x_arrayname; +} t_tabdump; + +static void tabdump_bang(t_tabdump *x, t_float findex) +{ + t_garray *A; + int npoints; + t_float *vec; + + if (!(A = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class))) + error("%s: no such array", x->x_arrayname->s_name); + else if (!garray_getfloatarray(A, &npoints, &vec)) + error("%s: bad template for tabdump", x->x_arrayname->s_name); + else + { + int n; + t_atom *atombuf = (t_atom *)getbytes(sizeof(t_atom)*npoints); + + for (n = 0; n < npoints; n++) SETFLOAT(&atombuf[n], vec[n]); + outlet_list(x->x_obj.ob_outlet, &s_list, npoints, atombuf); + } +} + + +static void tabdump_dump(t_tabdump *x, t_float min, t_float max) +{ + t_garray *A; + int npoints,nmin=(int)min,nmax=(int)max; + t_float *vec; + + if (!(A = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class))) + error("%s: no such array", x->x_arrayname->s_name); + else if (!garray_getfloatarray(A, &npoints, &vec)) + error("%s: bad template for tabdump", x->x_arrayname->s_name); + else if ((min<0)||(max<=min)||(max>npoints)) + error("tabdump: bad arguments min=%d max=%d for %s (%d elements)", + nmin,nmax,x->x_arrayname->s_name,npoints); + else + { + int n; + t_atom *atombuf; + + npoints=nmax-nmin; + atombuf = (t_atom *)getbytes(sizeof(t_atom)*npoints); + + for (n = 0; n < npoints; n++) SETFLOAT(&atombuf[n], vec[n+nmin]); + outlet_list(x->x_obj.ob_outlet, &s_list, npoints, atombuf); + } +} + + +static void tabdump_set(t_tabdump *x, t_symbol *s) +{ + x->x_arrayname = s; +} + +static void *tabdump_new(t_symbol *s) +{ + t_tabdump *x = (t_tabdump *)pd_new(tabdump_class); + x->x_arrayname = s; + outlet_new(&x->x_obj, &s_list); + + return (x); +} + +static void tabdump_helper(void) +{ + post("\n tabdump2 - object : dumps a table as a package of floats"); + post("'set <table>'\t: read out another table\n" + "'bang'\t\t: dump the table\n" + "'dump <min> <max>'\t\t: dump the table from <min> to <max> (without <max>)\n" + "outlet\t\t: table-data as package of floats"); + post("creation\t: \"tabdump2 <table>\""); + +} + +void tabdump2_setup(void) +{ + tabdump_class = class_new(gensym("tabdump2"), (t_newmethod)tabdump_new, + 0, sizeof(t_tabdump), 0, A_DEFSYM, 0); + class_addbang(tabdump_class, (t_method)tabdump_bang); + class_addmethod(tabdump_class, (t_method)tabdump_dump,gensym("dump"), + A_FLOAT,A_FLOAT); + class_addmethod(tabdump_class, (t_method)tabdump_set, gensym("set"), + A_SYMBOL, 0); + + class_addmethod(tabdump_class, (t_method)tabdump_helper, gensym("help"), 0); + +} + diff --git a/tabenv.c b/tabenv.c new file mode 100644 index 0000000..9b52fbe --- /dev/null +++ b/tabenv.c @@ -0,0 +1,294 @@ +/* +Copyright (C) 2002 Antoine Rousseau + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include "m_pd.h" +#include "math.h" + + +/* ---------------- tabenv - table envelope computer. ----------------- */ +/*------- (in fact it's a mix between env~ and tabplay~)----------------*/ + +#define MAXOVERLAP 10 +#define MAXVSTAKEN 64 + +typedef struct tabenv +{ + /*env part*/ + t_object x_obj; /* header */ + t_outlet *x_outlet; /* a "float" outlet */ + t_clock *x_clock; /* a "clock" object */ + float *x_buf; /* a Hanning window */ + int x_phase; /* number of points since last output */ + int x_period; /* requested period of output */ + int x_realperiod; /* period rounded up to vecsize multiple */ + int x_npoints; /* analysis window size in samples */ + float x_result; /* result to output */ + float x_sumbuf[MAXOVERLAP]; /* summing buffer */ + float x_f; + + /*tabplay part*/ + int x_tabphase; + int x_nsampsintab; + int x_limit; + float *x_vec; + t_symbol *x_arrayname; +} t_tabenv; + +t_class *tabenv_class; +static void tabenv_tick(t_tabenv *x); + +static void *tabenv_new(t_symbol *s,t_floatarg fnpoints, t_floatarg fperiod) +{ + int npoints = fnpoints; + int period = fperiod; + t_tabenv *x; + float *buf; + int i; + + if (npoints < 1) npoints = 1024; + if (period < 1) period = npoints/2; + if (period < npoints / MAXOVERLAP + 1) + period = npoints / MAXOVERLAP + 1; + if (!(buf = getbytes(sizeof(float) * (npoints + MAXVSTAKEN)))) + { + error("env: couldn't allocate buffer"); + return (0); + } + x = (t_tabenv *)pd_new(tabenv_class); + x->x_buf = buf; + x->x_npoints = npoints; + x->x_phase = 0; + x->x_period = period; + for (i = 0; i < MAXOVERLAP; i++) x->x_sumbuf[i] = 0; + for (i = 0; i < npoints; i++) + buf[i] = (1. - cos((2 * 3.14159 * i) / npoints))/npoints; + for (; i < npoints+MAXVSTAKEN; i++) buf[i] = 0; + x->x_clock = clock_new(x, (t_method)tabenv_tick); + x->x_outlet = outlet_new(&x->x_obj, gensym("float")); + x->x_f = 0; + + /* tabplay */ + x->x_tabphase = 0x7fffffff; + x->x_limit = 0; + x->x_arrayname = s; + + return (x); +} + +static t_int *sigenv_perform(t_int *w) +{ + t_tabenv *x = (t_tabenv *)(w[1]); + t_float *in = (t_float *)(w[2]); + int n = (int)(w[3]); + int count; + float *sump; + in += n; + for (count = x->x_phase, sump = x->x_sumbuf; + count < x->x_npoints; count += x->x_realperiod, sump++) + { + float *hp = x->x_buf + count; + float *fp = in; + float sum = *sump; + int i; + + for (i = 0; i < n; i++) + { + fp--; + sum += *hp++ * (*fp * *fp); + } + *sump = sum; + } + sump[0] = 0; + x->x_phase -= n; + if (x->x_phase < 0) + { + x->x_result = x->x_sumbuf[0]; + for (count = x->x_realperiod, sump = x->x_sumbuf; + count < x->x_npoints; count += x->x_realperiod, sump++) + sump[0] = sump[1]; + sump[0] = 0; + x->x_phase = x->x_realperiod - n; + clock_delay(x->x_clock, 0L); + } + return (w+4); +} + +static t_int *tabplay_tilde_perform(t_int *w) +{ + t_tabenv *x = (t_tabenv *)(w[1]); + t_float *out = (t_float *)(w[2]), *fp; + int n = (int)(w[3]), phase = x->x_phase, + endphase = (x->x_nsampsintab < x->x_limit ? + x->x_nsampsintab : x->x_limit), nxfer, n3; + if (!x->x_vec || phase >= endphase) + goto zero; + + nxfer = endphase - phase; + fp = x->x_vec + phase; + if (nxfer > n) + nxfer = n; + n3 = n - nxfer; + phase += nxfer; + while (nxfer--) + *out++ = *fp++; + if (phase >= endphase) + { + clock_delay(x->x_clock, 0); + x->x_phase = 0x7fffffff; + while (n3--) + *out++ = 0; + } + else x->x_phase = phase; + + return (w+4); +zero: + while (n--) *out++ = 0; + return (w+4); +} + + +static void tabenv_perform_64(t_tabenv *x,t_float *in) +{ + int n = 64; + int count; + float *sump; + in += n; + for (count = x->x_phase, sump = x->x_sumbuf; + count < x->x_npoints; count += x->x_realperiod, sump++) + { + float *hp = x->x_buf + count; + float *fp = in; + float sum = *sump; + int i; + + for (i = 0; i < n; i++) + { + fp--; + sum += *hp++ * (*fp * *fp); + } + *sump = sum; + } + sump[0] = 0; + x->x_phase -= n; + if (x->x_phase < 0) + { + x->x_result = x->x_sumbuf[0]; + for (count = x->x_realperiod, sump = x->x_sumbuf; + count < x->x_npoints; count += x->x_realperiod, sump++) + sump[0] = sump[1]; + sump[0] = 0; + x->x_phase = x->x_realperiod - n; + /*clock_delay(x->x_clock, 0L);*/ + outlet_float(x->x_outlet, powtodb(x->x_result)); + } +} + + +static void tabenv_set(t_tabenv *x, t_symbol *s) +{ + t_garray *a; + + x->x_arrayname = s; + if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class))) + { + if (*s->s_name) pd_error(x, "tabenv: %s: no such array", + x->x_arrayname->s_name); + x->x_vec = 0; + } + else if (!garray_getfloatarray(a, &x->x_nsampsintab, &x->x_vec)) + { + error("%s: bad template for tabenv", x->x_arrayname->s_name); + x->x_vec = 0; + } + else garray_usedindsp(a); +} + +static void sigenv_dsp(t_tabenv *x, t_signal **sp) +{ + if (x->x_period % sp[0]->s_n) x->x_realperiod = + x->x_period + sp[0]->s_n - (x->x_period % sp[0]->s_n); + else x->x_realperiod = x->x_period; + dsp_add(sigenv_perform, 3, x, sp[0]->s_vec, sp[0]->s_n); + if (sp[0]->s_n > MAXVSTAKEN) bug("sigenv_dsp"); +} + +static void tabenv_list(t_tabenv *x, t_symbol *s, + int argc, t_atom *argv) +{ + long start = atom_getfloatarg(0, argc, argv); + long length = atom_getfloatarg(1, argc, argv); + float *limitp,*p; + int i; + + tabenv_set(x, x->x_arrayname); + + if (start < 0) start = 0; + if (length <= 0) + x->x_limit = 0x7fffffff; + else + x->x_limit = start + length; + x->x_tabphase = start; + + if(length <= 0) length = x->x_nsampsintab - 1; + if(start >= x->x_nsampsintab) start = x->x_nsampsintab - 1; + if((start + length) >= x->x_nsampsintab) + length = x->x_nsampsintab - 1 - start; + + limitp = x->x_vec + start + length - 63; + /*limitp = x->x_vec + 2048;*/ + /*if (x->x_period % length) x->x_realperiod = + x->x_period + length - (x->x_period % length); + else*/ x->x_realperiod = x->x_period; + + for(p = x->x_vec + start; p < limitp ; p += 64) + tabenv_perform_64( x , p ); +} + +static void tabenv_reset(t_tabenv *x) +{ + int i; + x->x_phase = 0; + for (i = 0; i < MAXOVERLAP; i++) x->x_sumbuf[i] = 0; +} + +static void tabenv_tick(t_tabenv *x) /* callback function for the env clock */ +{ + outlet_float(x->x_outlet, powtodb(x->x_result)); +} + +static void tabenv_ff(t_tabenv *x) /* cleanup on free */ +{ + clock_free(x->x_clock); + freebytes(x->x_buf, (x->x_npoints + MAXVSTAKEN) * sizeof(float)); +} + + +void tabenv_setup(void ) +{ + tabenv_class = class_new(gensym("tabenv"), (t_newmethod)tabenv_new, + (t_method)tabenv_ff, sizeof(t_tabenv), 0, A_DEFSYM, A_DEFFLOAT, A_DEFFLOAT, 0); + CLASS_MAINSIGNALIN(tabenv_class, t_tabenv, x_f); + class_addmethod(tabenv_class, (t_method)tabenv_reset, + gensym("reset"), 0); + class_addmethod(tabenv_class, (t_method)tabenv_set, + gensym("set"), A_DEFSYM, 0); + class_addlist(tabenv_class, tabenv_list); + +} + diff --git a/tabreadl.c b/tabreadl.c new file mode 100644 index 0000000..e669bd8 --- /dev/null +++ b/tabreadl.c @@ -0,0 +1,84 @@ +/* +Copyright (C) 2002 Antoine Rousseau + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include "m_pd.h" +#include "math.h" + +/* ---------- tabreadl: control, linear interpolating ------------------------ */ + +static t_class *tabreadl_class; + +typedef struct _tabreadl +{ + t_object x_obj; + t_symbol *x_arrayname; +} t_tabreadl; + +static void tabreadl_float(t_tabreadl *x, t_float f) +{ + t_garray *a; + int npoints; + t_float *vec; + + if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class))) + error("%s: no such array", x->x_arrayname->s_name); + else if (!garray_getfloatarray(a, &npoints, &vec)) + error("%s: bad template for tabreadl", x->x_arrayname->s_name); + else + { + int n ; + float r,v; + + if (f < 0) f = 0; + else if (f >= npoints) f = npoints - 1; + n=f; + if(npoints>1){ + r=f-n; + v=vec[n]*(1-r)+vec[n+1]*r; + outlet_float(x->x_obj.ob_outlet, v ); + } + else + outlet_float(x->x_obj.ob_outlet, (npoints ? vec[n] : 0)); + } +} + +static void tabreadl_set(t_tabreadl *x, t_symbol *s) +{ + x->x_arrayname = s; +} + +static void *tabreadl_new(t_symbol *s) +{ + t_tabreadl *x = (t_tabreadl *)pd_new(tabreadl_class); + x->x_arrayname = s; + outlet_new(&x->x_obj, &s_float); + return (x); +} + +void tabreadl_setup(void) +{ + tabreadl_class = class_new(gensym("tabreadl"), (t_newmethod)tabreadl_new, + 0, sizeof(t_tabreadl), 0, A_DEFSYM, 0); + class_addfloat(tabreadl_class, (t_method)tabreadl_float); + class_addmethod(tabreadl_class, (t_method)tabreadl_set, gensym("set"), + A_SYMBOL, 0); + +} + + diff --git a/tabsort.c b/tabsort.c new file mode 100644 index 0000000..ec8fcf0 --- /dev/null +++ b/tabsort.c @@ -0,0 +1,124 @@ +/* +Copyright (C) 2002 Antoine Rousseau + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include "m_pd.h" +#include "math.h" + + +/* ---------------- tabsort - sort a table to a table ----------------- */ + + +typedef struct tabsort +{ + /*env part*/ + t_object x_obj; /* header */ + t_symbol *x_arrayname1; + t_symbol *x_arrayname2; +} t_tabsort; + +t_class *tabsort_class; + +static void *tabsort_new(t_symbol *tab1,t_symbol *tab2) +{ + t_tabsort *x; + x = (t_tabsort *)pd_new(tabsort_class); + + x->x_arrayname1 = tab1; + x->x_arrayname2 = tab2; + outlet_new((t_object*)x, &s_bang); + + return (x); +} + +static void tabsort_set1(t_tabsort *x, t_symbol *s) +{ + x->x_arrayname1 = s; +} +static void tabsort_set2(t_tabsort *x, t_symbol *s) +{ + x->x_arrayname2 = s; +} + +static void tabsort_float(t_tabsort *x, t_floatarg n) +{ + t_garray *a; + int n1,n2,i,j; + float *vec1,*vec2,tmp; + + if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname1, garray_class))) + { + if (*x->x_arrayname1->s_name) pd_error(x, "tabsort: %s: no such array", + x->x_arrayname1->s_name); + return; + } + else if (!garray_getfloatarray(a, &n1, &vec1)) + { + error("%s: bad template for tabsort", x->x_arrayname1->s_name); + return; + } + + if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname2, garray_class))) + { + if (*x->x_arrayname2->s_name) pd_error(x, "tabsort: %s: no such array", + x->x_arrayname2->s_name); + return; + } + else if (!garray_getfloatarray(a, &n2, &vec2)) + { + error("%s: bad template for tabsort", x->x_arrayname2->s_name); + return; + } + + if(n>n1) n=n1; + if(n>n2) n=n2; + + + for(i=0;i<n;vec2[i]=i++); + + for(i=0;i<n-1;i++) + for(j=n-1;j>i;j--) + if(vec1[(int)vec2[j-1]]<vec1[(int)vec2[j]]) + { + tmp=vec2[j]; + vec2[j]=vec2[j-1]; + vec2[j-1]=tmp; + } + + garray_redraw(a); + outlet_bang(((t_object *)x)->ob_outlet); +} + + +static void tabsort_ff(t_tabsort *x) /* cleanup on free */ +{ +} + + +void tabsort_setup(void ) +{ + tabsort_class = class_new(gensym("tabsort"), (t_newmethod)tabsort_new, + (t_method)tabsort_ff, sizeof(t_tabsort), 0, A_DEFSYM, A_DEFSYM, 0); + class_addmethod(tabsort_class, (t_method)tabsort_set1, + gensym("set1"), A_DEFSYM, 0); + class_addmethod(tabsort_class, (t_method)tabsort_set2, + gensym("set2"), A_DEFSYM, 0); + class_addfloat(tabsort_class, tabsort_float); + +} + diff --git a/tabsort2.c b/tabsort2.c new file mode 100644 index 0000000..63d0fd6 --- /dev/null +++ b/tabsort2.c @@ -0,0 +1,164 @@ +/* +Copyright (C) 2002 Antoine Rousseau + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include "m_pd.h" +#include "math.h" + + +/* ---------------- tabsort2 - sort a table to a table ----------------- */ + + +typedef struct tabsort2 +{ + t_object x_obj; /* header */ + t_symbol *x_arrayname1; + t_symbol *x_arrayname2; + t_symbol *x_arrayname3; + t_clock *x_clock; /* a "clock" object */ +} t_tabsort2; + +t_class *tabsort2_class; + +static void tabsort2_tick(t_tabsort2 *x); + +static void *tabsort2_new(t_symbol *tab1,t_symbol *tab2,t_symbol *tab3) +{ + t_tabsort2 *x; + x = (t_tabsort2 *)pd_new(tabsort2_class); + + x->x_arrayname1 = tab1; + x->x_arrayname2 = tab2; + x->x_arrayname3 = tab3; + x->x_clock = clock_new(x, (t_method)tabsort2_tick); + outlet_new((t_object*)x, &s_float); + + return (x); +} + +static void tabsort2_set1(t_tabsort2 *x, t_symbol *s) +{ + x->x_arrayname1 = s; +} +static void tabsort2_set2(t_tabsort2 *x, t_symbol *s) +{ + x->x_arrayname2 = s; +} + +static void tabsort2_set3(t_tabsort2 *x, t_symbol *s) +{ + x->x_arrayname3 = s; +} + +static void tabsort2_float(t_tabsort2 *x, t_floatarg n) +{ + t_garray *a; + int n1,n2,n3,i,j,h,sqn; + float *vec1,*vec2,*vec3,tmp; + + if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname1, garray_class))) + { + if (*x->x_arrayname1->s_name) pd_error(x, "tabsort2: %s: no such array", + x->x_arrayname1->s_name); + return; + } + else if (!garray_getfloatarray(a, &n1, &vec1)) + { + error("%s: bad template for tabsort2", x->x_arrayname1->s_name); + return; + } + + if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname2, garray_class))) + { + if (*x->x_arrayname2->s_name) pd_error(x, "tabsort2: %s: no such array", + x->x_arrayname2->s_name); + return; + } + else if (!garray_getfloatarray(a, &n2, &vec2)) + { + error("%s: bad template for tabsort2", x->x_arrayname2->s_name); + return; + } + + if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname3, garray_class))) + { + if (*x->x_arrayname3->s_name) pd_error(x, "tabsort2: %s: no such array", + x->x_arrayname3->s_name); + return; + } + else if (!garray_getfloatarray(a, &n3, &vec3)) + { + error("%s: bad template for tabsort2", x->x_arrayname3->s_name); + return; + } + + if(n>n1) n=n1; + if(n>n2) n=n2; + if(n>n3) n=n3; + + for(i=0;i<n;vec3[i]=i++); + + for(i=0;i<n-1;i++) + for(j=n-1;j>i;j--) + if(vec1[(int)vec3[j-1]]<vec1[(int)vec3[j]]) + { + tmp=vec3[j]; + vec3[j]=vec3[j-1]; + vec3[j-1]=tmp; + } + + sqn=(int)sqrt(n); + + for(h=0;h<sqn;h++) + for(i=0;i<sqn-1;i++) + for(j=sqn-1;j>i;j--) + if(vec2[(int)vec3[h*sqn+j-1]]<vec2[(int)vec3[h*sqn+j]]) + { + tmp=vec3[h*sqn+j]; + vec3[h*sqn+j]=vec3[h*sqn+j-1]; + vec3[h*sqn+j-1]=tmp; + } + + garray_redraw(a); + outlet_float(((t_object *)x)->ob_outlet,(float)sqn); +} + +static void tabsort2_tick(t_tabsort2 *x) /* callback function for the env clock */ +{ + + //clock_delay(x->x_clock, 0L); +} + +static void tabsort2_ff(t_tabsort2 *x) /* cleanup on free */ +{ + clock_free(x->x_clock); +} + + +void tabsort2_setup(void ) +{ + tabsort2_class = class_new(gensym("tabsort2"), (t_newmethod)tabsort2_new, + (t_method)tabsort2_ff, sizeof(t_tabsort2), 0, A_DEFSYM, A_DEFSYM, A_DEFSYM, 0); + class_addmethod(tabsort2_class, (t_method)tabsort2_set1, + gensym("set1"), A_DEFSYM, 0); + class_addmethod(tabsort2_class, (t_method)tabsort2_set2, + gensym("set2"), A_DEFSYM, 0); + class_addfloat(tabsort2_class, tabsort2_float); + +} + @@ -0,0 +1,253 @@ + /* + wacom graphire on serial port only... +*/ + +#include <m_imp.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> + +#define BUFSIZE 256 +#define HEADER_BIT 0x80 +#define ZAXIS_SIGN_BIT 0x40 +#define ZAXIS_BIT 0x04 +#define ZAXIS_BITS 0x3f +#define POINTER_BIT 0x20 +#define PROXIMITY_BIT 0x40 +#define BUTTON_FLAG 0x08 +#define BUTTONS_BITS 0x78 +#define TILT_SIGN_BIT 0x40 +#define TILT_BITS 0x3f + +/* defines to discriminate second side button and the eraser */ +#define ERASER_PROX 4 +#define OTHER_PROX 1 + +#define Threshold 1000 +unsigned char data[7]; + +typedef struct _wac +{ + t_object t_ob; + t_outlet *axis_out; + t_outlet *button_out; + t_symbol *file; + int fd; + int count; + int oldbuttons; + unsigned char data[BUFSIZE]; +}t_wac; + +t_class *wac_class; + +void wac_setup(void); +static void wac_read(t_wac *x,int fd); +static void wac_process(t_wac *x); + +static void wac_open(t_wac *x) +{ + if(x->fd>=0) return; + + x->fd = open (x->file->s_name, O_RDONLY | O_NONBLOCK); + if(x->fd<0){ + post("open (%s, O_RDONLY | O_NONBLOCK)",x->file->s_name); + perror("open"); + return; + } + sys_addpollfn(x->fd,(t_fdpollfn)wac_read,(void*)x); +} + +static void wac_close(t_wac *x) +{ + if(x->fd<0) return; + + sys_rmpollfn(x->fd); + close(x->fd); + x->fd=-1; +} + +static void wac_float(t_wac *x,t_floatarg connect) +{ + if(connect!=0) wac_open(x); + else wac_close(x); +} + +static void *wac_new(t_symbol *file) +{ + t_wac *x = (t_wac *)pd_new(wac_class); + + //if(file->s_name) + if(file!=&s_) + x->file=file; + else x->file=gensym("/dev/ttyS0"); + + post("wac_new file=%s",x->file->s_name); + x->axis_out = outlet_new(&x->t_ob, &s_list); + x->button_out = outlet_new(&x->t_ob, &s_list); + + x->fd=-1; + + return (void *)x; +} + +void wac_setup(void) +{ + wac_class = class_new(gensym("wac"),(t_newmethod)wac_new, + (t_method)wac_close, sizeof(t_wac), 0, A_DEFSYM, 0); + class_addfloat(wac_class, wac_float); + + +} + + +static void wac_read(t_wac *x,int fd) +{ + int len,i=0; + unsigned char b; + unsigned char buffer[BUFSIZE]; + + while((len=read(fd,buffer,BUFSIZE))> -1){ + + for(i=0;i<len;i++){ + if(buffer[i]&128) x->count=0; + x->data[x->count++]=buffer[i]; + if(x->count==7) wac_process(x); + } + } +} + +static void wac_process(t_wac *X) +{ + int is_stylus = 1, is_button, is_proximity, wheel=0; + int x, y, z, buttons, tx = 0, ty = 0; + unsigned char *data=X->data; + t_atom ats[3]; + + is_stylus = (data[0] & POINTER_BIT); + + if(!is_stylus) return; + + x = (((data[0] & 0x3) << 14) + + (data[1] << 7) + + data[2]); + y = (((data[3] & 0x3) << 14) + + (data[4] << 7) + + data[5]); + + + z = ((data[6] & ZAXIS_BITS) * 2) + + ((data[3] & ZAXIS_BIT) >> 2); + + //z = z*4 + ((data[0] & ZAXIS_BIT) >> 1); + + if (!(data[6] & ZAXIS_SIGN_BIT)) { + z += 128; + } + + is_proximity = (data[0] & PROXIMITY_BIT); + + buttons = ((data[3] & 0x38) >> 3); + /*if (is_stylus) { + buttons = ((data[3] & 0x30) >> 3) | + (z >= Threshold ? 1 : 0); + } + else { + buttons = (data[3] & 0x38) >> 3; + + wheel = (data[6] & 0x30) >> 4; + + if (data[6] & 0x40) { + wheel = -wheel; + } + }*/ + //is_button = (buttons != 0); + if(buttons!=X->oldbuttons) + { + X->oldbuttons=buttons; + + SETFLOAT(&ats[0],buttons&1); + SETFLOAT(&ats[1],(buttons&2)!=0); + SETFLOAT(&ats[2],(buttons&4)!=0); + outlet_list(X->button_out,0,3,ats); + } + SETFLOAT(&ats[0],x/5103.0); + SETFLOAT(&ats[1],y/3711.0); + SETFLOAT(&ats[2],z/256.0); + outlet_list(X->axis_out,0,3,ats); +} + /* Format of 7 bytes data packet for Wacom Tablets + Byte 1 + bit 7 Sync bit always 1 + bit 6 Pointing device detected + bit 5 Cursor = 0 / Stylus = 1 + bit 4 Reserved + bit 3 1 if a button on the pointing device has been pressed + bit 2 Reserved + bit 1 X15 + bit 0 X14 + + Byte 2 + bit 7 Always 0 + bits 6-0 = X13 - X7 + + Byte 3 + bit 7 Always 0 + bits 6-0 = X6 - X0 + + Byte 4 + bit 7 Always 0 + bit 6 B3 + bit 5 B2 + bit 4 B1 + bit 3 B0 + bit 2 P0 + bit 1 Y15 + bit 0 Y14 + + Byte 5 + bit 7 Always 0 + bits 6-0 = Y13 - Y7 + + Byte 6 + bit 7 Always 0 + bits 6-0 = Y6 - Y0 + + Byte 7 + bit 7 Always 0 + bit 6 Sign of pressure data + bit 5 P6 + bit 4 P5 + bit 3 P4 + bit 2 P3 + bit 1 P2 + bit 0 P1 + + byte 8 and 9 are optional and present only + in tilt mode. + + Byte 8 + bit 7 Always 0 + bit 6 Sign of tilt X + bit 5 Xt6 + bit 4 Xt5 + bit 3 Xt4 + bit 2 Xt3 + bit 1 Xt2 + bit 0 Xt1 + + Byte 9 + bit 7 Always 0 + bit 6 Sign of tilt Y + bit 5 Yt6 + bit 4 Yt5 + bit 3 Yt4 + bit 2 Yt3 + bit 1 Yt2 + bit 0 Yt1 + + */ + |