From 1baf1d957e195290cfd59089767ca63a547a9917 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Wed, 7 Apr 2004 14:32:29 +0000 Subject: This commit was generated by cvs2svn to compensate for changes in r1560, which included commits to RCS files with non-trunk default branches. svn path=/trunk/externals/mjlib/; revision=1561 --- metroplus.c | 177 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 177 insertions(+) create mode 100644 metroplus.c (limited to 'metroplus.c') diff --git a/metroplus.c b/metroplus.c new file mode 100644 index 0000000..aca86a3 --- /dev/null +++ b/metroplus.c @@ -0,0 +1,177 @@ +#ifdef NT +#include "stdafx.h" +#include +#endif +#include "m_pd.h" + +#include +#include +#include "metroplus.h" + +/** +* The metroplus object is a more complex version of the metro +* object - it allows a list of time intervals to be given which are +* sequentially used thus giving a more compelex timing source +* than the metro object +* +* the code is based on the metro code from the pd source code +*/ + +static t_class *metroplus_class; +static t_class *metroplus_2_class; + +/** +* clock tick - do a bang and wait the next +* time delay in the list +*/ + +static void metroplus_tick(t_metroplus *x) +{ + x->x_hit = 0; + outlet_bang(x->x_obj.ob_outlet); + if (!x->x_hit) clock_delay(x->x_clock, metroplus_getNextDelay(x) ); +} + +/** +* switch the metroplus object on or off +*/ + +static void metroplus_float(t_metroplus *x, t_float f) +{ + if (f != 0) metroplus_tick(x); + else clock_unset(x->x_clock); + x->x_hit = 1; +} + +/** +* a bang turns us on - a start message also calls this function +*/ + +static void metroplus_bang(t_metroplus *x) +{ + metroplus_float(x, 1); +} + +/** +* a stop message turns us off +*/ + +static void metroplus_stop(t_metroplus *x) +{ + metroplus_float(x, 0); +} + +/** +* free our clock and our timer array +*/ + +static void metroplus_free(t_metroplus *x) +{ + clock_free(x->x_clock); + free( x->x_times ); + pd_free( &( (t_metroplus*)x->x_shadow)->x_obj.ob_pd ); +} + +/** +* get the next delay time in the list - wrap +* if we have run over the end +*/ + +static float metroplus_getNextDelay( t_metroplus *x ) +{ + if ( x->x_idx == x->x_size ) + { + x->x_idx = 0; + } + return x->x_times[ x->x_idx++ ]; +} + +/* +* make a new metroplus - we can provide a list of times +* so read these in too +*/ + +static void *metroplus_new(t_symbol *s, int argc, t_atom *argv) +{ + int i; + t_metroplus *x = (t_metroplus *)pd_new(metroplus_class); + t_metroplus *x1 = (t_metroplus *)pd_new(metroplus_2_class); + x->x_shadow=x1; + x1->x_shadow=x; + x->x_times = NULL; + // a silly little kludge - out time_seq method assumes it is accessed from x1 + // so we have to pass a pointer to this so it can dereference it + metroplus_time_seq( x->x_shadow , s , argc , argv ); + x->x_clock = clock_new(x, (t_method)metroplus_tick); + outlet_new(&x->x_obj, gensym("bang")); + inlet_new( &x->x_obj , &x1->x_obj.ob_pd,0,0); + //inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("list"), gensym("tseq")); + return (x); +} + +/** +* set a time sequence and free the old array +*/ + +static void metroplus_time_seq( t_metroplus *x1, t_symbol *s, int ac, t_atom *av ) +{ + int i; + t_metroplus *x = x1->x_shadow; + if ( x->x_times != NULL ) + { + free( x->x_times ); + } + if ( ac > 0 ) + { + x->x_times = (float *) malloc( ac * sizeof( float )); + for( i = 0 ; i < ac ; i++ ) + { + float t = atom_getfloat( &av[i] ); + x->x_times[i] = t > 0 ? t : 10; + } + x->x_size=ac; + } + else + { + x->x_times = (float *) malloc( sizeof( float )); + x->x_times[0] = 10; + x->x_size=1; + } + x->x_idx = 0; + x->x_hit = 0; +} + +static void metroplus_time_float( t_metroplus *x1, t_float f ) +{ + int i; + t_metroplus *x = x1->x_shadow; + post("here with %f" , f ); + if ( x->x_times != NULL ) + { + free( x->x_times ); + } + x->x_times = (float *) malloc( sizeof( float )); + x->x_times[0] = f > 0 ? f : 10; + x->x_size=1; + x->x_idx = 0; + x->x_hit = 0; +} + +/** +* make a new one and setup all of our messages +*/ + + void metroplus_setup(void) +{ + metroplus_class = class_new(gensym("metroplus"), (t_newmethod)metroplus_new, + (t_method)metroplus_free, sizeof(t_metroplus), 0, A_GIMME, 0); + metroplus_2_class = class_new(gensym("metroplus (second inlet)"), 0, + 0, sizeof(t_metroplus), CLASS_PD | CLASS_NOINLET, 0); + class_addbang(metroplus_class, metroplus_bang); + class_addmethod(metroplus_class, (t_method)metroplus_stop, gensym("stop"), 0); + class_addmethod(metroplus_class, (t_method)metroplus_bang, gensym("start"), 0); + class_addmethod(metroplus_2_class, (t_method)metroplus_time_seq, gensym("list"),A_GIMME,0); + class_addmethod(metroplus_2_class, (t_method)metroplus_time_float ,gensym("float"),A_FLOAT,0); + class_sethelpsymbol(metroplus_class, gensym("mjLib/metroplus")); +} + -- cgit v1.2.1