From c2014a0a771e621cec552c6ee88daddcb46d13fe Mon Sep 17 00:00:00 2001 From: "N.N." Date: Mon, 21 Nov 2005 22:16:37 +0000 Subject: cyclone alpha55 (see notes.txt for cyclone and shared) svn path=/trunk/externals/miXed/; revision=4011 --- Makefile.common | 32 +++--- Makefile.dirs | 6 +- ViCious/cyclone/makefile | 2 +- ViCious/cyclone/objects | 1 + ViCious/notes.txt | 8 ++ ViCious/pddp/makefile | 2 +- ViCious/toxy/makefile | 2 +- cyclone/Makefile.sources | 1 + cyclone/build_counter | 4 +- cyclone/hammer/seq.c | 58 +++++++--- cyclone/notes.txt | 8 ++ cyclone/sickle/Line.c | 2 +- cyclone/sickle/Makefile.sources | 1 + cyclone/sickle/abs.c | 59 +++++++++- cyclone/sickle/allsickles.c | 2 + cyclone/sickle/curve.c | 2 +- cyclone/sickle/lores.c | 4 +- cyclone/sickle/onepole.c | 2 +- cyclone/sickle/overdrive.c | 80 ++++++++++++++ cyclone/sickle/rampsmooth.c | 8 +- cyclone/sickle/reson.c | 4 +- cyclone/sickle/slide.c | 3 +- cyclone/sickle/svf.c | 4 +- shared/Makefile.dirs | 2 +- shared/common/Makefile.sources | 1 + shared/common/fitter.c | 237 ++++++++++++++++++++++++++-------------- shared/common/fitter.h | 6 +- shared/common/loud.c | 16 ++- shared/common/loud.h | 2 +- shared/common/messtree.c | 144 ++++++++++++++++++++++++ shared/common/messtree.h | 47 ++++++++ shared/common/os.c | 99 +++++++++++++++++ shared/common/os.h | 15 +++ shared/common/port.c | 6 +- shared/common/qtree.c | 208 +++++++++++++++++++++++++++++++---- shared/common/qtree.h | 11 +- shared/getridof.baddeps | 5 +- shared/hammer/gui.c | 4 + shared/notes.txt | 21 +++- shared/shared.h | 13 +++ shared/unstable/fragile.c | 6 + shared/unstable/fragile.h | 1 + shared/unstable/loader.c | 220 +++++++++++++++++++++++++------------ shared/unstable/loader.h | 7 +- toxy/Makefile.objects | 1 + toxy/plustot.ar.c | 128 ++++++++++++++++++++++ toxy/plustot.c | 65 ++++++++++- toxy/plustot.h | 2 + 48 files changed, 1314 insertions(+), 248 deletions(-) create mode 100644 ViCious/notes.txt create mode 100644 cyclone/sickle/overdrive.c create mode 100644 shared/common/messtree.c create mode 100644 shared/common/messtree.h create mode 100644 toxy/plustot.ar.c diff --git a/Makefile.common b/Makefile.common index 6b33c72..7b35d7a 100644 --- a/Makefile.common +++ b/Makefile.common @@ -67,7 +67,8 @@ endif SHARED_DIR = $(ROOT_DIR)/shared OBJ_DIR = . -OUT_DIR = $(ROOT_DIR)/bin +BIN_DIR = $(ROOT_DIR)/bin +OUT_DIR = $(if $($1_SUBDIR),$(BIN_DIR)/$($1_SUBDIR),$(BIN_DIR)) # for current versions, $(BASE_DIR) equals $(BASE_NAME), for prior versions, # $(BASE_DIR) equals $(BASE_NAME)-$(VERSION) @@ -116,17 +117,18 @@ endif DBG_CFLAGS = CFLAGS = $(WARN_CFLAGS) $(OPT_CFLAGS) $(DEFINES) $(INCLUDES) -EXTERNS = $(foreach fn,$(CX_NAMES:.c=.$(X_SUFFIX)),$(OUT_DIR)/$(fn)) \ - $(foreach fn,$(AX_NAMES:.c=~.$(X_SUFFIX)),$(OUT_DIR)/$(fn)) \ - $(foreach fn,$(CX_CLASSES:=.$(X_SUFFIX)),$(OUT_DIR)/$(fn)) \ - $(foreach fn,$(AX_CLASSES:=~.$(X_SUFFIX)),$(OUT_DIR)/$(fn)) \ - $(foreach fn,$(LX_CLASSES:=.$(X_SUFFIX)),$(OUT_DIR)/$(fn)) \ - $(if $(LX_STUBCLASS),$(OUT_DIR)/$(LX_STUBCLASS:=.$(X_SUFFIX))) \ +EXTERNS = $(foreach fn,$(CX_NAMES:.c=.$(X_SUFFIX)),$(BIN_DIR)/$(fn)) \ + $(foreach fn,$(AX_NAMES:.c=~.$(X_SUFFIX)),$(BIN_DIR)/$(fn)) \ + $(foreach fn,$(CX_CLASSES:=.$(X_SUFFIX)),$(BIN_DIR)/$(fn)) \ + $(foreach fn,$(AX_CLASSES:=~.$(X_SUFFIX)),$(BIN_DIR)/$(fn)) \ + $(foreach fn,$(LX_CLASSES:=.$(X_SUFFIX)),$(BIN_DIR)/$(fn)) \ + $(if $(LX_STUBCLASS),$(BIN_DIR)/$(LX_STUBCLASS:=.$(X_SUFFIX))) \ $(foreach type,$(TYPES),\ - $(foreach fn,$(call TYPES_EXTERNS,$(type)),$(OUT_DIR)/$(fn))) + $(foreach fn,$(call TYPES_EXTERNS,$(type)), \ + $(call OUT_DIR,$(type))/$(fn))) -TYPES_RULE = $(foreach fn,$(call TYPES_EXTERNS,$1),$(OUT_DIR)/$(fn)): \ - $(OUT_DIR)/%$($1_TILDE).$(X_SUFFIX) \ +TYPES_RULE = $(foreach fn,$(call TYPES_EXTERNS,$1),$(call OUT_DIR,$1)/$(fn)): \ + $(call OUT_DIR,$1)/%$($1_TILDE).$(X_SUFFIX) \ : $(call TYPES_DIR,$1)%.o \ $($1_PRIVATEOBJECTS) $($1_FOREIGNOBJECTS) \ $(foreach obj,$($1_OBJECTS),$(SHARED_DIR)/$(obj)) \ @@ -179,7 +181,7 @@ OBJECTS = $(foreach fn,$(OTHER_SOURCES:.c=.o),$(OBJ_DIR)/$(fn)) \ # library stub equals $(BASE_NAME) by default, otherwise # it has to be declared explicitly in $(BASE_DIR)/Makefile.sources ifdef LX_STUBCLASS -$(OUT_DIR)/$(LX_STUBCLASS).$(X_SUFFIX): $(BASE_NAME)_loader.c $(LXSHOBJECTS) +$(BIN_DIR)/$(LX_STUBCLASS).$(X_SUFFIX): $(BASE_NAME)_loader.c $(LXSHOBJECTS) $(CC) -o $@ -Xlinker -defsym \ -Xlinker $(LX_STUBCLASS)_setup=$(BASE_NAME)_loader_setup \ $(CFLAGS) $(LFLAGS) $(LXSHOBJECTS) $< @@ -194,22 +196,22 @@ endif # rules for aliases must precede generic extern rules -$(OUT_DIR)/$(LX_STUB).%~.$(X_SUFFIX): $(BASE_NAME)_loader.c $(LXSHOBJECTS) +$(BIN_DIR)/$(LX_STUB).%~.$(X_SUFFIX): $(BASE_NAME)_loader.c $(LXSHOBJECTS) $(CC) -o $@ -Xlinker -defsym \ -Xlinker $(LX_STUB).$(*F)_tilde_setup=$(BASE_NAME)_loader_setup \ $(CFLAGS) $(LFLAGS) $(LXSHOBJECTS) $< -$(OUT_DIR)/$(LX_STUB).%.$(X_SUFFIX): $(BASE_NAME)_loader.c $(LXSHOBJECTS) +$(BIN_DIR)/$(LX_STUB).%.$(X_SUFFIX): $(BASE_NAME)_loader.c $(LXSHOBJECTS) $(CC) -o $@ -Xlinker -defsym \ -Xlinker $(LX_STUB).$(*F)_setup=$(BASE_NAME)_loader_setup \ $(CFLAGS) $(LFLAGS) $(LXSHOBJECTS) $< # generic rule for audio externals -$(OUT_DIR)/%~.$(X_SUFFIX): $(AX_DIR)%.c $(OBJECTS) +$(BIN_DIR)/%~.$(X_SUFFIX): $(AX_DIR)%.c $(OBJECTS) $(CC) -o $@ $(CFLAGS) $(LFLAGS) $(OBJECTS) $< # generic rule for control externals -$(OUT_DIR)/%.$(X_SUFFIX): $(CX_DIR)%.c $(OBJECTS) +$(BIN_DIR)/%.$(X_SUFFIX): $(CX_DIR)%.c $(OBJECTS) $(CC) -o $@ $(CFLAGS) $(LFLAGS) $(OBJECTS) $< SUBDIRS = @for i in $(MIXED_DIRS) and_in_case_it_is_null ; \ diff --git a/Makefile.dirs b/Makefile.dirs index e5521a0..e1a5d31 100644 --- a/Makefile.dirs +++ b/Makefile.dirs @@ -2,11 +2,9 @@ MIXED_DIRS = \ shared \ cyclone \ toxy \ - pddp \ - xeq + pddp RELEASE_DIRS = \ cyclone \ toxy \ - pddp \ - xeq + pddp diff --git a/ViCious/cyclone/makefile b/ViCious/cyclone/makefile index 4ae0367..fad65b0 100644 --- a/ViCious/cyclone/makefile +++ b/ViCious/cyclone/makefile @@ -12,7 +12,7 @@ VCLIBDIR = "e:\Program Files\Microsoft Visual Studio\Vc98\lib" ZIPCOMMAND = d:\dosowe\arc\info-zip\zip INCLUDES = /I. /I$(SHAREDDIR) /I$(PDDIR)\src -CFLAGS = /W3 /WX /DNT /DMSW /DPD /nologo +CFLAGS = /O2 /W3 /WX /DNT /DMSW /DPD /nologo LIBS = $(VCLIBDIR)\libc.lib \ $(VCLIBDIR)\oldnames.lib \ diff --git a/ViCious/cyclone/objects b/ViCious/cyclone/objects index 893d04b..66c21db 100644 --- a/ViCious/cyclone/objects +++ b/ViCious/cyclone/objects @@ -161,6 +161,7 @@ ALL_SICKLES = \ $(SRCDIR)\sickle\minmax.obj \ $(SRCDIR)\sickle\mstosamps.obj \ $(SRCDIR)\sickle\onepole.obj \ + $(SRCDIR)\sickle\overdrive.obj \ $(SRCDIR)\sickle\peakamp.obj \ $(SRCDIR)\sickle\peek.obj \ $(SRCDIR)\sickle\phasewrap.obj \ diff --git a/ViCious/notes.txt b/ViCious/notes.txt new file mode 100644 index 0000000..c996319 --- /dev/null +++ b/ViCious/notes.txt @@ -0,0 +1,8 @@ +TODO for ViCious + * use a newer default compiler than 6.0 + * conditionally use posix features (float versions of math calls, dirent) + +DONE for ViCious + +with cyclone alpha55 + * /O2 added to all makefiles (why was it not there in the first place?) diff --git a/ViCious/pddp/makefile b/ViCious/pddp/makefile index fee9c8e..657b0a7 100644 --- a/ViCious/pddp/makefile +++ b/ViCious/pddp/makefile @@ -12,7 +12,7 @@ VCLIBDIR = "e:\Program Files\Microsoft Visual Studio\Vc98\lib" ZIPCOMMAND = d:\dosowe\arc\info-zip\zip INCLUDES = /I. /I$(SHAREDDIR) /I$(PDDIR)\src -CFLAGS = /W3 /WX /DNT /DMSW /DPD /nologo +CFLAGS = /O2 /W3 /WX /DNT /DMSW /DPD /nologo LIBS = $(VCLIBDIR)\libc.lib \ $(VCLIBDIR)\oldnames.lib \ diff --git a/ViCious/toxy/makefile b/ViCious/toxy/makefile index 2cf8c51..fa59913 100644 --- a/ViCious/toxy/makefile +++ b/ViCious/toxy/makefile @@ -12,7 +12,7 @@ VCLIBDIR = "e:\Program Files\Microsoft Visual Studio\Vc98\lib" ZIPCOMMAND = d:\dosowe\arc\info-zip\zip INCLUDES = /I. /I$(SHAREDDIR) /I$(PDDIR)\src -CFLAGS = /W3 /WX /DNT /DMSW /DPD /nologo +CFLAGS = /O2 /W3 /WX /DNT /DMSW /DPD /nologo LIBS = $(VCLIBDIR)\libc.lib \ $(VCLIBDIR)\oldnames.lib \ diff --git a/cyclone/Makefile.sources b/cyclone/Makefile.sources index 96d3007..a5f40ca 100644 --- a/cyclone/Makefile.sources +++ b/cyclone/Makefile.sources @@ -149,6 +149,7 @@ sickle/minimum.c \ sickle/minmax.c \ sickle/mstosamps.c \ sickle/onepole.c \ +sickle/overdrive.c \ sickle/peakamp.c \ sickle/phasewrap.c \ sickle/pink.c \ diff --git a/cyclone/build_counter b/cyclone/build_counter index 5a0c15d..ab7d6ce 100644 --- a/cyclone/build_counter +++ b/cyclone/build_counter @@ -1,7 +1,7 @@ #define CYCLONE_VERSION "0.1" #define CYCLONE_RELEASE "alpha" -#define CYCLONE_BUILD 54 +#define CYCLONE_BUILD 55 #if 0 -CYCLONE_SNAPSHOT = 0.1-alpha54 +CYCLONE_SNAPSHOT = 0.1-alpha55 #endif diff --git a/cyclone/hammer/seq.c b/cyclone/hammer/seq.c index 38b0769..ce8c0a4 100644 --- a/cyclone/hammer/seq.c +++ b/cyclone/hammer/seq.c @@ -26,6 +26,11 @@ #define SEQ_TICKSPERSEC 48 #define SEQ_MINTICKDELAY 1. /* LATER rethink */ #define SEQ_TICKEPSILON ((double).0001) +#define SEQ_STARTEPSILON .0001 /* if inside: play unmodified */ +#define SEQ_TEMPOEPSILON .0001 /* if inside: pause */ + +#define SEQ_ISRUNNING(x) ((x)->x_prevtime > (double).0001) +#define SEQ_ISPAUSED(x) ((x)->x_prevtime <= (double).0001) enum { SEQ_IDLEMODE, SEQ_RECMODE, SEQ_PLAYMODE, SEQ_SLAVEMODE }; @@ -285,7 +290,7 @@ static void seq_startplayback(t_seq *x, int modechanged) } else { /* CHECKED timescale change */ - if (x->x_prevtime > 0.) /* running state */ + if (SEQ_ISRUNNING(x)) x->x_clockdelay -= clock_gettimesince(x->x_prevtime); x->x_clockdelay *= x->x_newtimescale / x->x_timescale; } @@ -429,7 +434,7 @@ static void seq_tick(t_seq *x) return; clock_delay(x->x_slaveclock, elapsed); seq_settimescale(x, (float)(elapsed * (SEQ_TICKSPERSEC / 1000.))); - if (x->x_prevtime > 0.) + if (SEQ_ISRUNNING(x)) { x->x_clockdelay -= clock_gettimesince(x->x_prevtime); x->x_clockdelay *= x->x_newtimescale / x->x_timescale; @@ -516,14 +521,14 @@ static void seq_append(t_seq *x) static void seq_start(t_seq *x, t_floatarg f) { - if (f < 0) + if (f < -SEQ_STARTEPSILON) { /* FIXME */ seq_setmode(x, SEQ_SLAVEMODE); } else { - seq_settimescale(x, (f == 0 ? 1. : 1024. / f)); + seq_settimescale(x, (f > SEQ_STARTEPSILON ? 1024. / f : 1.)); seq_setmode(x, SEQ_PLAYMODE); /* CHECKED 'start' stops recording */ } } @@ -562,8 +567,7 @@ static void seq_pause(t_seq *x) fittermax_warning(*(t_pd *)x, "'pause' not supported in Max"); warned = 1; } - if (x->x_mode == SEQ_PLAYMODE && - x->x_prevtime > 0.) /* running state */ + if (x->x_mode == SEQ_PLAYMODE && SEQ_ISRUNNING(x)) { x->x_clockdelay -= clock_gettimesince(x->x_prevtime); if (x->x_clockdelay < 0.) @@ -581,8 +585,7 @@ static void seq_continue(t_seq *x) fittermax_warning(*(t_pd *)x, "'continue' not supported in Max"); warned = 1; } - if (x->x_mode == SEQ_PLAYMODE && - x->x_prevtime <= 0.) /* pause state */ + if (x->x_mode == SEQ_PLAYMODE && SEQ_ISPAUSED(x)) { if (x->x_clockdelay < 0.) x->x_clockdelay = 0.; @@ -603,8 +606,8 @@ static void seq_goto(t_seq *x, t_floatarg f1, t_floatarg f2) { t_seqevent *ev; int ndx, nevents = x->x_nevents; - double ms = f1 * 1000. + f2, sum; - if (ms < SEQ_TICKEPSILON) + double ms = (double)f1 * 1000. + f2, sum; + if (ms <= SEQ_TICKEPSILON) ms = 0.; if (x->x_mode != SEQ_PLAYMODE) { @@ -624,7 +627,7 @@ static void seq_goto(t_seq *x, t_floatarg f1, t_floatarg f2) x->x_clockdelay = sum - SEQ_TICKEPSILON - ms; if (x->x_clockdelay < 0.) x->x_clockdelay = 0.; - if (x->x_prevtime > 0.) /* running state */ + if (SEQ_ISRUNNING(x)) { clock_delay(x->x_clock, x->x_clockdelay); x->x_prevtime = clock_getlogicaltime(); @@ -649,17 +652,42 @@ static void seq_scoretime(t_seq *x, t_symbol *s) t_atom aout[2]; double ms, clockdelay = x->x_clockdelay; t_float f1, f2; - if (x->x_prevtime > 0.) /* running state */ + if (SEQ_ISRUNNING(x)) clockdelay -= clock_gettimesince(x->x_prevtime); ms = x->x_nextscoretime - clockdelay / x->x_timescale; - f1 = ms / 1000.; - f2 = ms - f1; + /* Send ms as a pair of floats (f1, f2) = (coarse in sec, fine in msec). + Any ms may then be exactly reconstructed as (double)f1 * 1000. + f2. + Currently, f2 may be negative. LATER consider truncating f1 so that + only significant digits are on (when using 1 ms resolution, a float + stores only up to 8.7 minutes without distortion, 100 ms resolution + gives 14.5 hours of non-distorted floats, etc.) */ + f1 = ms * .001; + f2 = ms - (double)f1 * 1000.; + if (f2 < .001 && f2 > -.001) + f2 = 0.; SETFLOAT(&aout[0], f1); SETFLOAT(&aout[1], f2); pd_list(s->s_thing, &s_list, 2, aout); } } +static void seq_tempo(t_seq *x, t_floatarg f) +{ + static int warned = 0; + if (fittermax_get() && !warned) + { + fittermax_warning(*(t_pd *)x, "'tempo' not supported in Max"); + warned = 1; + } + if (f > SEQ_TEMPOEPSILON) + { + seq_settimescale(x, 1. / f); + if (x->x_mode == SEQ_PLAYMODE) + seq_startplayback(x, 0); + } + /* FIXME else pause, LATER reverse playback if (f < -SEQ_TEMPOEPSILON) */ +} + static void seq_cd(t_seq *x, t_symbol *s) { static int warned = 0; @@ -1206,6 +1234,8 @@ void seq_setup(void) gensym("goto"), A_DEFFLOAT, A_DEFFLOAT, 0); class_addmethod(seq_class, (t_method)seq_scoretime, gensym("scoretime"), A_SYMBOL, 0); + class_addmethod(seq_class, (t_method)seq_tempo, + gensym("tempo"), A_FLOAT, 0); class_addmethod(seq_class, (t_method)seq_cd, gensym("cd"), A_DEFSYM, 0); class_addmethod(seq_class, (t_method)seq_pwd, diff --git a/cyclone/notes.txt b/cyclone/notes.txt index 8ac4f0f..23152f7 100644 --- a/cyclone/notes.txt +++ b/cyclone/notes.txt @@ -4,6 +4,14 @@ TODO for cyclone DONE for cyclone +alpha55 + * new class: overdrive~ + * seq: + . new incompatible message 'tempo': 1-based coef, does not start playback + . fix for double-to-float-pair calc in 'scoretime' and 'goto' + * abs~: performance fix + * slide~, rampsmooth~: bashing denormals + alpha54 * comment: fixing namespace bug, reducing traffic * testmess: optionally filling message with symbols (numbers in hex form diff --git a/cyclone/sickle/Line.c b/cyclone/sickle/Line.c index eb8be26..4a8eccd 100644 --- a/cyclone/sickle/Line.c +++ b/cyclone/sickle/Line.c @@ -70,7 +70,7 @@ static t_int *line_perform(t_int *w) float curval = x->x_value; float inc = x->x_inc; float biginc = x->x_biginc; - if (PD_BADFLOAT(curval)) /* LATER rethink */ + if (PD_BIGORSMALL(curval)) /* LATER rethink */ curval = x->x_value = 0; retarget: if (x->x_retarget) diff --git a/cyclone/sickle/Makefile.sources b/cyclone/sickle/Makefile.sources index c66b33e..ce8b493 100644 --- a/cyclone/sickle/Makefile.sources +++ b/cyclone/sickle/Makefile.sources @@ -50,6 +50,7 @@ minimum.c \ minmax.c \ mstosamps.c \ onepole.c \ +overdrive.c \ peakamp.c \ peek.c \ phasewrap.c \ diff --git a/cyclone/sickle/abs.c b/cyclone/sickle/abs.c index cde26a5..777b891 100644 --- a/cyclone/sickle/abs.c +++ b/cyclone/sickle/abs.c @@ -1,14 +1,38 @@ -/* Copyright (c) 2002-2003 krzYszcz and others. +/* Copyright (c) 2002-2005 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ +#include #include "m_pd.h" #include "sickle/sic.h" +/* some random tests (average percentage in load meter and top): + gcc 3.3.5 -O6, p4 2.66GHz, 4500 copies: perform 56, perf8 57, perf0 94 + gcc 3.3.5 -O6, p4 2.66GHz, 9000 copies: perform 118, perf8 123, perf0 194 + vc 6.0 /O2, p3 800Mhz, 750 copies: perform 61, perf8 56, perf0 82 */ +#ifdef KRZYSZCZ +//#define ABS_TEST +#endif + +#ifdef ABS_TEST +#include "common/fitter.h" +#endif + typedef t_sic t_abs; static t_class *abs_class; static t_int *abs_perform(t_int *w) +{ + int nblock = (int)(w[1]); + t_float *in = (t_float *)(w[2]); + t_float *out = (t_float *)(w[3]); + while (nblock--) + *out++ = fabsf(*in++); + return (w + 4); +} + +#ifdef ABS_TEST +static t_int *abs_perf0(t_int *w) { int nblock = (int)(w[1]); t_float *in = (t_float *)(w[2]); @@ -21,9 +45,37 @@ static t_int *abs_perform(t_int *w) return (w + 4); } +static t_int *abs_perf8(t_int *w) +{ + int nblock = (int)(w[1])>>3; + t_float *in = (t_float *)(w[2]); + t_float *out = (t_float *)(w[3]); + while (nblock--) + { + *out++ = fabsf(*in++); + *out++ = fabsf(*in++); + *out++ = fabsf(*in++); + *out++ = fabsf(*in++); + *out++ = fabsf(*in++); + *out++ = fabsf(*in++); + *out++ = fabsf(*in++); + *out++ = fabsf(*in++); + } + return (w + 4); +} +#endif + static void abs_dsp(t_abs *x, t_signal **sp) { - dsp_add(abs_perform, 3, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec); +#ifdef ABS_TEST + t_symbol *tst = fitter_getsymbol(gensym("test")); + if (tst == gensym("unroll")) + dsp_add(abs_perf8, 3, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec); + else if (tst == gensym("branch")) + dsp_add(abs_perf0, 3, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec); + else +#endif + dsp_add(abs_perform, 3, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec); } static void *abs_new(void) @@ -39,4 +91,7 @@ void abs_tilde_setup(void) (t_newmethod)abs_new, 0, sizeof(t_abs), 0, 0); sic_setup(abs_class, abs_dsp, SIC_FLOATTOSIGNAL); +#ifdef ABS_TEST + fitter_setup(abs_class, 0); +#endif } diff --git a/cyclone/sickle/allsickles.c b/cyclone/sickle/allsickles.c index b8432d5..6c1141e 100644 --- a/cyclone/sickle/allsickles.c +++ b/cyclone/sickle/allsickles.c @@ -51,6 +51,7 @@ void minimum_tilde_setup(void); void minmax_tilde_setup(void); void mstosamps_tilde_setup(void); void onepole_tilde_setup(void); +void overdrive_tilde_setup(void); void peakamp_tilde_setup(void); void peek_tilde_setup(void); void phasewrap_tilde_setup(void); @@ -131,6 +132,7 @@ void allsickles_setup(void) minmax_tilde_setup(); mstosamps_tilde_setup(); onepole_tilde_setup(); + overdrive_tilde_setup(); peakamp_tilde_setup(); peek_tilde_setup(); phasewrap_tilde_setup(); diff --git a/cyclone/sickle/curve.c b/cyclone/sickle/curve.c index 730dd0d..669dd14 100644 --- a/cyclone/sickle/curve.c +++ b/cyclone/sickle/curve.c @@ -100,7 +100,7 @@ static t_int *curve_perform(t_int *w) double mm = x->x_mm; float dy = x->x_dy; float y0 = x->x_y0; - if (PD_BADFLOAT(curval)) /* LATER rethink */ + if (PD_BIGORSMALL(curval)) /* LATER rethink */ curval = x->x_value = 0; retarget: if (x->x_retarget) diff --git a/cyclone/sickle/lores.c b/cyclone/sickle/lores.c index 9449947..937f3b1 100644 --- a/cyclone/sickle/lores.c +++ b/cyclone/sickle/lores.c @@ -74,8 +74,8 @@ static t_int *lores_perform(t_int *w) ynm1 = yn; } /* LATER rethink */ - x->x_ynm1 = (PD_BADFLOAT(ynm1) ? 0. : ynm1); - x->x_ynm2 = (PD_BADFLOAT(ynm2) ? 0. : ynm2); + x->x_ynm1 = (PD_BIGORSMALL(ynm1) ? 0. : ynm1); + x->x_ynm2 = (PD_BIGORSMALL(ynm2) ? 0. : ynm2); return (w + 7); } diff --git a/cyclone/sickle/onepole.c b/cyclone/sickle/onepole.c index f06b581..0772c80 100644 --- a/cyclone/sickle/onepole.c +++ b/cyclone/sickle/onepole.c @@ -98,7 +98,7 @@ static t_int *onepole_perform(t_int *w) specifically: a1=b0-1 => a1 in [-.9999 .. -.01] => lowpass (stable) */ while (nblock--) *out++ = ynm1 = b0 * (*xin++ - ynm1) + ynm1; - x->x_ynm1 = (PD_BADFLOAT(ynm1) ? 0. : ynm1); + x->x_ynm1 = (PD_BIGORSMALL(ynm1) ? 0. : ynm1); return (w + 6); } diff --git a/cyclone/sickle/overdrive.c b/cyclone/sickle/overdrive.c new file mode 100644 index 0000000..1625dd4 --- /dev/null +++ b/cyclone/sickle/overdrive.c @@ -0,0 +1,80 @@ +/* Copyright (c) 2005 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include +#include "m_pd.h" +#include "sickle/sic.h" + +/* FIXME this is unnecessary in vc > 6.0 and darwin? */ +#if defined(MSW) || defined(MACOSX) +#define powf pow +#endif + +typedef struct _overdrive +{ + t_sic x_sic; + float x_drivefactor; +} t_overdrive; + +static t_class *overdrive_class; + +/* CHECKED this is redundant (a design flaw), LATER fitter-optionally use + float-to-signal conversion. */ +static void overdrive_float(t_overdrive *x, t_float f) +{ + x->x_drivefactor = f; +} + +static void overdrive_ft1(t_overdrive *x, t_floatarg f) +{ + x->x_drivefactor = f; +} + +/* CHECKED negative parameter values may cause output to go out of bounds */ +static t_int *overdrive_perform(t_int *w) +{ + float df = *(t_float *)(w[1]); + int nblock = (int)(w[2]); + t_float *in = (t_float *)(w[3]); + t_float *out = (t_float *)(w[4]); + while (nblock--) + { + float f = *in++; + if (f >= 1.) /* CHECKED incompatible (garbage for sig~ 1.) */ + *out++ = 1.; /* CHECKED constant for > 1. */ + else if (f > 0.) + *out++ = 1. - powf(1. - f, df); /* CHECKED */ + else if (f > -1.) /* CHECKED incompatible (garbage for sig~ -1.) */ + *out++ = powf(1. + f, df) - 1.; /* CHECKED */ + else + *out++ = -1.; /* CHECKED constant for < -1. */ + } + return (w + 5); +} + +static void overdrive_dsp(t_overdrive *x, t_signal **sp) +{ + dsp_add(overdrive_perform, 4, &x->x_drivefactor, + sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec); +} + +static void *overdrive_new(t_floatarg f) +{ + t_overdrive *x = (t_overdrive *)pd_new(overdrive_class); + x->x_drivefactor = f; + inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1")); + outlet_new((t_object *)x, &s_signal); + return (x); +} + +void overdrive_tilde_setup(void) +{ + overdrive_class = class_new(gensym("overdrive~"), + (t_newmethod)overdrive_new, 0, + sizeof(t_overdrive), 0, A_DEFFLOAT, 0); + /* CHECKED no float-to-signal conversion */ + sic_setup(overdrive_class, overdrive_dsp, overdrive_float); + class_addmethod(overdrive_class, (t_method)overdrive_ft1, + gensym("ft1"), A_FLOAT, 0); +} diff --git a/cyclone/sickle/rampsmooth.c b/cyclone/sickle/rampsmooth.c index c2023d8..848e304 100644 --- a/cyclone/sickle/rampsmooth.c +++ b/cyclone/sickle/rampsmooth.c @@ -3,8 +3,10 @@ * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include "m_pd.h" +#include "shared.h" #include "sickle/sic.h" +/* LATER select the mode fitter-optionally */ #define RAMPSMOOTH_GEOMETRIC /* geometric series (same as slide~) CHECKED */ #ifndef RAMPSMOOTH_GEOMETRIC #define RAMPSMOOTH_LINEAR @@ -82,8 +84,8 @@ static t_int *rampsmooth_perform(t_int *w) } else *out++ = target; } - x->x_last = last; - x->x_target = target; + x->x_last = (PD_BIGORSMALL(last) ? 0. : last); + x->x_target = (PD_BIGORSMALL(target) ? 0. : target); x->x_incr = incr; x->x_nleft = nleft; return (w + 5); @@ -120,7 +122,7 @@ static t_int *rampsmooth_perform(t_int *w) } *out++ = last = f; } - x->x_last = last; + x->x_last = (PD_BIGORSMALL(last) ? 0. : last); return (w + 5); } #endif diff --git a/cyclone/sickle/reson.c b/cyclone/sickle/reson.c index b072b32..40969c7 100644 --- a/cyclone/sickle/reson.c +++ b/cyclone/sickle/reson.c @@ -82,8 +82,8 @@ static t_int *reson_perform(t_int *w) x->x_xnm1 = xnm1; x->x_xnm2 = xnm2; /* LATER rethink */ - x->x_ynm1 = (PD_BADFLOAT(ynm1) ? 0. : ynm1); - x->x_ynm2 = (PD_BADFLOAT(ynm2) ? 0. : ynm2); + x->x_ynm1 = (PD_BIGORSMALL(ynm1) ? 0. : ynm1); + x->x_ynm2 = (PD_BIGORSMALL(ynm2) ? 0. : ynm2); return (w + 8); } diff --git a/cyclone/sickle/slide.c b/cyclone/sickle/slide.c index 92001b2..9846b94 100644 --- a/cyclone/sickle/slide.c +++ b/cyclone/sickle/slide.c @@ -3,6 +3,7 @@ * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include "m_pd.h" +#include "shared.h" #include "sickle/sic.h" #define SLIDE_DEFUP 1. @@ -48,7 +49,7 @@ static t_int *slide_perform(t_int *w) } *out++ = last; } - x->x_last = last; + x->x_last = (PD_BIGORSMALL(last) ? 0. : last); return (w + 7); } diff --git a/cyclone/sickle/svf.c b/cyclone/sickle/svf.c index 5bc0458..74fcf99 100644 --- a/cyclone/sickle/svf.c +++ b/cyclone/sickle/svf.c @@ -113,8 +113,8 @@ static t_int *svf_perform(t_int *w) band -= band * band * band * SVF_DRIVE; } /* LATER rethink */ - x->x_band = (PD_BADFLOAT(band) ? 0. : band); - x->x_low = (PD_BADFLOAT(low) ? 0. : low); + x->x_band = (PD_BIGORSMALL(band) ? 0. : band); + x->x_low = (PD_BIGORSMALL(low) ? 0. : low); return (w + 10); } diff --git a/shared/Makefile.dirs b/shared/Makefile.dirs index 0d88ac0..5764f41 100644 --- a/shared/Makefile.dirs +++ b/shared/Makefile.dirs @@ -1 +1 @@ -MIXED_DIRS = common hammer sickle toxy xeq unstable +MIXED_DIRS = common hammer sickle toxy unstable diff --git a/shared/common/Makefile.sources b/shared/common/Makefile.sources index 33bf597..72977d2 100644 --- a/shared/common/Makefile.sources +++ b/shared/common/Makefile.sources @@ -6,6 +6,7 @@ fitter.c \ grow.c \ lex.c \ loud.c \ +messtree.c \ mifi.c \ os.c \ patchvalue.c \ diff --git a/shared/common/fitter.c b/shared/common/fitter.c index faba970..48e5653 100644 --- a/shared/common/fitter.c +++ b/shared/common/fitter.c @@ -17,107 +17,156 @@ /* FIXME compatibility mode should be a standard Pd feature. When it is, it will be possible to simplify the implementation. Until then, - we have to handle multiple copies of the 'fittermode_value' variable + we have to handle multiple copies of the 'fitterstate_mode' variable (coming from different externals), and the only way is multicasting - through a symbol (#compatibility). */ -static t_symbol *fittermode_value = 0; - -typedef struct _fittermode_client -{ - t_class *fc_owner; - t_canvas *fc_canvas; - t_fittermode_callback fc_callback; - struct _fittermode_client *fc_next; -} t_fittermode_client; - -static t_fittermode_client *fittermode_clients = 0; -static t_class *fittermode_class = 0; -static t_pd *fittermode_target = 0; -static int fittermode_ready = 0; -static t_symbol *fitterps_hashcompatibility = 0; + through a symbol (#miXed). */ +static t_symbol *fitterstate_mode = 0; + +/* FIXME keep state in an extensible fitterstate_dictionary */ +static t_symbol *fitterstate_test = 0; + +typedef struct _fitterstate_client +{ + t_class *fc_owner; + t_canvas *fc_canvas; + t_fitterstate_callback fc_callback; + struct _fitterstate_client *fc_next; +} t_fitterstate_client; + +static t_fitterstate_client *fitterstate_clients = 0; +static t_class *fitterstate_class = 0; +static t_pd *fitterstate_target = 0; +static int fitterstate_ready = 0; +static t_symbol *fitterps_hashmiXed = 0; +static t_symbol *fitterps_mode = 0; +static t_symbol *fitterps_test = 0; static t_symbol *fitterps_max = 0; static t_symbol *fitterps_none = 0; -/* read access (query), only from fittermode_dosetup() */ -static void fittermode_bang(t_pd *x) +/* read access (query), called only from fitterstate_dosetup() + or through "#miXed" */ +static void fitterstate_bang(t_pd *x) { - if (fitterps_hashcompatibility) + if (fitterps_hashmiXed) { - if (fittermode_ready /* do not reply to own request */ - && fitterps_hashcompatibility->s_thing) - /* this proliferates for the third and subsequent - fittermode_dosetup() calls... */ - pd_symbol(fitterps_hashcompatibility->s_thing, - fittermode_value); + if (fitterstate_ready /* do not reply to own request */ + && fitterps_hashmiXed->s_thing) + { + t_atom atout[2]; + /* these proliferate for the third and subsequent + fitterstate_dosetup() calls... */ + SETSYMBOL(&atout[0], fitterps_mode); + SETSYMBOL(&atout[1], fitterstate_mode); + typedmess(fitterps_hashmiXed->s_thing, gensym("reply"), 2, atout); + SETSYMBOL(&atout[0], fitterps_test); + SETSYMBOL(&atout[1], fitterstate_test); + typedmess(fitterps_hashmiXed->s_thing, gensym("reply"), 2, atout); + } } - else loudbug_bug("fittermode_bang"); + else loudbug_bug("fitterstate_bang"); } -/* read access (reply), only from fitter_dosetup() */ -static void fittermode_symbol(t_pd *x, t_symbol *s) +/* read access (query), called only through "#miXed" */ +static void fitterstate_symbol(t_pd *x, t_symbol *s) { - if (!s || s == &s_) + if (fitterstate_ready && fitterps_hashmiXed && fitterps_hashmiXed->s_thing) { - loudbug_bug("fittermode_symbol"); - s = fitterps_none; + t_atom atout[2]; + if (s == fitterps_mode) + { + SETSYMBOL(&atout[0], fitterps_mode); + SETSYMBOL(&atout[1], fitterstate_mode); + typedmess(fitterps_hashmiXed->s_thing, gensym("reply"), 2, atout); + } + else if (s == fitterps_test) + { + SETSYMBOL(&atout[0], fitterps_test); + SETSYMBOL(&atout[1], fitterstate_test); + typedmess(fitterps_hashmiXed->s_thing, gensym("reply"), 2, atout); + } + else post("\"%s\": no such key in the miXed state", + (s ? s->s_name : "???")); } - fittermode_value = s; + else loudbug_bug("fitterstate_symbol"); } -/* write access, only from fitter_setmode() */ -static void fittermode_set(t_pd *x, t_symbol *s) +/* read access (reply), called only from fitter_dosetup() or through "#miXed" */ +static void fitterstate_reply(t_pd *x, t_symbol *s1, t_symbol *s2) { - t_fittermode_client *fc; - fittermode_value = s; - for (fc = fittermode_clients; fc; fc = fc->fc_next) + if (!s2 || s2 == &s_) + { + loudbug_bug("fitterstate_reply"); + s2 = fitterps_none; + } + if (s1 == fitterps_mode) + fitterstate_mode = s2; + else if (s1 == fitterps_test) + fitterstate_test = s2; +} + +/* write access, called only from fitter_setmode() or through "#miXed" */ +static void fitterstate_set(t_pd *x, t_symbol *s1, t_symbol *s2) +{ + t_fitterstate_client *fc; + if (s1 == fitterps_mode) + fitterstate_mode = s2; + else if (s1 == fitterps_test) + fitterstate_test = s2; + for (fc = fitterstate_clients; fc; fc = fc->fc_next) if (fc->fc_callback) fc->fc_callback(); } -static void fittermode_dosetup(int noquery) +static void fitterstate_dosetup(int noquery) { - if (fittermode_class || fittermode_target) - loudbug_bug("fittermode_dosetup"); - fitterps_hashcompatibility = gensym("#compatibility"); + if (fitterstate_class || fitterstate_target) + loudbug_bug("fitterstate_dosetup"); + fitterps_hashmiXed = gensym("#miXed"); + fitterps_mode = gensym("mode"); + fitterps_test = gensym("test"); fitterps_max = gensym("max"); fitterps_none = gensym("none"); - fittermode_value = fitterps_none; - fittermode_class = class_new(fitterps_hashcompatibility, - 0, 0, sizeof(t_pd), - CLASS_PD | CLASS_NOINLET, 0); - class_addbang(fittermode_class, fittermode_bang); - class_addsymbol(fittermode_class, fittermode_symbol); - class_addmethod(fittermode_class, - (t_method)fittermode_set, - gensym("set"), A_SYMBOL, 0); - fittermode_target = pd_new(fittermode_class); - pd_bind(fittermode_target, fitterps_hashcompatibility); + fitterstate_mode = fitterps_none; + fitterstate_test = fitterps_none; + fitterstate_class = class_new(fitterps_hashmiXed, + 0, 0, sizeof(t_pd), + CLASS_PD | CLASS_NOINLET, 0); + class_addbang(fitterstate_class, fitterstate_bang); + class_addsymbol(fitterstate_class, fitterstate_symbol); + class_addmethod(fitterstate_class, + (t_method)fitterstate_reply, + gensym("reply"), A_SYMBOL, A_SYMBOL, 0); + class_addmethod(fitterstate_class, + (t_method)fitterstate_set, + gensym("set"), A_SYMBOL, A_SYMBOL, 0); + fitterstate_target = pd_new(fitterstate_class); + pd_bind(fitterstate_target, fitterps_hashmiXed); if (!noquery) - pd_bang(fitterps_hashcompatibility->s_thing); - fittermode_ready = 1; + pd_bang(fitterps_hashmiXed->s_thing); + fitterstate_ready = 1; } -void fitter_setup(t_class *owner, t_fittermode_callback callback) +void fitter_setup(t_class *owner, t_fitterstate_callback callback) { - if (!fittermode_class) - fittermode_dosetup(0); + if (!fitterstate_class) + fitterstate_dosetup(0); if (callback) { - t_fittermode_client *fc = getbytes(sizeof(*fc)); + t_fitterstate_client *fc = getbytes(sizeof(*fc)); fc->fc_owner = owner; fc->fc_canvas = 0; /* a global client */ fc->fc_callback = callback; - fc->fc_next = fittermode_clients; - fittermode_clients = fc; + fc->fc_next = fitterstate_clients; + fitterstate_clients = fc; } } void fitter_drop(t_class *owner) { - if (fittermode_class && fitterps_hashcompatibility->s_thing) + if (fitterstate_class && fitterps_hashmiXed->s_thing) { - t_fittermode_client *fcp = 0, - *fc = fittermode_clients; + t_fitterstate_client *fcp = 0, + *fc = fitterstate_clients; while (fc) { if (fc->fc_owner == owner) @@ -125,7 +174,7 @@ void fitter_drop(t_class *owner) if (fcp) fcp->fc_next = fc->fc_next; else - fittermode_clients = fc->fc_next; + fitterstate_clients = fc->fc_next; break; } fcp = fc; @@ -139,48 +188,72 @@ void fitter_drop(t_class *owner) else loudbug_bug("fitter_drop 2"); } +t_float *fitter_getfloat(t_symbol *s) +{ + if (!fitterstate_class) + fitterstate_dosetup(0); + loudbug_bug("fitter_getfloat"); + return (0); +} + +t_symbol *fitter_getsymbol(t_symbol *s) +{ + if (!fitterstate_class) + fitterstate_dosetup(0); + if (s == fitterps_mode) + return (fitterstate_mode); + else if (s == fitterps_test) + return (fitterstate_test); + else + { + loudbug_bug("fitter_getsymbol"); + return (0); + } +} + void fitter_setmode(t_symbol *s) { if (!s || s == &s_) s = fitterps_none; post("setting compatibility mode to '%s'", s->s_name); - if (!fittermode_class) - fittermode_dosetup(1); - if (fitterps_hashcompatibility->s_thing) + if (!fitterstate_class) + fitterstate_dosetup(1); + if (fitterps_hashmiXed->s_thing) { - t_atom at; - SETSYMBOL(&at, s); - typedmess(fitterps_hashcompatibility->s_thing, gensym("set"), 1, &at); + t_atom atout[2]; + SETSYMBOL(&atout[0], fitterps_mode); + SETSYMBOL(&atout[1], s); + typedmess(fitterps_hashmiXed->s_thing, gensym("set"), 2, atout); } else loudbug_bug("fitter_setmode"); } t_symbol *fitter_getmode(void) { - if (!fittermode_class) - fittermode_dosetup(0); - return (fittermode_value); + if (!fitterstate_class) + fitterstate_dosetup(0); + return (fitterstate_mode); } void fittermax_set(void) { - if (!fittermode_class) - fittermode_dosetup(0); + if (!fitterstate_class) + fitterstate_dosetup(0); fitter_setmode(fitterps_max); } int fittermax_get(void) { - if (!fittermode_class) - fittermode_dosetup(0); - return (fittermode_value == fitterps_max); + if (!fitterstate_class) + fitterstate_dosetup(0); + return (fitterstate_mode == fitterps_max); } void fittermax_warning(t_class *c, char *fmt, ...) { - if (!fittermode_class) - fittermode_dosetup(0); - if (fittermode_value == fitterps_max) + if (!fitterstate_class) + fitterstate_dosetup(0); + if (fitterstate_mode == fitterps_max) { char buf[MAXPDSTRING]; va_list ap; diff --git a/shared/common/fitter.h b/shared/common/fitter.h index 2e5c24d..a6797e5 100644 --- a/shared/common/fitter.h +++ b/shared/common/fitter.h @@ -5,10 +5,12 @@ #ifndef __FITTER_H__ #define __FITTER_H__ -typedef void (*t_fittermode_callback)(void); +typedef void (*t_fitterstate_callback)(void); -void fitter_setup(t_class *owner, t_fittermode_callback callback); +void fitter_setup(t_class *owner, t_fitterstate_callback callback); void fitter_drop(t_class *owner); +t_float *fitter_getfloat(t_symbol *s); +t_symbol *fitter_getsymbol(t_symbol *s); void fitter_setmode(t_symbol *s); t_symbol *fitter_getmode(void); void fittermax_set(void); diff --git a/shared/common/loud.c b/shared/common/loud.c index e1e921d..7129962 100644 --- a/shared/common/loud.c +++ b/shared/common/loud.c @@ -88,12 +88,18 @@ void loud_errand(t_pd *x, char *fmt, ...) va_end(ap); } -void loud_syserror(t_pd *x, char *msg) +void loud_syserror(t_pd *x, char *fmt, ...) { - if (msg) - loud_error(x, "%s (%s)", msg, strerror(errno)); - else - loud_error(x, strerror(errno)); + if (fmt) + { + char buf[MAXPDSTRING]; + va_list ap; + va_start(ap, fmt); + vsprintf(buf, fmt, ap); + loud_error(x, "%s (%s)", buf, strerror(errno)); + va_end(ap); + } + else loud_error(x, strerror(errno)); } void loud_nomethod(t_pd *x, t_symbol *s) diff --git a/shared/common/loud.h b/shared/common/loud.h index 297b9c1..9497e0d 100644 --- a/shared/common/loud.h +++ b/shared/common/loud.h @@ -18,7 +18,7 @@ int shared_matchignorecase(char *test, char *pattern); char *loud_ordinal(int n); void loud_error(t_pd *x, char *fmt, ...); void loud_errand(t_pd *x, char *fmt, ...); -void loud_syserror(t_pd *x, char *msg); +void loud_syserror(t_pd *x, char *fmt, ...); void loud_nomethod(t_pd *x, t_symbol *s); void loud_messarg(t_pd *x, t_symbol *s); int loud_checkint(t_pd *x, t_float f, int *valuep, t_symbol *mess); diff --git a/shared/common/messtree.c b/shared/common/messtree.c new file mode 100644 index 0000000..6d778aa --- /dev/null +++ b/shared/common/messtree.c @@ -0,0 +1,144 @@ +/* Copyright (c) 2005 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* This module covers parsing of a single message received by an object + or used for creation of an object, as well as parsing of multiple messages + contained in an imported buffer, etc. */ + +#include "m_pd.h" +#include "common/loud.h" +#include "messtree.h" + +#ifdef KRZYSZCZ +#define MESSTREE_DEBUG +#endif + +/* There are two different messtree structures: the compile-time input + (t_messslot/t_messnode) and the run-time one (t_messtree). The reasons are: + to allow plugins to extend a message tree, and to make the compile-time + input initializer-friendly. */ + +struct _messtree +{ + t_messslot *mt_slot; + t_symbol *mt_selector; + t_messcall mt_method; + int mt_nonexclusive; + struct _messtree *mt_sublist; + struct _messtree *mt_next; +}; + +t_messtree *messtree_new(t_symbol *selector) +{ + t_messtree *mt = getbytes(sizeof(*mt)); + mt->mt_slot = 0; + mt->mt_selector = selector; + mt->mt_method = 0; /* LATER define a default */ + mt->mt_nonexclusive = 0; + mt->mt_sublist = 0; + mt->mt_next = 0; + return (mt); +} + +static void messtree_addnode(t_messtree *mt, t_messnode *mn) +{ + /* LATER respect mn->mn_index */ + t_messslot *ms; + int i; + for (i = 0, ms = mn->mn_table + mn->mn_nslots - 1; + i < mn->mn_nslots; i++, ms--) + { + t_messtree *bch = messtree_new(gensym(ms->ms_name)); + bch->mt_slot = ms; + bch->mt_method = ms->ms_call; + bch->mt_nonexclusive = (ms->ms_flags & MESSTREE_NONEXCLUSIVE); + bch->mt_next = mt->mt_sublist; + mt->mt_sublist = bch; + if (ms->ms_subnode) + messtree_addnode(bch, ms->ms_subnode); + } +} + +void messtree_add(t_messtree *mt, t_messnode *rootnode) +{ + messtree_addnode(mt, rootnode); +} + +t_messtree *messtree_build(t_messslot *rootslot) +{ + t_messtree *mt = messtree_new(gensym(rootslot->ms_name)); + mt->mt_slot = rootslot; + mt->mt_method = rootslot->ms_call; + mt->mt_nonexclusive = (rootslot->ms_flags & MESSTREE_NONEXCLUSIVE); + mt->mt_sublist = 0; + mt->mt_next = 0; + if (rootslot->ms_subnode) + messtree_addnode(mt, rootslot->ms_subnode); + return (mt); +} + +int messtree_doit(t_messtree *mt, t_messslot **msp, int *nargp, + t_pd *target, t_symbol *s, int ac, t_atom *av) +{ + int result = MESSTREE_OK, nargpdummy; + t_messslot *mspdummy; + if (!msp) + msp = &mspdummy; + if (!nargp) + nargp = &nargpdummy; + if (s && s != mt->mt_selector) + { + loud_warning(target, (target ? 0 : "messtree"), + "unexpected selector \"%s\"", s->s_name); + *msp = 0; + *nargp = 0; + return (MESSTREE_CORRUPT); + } + if (ac && av->a_type == A_SYMBOL) + { + t_messtree *bch; + for (bch = mt->mt_sublist; bch; bch = bch->mt_next) + { + if (av->a_w.w_symbol == bch->mt_selector) + { + if (bch->mt_sublist) + return (messtree_doit(bch, msp, nargp, target, + av->a_w.w_symbol, ac - 1, av + 1)); + else + { + if (target && bch->mt_method) + result = bch->mt_method(target, av->a_w.w_symbol, + ac - 1, av + 1); + *msp = (result == MESSTREE_OK ? bch->mt_slot : 0); + *nargp = ac - 1; + return (result); + } + } + } + if (mt->mt_nonexclusive) + { + if (target && mt->mt_method) + result = mt->mt_method(target, 0, ac, av); /* LATER rethink */ + *msp = (result == MESSTREE_OK ? mt->mt_slot : 0); + *nargp = ac; + return (result); + } + else + { + loud_warning(target, (target ? 0 : "messtree"), + "unknown property \"%s\"", av->a_w.w_symbol->s_name); + *msp = 0; + *nargp = 0; + return (MESSTREE_UNKNOWN); + } + } + else + { + if (target && mt->mt_method) + result = mt->mt_method(target, 0, ac, av); + *msp = (result == MESSTREE_OK ? mt->mt_slot : 0); + *nargp = ac; + return (result); + } +} diff --git a/shared/common/messtree.h b/shared/common/messtree.h new file mode 100644 index 0000000..a3a3326 --- /dev/null +++ b/shared/common/messtree.h @@ -0,0 +1,47 @@ +/* Copyright (c) 2005 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#ifndef __MESSTREE_H__ +#define __MESSTREE_H__ + +typedef int (*t_messcall)(t_pd *, t_symbol *, int, t_atom *); +typedef char *t_messarg; + +typedef struct _messslot +{ + char *ms_name; + t_messcall ms_call; + char *ms_argument; + int ms_flags; + struct _messnode *ms_subnode; +} t_messslot; + +typedef struct _messnode /* a parser's symbol definition, sort of... */ +{ + t_messslot *mn_table; + int mn_nslots; + int mn_index; +} t_messnode; + +EXTERN_STRUCT _messtree; +#define t_messtree struct _messtree + +#define MESSTREE_NSLOTS(slots) (sizeof(slots)/sizeof(*(slots))) + +enum { MESSTREE_OK, /* done current message parsing, parse next */ + MESSTREE_CONTINUE, /* continue current message parsing */ + MESSTREE_UNKNOWN, /* current message unknown, parse next */ + MESSTREE_CORRUPT, /* current message corrupt, parse next */ + MESSTREE_FATAL /* exit parsing */ +}; + +#define MESSTREE_NONEXCLUSIVE 1 + +t_messtree *messtree_new(t_symbol *selector); +void messtree_add(t_messtree *mt, t_messnode *rootnode); +t_messtree *messtree_build(t_messslot *rootslot); +int messtree_doit(t_messtree *mt, t_messslot **msp, int *nargp, + t_pd *target, t_symbol *s, int ac, t_atom *av); + +#endif diff --git a/shared/common/os.c b/shared/common/os.c index 9129f82..408fdfb 100644 --- a/shared/common/os.c +++ b/shared/common/os.c @@ -6,6 +6,7 @@ #include #else #include +#include #endif #include #include @@ -233,3 +234,101 @@ FILE *filewrite_open(char *filename, t_canvas *cv, int textmode) sys_bashfilename(path, path); return (fopen(path, (textmode ? "w" : "wb"))); } + +/* FIXME add MSW */ + +struct _osdir +{ +#ifndef MSW + DIR *dir_handle; + struct dirent *dir_entry; +#endif + int dir_flags; +}; + +/* returns 0 on error, a caller is then expected to call + loud_syserror(owner, "cannot open \"%s\"", dirname) */ +t_osdir *osdir_open(char *dirname) +{ +#ifndef MSW + DIR *handle = opendir(dirname); + if (handle) + { +#endif + t_osdir *dp = getbytes(sizeof(*dp)); +#ifndef MSW + dp->dir_handle = handle; + dp->dir_entry = 0; +#endif + dp->dir_flags = 0; + return (dp); +#ifndef MSW + } + else return (0); +#endif +} + +void osdir_setmode(t_osdir *dp, int flags) +{ + if (dp) + dp->dir_flags = flags; +} + +void osdir_close(t_osdir *dp) +{ + if (dp) + { +#ifndef MSW + closedir(dp->dir_handle); +#endif + freebytes(dp, sizeof(*dp)); + } +} + +void osdir_rewind(t_osdir *dp) +{ + if (dp) + { +#ifndef MSW + rewinddir(dp->dir_handle); + dp->dir_entry = 0; +#endif + } +} + +char *osdir_next(t_osdir *dp) +{ +#ifndef MSW + if (dp) + { + while (dp->dir_entry = readdir(dp->dir_handle)) + { + if (!dp->dir_flags || + (dp->dir_entry->d_type == DT_REG + && (dp->dir_flags & OSDIR_FILEMODE)) || + (dp->dir_entry->d_type == DT_DIR + && (dp->dir_flags & OSDIR_DIRMODE))) + return (dp->dir_entry->d_name); + } + } +#endif + return (0); +} + +int osdir_isfile(t_osdir *dp) +{ +#ifndef MSW + return (dp && dp->dir_entry && dp->dir_entry->d_type == DT_REG); +#else + return (0); +#endif +} + +int osdir_isdir(t_osdir *dp) +{ +#ifndef MSW + return (dp && dp->dir_entry && dp->dir_entry->d_type == DT_DIR); +#else + return (0); +#endif +} diff --git a/shared/common/os.h b/shared/common/os.h index f3dde89..7bf3c9a 100644 --- a/shared/common/os.h +++ b/shared/common/os.h @@ -5,9 +5,24 @@ #ifndef __OS_H__ #define __OS_H__ +EXTERN_STRUCT _osdir; +#define t_osdir struct _osdir + +#define OSDIR_FILEMODE 1 +#define OSDIR_DIRMODE 2 + int ospath_length(char *path, char *cwd); char *ospath_absolute(char *path, char *cwd, char *result); + FILE *fileread_open(char *filename, t_canvas *cv, int textmode); FILE *filewrite_open(char *filename, t_canvas *cv, int textmode); +t_osdir *osdir_open(char *dirname); +void osdir_setmode(t_osdir *dp, int flags); +void osdir_close(t_osdir *dp); +void osdir_rewind(t_osdir *dp); +char *osdir_next(t_osdir *dp); +int osdir_isfile(t_osdir *dp); +int osdir_isdir(t_osdir *dp); + #endif diff --git a/shared/common/port.c b/shared/common/port.c index 5845210..fe58b6e 100644 --- a/shared/common/port.c +++ b/shared/common/port.c @@ -35,8 +35,10 @@ #define PORT_INISTACK 256 /* LATER rethink */ #define PORT_INISIZE 512 /* LATER rethink */ -enum { PORT_OK, - PORT_NEXT, /* next line, please */ +/* FIXME use messtree api */ + +enum { PORT_OK, /* MESSTREE_CONTINUE */ + PORT_NEXT, /* next line, please: MESSTREE_OK */ PORT_UNKNOWN, PORT_CORRUPT, PORT_FATAL }; /* cf binport.c */ diff --git a/shared/common/qtree.c b/shared/common/qtree.c index 3d35769..b749b3a 100644 --- a/shared/common/qtree.c +++ b/shared/common/qtree.c @@ -294,7 +294,7 @@ static t_qnode *qtree_postinserthook(t_qnode *np) (which means foundp returns 1), a new node is inserted, unless hook is either empty, or returns null. Hook's nonempty return is the parent for the new node. It is expected to have no more than one child. */ -static t_qnode *qtree_doinsert(t_qtree *tree, double key, +static t_qnode *qtree_doinsert(t_qtree *tree, double key, t_qnode *preexisting, t_qtree_inserthook hook, int *foundp) { t_qnode *np, *parent, *result; @@ -302,11 +302,18 @@ static t_qnode *qtree_doinsert(t_qtree *tree, double key, *foundp = 0; if (!(np = tree->t_root)) { - if (!(np = getbytes(tree->t_nodesize))) + if (!(np = (tree->t_nodesize > 0 ? + getbytes(tree->t_nodesize) : preexisting))) + { + if (tree->t_nodesize == 0) + loudbug_bug("qtree_insert, node not supplied"); return (0); + } np->n_key = key; np->n_black = 1; + np->n_left = np->n_right = np->n_parent = 0; tree->t_root = tree->t_first = tree->t_last = np; + np->n_prev = np->n_next = 0; return (np); } @@ -343,8 +350,13 @@ static t_qnode *qtree_doinsert(t_qtree *tree, double key, addit: /* parent has no more than one child, new node becomes parent's immediate successor or predecessor */ - if (!(np = getbytes(tree->t_nodesize))) + if (!(np = (tree->t_nodesize > 0 ? + getbytes(tree->t_nodesize) : preexisting))) + { + if (tree->t_nodesize == 0) + loudbug_bug("qtree_insert, node not supplied"); return (0); + } np->n_key = key; np->n_parent = parent; if (leftchild) @@ -440,7 +452,8 @@ void qtree_delete(t_qtree *tree, t_qnode *gone) of gone's parent (if any). Successor always exists in this context, and it has no left child. The simplistic scheme is to replace gone's fields with successor's fields, and delete the successor. - We cannot do so, however, because successor may be pointed at... */ + We cannot do so, however, because 1. nodes may be caller-owned + (nodesize == 0), 2. successor may be pointed at... */ t_qnode *successor = gone->n_next; child = successor->n_right; successor->n_left = gone->n_left; @@ -624,7 +637,8 @@ void qtree_delete(t_qtree *tree, t_qnode *gone) child->n_black = 1; } done: - freebytes(gone, tree->t_nodesize); + if (tree->t_nodesize) + freebytes(gone, tree->t_nodesize); #ifdef QTREE_DEBUG qtree_verify(tree); #endif @@ -638,41 +652,189 @@ t_qnode *qtree_search(t_qtree *tree, double key) return (np); } -t_qnode *qtree_closest(t_qtree *tree, double key, int geqflag) +/* Returns the greatest node <= key, if any (may return null). + If deltap is not null, it will hold the abs diff (key - node.n_key). */ +t_qnode *qtree_closestunder(t_qtree *tree, double key, double *deltap) { t_qnode *np, *parent; if (!(np = tree->t_root)) return (0); do if (np->n_key == key) + { + if (deltap) + *deltap = 0.; return (np); - else - parent = np; + } + else parent = np; + while (np = (key < np->n_key ? np->n_left : np->n_right)); + if (np = (key < parent->n_key ? parent->n_prev : parent)) + { + if (deltap) + *deltap = key - np->n_key; + return (np); + } + else return (0); +} + +/* Returns the smallest node >= key, if any (may return null). + If deltap is not null, it will hold the abs diff (node.n_key - key). */ +t_qnode *qtree_closestover(t_qtree *tree, double key, double *deltap) +{ + t_qnode *np, *parent; + if (!(np = tree->t_root)) + return (0); + do + if (np->n_key == key) + { + if (deltap) + *deltap = 0.; + return (np); + } + else parent = np; while (np = (key < np->n_key ? np->n_left : np->n_right)); - if (geqflag) - return (key > parent->n_key ? parent->n_next : parent); + if (np = (key > parent->n_key ? parent->n_next : parent)) + { + if (deltap) + *deltap = np->n_key - key; + return (np); + } + else return (0); +} + +/* Returns the smallest node >= key or the greatest node <= key, whichever + makes the smallest abs diff, |key - node.n_key|. Returns null only for + an empty tree. If deltap is not null, it will hold the signed diff + (negative for an undernode, i.e. when node < key). */ +t_qnode *qtree_closest(t_qtree *tree, double key, double *deltap) +{ + t_qnode *np, *parent; + if (!(np = tree->t_root)) + return (0); + do + if (np->n_key == key) + { + if (deltap) + *deltap = 0.; + return (np); + } + else parent = np; + while (np = (key < np->n_key ? np->n_left : np->n_right)); + if (key > parent->n_key) + { + if (np = parent->n_next) + { + double delta1 = key - parent->n_key; + double delta2 = np->n_key - key; + if (delta1 < delta2) + { + if (deltap) + *deltap = -delta1; + return (parent); + } + else + { + if (deltap) + *deltap = delta2; + return (np); + } + } + else + { + if (deltap) + *deltap = parent->n_key - key; + return (parent); + } + } else - return (key < parent->n_key ? parent->n_prev : parent); + { + if (np = parent->n_prev) + { + double delta1 = key - np->n_key; + double delta2 = parent->n_key - key; + if (delta1 < delta2) + { + if (deltap) + *deltap = -delta1; + return (np); + } + else + { + if (deltap) + *deltap = delta2; + return (parent); + } + } + else + { + if (deltap) + *deltap = parent->n_key - key; + return (parent); + } + } } -t_qnode *qtree_insert(t_qtree *tree, double key, int *foundp) +t_qnode *qtree_insert(t_qtree *tree, double key, + t_qnode *preexisting, int *foundp) { - return (qtree_doinsert(tree, key, 0, foundp)); + int found; + return (qtree_doinsert(tree, key, preexisting, 0, + (foundp ? foundp : &found))); } -t_qnode *qtree_multiinsert(t_qtree *tree, double key, int fifoflag) +t_qnode *qtree_multiinsert(t_qtree *tree, double key, + t_qnode *preexisting, int fifoflag) { int found; - return (qtree_doinsert(tree, key, (fifoflag ? - qtree_postinserthook : - qtree_preinserthook), &found)); + return (qtree_doinsert(tree, key, preexisting, + (fifoflag ? + qtree_postinserthook : + qtree_preinserthook), &found)); +} + +t_qnode *qtree_override(t_qtree *tree, t_qnode *oldnode, t_qnode *newnode) +{ + if (tree->t_nodesize) + { + loudbug_bug("qtree_override 1"); + return (0); + } + else + { + newnode->n_key = oldnode->n_key; + newnode->n_black = oldnode->n_black; + if (newnode->n_left = oldnode->n_left) + newnode->n_left->n_parent = newnode; + if (newnode->n_right = oldnode->n_right) + newnode->n_right->n_parent = newnode; + if (newnode->n_parent = oldnode->n_parent) + { + if (oldnode == newnode->n_parent->n_left) + newnode->n_parent->n_left = newnode; + else if (oldnode == newnode->n_parent->n_right) + newnode->n_parent->n_right = newnode; + else + loudbug_bug("qtree_override 2"); + } + if (newnode->n_prev = oldnode->n_prev) + newnode->n_prev->n_next = newnode; + if (newnode->n_next = oldnode->n_next) + newnode->n_next->n_prev = newnode; + if (tree->t_root == oldnode) + tree->t_root = newnode; + if (tree->t_first == oldnode) + tree->t_first = newnode; + if (tree->t_last == oldnode) + tree->t_last = newnode; + return (newnode); + } } t_qnode *qtree_insertfloat(t_qtree *tree, double key, t_float f, int replaceflag) { int found; - t_qnode *np = qtree_doinsert(tree, key, 0, &found); + t_qnode *np = qtree_doinsert(tree, key, 0, 0, &found); if (np && (!found || replaceflag)) { if (tree->t_valuetype == QTREETYPE_FLOAT) @@ -695,7 +857,7 @@ t_qnode *qtree_insertsymbol(t_qtree *tree, double key, t_symbol *s, int replaceflag) { int found; - t_qnode *np = qtree_doinsert(tree, key, 0, &found); + t_qnode *np = qtree_doinsert(tree, key, 0, 0, &found); if (np && (!found || replaceflag)) { if (tree->t_valuetype == QTREETYPE_SYMBOL) @@ -718,7 +880,7 @@ t_qnode *qtree_insertatom(t_qtree *tree, double key, t_atom *ap, int replaceflag) { int found; - t_qnode *np = qtree_doinsert(tree, key, 0, &found); + t_qnode *np = qtree_doinsert(tree, key, 0, 0, &found); if (np && (!found || replaceflag)) { if (tree->t_valuetype == QTREETYPE_ATOM) @@ -771,11 +933,11 @@ void qtree_initcustom(t_qtree *tree, size_t nodesize, int freecount) void qtree_clear(t_qtree *tree, int freecount) { t_qnode *np, *next = tree->t_first; - while (next) + while (np = next) { - np = next; next = next->n_next; - freebytes(np, tree->t_nodesize); + if (tree->t_nodesize) + freebytes(np, tree->t_nodesize); } qtree_doinit(tree, tree->t_valuetype, tree->t_nodesize, 0); } diff --git a/shared/common/qtree.h b/shared/common/qtree.h index 97c2906..18e4098 100644 --- a/shared/common/qtree.h +++ b/shared/common/qtree.h @@ -60,10 +60,15 @@ typedef struct _qtree typedef void (*t_qnode_vshowhook)(t_qnode *, char *, unsigned); t_qnode *qtree_search(t_qtree *tree, double key); -t_qnode *qtree_closest(t_qtree *tree, double key, int geqflag); +t_qnode *qtree_closestunder(t_qtree *tree, double key, double *deltap); +t_qnode *qtree_closestover(t_qtree *tree, double key, double *deltap); +t_qnode *qtree_closest(t_qtree *tree, double key, double *deltap); -t_qnode *qtree_insert(t_qtree *tree, double key, int *foundp); -t_qnode *qtree_multiinsert(t_qtree *tree, double key, int fifoflag); +t_qnode *qtree_insert(t_qtree *tree, double key, + t_qnode *preexisting, int *foundp); +t_qnode *qtree_multiinsert(t_qtree *tree, double key, + t_qnode *preexisting, int fifoflag); +t_qnode *qtree_override(t_qtree *tree, t_qnode *oldnode, t_qnode *newnode); t_qnode *qtree_insertfloat(t_qtree *tree, double key, t_float f, int replaceflag); t_qnode *qtree_insertsymbol(t_qtree *tree, double key, t_symbol *s, diff --git a/shared/getridof.baddeps b/shared/getridof.baddeps index 7286cd6..2886622 100644 --- a/shared/getridof.baddeps +++ b/shared/getridof.baddeps @@ -3,8 +3,10 @@ Some are inevitable, but others can, and should be removed. unstable/fragile -> common/loud unstable/fringe -> unstable/forky +unstable/loader -> common/os common/loud common/props -> common/grow common/loud common/vefl -> common/loud, unstable/fragile +common/messtree -> common/loud common/qtree -> common/loud common/binport -> common/lex common/port -> common/loud, common/grow, common/binport, @@ -14,6 +16,7 @@ sickle/sic -> common/loud sickle/arsic -> common/loud, common/vefl, sickle/sic, unstable/fragile toxy/plusbob -> common/loud toxy/scriptlet -> common/loud, common/grow, common/props -xeq/squ* -> common/loud, common/fi, common/mifi, common/qtree, xeq/squ* +xeq/squ* -> common/loud, common/dict, common/qtree, common/messtree, + common/mifi, xeq/squ* vex/hyphen -> common/dict vex/sofi -> vex/bifi diff --git a/shared/hammer/gui.c b/shared/hammer/gui.c index 388b14b..104af3a 100644 --- a/shared/hammer/gui.c +++ b/shared/hammer/gui.c @@ -4,6 +4,10 @@ /* FIXME use guiconnect */ +/* LATER revisit tracking the mouse state within the focusless pd-gui + (event bindings are local only in tk8.4, and there is no other call + to XQueryPointer() but from winfo pointer). */ + #include #include #include "m_pd.h" diff --git a/shared/notes.txt b/shared/notes.txt index a823fad..43f4867 100644 --- a/shared/notes.txt +++ b/shared/notes.txt @@ -1,10 +1,29 @@ TODO for root and shared * fitter: abstraction-scoped, class-selective compatibility control - * fitter: mode list + * fitter: fittterstate map * hammerfile, hammergui: version control DONE for root and shared +with cyclone alpha55 + * new module: messtree + * qtree: + . nodes of a custom tree may be caller-owned: a caller may pass 0 as + nodesize to qtree_initcustom() and pass pre-allocated nodes to + insert/multiinsert calls + . new calls: qtree_override(), qtree_closestunder(), qtree_closestover() + . all "closest" calls report a diff between key requested and key found + * os: new calls (dummy under MSW, though): osdir_open(), osdir_setmode(), + osdir_close(), osdir_rewind(), osdir_next(), osdir_isfile(), osdir_isdir() + * loader: new calls, unstable_dirload_lib(), unstable_dirload_all() + * fitter: + . added "test" hook (as a first step towards a fittterstate map) + . new calls: fitter_getfloat(), fitter_getsymbol() + * fragile: new call fragile_class_getexterndir() + * loud: loud_syserror() accepts a format string + * support for building into subdirectory of the main bin directory + (so that a library may automatically load all its plugin externals) + with toxy alpha18 * plusbob: stubifying t_plusbob, in order to minimize memory leak to 4 words diff --git a/shared/shared.h b/shared/shared.h index a812ffe..0e60dbd 100644 --- a/shared/shared.h +++ b/shared/shared.h @@ -164,8 +164,21 @@ typedef union _shared_floatint #define SHARED_2PI 6.28318530718 #ifndef PD_BADFLOAT +#ifdef __i386__ #define PD_BADFLOAT(f) ((((*(unsigned int*)&(f))&0x7f800000)==0) || \ (((*(unsigned int*)&(f))&0x7f800000)==0x7f800000)) +#else +#define PD_BADFLOAT(f) 0 +#endif +#endif + +#ifndef PD_BIGORSMALL +#ifdef __i386__ +#define PD_BIGORSMALL(f) ((((*(unsigned int*)&(f))&0x60000000)==0) || \ + (((*(unsigned int*)&(f))&0x60000000)==0x60000000)) +#else +#define PD_BIGORSMALL(f) 0 +#endif #endif #endif diff --git a/shared/unstable/fragile.c b/shared/unstable/fragile.c index e65e6d4..82d5065 100644 --- a/shared/unstable/fragile.c +++ b/shared/unstable/fragile.c @@ -10,6 +10,12 @@ #include "unstable/pd_imp.h" #include "unstable/fragile.h" +/* this one rather belongs to fringe.c... */ +t_symbol *fragile_class_getexterndir(t_class *c) +{ + return (c->c_externdir); +} + int fragile_class_count(void) { return (pd_objectmaker->c_nmethod); diff --git a/shared/unstable/fragile.h b/shared/unstable/fragile.h index 1e2ea0e..9a5587d 100644 --- a/shared/unstable/fragile.h +++ b/shared/unstable/fragile.h @@ -5,6 +5,7 @@ #ifndef __FRAGILE_H__ #define __FRAGILE_H__ +t_symbol *fragile_class_getexterndir(t_class *c); int fragile_class_count(void); int fragile_class_getnames(t_atom *av, int maxnames); void fragile_class_raise(t_symbol *cname, t_newmethod thiscall); diff --git a/shared/unstable/loader.c b/shared/unstable/loader.c index 91b7ff3..4872500 100644 --- a/shared/unstable/loader.c +++ b/shared/unstable/loader.c @@ -1,12 +1,10 @@ -/* Copyright (c) 1997-2003 Miller Puckette, krzYszcz, and others. +/* Copyright (c) 1997-2005 Miller Puckette, krzYszcz, and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ /* This is just a not-yet-in-the-API-sys_load_lib() duplication (modulo differentiating the error return codes). LATER use the original. */ -#include "loader.h" - #ifdef __linux__ #include #endif @@ -22,8 +20,11 @@ #include #endif #include -#include "m_pd.h" #include +#include "m_pd.h" +#include "common/loud.h" +#include "common/os.h" +#include "loader.h" typedef void (*t_xxx)(void); @@ -48,92 +49,175 @@ static char sys_dllextent[] = ".dll"; #endif -int unstable_load_lib(char *dirname, char *classname) +static int unstable_doload_lib(char *dirname, char *classname) { - char symname[MAXPDSTRING], filename[MAXPDSTRING], dirbuf[MAXPDSTRING], - *nameptr, *lastdot; + char symname[MAXPDSTRING], filename[MAXPDSTRING], *lastdot; void *dlobj; t_xxx makeout; - int fd; #ifdef NT HINSTANCE ntdll; #endif -#if 0 - fprintf(stderr, "lib %s %s\n", dirname, classname); -#endif - if ((fd = open_via_path(dirname, classname, sys_dllextent, - dirbuf, &nameptr, MAXPDSTRING, 1)) < 0) - { - return (LOADER_NOFILE); - } - else - { - close(fd); - /* refabricate the pathname */ - strcpy(filename, dirbuf); - strcat(filename, "/"); - strcat(filename, nameptr); - /* extract the setup function name */ - if (lastdot = strrchr(nameptr, '.')) - *lastdot = 0; + /* refabricate the pathname */ + strcpy(filename, dirname); + strcat(filename, "/"); + strcat(filename, classname); + /* extract the setup function name */ + if (lastdot = strrchr(classname, '.')) + *lastdot = 0; #ifdef MACOSX - strcpy(symname, "_"); - strcat(symname, nameptr); + strcpy(symname, "_"); + strcat(symname, classname); #else - strcpy(symname, nameptr); + strcpy(symname, classname); #endif - /* if the last character is a tilde, replace with "_tilde" */ - if (symname[strlen(symname) - 1] == '~') - strcpy(symname + (strlen(symname) - 1), "_tilde"); - /* and append _setup to form the C setup function name */ - strcat(symname, "_setup"); + /* if the last character is a tilde, replace with "_tilde" */ + if (symname[strlen(symname) - 1] == '~') + strcpy(symname + (strlen(symname) - 1), "_tilde"); + /* and append _setup to form the C setup function name */ + strcat(symname, "_setup"); #ifdef __linux__ - dlobj = dlopen(filename, RTLD_NOW | RTLD_GLOBAL); - if (!dlobj) - { - post("%s: %s", filename, dlerror()); - return (LOADER_BADFILE); - } - makeout = (t_xxx)dlsym(dlobj, symname); + dlobj = dlopen(filename, RTLD_NOW | RTLD_GLOBAL); + if (!dlobj) + { + post("%s: %s", filename, dlerror()); + return (LOADER_BADFILE); + } + makeout = (t_xxx)dlsym(dlobj, symname); #endif #ifdef NT - sys_bashfilename(filename, filename); - ntdll = LoadLibrary(filename); - if (!ntdll) - { + sys_bashfilename(filename, filename); + ntdll = LoadLibrary(filename); + if (!ntdll) + { + post("%s: couldn't load", filename); + return (LOADER_BADFILE); + } + makeout = (t_xxx)GetProcAddress(ntdll, symname); +#endif +#ifdef MACOSX + { + NSObjectFileImage image; + void *ret; + NSSymbol s; + if ( NSCreateObjectFileImageFromFile( filename, &image) != NSObjectFileImageSuccess ) + { post("%s: couldn't load", filename); return (LOADER_BADFILE); } - makeout = (t_xxx)GetProcAddress(ntdll, symname); -#endif -#ifdef MACOSX - { - NSObjectFileImage image; - void *ret; - NSSymbol s; - if ( NSCreateObjectFileImageFromFile( filename, &image) != NSObjectFileImageSuccess ) - { - post("%s: couldn't load", filename); - return (LOADER_BADFILE); - } - ret = NSLinkModule( image, filename, - NSLINKMODULE_OPTION_BINDNOW - + NSLINKMODULE_OPTION_PRIVATE); + ret = NSLinkModule( image, filename, + NSLINKMODULE_OPTION_BINDNOW + + NSLINKMODULE_OPTION_PRIVATE); - s = NSLookupSymbolInModule(ret, symname); + s = NSLookupSymbolInModule(ret, symname); - if (s) - makeout = (t_xxx)NSAddressOfSymbol( s); - else makeout = 0; - } -#endif + if (s) + makeout = (t_xxx)NSAddressOfSymbol( s); + else makeout = 0; } +#endif if (!makeout) { - post("load_object: Symbol \"%s\" not found", symname); - return (LOADER_NOENTRY); + post("load_object: Symbol \"%s\" not found", symname); + return (LOADER_NOENTRY); } (*makeout)(); return (LOADER_OK); } + +/* start searching from dirname, then search the path */ +int unstable_load_lib(char *dirname, char *classname) +{ + char dirbuf[MAXPDSTRING], *nameptr; + int fd; + if ((fd = open_via_path(dirname, classname, sys_dllextent, + dirbuf, &nameptr, MAXPDSTRING, 1)) < 0) + { + return (LOADER_NOFILE); + } + else + { + close(fd); + return (unstable_doload_lib(dirbuf, nameptr)); + } +} + +/* only dirname is searched */ +int unstable_dirload_lib(char *dirname, char *classname) +{ + if (strlen(dirname) + strlen(classname) + strlen(sys_dllextent) + 3 < + MAXPDSTRING) + { + char namebuf[MAXPDSTRING], *slash, *nameptr; + strcpy(namebuf, dirname); + if (*dirname && namebuf[strlen(namebuf)-1] != '/') + strcat(namebuf, "/"); + strcat(namebuf, classname); + strcat(namebuf, sys_dllextent); + slash = strrchr(namebuf, '/'); + if (slash) + { + *slash = 0; + nameptr = slash + 1; + } + else nameptr = namebuf; + return (unstable_doload_lib(namebuf, nameptr)); + } + else return (LOADER_FAILED); +} + +/* return the number of successfully loaded libraries, or -1 on error */ +int unstable_dirload_all(char *dirname, int beloud, int withclasses) +{ + t_osdir *dp = osdir_open(dirname); + if (dp) + { + int result = 0; + char namebuf[MAXPDSTRING], *name; + osdir_setmode(dp, OSDIR_FILEMODE); + while (name = osdir_next(dp)) + { + int namelen = strlen(name), extlen = strlen(sys_dllextent); + if ((namelen -= extlen) > 0 && + strcmp(name + namelen, sys_dllextent) == 0) + { + strncpy(namebuf, name, namelen); + namebuf[namelen] = 0; + if (zgetfn(&pd_objectmaker, gensym(namebuf))) + { + if (beloud) + loud_warning(0, "xeq", "plugin \"%s\" already loaded", + namebuf); + } + else + { + int err; + if (beloud) + post("loading xeq plugin \"%s\"", namebuf); + err = unstable_dirload_lib(dirname, namebuf); + if (err == LOADER_NOFILE) + { + if (beloud) + loud_error(0, "xeq plugin \"%s\" disappeared", + namebuf); + } + else if (!zgetfn(&pd_objectmaker, gensym(namebuf))) + { + if (beloud) + loud_error(0, "library \"%s\" not compatible", + namebuf); + } + else result++; + } + } + } + osdir_close(dp); + return (result); + } + else + { + if (beloud) + loud_syserror(0, "cannot open \"%s\"", dirname); + return (-1); + } +} diff --git a/shared/unstable/loader.h b/shared/unstable/loader.h index e9766ac..7c18036 100644 --- a/shared/unstable/loader.h +++ b/shared/unstable/loader.h @@ -1,12 +1,15 @@ -/* Copyright (c) 2003 krzYszcz and others. +/* Copyright (c) 2003-2005 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #ifndef __LOADER_H__ #define __LOADER_H__ -enum { LOADER_OK, LOADER_NOFILE, LOADER_BADFILE, LOADER_NOENTRY }; +enum { LOADER_OK, LOADER_FAILED, + LOADER_NOFILE, LOADER_BADFILE, LOADER_NOENTRY }; int unstable_load_lib(char *dirname, char *classname); +int unstable_dirload_lib(char *dirname, char *classname); +int unstable_dirload_all(char *dirname, int beloud, int withclasses); #endif diff --git a/toxy/Makefile.objects b/toxy/Makefile.objects index b0300f0..3a947af 100644 --- a/toxy/Makefile.objects +++ b/toxy/Makefile.objects @@ -20,6 +20,7 @@ toxy/scriptlet.o \ toxy/plusbob.o PLUSTOT_PRIVATEOBJECTS = \ +plustot.ar.o \ plustot.env.o \ plustot.in.o \ plustot.var.o \ diff --git a/toxy/plustot.ar.c b/toxy/plustot.ar.c new file mode 100644 index 0000000..adca72c --- /dev/null +++ b/toxy/plustot.ar.c @@ -0,0 +1,128 @@ +/* Copyright (c) 2003-2005 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" +#include "common/loud.h" +#include "toxy/plusbob.h" +#include "plustot.h" + +typedef struct _plusproxy_ar +{ + t_pd pp_pd; + t_plustob *pp_tob; +} t_plusproxy_ar; + +typedef struct _plustot_ar +{ + t_plusobject x_plusobject; + t_glist *x_glist; + t_plustob *x_tob; + t_plusproxy_ar *x_proxy; +} t_plustot_ar; + +static t_class *plusproxy_ar_class; +static t_class *plustot_ar_class; + +static t_plusproxy_ar *plusproxy_ar_new(t_pd *master) +{ + t_plusproxy_ar *pp = (t_plusproxy_ar *)pd_new(plusproxy_ar_class); + pp->pp_tob = ((t_plustot_ar *)master)->x_tob; + return (pp); +} + +static void plusproxy_ar_float(t_plusproxy_ar *pp, t_float f) +{ + plustob_setfloat(pp->pp_tob, f); +} + +static void plusproxy_ar_symbol(t_plusproxy_ar *pp, t_symbol *s) +{ + plustob_setsymbol(pp->pp_tob, s); +} + +static void plusproxy_ar_list(t_plusproxy_ar *pp, + t_symbol *s, int ac, t_atom *av) +{ + plustob_setlist(pp->pp_tob, ac, av); +} + +static void plustot_ar_bang(t_plustot_ar *x) +{ + if (plustob_getvalue(x->x_tob)) + outlet_plusbob(((t_object *)x)->ob_outlet, (t_plusbob *)x->x_tob); +} + +static void plustot_ar_float(t_plustot_ar *x, t_float f) +{ + if (plustob_setfloat(x->x_tob, f)) + outlet_plusbob(((t_object *)x)->ob_outlet, (t_plusbob *)x->x_tob); +} + +static void plustot_ar_symbol(t_plustot_ar *x, t_symbol *s) +{ + if (plustob_setsymbol(x->x_tob, s)) + outlet_plusbob(((t_object *)x)->ob_outlet, (t_plusbob *)x->x_tob); +} + +static void plustot_ar_list(t_plustot_ar *x, t_symbol *s, int ac, t_atom *av) +{ + if (plustob_setlist(x->x_tob, ac, av)) + outlet_plusbob(((t_object *)x)->ob_outlet, (t_plusbob *)x->x_tob); +} + +static void plustot_ar_free(t_plustot_ar *x) +{ + plusbob_release((t_plusbob *)x->x_tob); + if (x->x_proxy) pd_free((t_pd *)x->x_proxy); + plusobject_free(&x->x_plusobject); +} + +void *plustot_ar_new(t_symbol *s, int ac, t_atom *av) +{ + t_plustot_ar *x = 0; + t_glist *glist = canvas_getcurrent(); + t_plustin *tin = 0; + t_plustob *tob = 0; + if ((tin = plustin_glistprovide(glist, PLUSTIN_GLIST_ANY, 0)) && + (tob = plustob_new(tin, 0))) + { + x = (t_plustot_ar *)plusobject_new(plustot_ar_class, s, ac, av, 0); + plusbob_preserve((t_plusbob *)tob); + plusbob_setowner((t_plusbob *)tob, (t_pd *)x); + plustob_setlist(tob, ac, av); + x->x_glist = glist; + x->x_tob = tob; + x->x_proxy = plusproxy_ar_new((t_pd *)x); + plusinlet_new(&x->x_plusobject, (t_pd *)x->x_proxy, 0, 0); + plusoutlet_new(&x->x_plusobject, &s_symbol); + } + else + { + loud_error(0, "+ar: cannot initialize"); + if (tin) + { + plusbob_preserve((t_plusbob *)tin); + plusbob_release((t_plusbob *)tin); + } + } + return (x); +} + +void plustot_ar_setup(void) +{ + plustot_ar_class = class_new(gensym("+ar"), 0, + (t_method)plustot_ar_free, + sizeof(t_plustot_ar), 0, 0); + plusclass_inherit(plustot_ar_class, gensym("+ar")); + class_addbang(plustot_ar_class, plustot_ar_bang); + class_addfloat(plustot_ar_class, plustot_ar_float); + class_addsymbol(plustot_ar_class, plustot_ar_symbol); + class_addlist(plustot_ar_class, plustot_ar_list); + + plusproxy_ar_class = class_new(gensym("+ar proxy"), 0, 0, + sizeof(t_plusproxy_ar), CLASS_PD, 0); + class_addfloat(plusproxy_ar_class, plusproxy_ar_float); + class_addsymbol(plusproxy_ar_class, plusproxy_ar_symbol); + class_addlist(plusproxy_ar_class, plusproxy_ar_list); +} diff --git a/toxy/plustot.c b/toxy/plustot.c index 865b39c..cb3917b 100644 --- a/toxy/plustot.c +++ b/toxy/plustot.c @@ -34,6 +34,7 @@ # define PLUSDEBUG_DECRREFCOUNT(ob, fn) Tcl_DecrRefCount(ob) #endif +static t_symbol *plusps_ar; static t_symbol *plusps_env; static t_symbol *plusps_in; static t_symbol *plusps_var; @@ -52,6 +53,7 @@ static void plussymbols_create(void) plusps_Tv = gensym("+Tv"); /* private */ + plusps_ar = gensym("+ar"); plusps_env = gensym("+env"); plusps_in = gensym("+in"); plusps_var = gensym("+var"); @@ -101,9 +103,10 @@ void plusloud_tclerror(t_pd *caller, Tcl_Interp *interp, char *msg) struct _plustin { - t_plusenv tin_env; - t_glist *tin_glist; - Tcl_Interp *tin_interp; + t_plusenv tin_env; + t_glist *tin_glist; + Tcl_Interp *tin_interp; + Tcl_CmdInfo *tin_cinfop; }; static t_plustype *plustin_basetype; @@ -144,11 +147,18 @@ t_plustin *plustin_create(t_plustype *tp, t_plusbob *parent, t_symbol *id) (id ? id->s_name : "default"), (int)interp); #endif tin->tin_interp = interp; + tin->tin_cinfop = 0; Tcl_Preserve(interp); if (Tcl_Init(interp) == TCL_ERROR) plusloud_tclerror(0, interp, "interpreter initialization failed"); else { + Tcl_CmdInfo cinfo; + /* store Tcl_CmdInfo for off-API Tcl_InfoObjCmd() */ + if (Tcl_GetCommandInfo(interp, "info", &cinfo) + && cinfo.isNativeObjectProc) + tin->tin_cinfop = copybytes(&cinfo, sizeof(*tin->tin_cinfop)); + /* create custom commands */ Tcl_CreateObjCommand(interp, "test::test", (Tcl_ObjCmdProc*)plustin_testCmd, (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL); @@ -168,6 +178,8 @@ static void plustin_delete(t_plustin *tin) loudbug_post("plustin_delete '%s' over %x", (id ? id->s_name : "default"), (int)tin->tin_interp); #endif + if (tin->tin_cinfop) + freebytes(tin->tin_cinfop, sizeof(*tin->tin_cinfop)); Tcl_Preserve(tin->tin_interp); if (!Tcl_InterpDeleted(tin->tin_interp)) Tcl_DeleteInterp(tin->tin_interp); @@ -179,6 +191,44 @@ Tcl_Interp *plustin_getinterp(t_plustin *tin) return (tin->tin_interp); } +int plustin_procargc(t_plustin *tin, char *pname) +{ + int result = -1; + if (tin->tin_cinfop) + { + /* FIXME preallocate */ + Tcl_Obj *argv[3]; + argv[0] = Tcl_NewStringObj("info", -1); + PLUSDEBUG_INCRREFCOUNT(argv[0], "plustin_procargc"); + argv[1] = Tcl_NewStringObj("args", -1); + PLUSDEBUG_INCRREFCOUNT(argv[0], "plustin_procargc"); + argv[2] = Tcl_NewStringObj(pname, -1); + PLUSDEBUG_INCRREFCOUNT(argv[1], "plustin_procargc"); + if ((*tin->tin_cinfop->objProc)(tin->tin_cinfop->objClientData, + tin->tin_interp, + 3, argv) == TCL_OK) + { + Tcl_Obj *rob; + if (rob = Tcl_GetObjResult(tin->tin_interp)) + { + PLUSDEBUG_INCRREFCOUNT(rob, "plustin_procargc"); + if (Tcl_ListObjLength(tin->tin_interp, rob, &result) != TCL_OK) + { + result = -1; + plusloud_tcldirty(0, "plustin_procargc"); + } + Tcl_ResetResult(tin->tin_interp); + PLUSDEBUG_DECRREFCOUNT(rob, "plustin_procargc"); + } + else plusloud_tcldirty(0, "plustin_procargc"); + } + PLUSDEBUG_DECRREFCOUNT(argv[0], "plustin_procargc"); + PLUSDEBUG_DECRREFCOUNT(argv[1], "plustin_procargc"); + PLUSDEBUG_DECRREFCOUNT(argv[2], "plustin_procargc"); + } + return (result); +} + t_symbol *plustin_glistid(t_glist *gl) { char buf[32]; @@ -2089,7 +2139,9 @@ static void *plustot_new(t_symbol *s, int ac, t_atom *av) { if (*cmdname->s_name == '+') { - if (cmdname == plusps_env) + if (cmdname == plusps_ar) + return (plustot_ar_new(cmdname, ac, av)); + else if (cmdname == plusps_env) return (plustot_env_new(cmdname, ac, av)); else if (cmdname == plusps_in) return (plustot_in_new(cmdname, ac, av)); @@ -2180,6 +2232,10 @@ static void *plustot_new(t_symbol *s, int ac, t_atom *av) res = plustot_makewords(x); if (res) { + /* FIXME [+tot +ar pname] */ + int n = plustin_procargc(tin, cmdname->s_name); + loudbug_post("plustin_procargc: %d", n); + /* creation time evaluation, LATER rethink: should this be immediate or scheduled? */ x->x_isloud = 0; @@ -2325,6 +2381,7 @@ void plustot_setup(void) plusvar_type = plustype_new(plustob_type, plusps_Tv, sizeof(t_plusvar), (t_plustypefn)plusvar_delete, 0, 0, 0); + plustot_ar_setup(); plustot_env_setup(); plustot_in_setup(); plustot_var_setup(); diff --git a/toxy/plustot.h b/toxy/plustot.h index 0cc6fa6..7022fd6 100644 --- a/toxy/plustot.h +++ b/toxy/plustot.h @@ -101,6 +101,7 @@ t_inlet *plusinlet_new(t_plusobject *po, t_pd *dest, t_outlet *plusoutlet_new(t_plusobject *po, t_symbol *s); void plusclass_inherit(t_class *c, t_symbol *s); +void plustot_ar_setup(void); void plustot_env_setup(void); void plustot_in_setup(void); void plustot_var_setup(void); @@ -108,6 +109,7 @@ void plustot_out_setup(void); void plustot_qlist_setup(void); void plustot_print_setup(void); +void *plustot_ar_new(t_symbol *s, int ac, t_atom *av); void *plustot_env_new(t_symbol *s, int ac, t_atom *av); void *plustot_in_new(t_symbol *s, int ac, t_atom *av); void *plustot_var_new(t_symbol *s, int ac, t_atom *av); -- cgit v1.2.1