diff options
author | Bryan Jurish <mukau@users.sourceforge.net> | 2006-02-02 12:49:19 +0000 |
---|---|---|
committer | Bryan Jurish <mukau@users.sourceforge.net> | 2006-02-02 12:49:19 +0000 |
commit | 0727bfcaf2bd48bf501a7fa95515c400a1996902 (patch) | |
tree | 81a3774a9601ba1242482696344f3de3e08f8f22 /gfsm/src/pd_state.c | |
parent | 6a4001a8538862ac02714a03fedd07c3b6f79366 (diff) |
initial cvs import
svn path=/trunk/externals/moocow/; revision=4536
Diffstat (limited to 'gfsm/src/pd_state.c')
-rw-r--r-- | gfsm/src/pd_state.c | 303 |
1 files changed, 303 insertions, 0 deletions
diff --git a/gfsm/src/pd_state.c b/gfsm/src/pd_state.c new file mode 100644 index 0000000..b7cd938 --- /dev/null +++ b/gfsm/src/pd_state.c @@ -0,0 +1,303 @@ +/*=============================================================================*\ + * File: pd_state.c + * Author: Bryan Jurish <moocow@ling.uni-potsdam.de> + * Description: finite state automata for Pd + * + * Copyright (c) 2004 Bryan Jurish. + * + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * See file LICENSE for further informations on licensing terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + *=============================================================================*/ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <pd_state.h> + +/*===================================================================== + * Structures and Types + *=====================================================================*/ +static t_class *pd_gfsm_state_class; + + +/*===================================================================== + * pd_gfsm_state: Methods + *=====================================================================*/ + +/*===================================================================== + * Constructors, etc. + */ + +/*-------------------------------------------------------------------- + * new() + */ +static void *pd_gfsm_state_new(t_symbol *sel, int argc, t_atom *argv) +{ + t_symbol *name = &s_; + t_pd_gfsm_state *x = (t_pd_gfsm_state *)pd_new(pd_gfsm_state_class); + + //-- defaults + x->x_id = gfsmNoState; + gfsm_arciter_close(&x->x_arci); + x->x_open = FALSE; + + //-- args + if (argc > 0) { + name = atom_getsymbolarg(0,argc,argv); + if (argc > 1) x->x_id = (gfsmStateId)atom_getfloatarg(1,argc,argv); + } + + //-- bindings + x->x_automaton_pd = pd_gfsm_automaton_pd_get(name); + x->x_automaton_pd->x_refcnt++; + + //-- outlets + x->x_valout = outlet_new(&x->x_obj, &s_anything); //-- value outlet + + return (void *)x; +} + +/*-------------------------------------------------------------------- + * free + */ +static void pd_gfsm_state_free(t_pd_gfsm_state *x) +{ + gfsm_arciter_close(&x->x_arci); + pd_gfsm_automaton_pd_release(x->x_automaton_pd); + + //-- do we need to do this? + outlet_free(x->x_valout); +} + +/*===================================================================== + * Basic Accessors + */ + +/*-------------------------------------------------------------------- + * automaton + */ +static void pd_gfsm_state_automaton(t_pd_gfsm_state *x, t_symbol *name) +{ + gfsm_arciter_close(&x->x_arci); + x->x_open = FALSE; + + if (name == x->x_automaton_pd->x_name) return; + pd_gfsm_automaton_pd_release(x->x_automaton_pd); + + x->x_automaton_pd = pd_gfsm_automaton_pd_get(name); + ++x->x_automaton_pd->x_refcnt; +} + + +/*-------------------------------------------------------------------- + * id + */ +static void pd_gfsm_state_id(t_pd_gfsm_state *x) +{ + SETSYMBOL(x->x_argv, gensym("id")); + if (x->x_id==gfsmNoState) SETSYMBOL(x->x_argv, &s_bang); + else SETFLOAT(x->x_argv, (t_float)(x->x_id)); + outlet_anything(x->x_valout, gensym("id"), 1, x->x_argv); +} + +/*-------------------------------------------------------------------- + * set + */ +static void pd_gfsm_state_set(t_pd_gfsm_state *x, t_floatarg qf) +{ + if (qf<0) qf = -qf; + gfsm_arciter_close(&x->x_arci); + x->x_open = FALSE; + x->x_id = gfsm_automaton_ensure_state(x->x_automaton_pd->x_automaton, (gfsmStateId)qf); +} + +/*-------------------------------------------------------------------- + * degree + */ +static void pd_gfsm_state_degree(t_pd_gfsm_state *x) +{ + gfsmState *s = gfsm_automaton_find_state(x->x_automaton_pd->x_automaton, x->x_id); + SETFLOAT(x->x_argv, (s ? (t_float)gfsm_state_out_degree(s) : 0)); + outlet_anything(x->x_valout, gensym("degree"), 1, x->x_argv); +} + +/*===================================================================== + * Navigation + */ + +/*-------------------------------------------------------------------- + * utility: outlet_arc() + */ +static void pd_gfsm_state_outlet_arc(t_pd_gfsm_state *x, t_symbol *sel) +{ + //outlet_anything(x->x_opout, op, 0, NULL); + if (gfsm_arciter_ok(&x->x_arci)) { + gfsmArc *a = gfsm_arciter_arc(&x->x_arci); + SETFLOAT(x->x_argv, (t_float)(a->target)); + SETFLOAT(x->x_argv+1, (t_float)(a->lower)); + SETFLOAT(x->x_argv+2, (t_float)(a->upper)); + SETFLOAT(x->x_argv+3, (t_float)(a->weight)); + outlet_anything(x->x_valout, sel, 4, x->x_argv); + } + else { + SETSYMBOL(x->x_argv, &s_bang); + outlet_anything(x->x_valout, sel, 1, x->x_argv); + } +} + +/*-------------------------------------------------------------------- + * arc_first + */ +static void pd_gfsm_state_arc_first(t_pd_gfsm_state *x) +{ + gfsm_arciter_close(&x->x_arci); + gfsm_arciter_open(&x->x_arci, x->x_automaton_pd->x_automaton, x->x_id); + x->x_open = TRUE; + pd_gfsm_state_outlet_arc(x, gensym("arc_first")); +} + +/*-------------------------------------------------------------------- + * arc_next + */ +static void pd_gfsm_state_arc_next(t_pd_gfsm_state *x) +{ + gfsmState *s = gfsm_automaton_find_state(x->x_automaton_pd->x_automaton, x->x_id); + if (s) { + if (x->x_open && gfsm_arciter_ok(&x->x_arci)) { + gfsm_arciter_next(&x->x_arci); + } else if (!x->x_open) { + gfsm_arciter_open(&x->x_arci, x->x_automaton_pd->x_automaton, x->x_id); + x->x_open = TRUE; + } + } + pd_gfsm_state_outlet_arc(x, gensym("arc_next")); +} + +/*-------------------------------------------------------------------- + * arc_seek + */ +static void pd_gfsm_state_arc_seek(t_pd_gfsm_state *x, t_float flo, t_float fhi) +{ + gfsmState *s = gfsm_automaton_find_state(x->x_automaton_pd->x_automaton, x->x_id); + if (s) { + if (x->x_open && gfsm_arciter_ok(&x->x_arci)) { + gfsm_arciter_next(&x->x_arci); + } else if (!x->x_open) { + gfsm_arciter_open(&x->x_arci, x->x_automaton_pd->x_automaton, x->x_id); + x->x_open = TRUE; + } + } + gfsm_arciter_seek_both(&x->x_arci, + (flo < 0 ? gfsmNoLabel : ((gfsmLabelVal)flo)), + (fhi < 0 ? gfsmNoLabel : ((gfsmLabelVal)fhi))); + pd_gfsm_state_outlet_arc(x, gensym("arc_seek")); +} + + +/*-------------------------------------------------------------------- + * arc_reset + */ +static void pd_gfsm_state_arc_reset(t_pd_gfsm_state *x) +{ + gfsm_arciter_close(&x->x_arci); + x->x_open = FALSE; +} + +/*-------------------------------------------------------------------- + * add_weight + */ +static void pd_gfsm_state_add_weight(t_pd_gfsm_state *x, + t_float fto, + t_float flo, + t_float fhi, + t_float w) +{ + gfsmStateId to = (fto < 0 ? (-fto) : ((gfsmStateId)fto)); + gfsmLabelVal lo = (flo < 0 ? gfsmNoLabel : ((gfsmLabelVal)flo)); + gfsmLabelVal hi = (fhi < 0 ? gfsmNoLabel : ((gfsmLabelVal)fhi)); + + if (x->x_open) pd_gfsm_state_arc_reset(x); + + gfsm_arciter_open(&x->x_arci, x->x_automaton_pd->x_automaton, x->x_id); + gfsm_arciter_seek_both(&x->x_arci, lo, hi); + + if (gfsm_arciter_ok(&x->x_arci)) { + gfsm_arciter_arc(&x->x_arci)->weight += w; + } else { + if (lo==gfsmNoLabel) lo = gfsmEpsilon; + if (hi==gfsmNoLabel) hi = gfsmEpsilon; + gfsm_automaton_add_arc(x->x_automaton_pd->x_automaton, x->x_id, to, lo, hi, w); + } + + pd_gfsm_state_arc_reset(x); +} + + + +/*===================================================================== + * Setup + */ + +/*-------------------------------------------------------------------- + * setup() + */ +void pd_gfsm_state_setup(void) +{ + //-- class + pd_gfsm_state_class = class_new(gensym("gfsm_state"), + (t_newmethod)pd_gfsm_state_new, + (t_method)pd_gfsm_state_free, + sizeof(t_pd_gfsm_state), + CLASS_DEFAULT, + A_GIMME, A_NULL); + + //-- methods: automaton + class_addmethod(pd_gfsm_state_class, + (t_method)pd_gfsm_state_automaton, + gensym("automaton"), + A_DEFSYM, A_NULL); + + //-- methods: id + class_addmethod(pd_gfsm_state_class, (t_method)pd_gfsm_state_id, + gensym("id"), A_NULL); + class_addmethod(pd_gfsm_state_class, (t_method)pd_gfsm_state_set, + gensym("set"), A_DEFFLOAT, A_NULL); + + //-- methods: degree + class_addmethod(pd_gfsm_state_class, (t_method)pd_gfsm_state_degree, + gensym("degree"), A_NULL); + + //-- methods: navigation + class_addmethod(pd_gfsm_state_class, (t_method)pd_gfsm_state_arc_first, + gensym("arc_first"), A_NULL); + class_addmethod(pd_gfsm_state_class, (t_method)pd_gfsm_state_arc_next, + gensym("arc_next"), A_NULL); + class_addmethod(pd_gfsm_state_class, (t_method)pd_gfsm_state_arc_seek, + gensym("arc_seek"), A_FLOAT, A_FLOAT, A_NULL); + class_addmethod(pd_gfsm_state_class, (t_method)pd_gfsm_state_arc_reset, + gensym("arc_reset"), A_NULL); + + //-- methods: manipulation + class_addmethod(pd_gfsm_state_class, (t_method)pd_gfsm_state_add_weight, + gensym("add_weight"), A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_NULL); + + //-- help symbol + class_sethelpsymbol(pd_gfsm_state_class, gensym("gfsm_state-help.pd")); +} |