#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); }