/*
* packel: get the nth element of a package
*
* (c) 1999-2011 IOhannes m zmölnig, forum::für::umläute, institute of electronic music and acoustics (iem)
*
* 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 .
*/
#include "zexy.h"
static t_class *packel_class;
typedef struct _packel
{
t_object x_obj;
t_float *position;
int count;
t_inlet**x_inlet;
t_outlet**x_outlet;
int x_warningflag;
} t_packel;
static void packel_outelement(t_packel*x, int id, t_symbol*s,int argc, t_atom*argv)
{
t_outlet*out=x->x_outlet[id];
int index= x->position[id];
if (index) {
t_atom *current;
int pos = (index < 0)?(argc+index):(index-1);
if(argc==0){
if (pos==0||pos==-1)outlet_bang(out);
return;
}
if (pos < 0 || pos >= argc)return;
current = &(argv[pos]);
switch (current->a_type) {
case A_NULL:
outlet_bang(out);
default:
outlet_list(out, gensym("list"), 1, current);
}
} else outlet_list(out, s, argc, argv);
}
static void packel_list(t_packel *x, t_symbol *s, int argc, t_atom *argv)
{
int c=x->count;
while(--c>=0) {
packel_outelement(x, c, s, argc, argv);
}
}
static void packel_anything(t_packel *x, t_symbol *s, int argc, t_atom *argv)
{
t_atom *av2 = (t_atom *)getbytes((argc + 1) * sizeof(t_atom));
int i;
if(x->x_warningflag){
pd_error(x, "deprecation warning: you should only use lists for list data");
x->x_warningflag=0;
}
for (i = 0; i < argc; i++)
av2[i + 1] = argv[i];
SETSYMBOL(av2, s);
packel_list(x, gensym("list"), argc+1, av2);
freebytes(av2, (argc + 1) * sizeof(t_atom));
}
static void packel_free(t_packel *x)
{
int i=0;
for(i=0; icount; i++) {
if(x->x_inlet &&x->x_inlet [i])inlet_free (x->x_inlet [i]);
if(x->x_outlet&&x->x_outlet[i])outlet_free(x->x_outlet[i]);
}
if(x->position)freebytes(x->position, x->count*sizeof(t_float));
if(x->x_inlet) freebytes(x->x_inlet, x->count*sizeof(t_inlet*));
if(x->x_outlet)freebytes(x->x_outlet, x->count*sizeof(t_outlet*));
}
static void *packel_new(t_symbol*s, int argc, t_atom*argv)
{
t_packel *x = (t_packel *)pd_new(packel_class);
x->count=(argc>0)?argc:1;
x->position=(t_float*)getbytes(x->count*sizeof(t_float));
x->x_inlet=(t_inlet**)getbytes(x->count*sizeof(t_inlet*));
x->x_outlet=(t_outlet**)getbytes(x->count*sizeof(t_outlet*));
if(argc<1) {
x->position[0]=0.f;
x->x_inlet[0]=floatinlet_new(&x->x_obj, x->position);
x->x_outlet[0]=outlet_new(&x->x_obj, 0);
} else {
int i=0;
for(i=0; icount; i++) {
x->position[i]=atom_getfloat(argv+i);
x->x_inlet [i]=floatinlet_new(&x->x_obj, x->position+i);
x->x_outlet [i]=outlet_new(&x->x_obj, 0);
}
}
x->x_warningflag=1;
return (x);
}
void packel_setup(void)
{
packel_class = class_new(gensym("packel"),
(t_newmethod)packel_new, (t_method)packel_free,
sizeof(t_packel), 0,
A_GIMME, 0);
class_addlist (packel_class, packel_list);
class_addanything(packel_class, packel_anything);
zexy_register("packel");
}