aboutsummaryrefslogtreecommitdiff
path: root/src/common~.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/common~.c')
-rw-r--r--src/common~.c247
1 files changed, 247 insertions, 0 deletions
diff --git a/src/common~.c b/src/common~.c
new file mode 100644
index 0000000..573eaf1
--- /dev/null
+++ b/src/common~.c
@@ -0,0 +1,247 @@
+//#include "commonget~.h"
+#include "m_pd.h"
+
+
+typedef struct _common {
+ t_symbol* name;
+ t_sample a[64];
+ t_sample b[64];
+ t_sample* w;
+ t_sample* r;
+ //int writers;
+ //int written;
+ int users;
+ struct _common* next;
+ struct _common* previous;
+ t_clock* clock;
+ int armed;
+
+} t_common;
+
+
+static t_common* common;
+
+
+// This should be triggered by the clock
+static void common_swap(t_common* pg) {
+ //post("clock");
+
+ t_sample* temp = pg->r;
+ pg->r = pg->w;
+ pg->w = temp;
+
+ int i;
+ t_sample* samples = pg->w;
+ for (i=0;i<64;i++) {
+ *samples++ = 0;
+
+ }
+
+ pg->armed = 0;
+
+ //if (pg == NULL) post("ouc");
+ //pg->written = 0;
+
+}
+
+static t_common* common_register(t_symbol* name) {
+
+ t_common* new_common;
+
+ //is_writer = is_writer ? 1 : 0;
+
+ t_common* pg = common;
+
+ if ( pg != NULL) {
+
+ // Search for previous common
+ while( pg ) {
+ if ( pg->name == name) {
+ //#ifdef PARAMDEBUG
+ // post("Found put/get with same name");
+ //#endif
+ //pg->writers = pg->writers + is_writer;
+ pg->users = pg->users + 1;
+ return pg;
+ }
+ if ( pg->next == NULL ) break;
+ pg = pg->next;
+ }
+ }
+
+
+ //post("Appending new put/get");
+ // Append new common
+ new_common = getbytes(sizeof(*new_common));
+ new_common->name = name;
+ //new_common->writers = is_writer;
+ new_common->users = 1;
+ new_common->armed = 0;
+
+ new_common->clock = clock_new(new_common, (t_method)common_swap);
+
+ new_common->r = new_common->a;
+ new_common->w = new_common->b;
+
+ new_common->previous = pg;
+ if ( pg) {
+ pg->next = new_common;
+ } else {
+ common = new_common;
+ }
+
+ return new_common;
+
+}
+
+
+static void common_unregister(t_common* pg) {
+
+ //post("Trying to remove %s",pg->name->s_name);
+
+ //if ( is_writer) pg->writers = pg->writers - 1;
+ pg->users = pg->users - 1;
+ if ( pg->users <= 0) {
+ //post("Removing last put/get of this name");
+ if (pg->previous) {
+ pg->previous->next = pg->next;
+ if (pg->next) pg->next->previous = pg->previous;
+ } else {
+ common = pg->next;
+ if ( pg->next != NULL) pg->next->previous = NULL;
+ }
+ clock_free(pg->clock);
+ freebytes(pg, sizeof *(pg) );
+ }
+}
+
+
+static void common_arm(t_common* pg) {
+
+ if (!pg->armed) {
+ pg->armed = 1;
+ clock_delay(pg->clock, 0);
+ }
+
+}
+
+///////////////
+// The class //
+///////////////
+
+static t_class *common_tilde_class;
+
+typedef struct _common_tilde {
+ t_object x_obj;
+ //t_sample f_common;
+ t_common* pg;
+ t_sample f;
+} t_common_tilde;
+
+static t_int* common_tilde_perform(t_int *w)
+{
+
+ t_common_tilde *x = (t_common_tilde *)(w[1]);
+
+ t_sample *in = (t_sample *)(w[2]);
+ t_sample *out= (t_sample *)(w[3]);
+ int n = (int)(w[4]);
+ int m;
+ t_sample *samples;
+
+
+ if ( x->pg) {
+
+ // Do adding
+ //if (x->pg->users > x->pg->writers) {
+ samples = x->pg->w;
+ m = n;
+ while (m--) {
+ *samples = *samples + *in;
+ samples++; in++;
+ }
+
+ //}
+
+
+ // Do reading
+ samples = x->pg->r;
+ m = n;
+ while (m--) {
+ *out++ = *samples++;
+ }
+
+ // Arm for swaping
+ common_arm( x->pg);
+
+ } else {
+
+ while (n--) {
+ *out++ = 0;
+ }
+
+ }
+
+ return (w+5);
+}
+
+
+static void common_tilde_set(t_common_tilde *x, t_symbol* s) {
+
+ if (gensym("") != s ) {
+ if ( x->pg ) {
+ if ( x->pg->name != s) {
+ common_unregister(x->pg);
+ x->pg = common_register(s);
+ }
+ } else {
+ x->pg = common_register(s);
+ }
+ }
+
+}
+
+
+static void common_tilde_dsp(t_common_tilde *x, t_signal **sp)
+{
+
+ if ( (int) sp[0]->s_n == 64 ) {
+ dsp_add(common_tilde_perform, 4, x,sp[0]->s_vec,sp[1]->s_vec, sp[0]->s_n);
+
+ } else {
+ error("common~ only works with a block size of 64");
+ }
+
+}
+
+static void common_tilde_free( t_common_tilde *x) {
+
+ if (x->pg) common_unregister(x->pg);
+}
+
+
+static void *common_tilde_new(t_symbol* s)
+{
+ t_common_tilde *x = (t_common_tilde *)pd_new(common_tilde_class);
+
+ if (gensym("") != s ) x->pg = common_register(s);
+
+ outlet_new(&x->x_obj, &s_signal);
+
+ return (void *)x;
+}
+
+void common_tilde_setup(void) {
+ common_tilde_class = class_new(gensym("common~"),
+ (t_newmethod)common_tilde_new,
+ (t_method)common_tilde_free, sizeof(t_common_tilde),
+ 0, A_DEFSYM, 0);
+
+ class_addmethod(common_tilde_class,
+ (t_method)common_tilde_dsp, gensym("dsp"), 0);
+
+ class_addmethod(common_tilde_class,
+ (t_method)common_tilde_set, gensym("set"), A_SYMBOL, 0);
+
+ CLASS_MAINSIGNALIN(common_tilde_class, t_common_tilde, f);
+}