diff options
Diffstat (limited to 'src/onlyone.c')
-rw-r--r-- | src/onlyone.c | 188 |
1 files changed, 188 insertions, 0 deletions
diff --git a/src/onlyone.c b/src/onlyone.c new file mode 100644 index 0000000..60287b0 --- /dev/null +++ b/src/onlyone.c @@ -0,0 +1,188 @@ + +#include "m_pd.h" + +struct _onlyone; + +typedef struct _oo { + struct _onlyone* x; + //t_symbol* name; + struct _oo* next; + struct _oo* previous; +} t_oo; + +static t_oo* oos = NULL; + +static t_class *onlyone_class; + +typedef struct _onlyone { + t_object x_obj; + t_outlet* outlet; + t_outlet* outlet2; + t_symbol* name; + int iamtheone; + t_symbol* s_empty; + //t_sample f_common; + //t_common* pg; + //t_sample f; +} t_onlyone; + + +static void onlyone_bang( t_onlyone *x) { + if (x->iamtheone) { + outlet_bang(x->outlet); + } else { + outlet_bang(x->outlet2); + } +} + + +static void onlyone_register(t_onlyone* x) { + + + t_oo* oo = oos; + + int outputme = 1; + + + t_oo* new_oo = getbytes(sizeof(*new_oo)); + new_oo->x = x; + + if ( oo != NULL) { + //post("oo is not null"); + if (outputme && (oo->x->name == x->name)) outputme = 0; + // Get the last oo + while (oo->next) { + oo = oo->next; + } + } + + // Append + + new_oo->previous = oo; + new_oo->next = NULL; + if (oo != NULL) { + oo->next = new_oo; + } else { + //post("Adding the first"); + oos = new_oo; + } + + x->iamtheone = outputme; + +} + + +static void onlyone_unregister(t_onlyone* x) { + + t_oo* oo = oos; + + t_onlyone* theotherone = NULL; + t_oo* deleteone = NULL; + + if ( oo != NULL) { + // Get the mathching oo and the x to output to + while ( oo ) { + if ( oo->x == x ) { + //post("Found oo to delete"); + deleteone = oo; + } else if (x->iamtheone && theotherone==NULL && (oo->x->name == x->name) ) { + theotherone = oo->x; + } + if ( deleteone && theotherone) break; + oo = oo->next; + } + + + + // Delete the oo matching the x that called this function + if (deleteone) { + + if (deleteone->previous) { + deleteone->previous->next = deleteone->next; + if (deleteone->next) deleteone->next->previous = deleteone->previous; + + } else { + oos = deleteone->next; + if ( deleteone->next != NULL) deleteone->next->previous = NULL; + } + + freebytes(deleteone,sizeof(*deleteone)); + x->iamtheone = 0; + x->name = NULL; + } else { + post("Hum, did not find oo to delete!"); + } + + // Output the bang to the other one + if (theotherone) { + theotherone->iamtheone = 1; + onlyone_bang(theotherone); + } + + } else { + post("Weird, the list is empty..."); + } + + // if (oos==NULL) post("this is the end"); + +} + + +static void onlyone_free( t_onlyone *x) { + + if ( x->name) onlyone_unregister(x); +} + +static void onlyone_set( t_onlyone *x, t_symbol *s) { + if ( s == x->s_empty) { + if ( x->name) { + onlyone_unregister(x); + //onlyone_bang(x); + } + } else if ( x->name && s != x->name) { + onlyone_unregister(x); + x->name = s; + onlyone_register(x); + //onlyone_bang(x); + } else if ( x->name == NULL) { + x->name = s; + onlyone_register(x); + //onlyone_bang(x); + } + onlyone_bang(x); +} + + + + +static void *onlyone_new(t_symbol* s) +{ + t_onlyone *x = (t_onlyone *)pd_new(onlyone_class); + + x->s_empty = gensym(""); + x->iamtheone = 0; + x->name = NULL; + + if ( s != x->s_empty) x->name = s; + + x->outlet = outlet_new(&x->x_obj, &s_bang); + + if ( x->name) onlyone_register(x); + + + x->outlet2 = outlet_new(&x->x_obj, &s_bang); + + return (void *)x; +} + +void onlyone_setup(void) { + onlyone_class = class_new(gensym("onlyone"), + (t_newmethod)onlyone_new, + (t_method)onlyone_free, sizeof(t_onlyone), + 0, A_DEFSYMBOL, 0); + + class_addbang(onlyone_class, onlyone_bang); + + class_addmethod(onlyone_class, (t_method)onlyone_set, gensym("set"),A_DEFSYMBOL,0); + +} |