aboutsummaryrefslogtreecommitdiff
path: root/metroplus.c
diff options
context:
space:
mode:
Diffstat (limited to 'metroplus.c')
-rw-r--r--metroplus.c177
1 files changed, 177 insertions, 0 deletions
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 <io.h>
+#endif
+#include "m_pd.h"
+
+#include <stdlib.h>
+#include<time.h>
+#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"));
+}
+