aboutsummaryrefslogtreecommitdiff
path: root/cyclone/hammer/Bucket.c
blob: 76a8f1090880eabe4eb9acdc37e7ce831ff9b08d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
/* Copyright (c) 2002-2003 krzYszcz and others.
 * For information on usage and redistribution, and for a DISCLAIMER OF ALL
 * WARRANTIES, see the file, "LICENSE.txt," in this distribution.  */

/* This is a modified version of Joseph A. Sarlo's code.
   The most important changes are listed in "pd-lib-notes.txt" file.  */

#include "m_pd.h"
#include "shared.h"

typedef struct _Bucket
{
    t_object    x_ob;
    int         x_numbucks;
    t_float    *x_bucks;   /* CHECKED: no limit */
    t_outlet  **x_outs;
    short int   x_frozen;  /* 0 for thawed, 1 for frozen */
    short int   x_dir;     /* 0 for L2R, 1 for R2L */
    short int   x_max5mode;  /* 0 for classic Max 4.6 mode, 
                              1 for Max 5 mode (with 2nd !0 argument) */
} t_Bucket;

static t_class *Bucket_class;

static void Bucket_bang(t_Bucket *x)
{
    int i = x->x_numbucks;
    /* CHECKED: outlets output in right-to-left order */
    while (i--) outlet_float(x->x_outs[i], x->x_bucks[i]);
}

static void Bucket_float(t_Bucket *x, t_float val)
{
    int i;

    if (!x->x_frozen)
	Bucket_bang(x);
    if (!x->x_dir)
    {
	for (i = x->x_numbucks - 1; i > 0; i--)
	    x->x_bucks[i] = x->x_bucks[i - 1];
	x->x_bucks[0] = val;
    }
    else
    {
	for (i = 0; i < x->x_numbucks - 1; i++)
	    x->x_bucks[i] = x->x_bucks[i + 1];
	x->x_bucks[x->x_numbucks - 1] = val;
    }
    if (x->x_max5mode && !x->x_frozen)
	Bucket_bang(x);
}

static void Bucket_freeze(t_Bucket *x)
{
    x->x_frozen = 1;
}

static void Bucket_thaw(t_Bucket *x)
{
    x->x_frozen = 0;
}

static void Bucket_roll(t_Bucket *x)
{
    if (x->x_dir)
	Bucket_float(x, x->x_bucks[0]);
    else
	Bucket_float(x, x->x_bucks[x->x_numbucks - 1]);
}

static void Bucket_rtol(t_Bucket *x)
{
    x->x_dir = 1;
}

static void Bucket_ltor(t_Bucket *x)
{
    x->x_dir = 0;
}

static void Bucket_set(t_Bucket *x, t_floatarg f)
{
    int i = x->x_numbucks;
    while (i--) x->x_bucks[i] = f;
    if (!x->x_frozen)  /* CHECKED */
	Bucket_bang(x);
}

static void Bucket_free(t_Bucket *x)
{
    if (x->x_bucks)
	freebytes(x->x_bucks, x->x_numbucks * sizeof(*x->x_bucks));
    if (x->x_outs)
	freebytes(x->x_outs, x->x_numbucks * sizeof(*x->x_outs));
}

static void *Bucket_new(t_floatarg val, t_floatarg max5mode)
{
    t_Bucket *x;
    int nbucks = (int)val;
    t_float *bucks;
    t_outlet **outs;
    if (nbucks < 1)
	nbucks = 1;
    if (!(bucks = (t_float *)getbytes(nbucks * sizeof(*bucks))))
	return (0);
    if (!(outs = (t_outlet **)getbytes(nbucks * sizeof(*outs))))
    {
	freebytes(bucks, nbucks * sizeof(*bucks));
	return (0);
    }
    x = (t_Bucket *)pd_new(Bucket_class);
    x->x_numbucks = nbucks;
    x->x_bucks = bucks;
    x->x_outs = outs;
    x->x_frozen = 0;
    x->x_dir = 0;
    x->x_max5mode = ((int)max5mode != 0);
    while (nbucks--) *outs++ = outlet_new((t_object *)x, &s_float);
    return (x);
}

void Bucket_setup(void)
{
    Bucket_class = class_new(gensym("Bucket"),
			     (t_newmethod)Bucket_new,
			     (t_method)Bucket_free,
			     sizeof(t_Bucket), 0, A_DEFFLOAT, A_DEFFLOAT, 0);
    class_addcreator((t_newmethod)Bucket_new, gensym("bucket"), A_DEFFLOAT, 0);
    class_addcreator((t_newmethod)Bucket_new, gensym("cyclone/bucket"), A_DEFFLOAT, 0);
    class_addbang(Bucket_class, Bucket_bang);
    class_addfloat(Bucket_class, Bucket_float);
    class_addmethod(Bucket_class, (t_method)Bucket_freeze, gensym("freeze"), 0);
    class_addmethod(Bucket_class, (t_method)Bucket_thaw, gensym("thaw"), 0);
    class_addmethod(Bucket_class, (t_method)Bucket_ltor, gensym("L2R"), 0);
    class_addmethod(Bucket_class, (t_method)Bucket_rtol, gensym("R2L"), 0);
    /* CHECKED (refman error) roll has no argument */
    class_addmethod(Bucket_class, (t_method)Bucket_roll, gensym("roll"), 0);
    /* 3.5 additions */
    class_addmethod(Bucket_class, (t_method)Bucket_set,
		    gensym("set"), A_FLOAT, 0);
    class_addmethod(Bucket_class, (t_method)Bucket_ltor, gensym("l2r"), 0);
    class_addmethod(Bucket_class, (t_method)Bucket_rtol, gensym("r2l"), 0);
    logpost(NULL, 4, "this is cyclone/Bucket %s, %dth %s build",
	 CYCLONE_VERSION, CYCLONE_BUILD, CYCLONE_RELEASE);    
}

void bucket_setup(void)
{
    Bucket_setup();
}