diff --git a/pd/src/s_main.c b/pd/src/s_main.c
index 38d79fa729b13c7fe34006d2d908e9abc98412f2..c6c48eee353b775d12cfcd159adfbf63a20c2080 100644
--- a/pd/src/s_main.c
+++ b/pd/src/s_main.c
@@ -106,7 +106,7 @@ t_sample* get_sys_soundin() { return sys_soundin; }
 int* get_sys_main_advance() { return &sys_main_advance; }
 double* get_sys_time_per_dsp_tick() { return &sys_time_per_dsp_tick; }
 int* get_sys_schedblocksize() { return &sys_schedblocksize; }
-double* get_sys_time() { return &sys_time; }
+double* get_sys_time() { return &pd_this->pd_systime; }
 t_float* get_sys_dacsr() { return &sys_dacsr; }
 int* get_sys_sleepgrain() { return &sys_sleepgrain; }
 int* get_sys_schedadvance() { return &sys_schedadvance; }
diff --git a/pd/src/s_path.c b/pd/src/s_path.c
index 659609d664b347174cf011e29c3d02ed762eb6d1..7d028d8c88b64626c1ed42b2ca9e7ed492268a83 100644
--- a/pd/src/s_path.c
+++ b/pd/src/s_path.c
@@ -40,8 +40,10 @@
 
 t_namelist *sys_externlist;
 t_namelist *sys_searchpath;
+t_namelist *sys_staticpath;
 t_namelist *sys_helppath;
 
+
     /* change '/' characters to the system's native file separator */
 void sys_bashfilename(const char *from, char *to)
 {
@@ -297,9 +299,12 @@ void sys_setextrapath(const char *p)
     namelist_free(pd_extrapath);
     /* add standard place for users to install stuff first */
 #ifdef __gnu_linux__
-    sys_expandpath("~/pd-l2ork-externals", pathbuf);
+    sys_expandpath("~/.local/lib/pd-l2ork/extra/", pathbuf);
     pd_extrapath = namelist_append(0, pathbuf, 0);
-    pd_extrapath = namelist_append(pd_extrapath, "/usr/local/lib/pd-l2ork-externals", 0);
+    sys_expandpath("~/pd-l2ork-externals", pathbuf);
+    pd_extrapath = namelist_append(pd_extrapath, pathbuf, 0);
+    pd_extrapath = namelist_append(pd_extrapath,
+        "/usr/local/lib/pd-l2ork-externals", 0);
 #endif
 
 #ifdef __APPLE__
@@ -309,9 +314,9 @@ void sys_setextrapath(const char *p)
 #endif
 
 #ifdef _WIN32
-    sys_expandpath("%ProgramFiles%/Common Files/Pd", pathbuf);
+    sys_expandpath("%AppData%/Pd", pathbuf);
     pd_extrapath = namelist_append(0, pathbuf, 0);
-    sys_expandpath("%UserProfile%/Application Data/Pd", pathbuf);
+    sys_expandpath("%CommonProgramFiles%/Pd", pathbuf);
     pd_extrapath = namelist_append(pd_extrapath, pathbuf, 0);
 #endif
     /* add built-in "extra" path last so its checked last */
@@ -468,6 +473,94 @@ int open_via_path(const char *dir, const char *name, const char *ext,
         size, bin, sys_searchpath));
 }
 
+    /* open a file with a UTF-8 filename
+    This is needed because WIN32 does not support UTF-8 filenames, only UCS2.
+    Having this function prevents lots of #ifdefs all over the place.
+    */
+#ifdef _WIN32
+int sys_open(const char *path, int oflag, ...)
+{
+    int i, fd;
+    char pathbuf[MAXPDSTRING];
+    wchar_t ucs2path[MAXPDSTRING];
+    sys_bashfilename(path, pathbuf);
+    u8_utf8toucs2(ucs2path, MAXPDSTRING, pathbuf, MAXPDSTRING-1);
+    /* For the create mode, Win32 does not have the same possibilities,
+     * so we ignore the argument and just hard-code read/write. */
+    if (oflag & O_CREAT)
+        fd = _wopen(ucs2path, oflag | O_BINARY, _S_IREAD | _S_IWRITE);
+    else
+        fd = _wopen(ucs2path, oflag | O_BINARY);
+    return fd;
+}
+
+FILE *sys_fopen(const char *filename, const char *mode)
+{
+    char namebuf[MAXPDSTRING];
+    wchar_t ucs2buf[MAXPDSTRING];
+    wchar_t ucs2mode[MAXPDSTRING];
+    sys_bashfilename(filename, namebuf);
+    u8_utf8toucs2(ucs2buf, MAXPDSTRING, namebuf, MAXPDSTRING-1);
+    /* mode only uses ASCII, so no need for a full conversion, just copy it */
+    mbstowcs(ucs2mode, mode, MAXPDSTRING);
+    return (_wfopen(ucs2buf, ucs2mode));
+}
+#else
+#include <stdarg.h>
+int sys_open(const char *path, int oflag, ...)
+{
+    int i, fd;
+    char pathbuf[MAXPDSTRING];
+    sys_bashfilename(path, pathbuf);
+    if (oflag & O_CREAT)
+    {
+        mode_t mode;
+        int imode;
+        va_list ap;
+        va_start(ap, oflag);
+
+        /* Mac compiler complains if we just set mode = va_arg ... so, even
+        though we all know it's just an int, we explicitly va_arg to an int
+        and then convert.
+           -> http://www.mail-archive.com/bug-gnulib@gnu.org/msg14212.html
+           -> http://bugs.debian.org/647345
+        */
+
+        imode = va_arg (ap, int);
+        mode = (mode_t)imode;
+        va_end(ap);
+        fd = open(pathbuf, oflag, mode);
+    }
+    else
+        fd = open(pathbuf, oflag);
+    return fd;
+}
+
+FILE *sys_fopen(const char *filename, const char *mode)
+{
+  char namebuf[MAXPDSTRING];
+  sys_bashfilename(filename, namebuf);
+  return fopen(namebuf, mode);
+}
+#endif /* _WIN32 */
+
+   /* close a previously opened file
+   this is needed on platforms where you cannot open/close resources
+   across dll-boundaries, but we provide it for other platforms as well */
+int sys_close(int fd)
+{
+#ifdef _WIN32
+    return _close(fd);  /* Bill Gates is a big fat hen */
+#else
+    return close(fd);
+#endif
+}
+
+int sys_fclose(FILE *stream)
+{
+    return fclose(stream);
+}
+
     /* Open a help file using the help search path.  We expect the ".pd"
     suffix here, even though we have to tear it back off for one of the
     search attempts. */
diff --git a/pd/src/x_midi.c b/pd/src/x_midi.c
index b43abe7219184145bc84b6df5b2f60631c32a88c..443295d54d1c7596b39bed73f0b8296f76d03f53 100644
--- a/pd/src/x_midi.c
+++ b/pd/src/x_midi.c
@@ -5,6 +5,7 @@
 /* MIDI. */
 
 #include "m_pd.h"
+#include "m_imp.h"
 void outmidi_noteon(int portno, int channel, int pitch, int velo);
 void outmidi_controlchange(int portno, int channel, int ctlno, int value);
 void outmidi_programchange(int portno, int channel, int value);
@@ -17,8 +18,6 @@ void outmidi_byte(int portno, int value);
 
 /* ----------------------- midiin and sysexin ------------------------- */
 
-static t_symbol *midiin_sym, *sysexin_sym;
-
 static t_class *midiin_class, *sysexin_class;
 
 typedef struct _midiin
@@ -33,10 +32,7 @@ static void *midiin_new( void)
     t_midiin *x = (t_midiin *)pd_new(midiin_class);
     x->x_outlet1 = outlet_new(&x->x_obj, &s_float);
     x->x_outlet2 = outlet_new(&x->x_obj, &s_float);
-    pd_bind(&x->x_obj.ob_pd, midiin_sym);
-#ifdef WIN32
-    pd_error(x, "midiin: windows: not supported");
-#endif
+    pd_bind(&x->x_obj.ob_pd, pd_this->pd_midiin_sym);
     return (x);
 }
 
@@ -48,7 +44,7 @@ static void midiin_list(t_midiin *x, t_symbol *s, int ac, t_atom *av)
 
 static void midiin_free(t_midiin *x)
 {
-    pd_unbind(&x->x_obj.ob_pd, midiin_sym);
+    pd_unbind(&x->x_obj.ob_pd, pd_this->pd_midiin_sym);
 }
 
 static void *sysexin_new( void)
@@ -56,16 +52,13 @@ static void *sysexin_new( void)
     t_midiin *x = (t_midiin *)pd_new(sysexin_class);
     x->x_outlet1 = outlet_new(&x->x_obj, &s_float);
     x->x_outlet2 = outlet_new(&x->x_obj, &s_float);
-    pd_bind(&x->x_obj.ob_pd, sysexin_sym);
-#ifdef WIN32
-    pd_error(x, "sysexin: windows: not supported");
-#endif
+    pd_bind(&x->x_obj.ob_pd, pd_this->pd_sysexin_sym);
     return (x);
 }
 
 static void sysexin_free(t_midiin *x)
 {
-    pd_unbind(&x->x_obj.ob_pd, sysexin_sym);
+    pd_unbind(&x->x_obj.ob_pd, pd_this->pd_sysexin_sym);
 }
 
 static void midiin_setup(void)
@@ -75,42 +68,38 @@ static void midiin_setup(void)
             CLASS_NOINLET, A_DEFFLOAT, 0);
     class_addlist(midiin_class, midiin_list);
     class_sethelpsymbol(midiin_class, gensym("midi"));
-    midiin_sym = gensym("#midiin");
 
     sysexin_class = class_new(gensym("sysexin"), (t_newmethod)sysexin_new,
         (t_method)sysexin_free, sizeof(t_midiin),
             CLASS_NOINLET, A_DEFFLOAT, 0);
     class_addlist(sysexin_class, midiin_list);
     class_sethelpsymbol(sysexin_class, gensym("midi"));
-    sysexin_sym = gensym("#sysexin");
 }
 
 void inmidi_byte(int portno, int byte)
 {
     t_atom at[2];
-    if (midiin_sym->s_thing)
+    if (pd_this->pd_midiin_sym->s_thing)
     {
         SETFLOAT(at, byte);
-        SETFLOAT(at+1, portno + 1);
-        pd_list(midiin_sym->s_thing, 0, 2, at);
+        SETFLOAT(at+1, portno);
+        pd_list(pd_this->pd_midiin_sym->s_thing, 0, 2, at);
     }
 }
 
 void inmidi_sysex(int portno, int byte)
 {
     t_atom at[2];
-    if (sysexin_sym->s_thing)
+    if (pd_this->pd_sysexin_sym->s_thing)
     {
         SETFLOAT(at, byte);
-        SETFLOAT(at+1, portno + 1);
-        pd_list(sysexin_sym->s_thing, 0, 2, at);
+        SETFLOAT(at+1, portno);
+        pd_list(pd_this->pd_sysexin_sym->s_thing, 0, 2, at);
     }
 }
 
 /* ----------------------- notein ------------------------- */
 
-static t_symbol *notein_sym;
-
 static t_class *notein_class;
 
 typedef struct _notein
@@ -129,7 +118,7 @@ static void *notein_new(t_floatarg f)
     x->x_outlet1 = outlet_new(&x->x_obj, &s_float);
     x->x_outlet2 = outlet_new(&x->x_obj, &s_float);
     if (f == 0) x->x_outlet3 = outlet_new(&x->x_obj, &s_float);
-    pd_bind(&x->x_obj.ob_pd, notein_sym);
+    pd_bind(&x->x_obj.ob_pd, pd_this->pd_notein_sym);
     return (x);
 }
 
@@ -154,7 +143,7 @@ static void notein_list(t_notein *x, t_symbol *s, int argc, t_atom *argv)
 
 static void notein_free(t_notein *x)
 {
-    pd_unbind(&x->x_obj.ob_pd, notein_sym);
+    pd_unbind(&x->x_obj.ob_pd, pd_this->pd_notein_sym);
 }
 
 static void notein_setup(void)
@@ -162,25 +151,23 @@ static void notein_setup(void)
     notein_class = class_new(gensym("notein"), (t_newmethod)notein_new,
         (t_method)notein_free, sizeof(t_notein), CLASS_NOINLET, A_DEFFLOAT, 0);
     class_addlist(notein_class, notein_list);
-    notein_sym = gensym("#notein");
+    class_sethelpsymbol(notein_class, gensym("midi"));
 }
 
 void inmidi_noteon(int portno, int channel, int pitch, int velo)
 {
-    if (notein_sym->s_thing)
+    if (pd_this->pd_notein_sym->s_thing)
     {
         t_atom at[3];
         SETFLOAT(at, pitch);
         SETFLOAT(at+1, velo);
         SETFLOAT(at+2, (channel + (portno << 4) + 1));
-        pd_list(notein_sym->s_thing, &s_list, 3, at);
+        pd_list(pd_this->pd_notein_sym->s_thing, &s_list, 3, at);
     }
 }
 
 /* ----------------------- ctlin ------------------------- */
 
-static t_symbol *ctlin_sym;
-
 static t_class *ctlin_class;
 
 typedef struct _ctlin
@@ -208,7 +195,7 @@ static void *ctlin_new(t_symbol *s, int argc, t_atom *argv)
         if (x->x_ctlno < 0) x->x_outlet2 = outlet_new(&x->x_obj, &s_float);
         x->x_outlet3 = outlet_new(&x->x_obj, &s_float);
     }
-    pd_bind(&x->x_obj.ob_pd, ctlin_sym);
+    pd_bind(&x->x_obj.ob_pd, pd_this->pd_ctlin_sym);
     return (x);
 }
 
@@ -226,34 +213,32 @@ static void ctlin_list(t_ctlin *x, t_symbol *s, int argc, t_atom *argv)
 
 static void ctlin_free(t_ctlin *x)
 {
-    pd_unbind(&x->x_obj.ob_pd, ctlin_sym);
+    pd_unbind(&x->x_obj.ob_pd, pd_this->pd_ctlin_sym);
 }
 
 static void ctlin_setup(void)
 {
-    ctlin_class = class_new(gensym("ctlin"), (t_newmethod)ctlin_new, 
+    ctlin_class = class_new(gensym("ctlin"), (t_newmethod)ctlin_new,
         (t_method)ctlin_free, sizeof(t_ctlin),
             CLASS_NOINLET, A_GIMME, 0);
     class_addlist(ctlin_class, ctlin_list);
-    ctlin_sym = gensym("#ctlin");
+    class_sethelpsymbol(ctlin_class, gensym("midi"));
 }
 
 void inmidi_controlchange(int portno, int channel, int ctlnumber, int value)
 {
-    if (ctlin_sym->s_thing)
+    if (pd_this->pd_ctlin_sym->s_thing)
     {
         t_atom at[3];
         SETFLOAT(at, ctlnumber);
         SETFLOAT(at+1, value);
         SETFLOAT(at+2, (channel + (portno << 4) + 1));
-        pd_list(ctlin_sym->s_thing, &s_list, 3, at);
+        pd_list(pd_this->pd_ctlin_sym->s_thing, &s_list, 3, at);
     }
 }
 
 /* ----------------------- pgmin ------------------------- */
 
-static t_symbol *pgmin_sym;
-
 static t_class *pgmin_class;
 
 typedef struct _pgmin
@@ -270,7 +255,7 @@ static void *pgmin_new(t_floatarg f)
     x->x_channel = f;
     x->x_outlet1 = outlet_new(&x->x_obj, &s_float);
     if (f == 0) x->x_outlet2 = outlet_new(&x->x_obj, &s_float);
-    pd_bind(&x->x_obj.ob_pd, pgmin_sym);
+    pd_bind(&x->x_obj.ob_pd, pd_this->pd_pgmin_sym);
     return (x);
 }
 
@@ -292,7 +277,7 @@ static void pgmin_list(t_pgmin *x, t_symbol *s, int argc, t_atom *argv)
 
 static void pgmin_free(t_pgmin *x)
 {
-    pd_unbind(&x->x_obj.ob_pd, pgmin_sym);
+    pd_unbind(&x->x_obj.ob_pd, pd_this->pd_pgmin_sym);
 }
 
 static void pgmin_setup(void)
@@ -301,24 +286,22 @@ static void pgmin_setup(void)
         (t_method)pgmin_free, sizeof(t_pgmin),
             CLASS_NOINLET, A_DEFFLOAT, 0);
     class_addlist(pgmin_class, pgmin_list);
-    pgmin_sym = gensym("#pgmin");
+    class_sethelpsymbol(pgmin_class, gensym("midi"));
 }
 
 void inmidi_programchange(int portno, int channel, int value)
 {
-    if (pgmin_sym->s_thing)
+    if (pd_this->pd_pgmin_sym->s_thing)
     {
         t_atom at[2];
         SETFLOAT(at, value + 1);
         SETFLOAT(at+1, (channel + (portno << 4) + 1));
-        pd_list(pgmin_sym->s_thing, &s_list, 2, at);
+        pd_list(pd_this->pd_pgmin_sym->s_thing, &s_list, 2, at);
     }
 }
 
 /* ----------------------- bendin ------------------------- */
 
-static t_symbol *bendin_sym;
-
 static t_class *bendin_class;
 
 typedef struct _bendin
@@ -335,7 +318,7 @@ static void *bendin_new(t_floatarg f)
     x->x_channel = f;
     x->x_outlet1 = outlet_new(&x->x_obj, &s_float);
     if (f == 0) x->x_outlet2 = outlet_new(&x->x_obj, &s_float);
-    pd_bind(&x->x_obj.ob_pd, bendin_sym);
+    pd_bind(&x->x_obj.ob_pd, pd_this->pd_bendin_sym);
     return (x);
 }
 
@@ -357,7 +340,7 @@ static void bendin_list(t_bendin *x, t_symbol *s, int argc, t_atom *argv)
 
 static void bendin_free(t_bendin *x)
 {
-    pd_unbind(&x->x_obj.ob_pd, bendin_sym);
+    pd_unbind(&x->x_obj.ob_pd, pd_this->pd_bendin_sym);
 }
 
 static void bendin_setup(void)
@@ -365,24 +348,22 @@ static void bendin_setup(void)
     bendin_class = class_new(gensym("bendin"), (t_newmethod)bendin_new,
         (t_method)bendin_free, sizeof(t_bendin), CLASS_NOINLET, A_DEFFLOAT, 0);
     class_addlist(bendin_class, bendin_list);
-    bendin_sym = gensym("#bendin");
+    class_sethelpsymbol(bendin_class, gensym("midi"));
 }
 
 void inmidi_pitchbend(int portno, int channel, int value)
 {
-    if (bendin_sym->s_thing)
+    if (pd_this->pd_bendin_sym->s_thing)
     {
         t_atom at[2];
         SETFLOAT(at, value);
         SETFLOAT(at+1, (channel + (portno << 4) + 1));
-        pd_list(bendin_sym->s_thing, &s_list, 2, at);
+        pd_list(pd_this->pd_bendin_sym->s_thing, &s_list, 2, at);
     }
 }
 
 /* ----------------------- touchin ------------------------- */
 
-static t_symbol *touchin_sym;
-
 static t_class *touchin_class;
 
 typedef struct _touchin
@@ -399,7 +380,7 @@ static void *touchin_new(t_floatarg f)
     x->x_channel = f;
     x->x_outlet1 = outlet_new(&x->x_obj, &s_float);
     if (f == 0) x->x_outlet2 = outlet_new(&x->x_obj, &s_float);
-    pd_bind(&x->x_obj.ob_pd, touchin_sym);
+    pd_bind(&x->x_obj.ob_pd, pd_this->pd_touchin_sym);
     return (x);
 }
 
@@ -421,7 +402,7 @@ static void touchin_list(t_touchin *x, t_symbol *s, int argc, t_atom *argv)
 
 static void touchin_free(t_touchin *x)
 {
-    pd_unbind(&x->x_obj.ob_pd, touchin_sym);
+    pd_unbind(&x->x_obj.ob_pd, pd_this->pd_touchin_sym);
 }
 
 static void touchin_setup(void)
@@ -431,24 +412,21 @@ static void touchin_setup(void)
             CLASS_NOINLET, A_DEFFLOAT, 0);
     class_addlist(touchin_class, touchin_list);
     class_sethelpsymbol(touchin_class, gensym("midi"));
-    touchin_sym = gensym("#touchin");
 }
 
 void inmidi_aftertouch(int portno, int channel, int value)
 {
-    if (touchin_sym->s_thing)
+    if (pd_this->pd_touchin_sym->s_thing)
     {
         t_atom at[2];
         SETFLOAT(at, value);
         SETFLOAT(at+1, (channel + (portno << 4) + 1));
-        pd_list(touchin_sym->s_thing, &s_list, 2, at);
+        pd_list(pd_this->pd_touchin_sym->s_thing, &s_list, 2, at);
     }
 }
 
 /* ----------------------- polytouchin ------------------------- */
 
-static t_symbol *polytouchin_sym;
-
 static t_class *polytouchin_class;
 
 typedef struct _polytouchin
@@ -467,7 +445,7 @@ static void *polytouchin_new(t_floatarg f)
     x->x_outlet1 = outlet_new(&x->x_obj, &s_float);
     x->x_outlet2 = outlet_new(&x->x_obj, &s_float);
     if (f == 0) x->x_outlet3 = outlet_new(&x->x_obj, &s_float);
-    pd_bind(&x->x_obj.ob_pd, polytouchin_sym);
+    pd_bind(&x->x_obj.ob_pd, pd_this->pd_polytouchin_sym);
     return (x);
 }
 
@@ -493,7 +471,7 @@ static void polytouchin_list(t_polytouchin *x, t_symbol *s, int argc,
 
 static void polytouchin_free(t_polytouchin *x)
 {
-    pd_unbind(&x->x_obj.ob_pd, polytouchin_sym);
+    pd_unbind(&x->x_obj.ob_pd, pd_this->pd_polytouchin_sym);
 }
 
 static void polytouchin_setup(void)
@@ -503,27 +481,24 @@ static void polytouchin_setup(void)
         sizeof(t_polytouchin), CLASS_NOINLET, A_DEFFLOAT, 0);
     class_addlist(polytouchin_class, polytouchin_list);
     class_sethelpsymbol(polytouchin_class, gensym("midi"));
-    polytouchin_sym = gensym("#polytouchin");
 }
 
 void inmidi_polyaftertouch(int portno, int channel, int pitch, int value)
 {
-    if (polytouchin_sym->s_thing)
+    if (pd_this->pd_polytouchin_sym->s_thing)
     {
         t_atom at[3];
         SETFLOAT(at, pitch);
         SETFLOAT(at+1, value);
         SETFLOAT(at+2, (channel + (portno << 4) + 1));
-        pd_list(polytouchin_sym->s_thing, &s_list, 3, at);
+        pd_list(pd_this->pd_polytouchin_sym->s_thing, &s_list, 3, at);
     }
 }
 
 /*----------------------- midiclkin--(midi F8 message )---------------------*/
-static t_symbol *midiclkin_sym;
 
 static t_class *midiclkin_class;
 
-
 typedef struct _midiclkin
 {
     t_object x_obj;
@@ -536,7 +511,7 @@ static void *midiclkin_new(t_floatarg f)
     t_midiclkin *x = (t_midiclkin *)pd_new(midiclkin_class);
     x->x_outlet1 = outlet_new(&x->x_obj, &s_float);
     x->x_outlet2 = outlet_new(&x->x_obj, &s_float);
-    pd_bind(&x->x_obj.ob_pd, midiclkin_sym);
+    pd_bind(&x->x_obj.ob_pd, pd_this->pd_midiclkin_sym);
     return (x);
 }
 
@@ -550,17 +525,16 @@ static void midiclkin_list(t_midiclkin *x, t_symbol *s, int argc, t_atom *argv)
 
 static void midiclkin_free(t_midiclkin *x)
 {
-    pd_unbind(&x->x_obj.ob_pd, midiclkin_sym);
+    pd_unbind(&x->x_obj.ob_pd, pd_this->pd_midiclkin_sym);
 }
 
 static void midiclkin_setup(void)
 {
-    midiclkin_class = class_new(gensym("midiclkin"), 
-        (t_newmethod)midiclkin_new, (t_method)midiclkin_free, 
+    midiclkin_class = class_new(gensym("midiclkin"),
+        (t_newmethod)midiclkin_new, (t_method)midiclkin_free,
             sizeof(t_midiclkin), CLASS_NOINLET, A_DEFFLOAT, 0);
     class_addlist(midiclkin_class, midiclkin_list);
         class_sethelpsymbol(midiclkin_class, gensym("midi"));
-    midiclkin_sym = gensym("#midiclkin");
 }
 
 void inmidi_clk(double timing)
@@ -568,14 +542,14 @@ void inmidi_clk(double timing)
 
     static t_float prev = 0;
     static t_float count = 0;
-    t_float diff;
+    t_float cur,diff;
 
-    if (midiclkin_sym->s_thing)
+    if (pd_this->pd_midiclkin_sym->s_thing)
     {
         t_atom at[2];
         diff =timing - prev;
         count++;
-   
+
         if (count == 3)
         {  /* 24 count per quoter note */
              SETFLOAT(at, 1 );
@@ -584,15 +558,13 @@ void inmidi_clk(double timing)
         else SETFLOAT(at, 0);
 
         SETFLOAT(at+1, diff);
-        pd_list(midiclkin_sym->s_thing, &s_list, 2, at);
+        pd_list(pd_this->pd_midiclkin_sym->s_thing, &s_list, 2, at);
         prev = timing;
     }
 }
 
 /*----------midirealtimein (midi FA,FB,FC,FF message )-----------------*/
 
-static t_symbol *midirealtimein_sym;
-
 static t_class *midirealtimein_class;
 
 typedef struct _midirealtimein
@@ -607,10 +579,7 @@ static void *midirealtimein_new( void)
     t_midirealtimein *x = (t_midirealtimein *)pd_new(midirealtimein_class);
     x->x_outlet1 = outlet_new(&x->x_obj, &s_float);
     x->x_outlet2 = outlet_new(&x->x_obj, &s_float);
-    pd_bind(&x->x_obj.ob_pd, midirealtimein_sym);
-#ifndef MSW
-    pd_error(x, "midirealtimein: works under MSW only");
-#endif
+    pd_bind(&x->x_obj.ob_pd, pd_this->pd_midirealtimein_sym);
     return (x);
 }
 
@@ -626,27 +595,26 @@ static void midirealtimein_list(t_midirealtimein *x, t_symbol *s,
 
 static void midirealtimein_free(t_midirealtimein *x)
 {
-    pd_unbind(&x->x_obj.ob_pd, midirealtimein_sym);
+    pd_unbind(&x->x_obj.ob_pd, pd_this->pd_midirealtimein_sym);
 }
 
 static void midirealtimein_setup(void)
 {
-    midirealtimein_class = class_new(gensym("midirealtimein"), 
-        (t_newmethod)midirealtimein_new, (t_method)midirealtimein_free, 
+    midirealtimein_class = class_new(gensym("midirealtimein"),
+        (t_newmethod)midirealtimein_new, (t_method)midirealtimein_free,
             sizeof(t_midirealtimein), CLASS_NOINLET, A_DEFFLOAT, 0);
     class_addlist(midirealtimein_class, midirealtimein_list);
         class_sethelpsymbol(midirealtimein_class, gensym("midi"));
-    midirealtimein_sym = gensym("#midirealtimein");
 }
 
 void inmidi_realtimein(int portno, int SysMsg)
 {
-    if (midirealtimein_sym->s_thing)
+    if (pd_this->pd_midirealtimein_sym->s_thing)
     {
         t_atom at[2];
         SETFLOAT(at, portno);
         SETFLOAT(at+1, SysMsg);
-        pd_list(midirealtimein_sym->s_thing, &s_list, 2, at);
+        pd_list(pd_this->pd_midirealtimein_sym->s_thing, &s_list, 2, at);
     }
 }
 
@@ -668,9 +636,6 @@ static void *midiout_new(t_floatarg portno)
     if (portno <= 0) portno = 1;
     x->x_portno = portno;
     floatinlet_new(&x->x_obj, &x->x_portno);
-#ifdef __irix__
-    post("midiout: unimplemented in IRIX");
-#endif
     return (x);
 }
 
@@ -723,6 +688,7 @@ static void noteout_setup(void)
     noteout_class = class_new(gensym("noteout"), (t_newmethod)noteout_new, 0,
         sizeof(t_noteout), 0, A_DEFFLOAT, 0);
     class_addfloat(noteout_class, noteout_float);
+    class_sethelpsymbol(noteout_class, gensym("midi"));
 }
 
 
@@ -762,6 +728,7 @@ static void ctlout_setup(void)
     ctlout_class = class_new(gensym("ctlout"), (t_newmethod)ctlout_new, 0,
         sizeof(t_ctlout), 0, A_DEFFLOAT, A_DEFFLOAT, 0);
     class_addfloat(ctlout_class, ctlout_float);
+    class_sethelpsymbol(ctlout_class, gensym("midi"));
 }
 
 
@@ -801,6 +768,7 @@ static void pgmout_setup(void)
     pgmout_class = class_new(gensym("pgmout"), (t_newmethod)pgmout_new, 0,
         sizeof(t_pgmout), 0, A_DEFFLOAT, 0);
     class_addfloat(pgmout_class, pgmout_float);
+    class_sethelpsymbol(pgmout_class, gensym("midi"));
 }
 
 
@@ -837,6 +805,7 @@ static void bendout_setup(void)
     bendout_class = class_new(gensym("bendout"), (t_newmethod)bendout_new, 0,
         sizeof(t_bendout), 0, A_DEFFLOAT, 0);
     class_addfloat(bendout_class, bendout_float);
+    class_sethelpsymbol(bendout_class, gensym("midi"));
 }
 
 /* -------------------------- touch -------------------------- */
@@ -906,7 +875,7 @@ static void polytouchout_float(t_polytouchout *x, t_float n)
 
 static void polytouchout_setup(void)
 {
-    polytouchout_class = class_new(gensym("polytouchout"), 
+    polytouchout_class = class_new(gensym("polytouchout"),
         (t_newmethod)polytouchout_new, 0,
         sizeof(t_polytouchout), 0, A_DEFFLOAT, 0);
     class_addfloat(polytouchout_class, polytouchout_float);
@@ -955,7 +924,7 @@ static void makenote_tick(t_hang *hang)
     outlet_float(x->x_velout, 0);
     outlet_float(x->x_pitchout, hang->h_pitch);
     if (x->x_hang == hang) x->x_hang = hang->h_next;
-    else for (h2 = x->x_hang; h3 = h2->h_next; h2 = h3)
+    else for (h2 = x->x_hang; (h3 = h2->h_next); h2 = h3)
     {
         if (h3 == hang)
         {
@@ -985,7 +954,7 @@ static void makenote_float(t_makenote *x, t_float f)
 static void makenote_stop(t_makenote *x)
 {
     t_hang *hang;
-    while (hang = x->x_hang)
+    while ((hang = x->x_hang))
     {
         outlet_float(x->x_velout, 0);
         outlet_float(x->x_pitchout, hang->h_pitch);
@@ -998,7 +967,7 @@ static void makenote_stop(t_makenote *x)
 static void makenote_clear(t_makenote *x)
 {
     t_hang *hang;
-    while (hang = x->x_hang)
+    while ((hang = x->x_hang))
     {
         x->x_hang = hang->h_next;
         clock_free(hang->h_clock);
@@ -1008,7 +977,7 @@ static void makenote_clear(t_makenote *x)
 
 static void makenote_setup(void)
 {
-    makenote_class = class_new(gensym("makenote"), 
+    makenote_class = class_new(gensym("makenote"),
         (t_newmethod)makenote_new, (t_method)makenote_clear,
         sizeof(t_makenote), 0, A_DEFFLOAT, A_DEFFLOAT, 0);
     class_addfloat(makenote_class, makenote_float);
@@ -1038,9 +1007,10 @@ static void *stripnote_new(void )
     x->x_velout = outlet_new(&x->x_obj, &s_float);
     return (x);
 }
-    
+
 static void stripnote_float(t_stripnote *x, t_float f)
 {
+    t_hang *hang;
     if (!x->x_velo) return;
     outlet_float(x->x_velout, x->x_velo);
     outlet_float(x->x_pitchout, f);
@@ -1179,7 +1149,7 @@ static void poly_free(t_poly *x)
 
 static void poly_setup(void)
 {
-    poly_class = class_new(gensym("poly"), 
+    poly_class = class_new(gensym("poly"),
         (t_newmethod)poly_new, (t_method)poly_free,
         sizeof(t_poly), 0, A_DEFFLOAT, A_DEFFLOAT, 0);
     class_addfloat(poly_class, poly_float);
@@ -1225,7 +1195,7 @@ static void bag_float(t_bag *x, t_float f)
         if (!x->x_first) x->x_first = bagelem;
         else    /* LATER replace with a faster algorithm */
         {
-            for (e2 = x->x_first; e3 = e2->e_next; e2 = e3)
+            for (e2 = x->x_first; (e3 = e2->e_next); e2 = e3)
                 ;
             e2->e_next = bagelem;
         }
@@ -1240,7 +1210,7 @@ static void bag_float(t_bag *x, t_float f)
             freebytes(bagelem, sizeof(*bagelem));
             return;
         }
-        for (e2 = x->x_first; e3 = e2->e_next; e2 = e3)
+        for (e2 = x->x_first; (e3 = e2->e_next); e2 = e3)
             if (e3->e_value == f)
         {
             e2->e_next = e3->e_next;
@@ -1253,7 +1223,7 @@ static void bag_float(t_bag *x, t_float f)
 static void bag_flush(t_bag *x)
 {
     t_bagelem *bagelem;
-    while (bagelem = x->x_first)
+    while ((bagelem = x->x_first))
     {
         outlet_float(x->x_obj.ob_outlet, bagelem->e_value);
         x->x_first = bagelem->e_next;
@@ -1264,7 +1234,7 @@ static void bag_flush(t_bag *x)
 static void bag_clear(t_bag *x)
 {
     t_bagelem *bagelem;
-    while (bagelem = x->x_first)
+    while ((bagelem = x->x_first))
     {
         x->x_first = bagelem->e_next;
         freebytes(bagelem, sizeof(*bagelem));
@@ -1273,7 +1243,7 @@ static void bag_clear(t_bag *x)
 
 static void bag_setup(void)
 {
-    bag_class = class_new(gensym("bag"), 
+    bag_class = class_new(gensym("bag"),
         (t_newmethod)bag_new, (t_method)bag_clear,
         sizeof(t_bag), 0, 0);
     class_addfloat(bag_class, bag_float);
@@ -1281,6 +1251,10 @@ static void bag_setup(void)
     class_addmethod(bag_class, (t_method)bag_clear, gensym("clear"), 0);
 }
 
+void sys_setmidiprefix(const char *prefix)
+{
+}
+
 void x_midi_setup(void)
 {
     midiin_setup();
diff --git a/pd/src/x_misc.c b/pd/src/x_misc.c
index f313041026ea6d0ec14b1553aa271febf20d4730..9f019cbf0d8905ede5aab1b7761eac19721fc390 100644
--- a/pd/src/x_misc.c
+++ b/pd/src/x_misc.c
@@ -390,6 +390,406 @@ static void realtime_setup(void)
         0);
 }
 
+/* ---------- oscparse - parse simple OSC messages ----------------- */
+
+static t_class *oscparse_class;
+
+typedef struct _oscparse
+{
+    t_object x_obj;
+} t_oscparse;
+
+#define ROUNDUPTO4(x) (((x) + 3) & (~3))
+
+#define READINT(x)  ((((int)(((x)  )->a_w.w_float)) & 0xff) << 24) | \
+                    ((((int)(((x)+1)->a_w.w_float)) & 0xff) << 16) | \
+                    ((((int)(((x)+2)->a_w.w_float)) & 0xff) << 8) | \
+                    ((((int)(((x)+3)->a_w.w_float)) & 0xff) << 0)
+
+static t_symbol *grabstring(int argc, t_atom *argv, int *ip, int slash)
+{
+    char buf[MAXPDSTRING];
+    int first, nchar;
+    if (slash)
+        while (*ip < argc && argv[*ip].a_w.w_float == '/')
+            (*ip)++;
+    for (nchar = 0; nchar < MAXPDSTRING-1 && *ip < argc; nchar++, (*ip)++)
+    {
+        char c = argv[*ip].a_w.w_float;
+        if (c == 0 || (slash && c == '/'))
+            break;
+        buf[nchar] = c;
+    }
+    buf[nchar] = 0;
+    if (!slash)
+        *ip = ROUNDUPTO4(*ip+1);
+    if (*ip > argc)
+        *ip = argc;
+    return (gensym(buf));
+}
+
+static void oscparse_list(t_oscparse *x, t_symbol *s, int argc, t_atom *argv)
+{
+    int i, j, j2, k, outc = 1, blob = 0, typeonset, dataonset, nfield;
+    t_atom *outv;
+    if (!argc)
+        return;
+    for (i = 0; i < argc; i++)
+        if (argv[i].a_type != A_FLOAT)
+    {
+        pd_error(x, "oscparse: takes numbers only");
+        return;
+    }
+    if (argv[0].a_w.w_float == '#') /* it's a bundle */
+    {
+        if (argv[1].a_w.w_float != 'b' || argc < 16)
+        {
+            pd_error(x, "oscparse: malformed bundle");
+            return;
+        }
+            /* we ignore the timetag since there's no correct way to
+            convert it to Pd logical time that I can think of.  LATER
+            consider at least outputting timetag differentially converted
+            into Pd time units. */
+        for (i = 16; i < argc-4; )
+        {
+            int msize = READINT(argv+i);
+            if (msize <= 0 || msize & 3)
+            {
+                pd_error(x, "oscparse: bad bundle element size");
+                return;
+            }
+            oscparse_list(x, 0, msize, argv+i+4);
+            i += msize+4;
+        }
+        return;
+    }
+    else if (argv[0].a_w.w_float != '/')
+    {
+        pd_error(x, "oscparse: not an OSC message (no leading slash)");
+        return;
+    }
+    for (i = 1; i < argc && argv[i].a_w.w_float != 0; i++)
+        if (argv[i].a_w.w_float == '/')
+            outc++;
+    i = ROUNDUPTO4(i+1);
+    if (argv[i].a_w.w_float != ',' || (i+1) >= argc)
+    {
+        pd_error(x, "oscparse: malformed type string (char %d, index %d)",
+            (int)(argv[i].a_w.w_float), i);
+        return;
+    }
+    typeonset = ++i;
+    for (; i < argc && argv[i].a_w.w_float != 0; i++)
+        if (argv[i].a_w.w_float == 'b')
+            blob = 1;
+    nfield = i - typeonset;
+    if (blob)
+        outc += argc - typeonset;
+    else outc += nfield;
+    outv = (t_atom *)alloca(outc * sizeof(t_atom));
+    dataonset = ROUNDUPTO4(i + 1);
+    /* post("outc %d, typeonset %d, dataonset %d, nfield %d", outc, typeonset,
+        dataonset, nfield); */
+    for (i = j = 0; i < typeonset-1 && argv[i].a_w.w_float != 0 &&
+        j < outc; j++)
+            SETSYMBOL(outv+j, grabstring(argc, argv, &i, 1));
+    for (i = typeonset, k = dataonset; i < typeonset + nfield; i++)
+    {
+        union
+        {
+            float z_f;
+            uint32_t z_i;
+        } z;
+        float f;
+        int blobsize;
+        switch ((int)(argv[i].a_w.w_float))
+        {
+        case 'f':
+            if (k > argc - 4)
+                goto tooshort;
+            z.z_i = READINT(argv+k);
+            f = z.z_f;
+            if (PD_BADFLOAT(f))
+                f = 0;
+            if (j >= outc)
+            {
+                bug("oscparse 1: %d >=%d", j, outc);
+                return;
+            }
+            SETFLOAT(outv+j, f);
+            j++; k += 4;
+            break;
+        case 'i':
+            if (k > argc - 4)
+                goto tooshort;
+            if (j >= outc)
+            {
+                bug("oscparse 2");
+                return;
+            }
+            SETFLOAT(outv+j, READINT(argv+k));
+            j++; k += 4;
+            break;
+        case 's':
+            if (j >= outc)
+            {
+                bug("oscparse 3");
+                return;
+            }
+            SETSYMBOL(outv+j, grabstring(argc, argv, &k, 0));
+            j++;
+            break;
+        case 'b':
+            if (k > argc - 4)
+                goto tooshort;
+            blobsize = READINT(argv+k);
+            k += 4;
+            if (blobsize < 0 || blobsize > argc - k)
+                goto tooshort;
+            if (j + blobsize + 1 > outc)
+            {
+                bug("oscparse 4");
+                return;
+            }
+            if (k + blobsize > argc)
+                goto tooshort;
+            SETFLOAT(outv+j, blobsize);
+            j++;
+            for (j2 = 0; j2 < blobsize; j++, j2++, k++)
+                SETFLOAT(outv+j, argv[k].a_w.w_float);
+            k = ROUNDUPTO4(k);
+            break;
+        default:
+            pd_error(x, "oscparse: unknown tag '%c' (%d)",
+                (int)(argv[i].a_w.w_float), (int)(argv[i].a_w.w_float));
+        }
+    }
+    outlet_list(x->x_obj.ob_outlet, 0, j, outv);
+    return;
+tooshort:
+    pd_error(x, "oscparse: OSC message ended prematurely");
+}
+
+static t_oscparse *oscparse_new(t_symbol *s, int argc, t_atom *argv)
+{
+    t_oscparse *x = (t_oscparse *)pd_new(oscparse_class);
+    outlet_new(&x->x_obj, gensym("list"));
+    return (x);
+}
+
+void oscparse_setup(void)
+{
+    oscparse_class = class_new(gensym("oscparse"), (t_newmethod)oscparse_new,
+        0, sizeof(t_oscparse), 0, A_GIMME, 0);
+    class_addlist(oscparse_class, oscparse_list);
+}
+
+/* --------- oscformat - format simple OSC messages -------------- */
+static t_class *oscformat_class;
+
+typedef struct _oscformat
+{
+    t_object x_obj;
+    char *x_pathbuf;
+    int x_pathsize;
+    t_symbol *x_format;
+} t_oscformat;
+
+static void oscformat_set(t_oscformat *x, t_symbol *s, int argc, t_atom *argv)
+{
+    char buf[MAXPDSTRING];
+    int i, newsize;
+    *x->x_pathbuf = 0;
+    buf[0] = '/';
+    for (i = 0; i < argc; i++)
+    {
+        char *where = (argv[i].a_type == A_SYMBOL &&
+            *argv[i].a_w.w_symbol->s_name == '/' ? buf : buf+1);
+        atom_string(&argv[i], where, MAXPDSTRING-1);
+        if ((newsize = strlen(buf) + strlen(x->x_pathbuf) + 1) > x->x_pathsize)
+        {
+            x->x_pathbuf = resizebytes(x->x_pathbuf, x->x_pathsize, newsize);
+            x->x_pathsize = newsize;
+        }
+        strcat(x->x_pathbuf, buf);
+    }
+}
+
+static void oscformat_format(t_oscformat *x, t_symbol *s)
+{
+    char *sp;
+    for (sp = s->s_name; *sp; sp++)
+    {
+        if (*sp != 'f' && *sp != 'i' && *sp != 's' && *sp != 'b')
+        {
+            pd_error(x,
+                "oscformat '%s' may only contain 'f', 'i'. 's', and/or 'b'",
+                    sp);
+            return;
+        }
+    }
+    x->x_format = s;
+}
+
+#define WRITEINT(msg, i)    SETFLOAT((msg),   (((i) >> 24) & 0xff)); \
+                            SETFLOAT((msg)+1, (((i) >> 16) & 0xff)); \
+                            SETFLOAT((msg)+2, (((i) >>  8) & 0xff)); \
+                            SETFLOAT((msg)+3, (((i)      ) & 0xff))
+
+static void putstring(t_atom *msg, int *ip, const char *s)
+{
+    const char *sp = s;
+    do
+    {
+        SETFLOAT(&msg[*ip], *sp & 0xff);
+        (*ip)++;
+    }
+    while (*sp++);
+    while (*ip & 3)
+    {
+        SETFLOAT(&msg[*ip], 0);
+        (*ip)++;
+    }
+}
+
+static void oscformat_list(t_oscformat *x, t_symbol *s, int argc, t_atom *argv)
+{
+    int typeindex = 0, j, msgindex, msgsize, datastart, ndata;
+    t_atom *msg;
+    char *sp, *formatp = x->x_format->s_name, typecode;
+        /* pass 1: go through args to find overall message size */
+    for (j = ndata = 0, sp = formatp, msgindex = 0; j < argc;)
+    {
+        if (*sp)
+            typecode = *sp++;
+        else if (argv[j].a_type == A_SYMBOL)
+            typecode = 's';
+        else typecode = 'f';
+        if (typecode == 's')
+            msgindex += ROUNDUPTO4(strlen(argv[j].a_w.w_symbol->s_name) + 1);
+        else if (typecode == 'b')
+        {
+            int blobsize = 0x7fffffff, blobindex;
+                /* check if we have a nonnegative size field */
+            if (argv[j].a_type == A_FLOAT &&
+                (int)(argv[j].a_w.w_float) >= 0)
+                    blobsize = (int)(argv[j].a_w.w_float);
+            if (blobsize > argc - j - 1)
+                blobsize = argc - j - 1;    /* if no or bad size, eat it all */
+            msgindex += 4 + ROUNDUPTO4(blobsize);
+            j += blobsize;
+        }
+        else msgindex += 4;
+        j++;
+        ndata++;
+    }
+    datastart = ROUNDUPTO4(strlen(x->x_pathbuf)+1) + ROUNDUPTO4(ndata + 2);
+    msgsize = datastart + msgindex;
+    msg = (t_atom *)alloca(msgsize * sizeof(t_atom));
+    putstring(msg, &typeindex, x->x_pathbuf);
+    SETFLOAT(&msg[typeindex], ',');
+    typeindex++;
+        /* pass 2: fill in types and data portion of packet */
+    for (j = 0, sp = formatp, msgindex = datastart; j < argc;)
+    {
+        if (*sp)
+            typecode = *sp++;
+        else if (argv[j].a_type == A_SYMBOL)
+            typecode = 's';
+        else typecode = 'f';
+        SETFLOAT(&msg[typeindex], typecode & 0xff);
+        typeindex++;
+        if (typecode == 'f')
+        {
+            union
+            {
+                float z_f;
+                uint32_t z_i;
+            } z;
+            z.z_f = atom_getfloat(&argv[j]);
+            WRITEINT(msg+msgindex, z.z_i);
+            msgindex += 4;
+        }
+        else if (typecode == 'i')
+        {
+            int dat = atom_getfloat(&argv[j]);
+            WRITEINT(msg+msgindex, dat);
+            msgindex += 4;
+        }
+        else if (typecode == 's')
+            putstring(msg, &msgindex, argv[j].a_w.w_symbol->s_name);
+        else if (typecode == 'b')
+        {
+            int blobsize = 0x7fffffff, blobindex;
+            if (argv[j].a_type == A_FLOAT &&
+                (int)(argv[j].a_w.w_float) >= 0)
+                    blobsize = (int)(argv[j].a_w.w_float);
+            if (blobsize > argc - j - 1)
+                blobsize = argc - j - 1;
+            WRITEINT(msg+msgindex, blobsize);
+            msgindex += 4;
+            for (blobindex = 0; blobindex < blobsize; blobindex++)
+                SETFLOAT(msg+msgindex+blobindex,
+                    (argv[j+1+blobindex].a_type == A_FLOAT ?
+                        argv[j+1+blobindex].a_w.w_float :
+                        (argv[j+1+blobindex].a_type == A_SYMBOL ?
+                            argv[j+1+blobindex].a_w.w_symbol->s_name[0] & 0xff :
+                            0)));
+            j += blobsize;
+            while (blobsize & 3)
+                SETFLOAT(msg+msgindex+blobsize, 0), blobsize++;
+            msgindex += blobsize;
+        }
+        j++;
+    }
+    SETFLOAT(&msg[typeindex], 0);
+    typeindex++;
+    while (typeindex & 3)
+        SETFLOAT(&msg[typeindex], 0), typeindex++;
+    if (typeindex != datastart || msgindex != msgsize)
+        bug("oscformat: typeindex %d, datastart %d, msgindex %d, msgsize %d",
+            typeindex, datastart, msgindex, msgsize);
+    /* else post("datastart %d, msgsize %d", datastart, msgsize); */
+    outlet_list(x->x_obj.ob_outlet, 0, msgsize, msg);
+}
+
+static void oscformat_free(t_oscformat *x)
+{
+    freebytes(x->x_pathbuf, x->x_pathsize);
+}
+
+static void *oscformat_new(t_symbol *s, int argc, t_atom *argv)
+{
+    t_oscformat *x = (t_oscformat *)pd_new(oscformat_class);
+    outlet_new(&x->x_obj, gensym("list"));
+    x->x_pathbuf = getbytes(1);
+    x->x_pathsize = 1;
+    *x->x_pathbuf = 0;
+    x->x_format = &s_;
+    if (argc > 1 && argv[0].a_type == A_SYMBOL &&
+        argv[1].a_type == A_SYMBOL &&
+            !strcmp(argv[0].a_w.w_symbol->s_name, "-f"))
+    {
+        oscformat_format(x, argv[1].a_w.w_symbol);
+        argc -= 2;
+        argv += 2;
+    }
+    oscformat_set(x, 0, argc, argv);
+    return (x);
+}
+
+void oscformat_setup(void)
+{
+    oscformat_class = class_new(gensym("oscformat"), (t_newmethod)oscformat_new,
+        (t_method)oscformat_free, sizeof(t_oscformat), 0, A_GIMME, 0);
+    class_addmethod(oscformat_class, (t_method)oscformat_set,
+        gensym("set"), A_GIMME, 0);
+    class_addmethod(oscformat_class, (t_method)oscformat_format,
+        gensym("format"), A_DEFSYM, 0);
+    class_addlist(oscformat_class, oscformat_list);
+}
+
 void x_misc_setup(void)
 {
     random_setup();
@@ -400,4 +800,6 @@ void x_misc_setup(void)
     serial_setup();
     cputime_setup();
     realtime_setup();
+    oscparse_setup();
+    oscformat_setup();
 }
diff --git a/pd/src/x_net.c b/pd/src/x_net.c
index bb3c4970274dd7a3c3d6b6fa30e3c4be005ba20d..ed7aa2ec0bc57d53e14ecf582fbce1415ae22439 100644
--- a/pd/src/x_net.c
+++ b/pd/src/x_net.c
@@ -9,7 +9,7 @@
 
 #include <sys/types.h>
 #include <string.h>
-#ifdef MSW
+#ifdef _WIN32
 #include <winsock.h>
 #else
 #include <sys/socket.h>
@@ -20,33 +20,152 @@
 #define SOCKET_ERROR -1
 #endif
 
+#ifdef _WIN32
+# include <malloc.h> /* MSVC or mingw on windows */
+#elif defined(__linux__) || defined(__APPLE__)
+# include <alloca.h> /* linux, mac, mingw, cygwin */
+#else
+# include <stdlib.h> /* BSDs for example */
+#endif
+
 static t_class *netsend_class;
 
 typedef struct _netsend
 {
     t_object x_obj;
-    int x_fd;
+    t_outlet *x_msgout;
+    t_outlet *x_connectout;
+    int x_sockfd;
     int x_protocol;
+    int x_bin;
 } t_netsend;
 
-static void *netsend_new(t_floatarg udpflag)
+static t_class *netreceive_class;
+
+typedef struct _netreceive
+{
+    t_netsend x_ns;
+    int x_nconnections;
+    int x_sockfd;
+    int *x_connections;
+    int x_old;
+} t_netreceive;
+
+static void netreceive_notify(t_netreceive *x, int fd);
+
+static void *netsend_new(t_symbol *s, int argc, t_atom *argv)
 {
     t_netsend *x = (t_netsend *)pd_new(netsend_class);
     outlet_new(&x->x_obj, &s_float);
-    x->x_fd = -1;
-    x->x_protocol = (udpflag != 0 ? SOCK_DGRAM : SOCK_STREAM);
+    x->x_protocol = SOCK_STREAM;
+    x->x_bin = 0;
+    if (argc && argv->a_type == A_FLOAT)
+    {
+        x->x_protocol = (argv->a_w.w_float != 0 ? SOCK_DGRAM : SOCK_STREAM);
+        argc = 0;
+    }
+    else while (argc && argv->a_type == A_SYMBOL &&
+        *argv->a_w.w_symbol->s_name == '-')
+    {
+        if (!strcmp(argv->a_w.w_symbol->s_name, "-b"))
+            x->x_bin = 1;
+        else if (!strcmp(argv->a_w.w_symbol->s_name, "-u"))
+            x->x_protocol = SOCK_DGRAM;
+        else
+        {
+            pd_error(x, "netsend: unknown flag ...");
+            postatom(argc, argv); endpost();
+        }
+        argc--; argv++;
+    }
+    if (argc)
+    {
+        pd_error(x, "netsend: extra arguments ignored:");
+        postatom(argc, argv); endpost();
+    }
+    x->x_sockfd = -1;
+    x->x_msgout = outlet_new(&x->x_obj, &s_anything);
     return (x);
 }
 
+static void netsend_readbin(t_netsend *x, int fd)
+{
+    unsigned char inbuf[MAXPDSTRING];
+    int ret = recv(fd, inbuf, MAXPDSTRING, 0), i;
+    if (!x->x_msgout)
+    {
+        bug("netsend_readbin");
+        return;
+    }
+    if (ret <= 0)
+    {
+        if (ret < 0)
+            sys_sockerror("recv");
+        sys_rmpollfn(fd);
+        sys_closesocket(fd);
+        if (x->x_obj.ob_pd == netreceive_class)
+            netreceive_notify((t_netreceive *)x, fd);
+    }
+    else if (x->x_protocol == SOCK_DGRAM)
+    {
+        t_atom *ap = (t_atom *)alloca(ret * sizeof(t_atom));
+        for (i = 0; i < ret; i++)
+            SETFLOAT(ap+i, inbuf[i]);
+        outlet_list(x->x_msgout, 0, ret, ap);
+    }
+    else
+    {
+        for (i = 0; i < ret; i++)
+            outlet_float(x->x_msgout, inbuf[i]);
+    }
+}
+
+static void netsend_doit(void *z, t_binbuf *b)
+{
+    t_atom messbuf[1024];
+    t_netsend *x = (t_netsend *)z;
+    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, "netreceive: 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 netsend_connect(t_netsend *x, t_symbol *hostname,
     t_floatarg fportno)
 {
-    struct sockaddr_in server;
+    struct sockaddr_in server = {0};
     struct hostent *hp;
     int sockfd;
     int portno = fportno;
     int intarg;
-    if (x->x_fd >= 0)
+    if (x->x_sockfd >= 0)
     {
         error("netsend_connect: already connected");
         return;
@@ -68,6 +187,7 @@ static void netsend_connect(t_netsend *x, t_symbol *hostname,
     if (hp == 0)
     {
         post("bad host?\n");
+        sys_closesocket(sockfd);
         return;
     }
 #if 0
@@ -76,6 +196,10 @@ static void netsend_connect(t_netsend *x, t_symbol *hostname,
         &intarg, sizeof(intarg)) < 0)
             post("setsockopt (SO_RCVBUF) failed\n");
 #endif
+    intarg = 1;
+    if(setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST,
+                  (const void *)&intarg, sizeof(intarg)) < 0)
+        post("setting SO_BROADCAST");
         /* for stream (TCP) sockets, specify "nodelay" */
     if (x->x_protocol == SOCK_STREAM)
     {
@@ -98,67 +222,105 @@ static void netsend_connect(t_netsend *x, t_symbol *hostname,
         sys_closesocket(sockfd);
         return;
     }
-    x->x_fd = sockfd;
+    x->x_sockfd = sockfd;
+    if (x->x_msgout)    /* add polling function for return messages */
+    {
+        if (x->x_bin)
+            sys_addpollfn(sockfd, (t_fdpollfn)netsend_readbin, x);
+        else
+        {
+            t_socketreceiver *y =
+                socketreceiver_new((void *)x, 0, netsend_doit,
+                    x->x_protocol == SOCK_DGRAM);
+            sys_addpollfn(sockfd, (t_fdpollfn)socketreceiver_read, y);
+        }
+    }
     outlet_float(x->x_obj.ob_outlet, 1);
 }
 
 static void netsend_disconnect(t_netsend *x)
 {
-    if (x->x_fd >= 0)
+    if (x->x_sockfd >= 0)
     {
-        sys_closesocket(x->x_fd);
-        x->x_fd = -1;
+        sys_rmpollfn(x->x_sockfd);
+        sys_closesocket(x->x_sockfd);
+        x->x_sockfd = -1;
         outlet_float(x->x_obj.ob_outlet, 0);
     }
 }
 
-static void netsend_send(t_netsend *x, t_symbol *s, int argc, t_atom *argv)
+static int netsend_dosend(t_netsend *x, int sockfd,
+    t_symbol *s, int argc, t_atom *argv)
 {
-    if (x->x_fd >= 0)
+    char *buf, *bp;
+    int length, sent, fail = 0;
+    t_binbuf *b = 0;
+    if (x->x_bin)
+    {
+        int i;
+        buf = alloca(argc);
+        for (i = 0; i < argc; i++)
+            ((unsigned char *)buf)[i] = atom_getfloatarg(i, argc, argv);
+        length = argc;
+    }
+    else
     {
-        t_binbuf *b = binbuf_new();
-        char *buf, *bp;
-        int length, sent;
         t_atom at;
+        b = binbuf_new();
         binbuf_add(b, argc, argv);
         SETSEMI(&at);
         binbuf_add(b, 1, &at);
         binbuf_gettext(b, &buf, &length);
-        for (bp = buf, sent = 0; sent < length;)
+    }
+    for (bp = buf, sent = 0; sent < length;)
+    {
+        static double lastwarntime;
+        static double pleasewarn;
+        double timebefore = sys_getrealtime();
+        int res = send(sockfd, bp, length-sent, 0);
+        double timeafter = sys_getrealtime();
+        int late = (timeafter - timebefore > 0.005);
+        if (late || pleasewarn)
         {
-            static double lastwarntime;
-            static double pleasewarn;
-            double timebefore = sys_getrealtime();
-            int res = send(x->x_fd, bp, length-sent, 0);
-            double timeafter = sys_getrealtime();
-            int late = (timeafter - timebefore > 0.005);
-            if (late || pleasewarn)
+            if (timeafter > lastwarntime + 2)
             {
-                if (timeafter > lastwarntime + 2)
-                {
-                     post("netsend blocked %d msec",
-                        (int)(1000 * ((timeafter - timebefore) + pleasewarn)));
-                     pleasewarn = 0;
-                     lastwarntime = timeafter;
-                }
-                else if (late) pleasewarn += timeafter - timebefore;
-            }
-            if (res <= 0)
-            {
-                sys_sockerror("netsend");
-                netsend_disconnect(x);
-                break;
-            }
-            else
-            {
-                sent += res;
-                bp += res;
+                 post("netsend/netreceive blocked %d msec",
+                    (int)(1000 * ((timeafter - timebefore) +
+                        pleasewarn)));
+                 pleasewarn = 0;
+                 lastwarntime = timeafter;
             }
+            else if (late) pleasewarn += timeafter - timebefore;
+        }
+        if (res <= 0)
+        {
+            sys_sockerror("netsend");
+            fail = 1;
+            break;
         }
+        else
+        {
+            sent += res;
+            bp += res;
+        }
+    }
+    done:
+    if (!x->x_bin)
+    {
         t_freebytes(buf, length);
         binbuf_free(b);
     }
-    else error("netsend: not connected");
+    return (fail);
+}
+
+
+static void netsend_send(t_netsend *x, t_symbol *s, int argc, t_atom *argv)
+{
+    if (x->x_sockfd >= 0)
+    {
+        if (netsend_dosend(x, x->x_sockfd, s, argc, argv))
+            netsend_disconnect(x);
+    }
 }
 
 static void netsend_free(t_netsend *x)
@@ -170,7 +332,7 @@ static void netsend_setup(void)
 {
     netsend_class = class_new(gensym("netsend"), (t_newmethod)netsend_new,
         (t_method)netsend_free,
-        sizeof(t_netsend), 0, A_DEFFLOAT, 0);
+        sizeof(t_netsend), 0, A_GIMME, 0);
     class_addmethod(netsend_class, (t_method)netsend_connect,
         gensym("connect"), A_SYMBOL, A_FLOAT, 0);
     class_addmethod(netsend_class, (t_method)netsend_disconnect,
@@ -180,184 +342,229 @@ static void netsend_setup(void)
 }
 
 /* ----------------------------- netreceive ------------------------- */
-
-static t_class *netreceive_class;
-
-typedef struct _netreceive
-{
-    t_object x_obj;
-    t_outlet *x_msgout;
-    t_outlet *x_connectout;
-    int x_acceptsocket;
-    int x_connectsocket;
-    int x_nconnections;
-    int x_udp;
-} t_netreceive;
-
-static void netreceive_notify(t_netreceive *x)
-{
-    outlet_float(x->x_connectout, --x->x_nconnections);
-}
-
-static void netreceive_doit(void *z, t_binbuf *b)
+static void netreceive_notify(t_netreceive *x, int fd)
 {
-    t_netreceive *x = (t_netreceive *)z;
-    int msg, natom = binbuf_getnatom(b);
-    t_atom *at = binbuf_getvec(b);
-    for (msg = 0; msg < natom;)
+    int i;
+    for (i = 0; i < x->x_nconnections; i++)
     {
-        int emsg;
-        for (emsg = msg; emsg < natom && at[emsg].a_type != A_COMMA
-            && at[emsg].a_type != A_SEMI; emsg++)
-                ;
-        if (emsg > msg)
+        if (x->x_connections[i] == fd)
         {
-            int i;
-            for (i = msg; i < emsg; i++)
-                if (at[i].a_type == A_DOLLAR || at[i].a_type == A_DOLLSYM)
-            {
-                pd_error(x, "netreceive: 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);
+            memmove(x->x_connections+i, x->x_connections+(i+1),
+                sizeof(int) * (x->x_nconnections - (i+1)));
+            x->x_connections = (int *)t_resizebytes(x->x_connections,
+                x->x_nconnections * sizeof(int),
+                    (x->x_nconnections-1) * sizeof(int));
+            x->x_nconnections--;
         }
-    nodice:
-        msg = emsg + 1;
     }
+    outlet_float(x->x_ns.x_connectout, x->x_nconnections);
 }
 
 static void netreceive_connectpoll(t_netreceive *x)
 {
-    int fd = accept(x->x_connectsocket, 0, 0);
+    int fd = accept(x->x_ns.x_sockfd, 0, 0);
     if (fd < 0) post("netreceive: accept failed");
     else
     {
-        t_socketreceiver *y = socketreceiver_new((void *)x, 
+        int nconnections = x->x_nconnections+1;
+
+        x->x_connections = (int *)t_resizebytes(x->x_connections,
+            x->x_nconnections * sizeof(int), nconnections * sizeof(int));
+        x->x_connections[x->x_nconnections] = fd;
+        if (x->x_ns.x_bin)
+            sys_addpollfn(fd, (t_fdpollfn)netsend_readbin, x);
+        else
+        {
+            t_socketreceiver *y = socketreceiver_new((void *)x,
             (t_socketnotifier)netreceive_notify,
-                (x->x_msgout ? netreceive_doit : 0), 0);
-        sys_addpollfn(fd, (t_fdpollfn)socketreceiver_read, y);
-        x->x_acceptsocket = fd;
-        outlet_float(x->x_connectout, ++x->x_nconnections);
+                (x->x_ns.x_msgout ? netsend_doit : 0), 0);
+            sys_addpollfn(fd, (t_fdpollfn)socketreceiver_read, y);
+        }
+        outlet_float(x->x_ns.x_connectout, (x->x_nconnections = nconnections));
     }
 }
 
-static void *netreceive_new(t_symbol *compatflag,
-    t_floatarg fportno, t_floatarg udpflag)
+static void netreceive_closeall(t_netreceive *x)
 {
-    t_netreceive *x;
-    struct sockaddr_in server;
-    int sockfd, portno = fportno, udp = (udpflag != 0);
-    int old = !strcmp(compatflag->s_name , "old");
-    int intarg;
-        /* create a socket */
-    sockfd = socket(AF_INET, (udp ? SOCK_DGRAM : SOCK_STREAM), 0);
-#if 0
-    fprintf(stderr, "receive socket %d\n", sockfd);
-#endif
-    if (sockfd < 0)
+    int i;
+    for (i = 0; i < x->x_nconnections; i++)
+    {
+        sys_rmpollfn(x->x_connections[i]);
+        sys_closesocket(x->x_connections[i]);
+    }
+    x->x_connections = (int *)t_resizebytes(x->x_connections,
+        x->x_nconnections * sizeof(int), 0);
+    x->x_nconnections = 0;
+    if (x->x_ns.x_sockfd >= 0)
+    {
+        sys_rmpollfn(x->x_ns.x_sockfd);
+        sys_closesocket(x->x_ns.x_sockfd);
+    }
+    x->x_ns.x_sockfd = -1;
+}
+
+static void netreceive_listen(t_netreceive *x, t_floatarg fportno)
+{
+    int portno = fportno, intarg;
+    struct sockaddr_in server = {0};
+    netreceive_closeall(x);
+    if (portno <= 0)
+        return;
+    x->x_ns.x_sockfd = socket(AF_INET, x->x_ns.x_protocol, 0);
+    if (x->x_ns.x_sockfd < 0)
     {
         sys_sockerror("socket");
-        return (0);
+        return;
     }
-    server.sin_family = AF_INET;
-    server.sin_addr.s_addr = INADDR_ANY;
+#if 0
+    fprintf(stderr, "receive socket %d\n", x->x_ sockfd);
+#endif
 
 #if 1
         /* ask OS to allow another Pd to repoen this port after we close it. */
     intarg = 1;
-    if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
+    if (setsockopt(x->x_ns.x_sockfd, SOL_SOCKET, SO_REUSEADDR,
         (char *)&intarg, sizeof(intarg)) < 0)
-            post("setsockopt (SO_REUSEADDR) failed\n");
+            post("netreceive: setsockopt (SO_REUSEADDR) failed\n");
 #endif
 #if 0
     intarg = 0;
-    if (setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF,
+    if (setsockopt(x->x_ns.x_sockfd, SOL_SOCKET, SO_RCVBUF,
         &intarg, sizeof(intarg)) < 0)
             post("setsockopt (SO_RCVBUF) failed\n");
 #endif
+    intarg = 1;
+    if (setsockopt(x->x_ns.x_sockfd, SOL_SOCKET, SO_BROADCAST,
+        (const void *)&intarg, sizeof(intarg)) < 0)
+            post("netreceive: failed to sett SO_BROADCAST");
         /* Stream (TCP) sockets are set NODELAY */
-    if (!udp)
+    if (x->x_ns.x_protocol == SOCK_STREAM)
     {
         intarg = 1;
-        if (setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY,
+        if (setsockopt(x->x_ns.x_sockfd, IPPROTO_TCP, TCP_NODELAY,
             (char *)&intarg, sizeof(intarg)) < 0)
                 post("setsockopt (TCP_NODELAY) failed\n");
     }
-        /* assign server port number */
+        /* assign server port number etc */
+    server.sin_family = AF_INET;
+    server.sin_addr.s_addr = INADDR_ANY;
     server.sin_port = htons((u_short)portno);
 
         /* name the socket */
-    if (bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0)
+    if (bind(x->x_ns.x_sockfd, (struct sockaddr *)&server, sizeof(server)) < 0)
     {
         sys_sockerror("bind");
-        sys_closesocket(sockfd);
-        return (0);
-    }
-    x = (t_netreceive *)pd_new(netreceive_class);
-    if (old)
-    {
-        /* old style, nonsecure version */
-        x->x_msgout = 0;
+        sys_closesocket(x->x_ns.x_sockfd);
+        x->x_ns.x_sockfd = -1;
+        return;
     }
-    else x->x_msgout = outlet_new(&x->x_obj, &s_anything);
-
-    x->x_acceptsocket = -1;
 
-    if (udp)        /* datagram protocol */
+    if (x->x_ns.x_protocol == SOCK_DGRAM)        /* datagram protocol */
     {
-        t_socketreceiver *y = socketreceiver_new((void *)x, 
-            (t_socketnotifier)netreceive_notify,
-                (x->x_msgout ? netreceive_doit : 0), 1);
-        sys_addpollfn(sockfd, (t_fdpollfn)socketreceiver_read, y);
-        x->x_connectout = 0;
+        if (x->x_ns.x_bin)
+            sys_addpollfn(x->x_ns.x_sockfd, (t_fdpollfn)netsend_readbin, x);
+        else
+        {
+            t_socketreceiver *y = socketreceiver_new((void *)x,
+                (t_socketnotifier)netreceive_notify,
+                    (x->x_ns.x_msgout ? netsend_doit : 0), 1);
+            sys_addpollfn(x->x_ns.x_sockfd, (t_fdpollfn)socketreceiver_read, y);
+            x->x_ns.x_connectout = 0;
+        }
     }
     else        /* streaming protocol */
     {
-        if (listen(sockfd, 5) < 0)
+        if (listen(x->x_ns.x_sockfd, 5) < 0)
         {
             sys_sockerror("listen");
-            sys_closesocket(sockfd);
-            sockfd = -1;
+            sys_closesocket(x->x_ns.x_sockfd);
+            x->x_ns.x_sockfd = -1;
         }
         else
         {
-            sys_addpollfn(sockfd, (t_fdpollfn)netreceive_connectpoll, x);
-            x->x_connectout = outlet_new(&x->x_obj, &s_float);
+            sys_addpollfn(x->x_ns.x_sockfd, (t_fdpollfn)netreceive_connectpoll, x);
+            x->x_ns.x_connectout = outlet_new(&x->x_ns.x_obj, &s_float);
         }
     }
-    x->x_connectsocket = sockfd;
-    x->x_nconnections = 0;
-    x->x_udp = udp;
+}
 
-    return (x);
+
+static void netreceive_send(t_netreceive *x,
+    t_symbol *s, int argc, t_atom *argv)
+{
+    int i;
+    for (i = 0; i < x->x_nconnections; i++)
+    {
+        if (netsend_dosend(&x->x_ns, x->x_connections[i], s, argc, argv))
+            pd_error(x, "netreceive send message failed");
+                /* should we now close the connection? */
+    }
 }
 
-static void netreceive_free(t_netreceive *x)
+static void *netreceive_new(t_symbol *s, int argc, t_atom *argv)
 {
-        /* LATER make me clean up open connections */
-    if (x->x_connectsocket >= 0)
+    t_netreceive *x = (t_netreceive *)pd_new(netreceive_class);
+    int portno = 0;
+    x->x_ns.x_protocol = SOCK_STREAM;
+    x->x_old = 0;
+    x->x_ns.x_bin = 0;
+    x->x_nconnections = 0;
+    x->x_connections = (int *)t_getbytes(0);
+    x->x_ns.x_sockfd = -1;
+    if (argc && argv->a_type == A_FLOAT)
     {
-        sys_rmpollfn(x->x_connectsocket);
-        if (x->x_acceptsocket >= 0)
-            sys_rmpollfn(x->x_acceptsocket);
-        sys_closesocket(x->x_connectsocket);
+        portno = atom_getfloatarg(0, argc, argv);
+        x->x_ns.x_protocol = (atom_getfloatarg(1, argc, argv) != 0 ?
+            SOCK_DGRAM : SOCK_STREAM);
+        x->x_old = (!strcmp(atom_getsymbolarg(2, argc, argv)->s_name, "old"));
+        argc = 0;
     }
+    else
+    {
+        while (argc && argv->a_type == A_SYMBOL &&
+            *argv->a_w.w_symbol->s_name == '-')
+        {
+            if (!strcmp(argv->a_w.w_symbol->s_name, "-b"))
+                x->x_ns.x_bin = 1;
+            else if (!strcmp(argv->a_w.w_symbol->s_name, "-u"))
+                x->x_ns.x_protocol = SOCK_DGRAM;
+            else
+            {
+                pd_error(x, "netreceive: unknown flag ...");
+                postatom(argc, argv); endpost();
+            }
+            argc--; argv++;
+        }
+    }
+    if (argc && argv->a_type == A_FLOAT)
+        portno = argv->a_w.w_float, argc--, argv++;
+    if (argc)
+    {
+        pd_error(x, "netreceive: extra arguments ignored:");
+        postatom(argc, argv); endpost();
+    }
+    if (x->x_old)
+    {
+        /* old style, nonsecure version */
+        x->x_ns.x_msgout = 0;
+    }
+    else x->x_ns.x_msgout = outlet_new(&x->x_ns.x_obj, &s_anything);
+        /* create a socket */
+    if (portno > 0)
+        netreceive_listen(x, portno);
+
+    return (x);
 }
 
 static void netreceive_setup(void)
 {
     netreceive_class = class_new(gensym("netreceive"),
-        (t_newmethod)netreceive_new, (t_method)netreceive_free,
-        sizeof(t_netreceive), CLASS_NOINLET, A_DEFFLOAT, A_DEFFLOAT, 
-            A_DEFSYM, 0);
+        (t_newmethod)netreceive_new, (t_method)netreceive_closeall,
+        sizeof(t_netreceive), 0, A_GIMME, 0);
+    class_addmethod(netreceive_class, (t_method)netreceive_listen,
+        gensym("listen"), A_FLOAT, 0);
+    class_addmethod(netreceive_class, (t_method)netreceive_send,
+        gensym("send"), A_GIMME, 0);
 }
 
 void x_net_setup(void)
diff --git a/pd/src/x_qlist.c b/pd/src/x_qlist.c
deleted file mode 100644
index a2300b8776d4b3910f6294d1b167c51385991142..0000000000000000000000000000000000000000
--- a/pd/src/x_qlist.c
+++ /dev/null
@@ -1,346 +0,0 @@
-/* Copyright (c) 1997-1999 Miller Puckette and others.
-* For information on usage and redistribution, and for a DISCLAIMER OF ALL
-* WARRANTIES, see the file, "LICENSE.txt," in this distribution.  */
-
-#include "config.h"
-
-#include "m_pd.h"
-#include <string.h>
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#ifdef HAVE_IO_H
-#include <io.h>
-#endif
-
-typedef struct _qlist
-{
-    t_object x_ob;
-    t_outlet *x_bangout;
-    void *x_binbuf;
-    int x_onset;                /* playback position */
-    t_clock *x_clock;
-    t_float x_tempo;
-    double x_whenclockset;
-    t_float x_clockdelay;
-    t_symbol *x_dir;
-    t_canvas *x_canvas;
-    int x_reentered;
-} t_qlist;
-
-static void qlist_tick(t_qlist *x);
-
-static t_class *qlist_class;
-
-static void *qlist_new( void)
-{
-    t_qlist *x = (t_qlist *)pd_new(qlist_class);
-    x->x_binbuf = binbuf_new();
-    x->x_clock = clock_new(x, (t_method)qlist_tick);
-    outlet_new(&x->x_ob, &s_list);
-    x->x_bangout = outlet_new(&x->x_ob, &s_bang);
-    x->x_onset = 0x7fffffff;
-    x->x_tempo = 1;
-    x->x_whenclockset = 0;
-    x->x_clockdelay = 0;
-    x->x_canvas = canvas_getcurrent();
-    x->x_reentered = 0;
-    return (x);
-}
-
-static void qlist_rewind(t_qlist *x)
-{
-    x->x_onset = 0;
-    if (x->x_clock) clock_unset(x->x_clock);
-    x->x_whenclockset = 0;
-    x->x_reentered = 1;
-}
-
-static void qlist_donext(t_qlist *x, int drop, int automatic)
-{
-    t_pd *target = 0;
-    while (1)
-    {
-        int argc = binbuf_getnatom(x->x_binbuf),
-            count, onset = x->x_onset, onset2, wasreentered;
-        t_atom *argv = binbuf_getvec(x->x_binbuf);
-        t_atom *ap = argv + onset, *ap2;
-        if (onset >= argc) goto end;
-        while (ap->a_type == A_SEMI || ap->a_type == A_COMMA)
-        {
-            if (ap->a_type == A_SEMI) target = 0;
-            onset++, ap++;
-            if (onset >= argc) goto end;
-        }
-
-        if (!target && ap->a_type == A_FLOAT)
-        {
-            ap2 = ap + 1;
-            onset2 = onset + 1;
-            while (onset2 < argc && ap2->a_type == A_FLOAT)
-                onset2++, ap2++;
-            x->x_onset = onset2;
-            if (automatic)
-            {
-                clock_delay(x->x_clock,
-                    x->x_clockdelay = ap->a_w.w_float * x->x_tempo);
-                x->x_whenclockset = clock_getsystime();
-            }
-            else outlet_list(x->x_ob.ob_outlet, 0, onset2-onset, ap);
-            return;
-        }
-        ap2 = ap + 1;
-        onset2 = onset + 1;
-        while (onset2 < argc &&
-            (ap2->a_type == A_FLOAT || ap2->a_type == A_SYMBOL))
-                onset2++, ap2++;
-        x->x_onset = onset2;
-        count = onset2 - onset;
-        if (!target)
-        {
-            if (ap->a_type != A_SYMBOL) continue;
-            else if (!(target = ap->a_w.w_symbol->s_thing))
-            {
-                pd_error(x, "qlist: %s: no such object",
-                    ap->a_w.w_symbol->s_name);
-                continue;
-            }
-            ap++;
-            onset++;
-            count--;
-            if (!count) 
-            {
-                x->x_onset = onset2;
-                continue;
-            }
-        }
-        wasreentered = x->x_reentered;
-        x->x_reentered = 0;
-        if (!drop)
-        {   
-            if (ap->a_type == A_FLOAT)
-                typedmess(target, &s_list, count, ap);
-            else if (ap->a_type == A_SYMBOL)
-                typedmess(target, ap->a_w.w_symbol, count-1, ap+1);
-        }
-        if (x->x_reentered)
-            return;
-        x->x_reentered = wasreentered;
-    }  /* while (1); never falls through */
-
-end:
-    x->x_onset = 0x7fffffff;
-    outlet_bang(x->x_bangout);
-    x->x_whenclockset = 0;
-}
-
-static void qlist_next(t_qlist *x, t_floatarg drop)
-{
-    qlist_donext(x, drop != 0, 0);
-}
-
-static void qlist_bang(t_qlist *x)
-{
-    qlist_rewind(x);
-    qlist_donext(x, 0, 1);
-}
-
-static void qlist_tick(t_qlist *x)
-{
-    x->x_whenclockset = 0;
-    qlist_donext(x, 0, 1);
-}
-
-static void qlist_add(t_qlist *x, t_symbol *s, int ac, t_atom *av)
-{
-    t_atom a;
-    SETSEMI(&a);
-    binbuf_add(x->x_binbuf, ac, av);
-    binbuf_add(x->x_binbuf, 1, &a);
-}
-
-static void qlist_add2(t_qlist *x, t_symbol *s, int ac, t_atom *av)
-{
-    binbuf_add(x->x_binbuf, ac, av);
-}
-
-static void qlist_clear(t_qlist *x)
-{
-    qlist_rewind(x);
-    binbuf_clear(x->x_binbuf);
-}
-
-static void qlist_set(t_qlist *x, t_symbol *s, int ac, t_atom *av)
-{
-    qlist_clear(x);
-    qlist_add(x, s, ac, av);
-}
-
-static void qlist_read(t_qlist *x, t_symbol *filename, t_symbol *format)
-{
-    int cr = 0;
-    if (!strcmp(format->s_name, "cr"))
-        cr = 1;
-    else if (*format->s_name)
-        pd_error(x, "qlist_read: unknown flag: %s", format->s_name);
-
-    if (binbuf_read_via_canvas(x->x_binbuf, filename->s_name, x->x_canvas, cr))
-            pd_error(x, "%s: read failed", filename->s_name);
-    x->x_onset = 0x7fffffff;
-    x->x_reentered = 1;
-}
-
-static void qlist_write(t_qlist *x, t_symbol *filename, t_symbol *format)
-{
-    int cr = 0;
-    char buf[MAXPDSTRING];
-    canvas_makefilename(x->x_canvas, filename->s_name,
-        buf, MAXPDSTRING);
-    if (!strcmp(format->s_name, "cr"))
-        cr = 1;
-    else if (*format->s_name)
-        pd_error(x, "qlist_read: unknown flag: %s", format->s_name);
-    if (binbuf_write(x->x_binbuf, buf, "", cr))
-            pd_error(x, "%s: write failed", filename->s_name);
-}
-
-static void qlist_print(t_qlist *x)
-{
-    post("--------- textfile or qlist contents: -----------");
-    binbuf_print(x->x_binbuf);
-}
-
-static void qlist_tempo(t_qlist *x, t_float f)
-{
-    t_float newtempo;
-    if (f < 1e-20) f = 1e-20;
-    else if (f > 1e20) f = 1e20;
-    newtempo = 1./f;
-    if (x->x_whenclockset != 0)
-    {
-        t_float elapsed = clock_gettimesince(x->x_whenclockset);
-        t_float left = x->x_clockdelay - elapsed;
-        if (left < 0) left = 0;
-        left *= newtempo / x->x_tempo;
-        clock_delay(x->x_clock, left);
-    }
-    x->x_tempo = newtempo;
-}
-
-static void qlist_free(t_qlist *x)
-{
-    binbuf_free(x->x_binbuf);
-    if (x->x_clock) clock_free(x->x_clock);
-}
-
-/* -------------------- textfile ------------------------------- */
-
-static t_class *textfile_class;
-typedef t_qlist t_textfile;
-
-static void *textfile_new( void)
-{
-    t_textfile *x = (t_textfile *)pd_new(textfile_class);
-    x->x_binbuf = binbuf_new();
-    outlet_new(&x->x_ob, &s_list);
-    x->x_bangout = outlet_new(&x->x_ob, &s_bang);
-    x->x_onset = 0x7fffffff;
-    x->x_reentered = 0;
-    x->x_tempo = 1;
-    x->x_whenclockset = 0;
-    x->x_clockdelay = 0;
-    x->x_clock = NULL;
-    x->x_canvas = canvas_getcurrent();
-    return (x);
-}
-
-static void textfile_bang(t_textfile *x)
-{
-    int argc = binbuf_getnatom(x->x_binbuf), onset = x->x_onset, onset2;
-    t_atom *argv = binbuf_getvec(x->x_binbuf);
-    t_atom *ap = argv + onset, *ap2;
-    while (onset < argc &&
-        (ap->a_type == A_SEMI || ap->a_type == A_COMMA))
-            onset++, ap++;
-    onset2 = onset;
-    ap2 = ap;
-    while (onset2 < argc &&
-        (ap2->a_type != A_SEMI && ap2->a_type != A_COMMA))
-            onset2++, ap2++;
-    if (onset2 > onset)
-    {
-        x->x_onset = onset2;
-        if (ap->a_type == A_SYMBOL)
-            outlet_anything(x->x_ob.ob_outlet, ap->a_w.w_symbol,
-                onset2-onset-1, ap+1);
-        else outlet_list(x->x_ob.ob_outlet, 0, onset2-onset, ap);
-    }
-    else
-    {
-        x->x_onset = 0x7fffffff;
-        outlet_bang(x->x_bangout);
-    }
-}
-
-static void textfile_rewind(t_qlist *x)
-{
-    x->x_onset = 0;
-}
-
-static void textfile_free(t_textfile *x)
-{
-    binbuf_free(x->x_binbuf);
-}
-
-/* ---------------- global setup function -------------------- */
-
-void x_qlist_setup(void )
-{
-    qlist_class = class_new(gensym("qlist"), (t_newmethod)qlist_new,
-        (t_method)qlist_free, sizeof(t_qlist), 0, 0);
-    class_addmethod(qlist_class, (t_method)qlist_rewind, gensym("rewind"), 0);
-    class_addmethod(qlist_class, (t_method)qlist_next,
-        gensym("next"), A_DEFFLOAT, 0);  
-    class_addmethod(qlist_class, (t_method)qlist_set, gensym("set"),
-        A_GIMME, 0);
-    class_addmethod(qlist_class, (t_method)qlist_clear, gensym("clear"), 0);
-    class_addmethod(qlist_class, (t_method)qlist_add, gensym("add"),
-        A_GIMME, 0);
-    class_addmethod(qlist_class, (t_method)qlist_add2, gensym("add2"),
-        A_GIMME, 0);
-    class_addmethod(qlist_class, (t_method)qlist_add, gensym("append"),
-        A_GIMME, 0);
-    class_addmethod(qlist_class, (t_method)qlist_read, gensym("read"),
-        A_SYMBOL, A_DEFSYM, 0);
-    class_addmethod(qlist_class, (t_method)qlist_write, gensym("write"),
-        A_SYMBOL, A_DEFSYM, 0);
-    class_addmethod(qlist_class, (t_method)qlist_print, gensym("print"),
-        A_DEFSYM, 0);
-    class_addmethod(qlist_class, (t_method)qlist_tempo,
-        gensym("tempo"), A_FLOAT, 0);
-    class_addbang(qlist_class, qlist_bang);
-
-    textfile_class = class_new(gensym("textfile"), (t_newmethod)textfile_new,
-        (t_method)textfile_free, sizeof(t_textfile), 0, 0);
-    class_addmethod(textfile_class, (t_method)textfile_rewind, gensym("rewind"),
-        0);
-    class_addmethod(textfile_class, (t_method)qlist_set, gensym("set"),
-        A_GIMME, 0);
-    class_addmethod(textfile_class, (t_method)qlist_clear, gensym("clear"), 0);
-    class_addmethod(textfile_class, (t_method)qlist_add, gensym("add"),
-        A_GIMME, 0);
-    class_addmethod(textfile_class, (t_method)qlist_add2, gensym("add2"),
-        A_GIMME, 0);
-    class_addmethod(textfile_class, (t_method)qlist_add, gensym("append"),
-        A_GIMME, 0);
-    class_addmethod(textfile_class, (t_method)qlist_read, gensym("read"), 
-        A_SYMBOL, A_DEFSYM, 0);
-    class_addmethod(textfile_class, (t_method)qlist_write, gensym("write"), 
-        A_SYMBOL, A_DEFSYM, 0);
-    class_addmethod(textfile_class, (t_method)qlist_print, gensym("print"),
-        A_DEFSYM, 0);
-    class_addbang(textfile_class, textfile_bang);
-}
-
diff --git a/pd/src/x_time.c b/pd/src/x_time.c
index 5dc9d37ffeda5b2b867b379b6b73aba4206b2c08..66ce261b2974ae0350a5eb2cf6f99465181c91ff 100644
--- a/pd/src/x_time.c
+++ b/pd/src/x_time.c
@@ -6,6 +6,60 @@
 
 #include "m_pd.h"
 #include <stdio.h>
+#include <string.h>
+
+    /* parse a time unit such as "5 msec", "60 perminute", or "1 sample" to
+    a form usable by clock_setunit)( and clock_gettimesincewithunits().
+    This brute-force search through symbols really ought not to be done on
+    the fly for incoming 'tempo' messages, hmm...  This isn't public because
+    its interface migth want to change - but it's used in x_text.c as well
+    as here. */
+void parsetimeunits(void *x, t_float amount, t_symbol *unitname,
+    t_float *unit, int *samps)
+{
+    char *s = unitname->s_name;
+    if (amount <= 0)
+        amount = 1;
+    if (s[0] == 'p' && s[1] == 'e' && s[2] == 'r')  /* starts with 'per' */
+    {
+        char *s2 = s+3;
+        if (!strcmp(s2, "millisecond") || !strcmp(s2, "msec"))  /* msec */
+            *samps = 0, *unit = 1./amount;
+        else if (!strncmp(s2, "sec", 3))        /* seconds */
+            *samps = 0, *unit = 1000./amount;
+        else if (!strncmp(s2, "min", 3))        /* minutes */
+            *samps = 0, *unit = 60000./amount;
+        else if (!strncmp(s2, "sam", 3))        /* samples */
+            *samps = 1, *unit = 1./amount;
+        else goto fail;
+    }
+    else
+    {
+            /* empty string defaults to msec */
+        if (!strcmp(s, "millisecond") || !strcmp(s, "msec"))
+            *samps = 0, *unit = amount;
+        else if (!strncmp(s, "sec", 3))
+            *samps = 0, *unit = 1000.*amount;
+        else if (!strncmp(s, "min", 3))
+            *samps = 0, *unit = 60000.*amount;
+        else if (!strncmp(s, "sam", 3))
+            *samps = 1, *unit = amount;
+        else
+        {
+        fail:
+                /* empty time unit specification defaults to 1 msec for
+                back compatibility, since it's possible someone threw a
+                float argument to timer which had previously been ignored. */
+            if (*s)
+                pd_error(x, "%s: unknown time unit", s);
+            else pd_error(x,
+                "tempo setting needs time unit ('sec', 'samp', 'permin', etc.");
+            *unit = 1;
+            *samps = 0;
+        }
+    }
+}
+
 /* -------------------------- delay ------------------------------ */
 static t_class *delay_class;
 
@@ -16,6 +70,17 @@ typedef struct _delay
     double x_deltime;
 } t_delay;
 
+static void delay_ft1(t_delay *x, t_floatarg g)
+{
+    if (g < 0) g = 0;
+    x->x_deltime = g;
+}
+
+static void delay_tick(t_delay *x)
+{
+    outlet_bang(x->x_obj.ob_outlet);
+}
+
 static void delay_bang(t_delay *x)
 {
     clock_delay(x->x_clock, x->x_deltime);
@@ -26,21 +91,18 @@ static void delay_stop(t_delay *x)
     clock_unset(x->x_clock);
 }
 
-static void delay_ft1(t_delay *x, t_floatarg g)
-{
-    if (g < 0) g = 0;
-    x->x_deltime = g;
-}
-
 static void delay_float(t_delay *x, t_float f)
 {
     delay_ft1(x, f);
     delay_bang(x);
 }
 
-static void delay_tick(t_delay *x)
+static void delay_tempo(t_delay *x, t_symbol *unitname, t_floatarg tempo)
 {
-    outlet_bang(x->x_obj.ob_outlet);
+    t_float unit;
+    int samps;
+    parsetimeunits(x, tempo, unitname, &unit, &samps);
+    clock_setunit(x->x_clock, unit, samps);
 }
 
 static void delay_free(t_delay *x)
@@ -48,25 +110,31 @@ static void delay_free(t_delay *x)
     clock_free(x->x_clock);
 }
 
-static void *delay_new(t_floatarg f)
+static void *delay_new(t_symbol *unitname, t_floatarg f, t_floatarg tempo)
 {
     t_delay *x = (t_delay *)pd_new(delay_class);
     delay_ft1(x, f);
     x->x_clock = clock_new(x, (t_method)delay_tick);
     outlet_new(&x->x_obj, gensym("bang"));
     inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("ft1"));
+    if (tempo != 0)
+        delay_tempo(x, unitname, tempo);
     return (x);
 }
 
 static void delay_setup(void)
 {
     delay_class = class_new(gensym("delay"), (t_newmethod)delay_new,
-        (t_method)delay_free, sizeof(t_delay), 0, A_DEFFLOAT, 0);
-    class_addcreator((t_newmethod)delay_new, gensym("del"), A_DEFFLOAT, 0);
+        (t_method)delay_free, sizeof(t_delay), 0,
+            A_DEFFLOAT, A_DEFFLOAT, A_DEFSYM, 0);
+    class_addcreator((t_newmethod)delay_new, gensym("del"),
+        A_DEFFLOAT, A_DEFFLOAT, A_DEFSYM, 0);
     class_addbang(delay_class, delay_bang);
     class_addmethod(delay_class, (t_method)delay_stop, gensym("stop"), 0);
     class_addmethod(delay_class, (t_method)delay_ft1,
         gensym("ft1"), A_FLOAT, 0);
+    class_addmethod(delay_class, (t_method)delay_tempo,
+        gensym("tempo"), A_FLOAT, A_SYMBOL, 0);
     class_addfloat(delay_class, (t_method)delay_float);
 }
 
@@ -81,6 +149,13 @@ typedef struct _metro
     int x_hit;
 } t_metro;
 
+static void metro_ft1(t_metro *x, t_floatarg g)
+{
+    if (g <= 0) /* as of 0.45, we're willing to try any positive time value */
+        g = 1;  /* but default to 1 (arbitrary and probably not so good) */
+    x->x_deltime = g;
+}
+
 static void metro_tick(t_metro *x)
 {
     x->x_hit = 0;
@@ -105,10 +180,12 @@ static void metro_stop(t_metro *x)
     metro_float(x, 0);
 }
 
-static void metro_ft1(t_metro *x, t_floatarg g)
+static void metro_tempo(t_metro *x, t_symbol *unitname, t_floatarg tempo)
 {
-    if (g < 1) g = 1;
-    x->x_deltime = g;
+    t_float unit;
+    int samps;
+    parsetimeunits(x, tempo, unitname, &unit, &samps);
+    clock_setunit(x->x_clock, unit, samps);
 }
 
 static void metro_free(t_metro *x)
@@ -116,7 +193,7 @@ static void metro_free(t_metro *x)
     clock_free(x->x_clock);
 }
 
-static void *metro_new(t_floatarg f)
+static void *metro_new(t_symbol *unitname, t_floatarg f, t_floatarg tempo)
 {
     t_metro *x = (t_metro *)pd_new(metro_class);
     metro_ft1(x, f);
@@ -124,21 +201,27 @@ static void *metro_new(t_floatarg f)
     x->x_clock = clock_new(x, (t_method)metro_tick);
     outlet_new(&x->x_obj, gensym("bang"));
     inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("ft1"));
+    if (tempo != 0)
+        metro_tempo(x, unitname, tempo);
     return (x);
 }
 
 static void metro_setup(void)
 {
     metro_class = class_new(gensym("metro"), (t_newmethod)metro_new,
-        (t_method)metro_free, sizeof(t_metro), 0, A_DEFFLOAT, 0);
+        (t_method)metro_free, sizeof(t_metro), 0,
+            A_DEFFLOAT, A_DEFFLOAT, A_DEFSYM, 0);
     class_addbang(metro_class, metro_bang);
     class_addmethod(metro_class, (t_method)metro_stop, gensym("stop"), 0);
     class_addmethod(metro_class, (t_method)metro_ft1, gensym("ft1"),
         A_FLOAT, 0);
+    class_addmethod(metro_class, (t_method)metro_tempo,
+        gensym("tempo"), A_FLOAT, A_SYMBOL, 0);
     class_addfloat(metro_class, (t_method)metro_float);
 }
 
 /* -------------------------- line ------------------------------ */
+#define DEFAULTLINEGRAIN 20
 static t_class *line_class;
 
 typedef struct _line
@@ -168,6 +251,8 @@ static void line_tick(t_line *x)
         outlet_float(x->x_obj.ob_outlet,
             x->x_setval + x->x_1overtimediff * (timenow - x->x_prevtime)
                 * (x->x_targetval - x->x_setval));
+        if (x->x_grain <= 0)
+            x->x_grain = DEFAULTLINEGRAIN;
         clock_delay(x->x_clock,
             (x->x_grain > msectogo ? msectogo : x->x_grain));
     }
@@ -188,9 +273,11 @@ static void line_float(t_line *x, t_float f)
         line_tick(x);
         x->x_gotinlet = 0;
         x->x_1overtimediff = 1./ (x->x_targettime - timenow);
+        if (x->x_grain <= 0)
+            x->x_grain = DEFAULTLINEGRAIN;
         clock_delay(x->x_clock,
             (x->x_grain > x->x_in1val ? x->x_in1val : x->x_grain));
-    
+
     }
     else
     {
@@ -232,10 +319,10 @@ static void *line_new(t_floatarg f, t_floatarg grain)
     x->x_1overtimediff = 1;
     x->x_clock = clock_new(x, (t_method)line_tick);
     x->x_targettime = x->x_prevtime = clock_getsystime();
-    if (grain <= 0) grain = 20;
     x->x_grain = grain;
     outlet_new(&x->x_obj, gensym("float"));
     inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("ft1"));
+    floatinlet_new(&x->x_obj, &x->x_grain);
     return (x);
 }
 
@@ -259,33 +346,53 @@ typedef struct _timer
 {
     t_object x_obj;
     double x_settime;
+    double x_moreelapsed;
+    t_float x_unit;
+    int x_samps;
 } t_timer;
 
 static void timer_bang(t_timer *x)
 {
     x->x_settime = clock_getsystime();
+    x->x_moreelapsed = 0;
 }
 
 static void timer_bang2(t_timer *x)
 {
-    outlet_float(x->x_obj.ob_outlet, clock_gettimesince(x->x_settime));
+    outlet_float(x->x_obj.ob_outlet,
+        clock_gettimesincewithunits(x->x_settime, x->x_unit, x->x_samps)
+            + x->x_moreelapsed);
+}
+
+static void timer_tempo(t_timer *x, t_symbol *unitname, t_floatarg tempo)
+{
+    x->x_moreelapsed +=  clock_gettimesincewithunits(x->x_settime,
+        x->x_unit, x->x_samps);
+    x->x_settime = clock_getsystime();
+    parsetimeunits(x, tempo, unitname, &x->x_unit, &x->x_samps);
 }
 
-static void *timer_new(t_floatarg f)
+static void *timer_new(t_symbol *unitname, t_floatarg tempo)
 {
     t_timer *x = (t_timer *)pd_new(timer_class);
+    x->x_unit = 1;
+    x->x_samps = 0;
     timer_bang(x);
     outlet_new(&x->x_obj, gensym("float"));
     inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("bang"), gensym("bang2"));
+    if (tempo != 0)
+        timer_tempo(x, unitname, tempo);
     return (x);
 }
 
 static void timer_setup(void)
 {
     timer_class = class_new(gensym("timer"), (t_newmethod)timer_new, 0,
-        sizeof(t_timer), 0, A_DEFFLOAT, 0);
+        sizeof(t_timer), 0, A_DEFFLOAT, A_DEFSYM, 0);
     class_addbang(timer_class, timer_bang);
     class_addmethod(timer_class, (t_method)timer_bang2, gensym("bang2"), 0);
+    class_addmethod(timer_class, (t_method)timer_tempo,
+        gensym("tempo"), A_FLOAT, A_SYMBOL, 0);
 }
 
 
@@ -419,7 +526,7 @@ static void hang_tick(t_hang *h)
     int i;
     union word *w;
     if (x->x_hang == h) x->x_hang = h->h_next;
-    else for (h2 = x->x_hang; h3 = h2->h_next; h2 = h3)
+    else for (h2 = x->x_hang; (h3 = h2->h_next); h2 = h3)
     {
         if (h3 == h)
         {
@@ -439,6 +546,7 @@ static void hang_tick(t_hang *h)
                 outlet_pointer(p->p_outlet, w->w_gpointer);
             else pd_error(x, "pipe: stale pointer");
             break;
+        default: break;
         }
     }
     hang_free(h);
@@ -478,6 +586,7 @@ static void pipe_list(t_pipe *x, t_symbol *s, int ac, t_atom *av)
                 if (gp->gp_stub) gp->gp_stub->gs_refcount++;
             }
             gp++;
+        default: break;
         }
     }
     for (i = 0, gp = x->x_gp, gp2 = h->h_gp, p = x->x_vec, w = h->h_vec;
@@ -506,17 +615,23 @@ static void pipe_flush(t_pipe *x)
 static void pipe_clear(t_pipe *x)
 {
     t_hang *hang;
-    while (hang = x->x_hang)
+    while ((hang = x->x_hang))
     {
         x->x_hang = hang->h_next;
         hang_free(hang);
     }
 }
 
+static void pipe_free(t_pipe *x)
+{
+    pipe_clear(x);
+    freebytes(x->x_vec, x->x_n * sizeof(*x->x_vec));
+}
+
 static void pipe_setup(void)
 {
-    pipe_class = class_new(gensym("pipe"), 
-        (t_newmethod)pipe_new, (t_method)pipe_clear,
+    pipe_class = class_new(gensym("pipe"),
+        (t_newmethod)pipe_new, (t_method)pipe_free,
         sizeof(t_pipe), 0, A_GIMME, 0);
     class_addlist(pipe_class, pipe_list);
     class_addmethod(pipe_class, (t_method)pipe_flush, gensym("flush"), 0);