/*
* pack: a type-agnostic version of [pack]
*
* (c) 2007-2011 forum::für::umläute
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see .
*/
/*
* this version of [pack] does not care about types, so you can send a symbol to a float inlet and vice versa
* you can also initialize it with symbols, e.g. [pack foo bar] will output [list foo bar( when banged
*
* for know this object is named [zexy/pack], as there might be some issues with compatibility with the original [pack]
*/
#include "zexy.h"
#include
/* ------------------------- zexy/pack ------------------------------- */
static t_class *zpack_class;
static t_class *zpackproxy_class;
typedef struct _zpack
{
t_object x_obj;
struct _zpackproxy **x_proxy;
t_inlet **in;
t_atom*x_argv;
int x_argc;
} t_zpack;
typedef struct _zpackproxy
{
t_pd p_pd;
t_zpack *p_master;
int id;
} t_zpackproxy;
static void setatom(t_zpack *x, t_atom*from, int to) {
x->x_argv[to].a_type=from->a_type;
x->x_argv[to].a_w =from->a_w;
}
static void zpack_bang(t_zpack*x) {
outlet_list(x->x_obj.ob_outlet, gensym("list"), x->x_argc, x->x_argv);
}
static void zpack_any(t_zpack*x, t_symbol *s, int argc, t_atom *argv) {
int i=0;
int count=x->x_argc;
if(NULL!=s && x->x_argc>0) {
t_atom a;
SETSYMBOL(&a, s);
setatom(x, &a, i++);
count--;
}
if(count>argc)
count=argc;
while(count-->0) {
setatom(x, argv++, i++);
}
zpack_bang(x);
}
static void zpack_list(t_zpack*x, t_symbol *s, int argc, t_atom *argv) {
zpack_any(x, 0, argc, argv);
}
static void zpack_proxy_list(t_zpackproxy *y, t_symbol *s, int argc, t_atom *argv)
{
/* until we have lists of lists, this only uses the 1st element */
if(argc>0) /* this filters out 'bang', and allows 'list', 'float' and 'symbol' */
setatom(y->p_master, argv, y->id);
}
static void zpack_proxy_any(t_zpackproxy *y, t_symbol *s, int argc, t_atom *argv)
{
/* until we have lists of lists, this only uses the selector */
t_atom a;
SETSYMBOL(&a, s);
setatom(y->p_master, &a, y->id);
}
static void *zpack_new(t_symbol *s, int argc, t_atom *argv)
{
t_zpack *x = (t_zpack *)pd_new(zpack_class);
int n =0;
x->x_argc = (argc < 1)?2:argc;
if(argc<1) {
x->x_argv=(t_atom*)getbytes(2*sizeof(t_atom));
SETFLOAT(x->x_argv+0, 0.f);
SETFLOAT(x->x_argv+1, 0.f);
} else {
int i=0;
x->x_argv=(t_atom*)getbytes(x->x_argc*sizeof(t_atom));
for(i=0; ix_argc; i++)
setatom(x, argv+i, i);
}
x->in = (t_inlet **)getbytes(x->x_argc * sizeof(t_inlet *));
x->x_proxy = (t_zpackproxy**)getbytes(x->x_argc * sizeof(t_zpackproxy*));
x->in[0] =0;
x->x_proxy[0]=0;
for (n = 1; nx_argc; n++) {
x->x_proxy[n]=(t_zpackproxy*)pd_new(zpackproxy_class);
x->x_proxy[n]->p_master = x;
x->x_proxy[n]->id=n;
x->in[n] = inlet_new ((t_object*)x, (t_pd*)x->x_proxy[n], 0,0);
}
outlet_new(&x->x_obj, 0);
return (x);
}
static void zpack_free(t_zpack*x){
const int count = x->x_argc;
if(x->in && x->x_proxy){
int n=0;
for(n=0; nin[n]){
inlet_free(x->in[n]);
}
x->in[n]=0;
if(x->x_proxy[n]){
t_zpackproxy *y=x->x_proxy[n];
y->p_master=0;
y->id=0;
pd_free(&y->p_pd);
}
x->x_proxy[n]=0;
}
freebytes(x->in, x->x_argc * sizeof(t_inlet *));
freebytes(x->x_proxy, x->x_argc * sizeof(t_zpackproxy*));
}
}
void zpack_setup(void)
{
zpack_class = class_new(gensym("zexy/pack"), (t_newmethod)zpack_new,
(t_method)zpack_free, sizeof(t_zpack), 0, A_GIMME, 0);
#if 0
/* oops Pd>=0.42 allows us to override built-ins
* this is bad as long as the 2 objects are not compatible */
class_addcreator((t_newmethod)zpack_new, gensym("pack"), A_GIMME, 0);
#endif
class_addbang(zpack_class, zpack_bang);
class_addlist(zpack_class, zpack_list);
class_addanything(zpack_class, zpack_any);
zpackproxy_class = class_new(gensym("zpack proxy"), 0, 0,
sizeof(t_zpackproxy),
CLASS_PD | CLASS_NOINLET, 0);
class_addlist(zpackproxy_class, zpack_proxy_list);
class_addanything(zpackproxy_class, zpack_proxy_any);
zexy_register("pack");
}
void pack_setup(void)
{
zpack_setup();
}