diff options
Diffstat (limited to 'cyclone/hammer/Table.c')
-rw-r--r-- | cyclone/hammer/Table.c | 454 |
1 files changed, 454 insertions, 0 deletions
diff --git a/cyclone/hammer/Table.c b/cyclone/hammer/Table.c new file mode 100644 index 0000000..d60d3ca --- /dev/null +++ b/cyclone/hammer/Table.c @@ -0,0 +1,454 @@ +/* Copyright (c) 2004 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 <stdio.h> +#include <string.h> +#include "m_pd.h" +#include "g_canvas.h" +#include "common/loud.h" +#include "common/grow.h" +#include "hammer/file.h" + +#define TABLE_DEBUG + +#define TABLE_INISIZE 256 /* LATER rethink */ +#define TABLE_DEFLENGTH 128 +#define TABLE_MINLENGTH 2 +#define TABLE_MAXLENGTH 16383 + +typedef struct _tablecommon +{ + t_pd c_pd; + struct _table *c_refs; /* used in read-banging and dirty flag handling */ + int c_embedflag; /* common field (CHECKED in 'TEXT') */ + int c_loading; + int c_relinked; + int c_size; /* as allocated */ + int c_length; /* as used */ + int *c_table; + int c_tableini[TABLE_INISIZE]; + t_symbol *c_filename; + t_canvas *c_lastcanvas; + t_hammerfile *c_filehandle; +} t_tablecommon; + +typedef struct _table +{ + t_object x_ob; + t_canvas *x_canvas; + t_symbol *x_name; + t_tablecommon *x_common; + t_float x_value; + int x_valueset; + int x_head; + t_hammerfile *x_filehandle; + t_outlet *x_bangout; + struct _table *x_next; +} t_table; + +static t_class *table_class; +static t_class *tablecommon_class; + +static void tablecommon_modified(t_tablecommon *cc, int relinked) +{ + if (cc->c_loading) + return; + if (relinked) + { + cc->c_relinked = 1; + } + if (cc->c_embedflag) + { + t_table *x; + for (x = cc->c_refs; x; x = x->x_next) + if (x->x_canvas && glist_isvisible(x->x_canvas)) + canvas_dirty(x->x_canvas, 1); + } +} + +static void tablecommon_doread(t_tablecommon *cc, t_symbol *fn, t_canvas *cv) +{ + /* FIXME */ +} + +static void tablecommon_readhook(t_pd *z, t_symbol *fn, int ac, t_atom *av) +{ + tablecommon_doread((t_tablecommon *)z, fn, 0); +} + +static void tablecommon_dowrite(t_tablecommon *cc, t_symbol *fn, t_canvas *cv) +{ + /* FIXME */ +} + +static void tablecommon_writehook(t_pd *z, t_symbol *fn, int ac, t_atom *av) +{ + tablecommon_dowrite((t_tablecommon *)z, fn, 0); +} + +static void table_embedhook(t_pd *z, t_binbuf *bb, t_symbol *bindsym) +{ + /* FIXME */ +} + +static void tablecommon_editorhook(t_pd *z, t_symbol *s, int ac, t_atom *av) +{ + /* FIXME */ +} + +static t_tablecommon *table_checkcommon(t_table *x) +{ + if (x->x_name && + x->x_common != (t_tablecommon *)pd_findbyclass(x->x_name, + tablecommon_class)) + { + bug("table_checkcommon"); + return (0); + } + return (x->x_common); +} + +static void table_unbind(t_table *x) +{ + /* LATER consider calling table_checkcommon(x) */ + t_tablecommon *cc = x->x_common; + t_table *prev, *next; + if ((prev = cc->c_refs) == x) + { + if (!(cc->c_refs = x->x_next)) + { + hammerfile_free(cc->c_filehandle); + cc->c_loading = 1; /* disable dirty-flag handling, LATER rethink */ + if (cc->c_table != cc->c_tableini) + freebytes(cc->c_table, cc->c_size * sizeof(*cc->c_table)); + if (x->x_name) pd_unbind(&cc->c_pd, x->x_name); + pd_free(&cc->c_pd); + } + } + else if (prev) + { + while (next = prev->x_next) + { + if (next == x) + { + prev->x_next = next->x_next; + break; + } + prev = next; + } + } + x->x_common = 0; + x->x_name = 0; + x->x_next = 0; +} + +static void table_bind(t_table *x, t_symbol *name) +{ + t_tablecommon *cc = 0; + if (name == &s_) + name = 0; + else if (name) + cc = (t_tablecommon *)pd_findbyclass(name, tablecommon_class); + if (!cc) + { + cc = (t_tablecommon *)pd_new(tablecommon_class); + cc->c_refs = 0; + cc->c_embedflag = 0; + cc->c_loading = 0; + cc->c_size = TABLE_INISIZE; + cc->c_length = TABLE_DEFLENGTH; + cc->c_table = cc->c_tableini; + if (name) + { + pd_bind(&cc->c_pd, name); + /* LATER rethink canvas unpredictability */ + tablecommon_doread(cc, name, x->x_canvas); + } + else + { + cc->c_filename = 0; + cc->c_lastcanvas = 0; + } + cc->c_filehandle = hammerfile_new((t_pd *)cc, 0, tablecommon_readhook, + tablecommon_writehook, + tablecommon_editorhook); + } + x->x_common = cc; + x->x_name = name; + x->x_next = cc->c_refs; + cc->c_refs = x; +} + +static int table_rebind(t_table *x, t_symbol *name) +{ + t_tablecommon *cc; + if (name && name != &s_ && + (cc = (t_tablecommon *)pd_findbyclass(name, tablecommon_class))) + { + table_unbind(x); + x->x_common = cc; + x->x_name = name; + x->x_next = cc->c_refs; + cc->c_refs = x; + return (1); + } + else return (0); +} + +static void table_dooutput(t_table *x, int ndx) +{ + t_tablecommon *cc = x->x_common; + /* CHECKED ndx silently truncated */ + if (ndx < 0) + ndx = 0; + else if (ndx > cc->c_length) + ndx = cc->c_length - 1; + outlet_float(((t_object *)x)->ob_outlet, (t_float)cc->c_table[ndx]); +} + +static void table_setvalue(t_table *x, int ndx, int v) +{ + t_tablecommon *cc = x->x_common; + /* CHECKED ndx silently truncated */ + if (ndx < 0) + ndx = 0; + else if (ndx > cc->c_length) + ndx = cc->c_length - 1; + cc->c_table[ndx] = v; /* CHECKED no truncation */ +} + +static void table_bang(t_table *x) +{ + /* FIXME */ +} + +static void table_float(t_table *x, t_float f) +{ + int ndx = (int)f; /* CHECKED floats are truncated */ + if (x->x_valueset) + { + table_setvalue(x, ndx, x->x_value); + x->x_valueset = 0; + } + else table_dooutput(x, ndx); + /* CHECKME if head is updated */ + x->x_head = ndx; +} + +static void table_ft1(t_table *x, t_floatarg f) +{ + x->x_value = (int)f; /* CHECKED floats are truncated */ + x->x_valueset = 1; +} + +static void table_cancel(t_table *x) +{ + x->x_valueset = 0; +} + +static void table_clear(t_table *x) +{ + t_tablecommon *cc = x->x_common; + int ndx = cc->c_length; + int *ptr = cc->c_table; + while (ndx--) *ptr++ = 0; + /* CHECKME head */ +} + +static void table_next(t_table *x) +{ + table_dooutput(x, x->x_head++); + if (x->x_head >= x->x_common->c_length) + x->x_head = 0; +} + +static void table_prev(t_table *x) +{ + table_dooutput(x, x->x_head--); + if (x->x_head < 0) + x->x_head = x->x_common->c_length - 1; +} + +static void table_goto(t_table *x, t_floatarg f) +{ + t_tablecommon *cc = x->x_common; + int ndx = (int)f; /* CHECKED floats are truncated */ + /* CHECKED ndx silently truncated */ + if (ndx < 0) + ndx = 0; + else if (ndx > cc->c_length) + ndx = cc->c_length - 1; + x->x_head = ndx; +} + +static void table_length(t_table *x) +{ + outlet_float(((t_object *)x)->ob_outlet, (t_float)x->x_common->c_length); +} + +static void table_min(t_table *x) +{ + /* FIXME */ +} + +static void table_max(t_table *x) +{ + /* FIXME */ +} + +static void table_refer(t_table *x, t_symbol *s) +{ + if (!table_rebind(x, s)) + { + /* LATER consider complaining */ + } +} + +static void table_flags(t_table *x, t_float f1, t_float f2) +{ + int i1; + if (loud_checkint((t_pd *)x, f1, &i1, gensym("flags"))) + { + t_tablecommon *cc = x->x_common; + cc->c_embedflag = (i1 != 0); + } + /* FIXME don't save flag */ +} + +static void table_read(t_table *x, t_symbol *s) +{ + t_tablecommon *cc = x->x_common; + if (s && s != &s_) + tablecommon_doread(cc, s, x->x_canvas); + else + hammerpanel_open(cc->c_filehandle, 0); +} + +static void table_write(t_table *x, t_symbol *s) +{ + t_tablecommon *cc = x->x_common; + if (s && s != &s_) + tablecommon_dowrite(cc, s, x->x_canvas); + else + hammerpanel_save(cc->c_filehandle, 0, 0); /* CHECKME default name */ +} + +static void table_dump(t_table *x) +{ + t_tablecommon *cc = x->x_common; + /* FIXME */ +} + +static void table_open(t_table *x) +{ + t_tablecommon *cc = x->x_common; + /* FIXME */ +} + +static void table_wclose(t_table *x) +{ + /* FIXME */ +} + +static void table_click(t_table *x, t_floatarg xpos, t_floatarg ypos, + t_floatarg shift, t_floatarg ctrl, t_floatarg alt) +{ + table_open(x); +} + +#ifdef TABLE_DEBUG +static void table_debug(t_table *x, t_floatarg f) +{ + t_tablecommon *cc = table_checkcommon(x); + if (cc) + { + t_table *x1 = cc->c_refs; + int i = 0; + while (x1) i++, x1 = x1->x_next; + post("refcount %d", i); + } +} +#endif + +static void table_free(t_table *x) +{ + hammerfile_free(x->x_filehandle); + table_unbind(x); +} + +static void *table_new(t_symbol *s) +{ + t_table *x = (t_table *)pd_new(table_class); + static int warned = 0; + if (!warned) + { + loud_warning((t_pd *)x, 0, "Table is not ready yet"); + warned = 1; + } + x->x_canvas = canvas_getcurrent(); + x->x_valueset = 0; + x->x_head = 0; + inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1")); + outlet_new((t_object *)x, &s_float); + x->x_bangout = outlet_new((t_object *)x, &s_bang); + x->x_filehandle = hammerfile_new((t_pd *)x, table_embedhook, 0, 0, 0); + table_bind(x, s); + return (x); +} + +void Table_setup(void) +{ + table_class = class_new(gensym("Table"), + (t_newmethod)table_new, + (t_method)table_free, + sizeof(t_table), 0, A_DEFSYM, 0); + class_addbang(table_class, table_bang); + class_addfloat(table_class, table_float); + class_addmethod(table_class, (t_method)table_ft1, + gensym("ft1"), A_FLOAT, 0); + class_addmethod(table_class, (t_method)table_cancel, + gensym("cancel"), 0); + class_addmethod(table_class, (t_method)table_clear, + gensym("clear"), 0); + class_addmethod(table_class, (t_method)table_next, + gensym("next"), 0); + class_addmethod(table_class, (t_method)table_prev, + gensym("prev"), 0); + class_addmethod(table_class, (t_method)table_goto, + gensym("goto"), A_FLOAT, 0); + class_addmethod(table_class, (t_method)table_length, + gensym("length"), 0); + class_addmethod(table_class, (t_method)table_min, + gensym("min"), 0); + class_addmethod(table_class, (t_method)table_max, + gensym("max"), 0); + class_addmethod(table_class, (t_method)table_refer, + gensym("refer"), A_SYMBOL, 0); + class_addmethod(table_class, (t_method)table_flags, + gensym("flags"), A_FLOAT, A_FLOAT, 0); + class_addmethod(table_class, (t_method)table_read, + gensym("read"), A_DEFSYM, 0); + class_addmethod(table_class, (t_method)table_write, + gensym("write"), A_DEFSYM, 0); + class_addmethod(table_class, (t_method)table_dump, + gensym("dump"), 0); + class_addmethod(table_class, (t_method)table_open, + gensym("open"), 0); + class_addmethod(table_class, (t_method)table_wclose, + gensym("wclose"), 0); + class_addmethod(table_class, (t_method)table_click, + gensym("click"), + A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); +#ifdef TABLE_DEBUG + class_addmethod(table_class, (t_method)table_debug, + gensym("debug"), A_DEFFLOAT, 0); +#endif + hammerfile_setup(table_class, 1); + tablecommon_class = class_new(gensym("Table"), 0, 0, + sizeof(t_tablecommon), CLASS_PD, 0); + /* this call is a nop (tablecommon does not embed, and the hammerfile + class itself has been already set up above), but it is better to + have it around, just in case... */ + hammerfile_setup(tablecommon_class, 0); +} |