aboutsummaryrefslogtreecommitdiff
path: root/src/onlyone.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/onlyone.c')
-rw-r--r--src/onlyone.c188
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);
+
+}