Update of /cvsroot/pure-data/externals/pdp/modules/image_basic
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv6756/modules/image_basic
Added Files:
Makefile README pdp_add.c pdp_bq.c pdp_cheby.c pdp_constant.c
pdp_conv.c pdp_gain.c pdp_logic.c pdp_mix.c pdp_mul.c
pdp_noise.c pdp_plasma.c pdp_randmix.c pdp_stateless.c
pdp_zoom.c
Log Message:
checking in pdp 0.12.4 from http://zwizwa.fartit.com/pd/pdp/pdp-0.12.4.tar.gz
--- NEW FILE: pdp_plasma.c ---
/*
* Pure Data Packet module.
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include "pdp.h"
#include "pdp_imagebase.h"
typedef struct pdp_plasma_struct
{
t_pdp_imagebase x_base;
int x_packet0;
t_outlet *x_outlet0;
void *x_plasmagen;
t_symbol *x_type;
unsigned int x_width;
unsigned int x_height;
} t_pdp_plasma;
void pdp_plasma_type(t_pdp_plasma *x, t_symbol *s)
{
x->x_type = s;
}
void pdp_plasma_random(t_pdp_plasma *x, t_floatarg seed)
{
if (seed == 0.0f) seed = (float)random();
pdp_imageproc_plasma_setseed(x->x_plasmagen, seed);
}
void pdp_plasma_turbulence(t_pdp_plasma *x, t_floatarg f)
{
pdp_imageproc_plasma_setturbulence(x->x_plasmagen, f);
}
/* called inside pdp thread */
static void pdp_plasma_process(t_pdp_plasma *x)
{
/* seed the 16 bit rng with a new random number from the clib */
pdp_plasma_random(x, 0.0f);
/* create new packet */
if (x->x_type == gensym("grey")) {x->x_packet0 = pdp_packet_new_image_grey(x->x_width, x->x_height);}
else if (x->x_type == gensym("yv12")) {x->x_packet0 = pdp_packet_new_image_YCrCb(x->x_width, x->x_height);}
else return;
/* call the image processor */
pdp_imageproc_dispatch_1buf(&pdp_imageproc_plasma_process, x->x_plasmagen,
-1, x->x_packet0);
}
/* called inside pd thread: involves an outlet */
static void pdp_plasma_postproc(t_pdp_plasma *x)
{
pdp_packet_pass_if_valid(x->x_outlet0, &x->x_packet0);
}
static void pdp_plasma_bang(t_pdp_plasma *x)
{
pdp_base_bang(x);
}
static void pdp_plasma_dim(t_pdp_plasma *x, t_floatarg w, t_floatarg h)
{
x->x_width = pdp_imageproc_legalwidth((int)w);
x->x_height = pdp_imageproc_legalheight((int)h);
//post("dims %d %d", x->x_width, x->x_height);
}
static void pdp_plasma_free(t_pdp_plasma *x)
{
pdp_imagebase_free(x);
/* tidy up */
pdp_packet_mark_unused(x->x_packet0);
pdp_imageproc_plasma_delete(x->x_plasmagen);
}
t_class *pdp_plasma_class;
void *pdp_plasma_new(void)
{
int i;
t_pdp_plasma *x = (t_pdp_plasma *)pd_new(pdp_plasma_class);
pdp_imagebase_init(x);
pdp_base_disable_active_inlet(x);
pdp_base_set_process_method(x, (t_pdp_method)pdp_plasma_process);
pdp_base_set_postproc_method(x, (t_pdp_method)pdp_plasma_postproc);
pdp_base_add_gen_inlet(x, gensym("float"), gensym("turbulence"));
x->x_outlet0 = pdp_base_add_pdp_outlet(x);
x->x_packet0 = -1;
x->x_width = 320;
x->x_height = 240;
x->x_plasmagen = pdp_imageproc_plasma_new();
pdp_plasma_random(x, 0.0f);
pdp_plasma_type(x, gensym("yv12"));
pdp_plasma_turbulence(x, 0.1);
return (void *)x;
}
#ifdef __cplusplus
extern "C"
{
#endif
void pdp_plasma_setup(void)
{
pdp_plasma_class = class_new(gensym("pdp_plasma"), (t_newmethod)pdp_plasma_new,
(t_method)pdp_plasma_free, sizeof(t_pdp_plasma), 0, A_NULL);
pdp_imagebase_setup(pdp_plasma_class);
class_addmethod(pdp_plasma_class, (t_method)pdp_plasma_random, gensym("seed"), A_DEFFLOAT, A_NULL);
class_addmethod(pdp_plasma_class, (t_method)pdp_plasma_turbulence, gensym("turbulence"), A_DEFFLOAT, A_NULL);
class_addmethod(pdp_plasma_class, (t_method)pdp_plasma_type, gensym("type"), A_SYMBOL, A_NULL);
class_addmethod(pdp_plasma_class, (t_method)pdp_plasma_dim, gensym("dim"), A_FLOAT, A_FLOAT, A_NULL);
class_addmethod(pdp_plasma_class, (t_method)pdp_plasma_bang, gensym("bang"), A_NULL);
}
#ifdef __cplusplus
}
#endif
--- NEW FILE: pdp_noise.c ---
/*
* Pure Data Packet module.
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include "pdp.h"
#include "pdp_imagebase.h"
typedef struct pdp_noise_struct
{
t_pdp_imagebase x_base;
int x_packet0;
t_outlet *x_outlet0;
void *x_noisegen;
t_symbol *x_type;
unsigned int x_width;
unsigned int x_height;
} t_pdp_noise;
void pdp_noise_type(t_pdp_noise *x, t_symbol *s)
{
x->x_type = s;
}
void pdp_noise_random(t_pdp_noise *x, t_floatarg seed)
{
if (seed == 0.0f) seed = (float)random();
pdp_imageproc_random_setseed(x->x_noisegen, seed);
}
/* called inside pdp thread */
static void pdp_noise_process(t_pdp_noise *x)
{
/* seed the 16 bit rng with a new random number from the clib */
pdp_noise_random(x, 0.0f);
/* create new packet */
if (x->x_type == gensym("grey")) {
x->x_packet0 = pdp_packet_new_image_grey(x->x_width, x->x_height);
}
else if (x->x_type == gensym("yv12")) {
x->x_packet0 = pdp_packet_new_image_YCrCb(x->x_width, x->x_height);
}
else return;
/* call the image processor */
pdp_imageproc_dispatch_1buf(&pdp_imageproc_random_process, x->x_noisegen,
-1, x->x_packet0);
}
/* called inside pd thread: involves an outlet */
static void pdp_noise_postproc(t_pdp_noise *x)
{
pdp_packet_pass_if_valid(x->x_outlet0, &x->x_packet0);
}
static void pdp_noise_bang(t_pdp_noise *x)
{
pdp_base_bang(x);
}
static void pdp_noise_dim(t_pdp_noise *x, t_floatarg w, t_floatarg h)
{
x->x_width = pdp_imageproc_legalwidth((int)w);
x->x_height = pdp_imageproc_legalheight((int)h);
//post("dims %d %d", x->x_width, x->x_height);
}
static void pdp_noise_free(t_pdp_noise *x)
{
pdp_imagebase_free(x);
/* tidy up */
pdp_packet_mark_unused(x->x_packet0);
pdp_imageproc_random_delete(x->x_noisegen);
}
t_class *pdp_noise_class;
void *pdp_noise_new(void)
{
int i;
t_pdp_noise *x = (t_pdp_noise *)pd_new(pdp_noise_class);
pdp_imagebase_init(x);
pdp_base_disable_active_inlet(x);
pdp_base_set_process_method(x, (t_pdp_method)pdp_noise_process);
pdp_base_set_postproc_method(x, (t_pdp_method)pdp_noise_postproc);
x->x_outlet0 = pdp_base_add_pdp_outlet(x);
x->x_packet0 = -1;
x->x_width = 320;
x->x_height = 240;
x->x_noisegen = pdp_imageproc_random_new();
pdp_noise_random(x, 0.0f);
pdp_noise_type(x, gensym("yv12"));
return (void *)x;
}
#ifdef __cplusplus
extern "C"
{
#endif
void pdp_noise_setup(void)
{
pdp_noise_class = class_new(gensym("pdp_noise"), (t_newmethod)pdp_noise_new,
(t_method)pdp_noise_free, sizeof(t_pdp_noise), 0, A_NULL);
pdp_imagebase_setup(pdp_noise_class);
class_addmethod(pdp_noise_class, (t_method)pdp_noise_random, gensym("seed"), A_DEFFLOAT, A_NULL);
class_addmethod(pdp_noise_class, (t_method)pdp_noise_type, gensym("type"), A_SYMBOL, A_NULL);
class_addmethod(pdp_noise_class, (t_method)pdp_noise_dim, gensym("dim"), A_FLOAT, A_FLOAT, A_NULL);
class_addmethod(pdp_noise_class, (t_method)pdp_noise_bang, gensym("bang"), A_NULL);
}
#ifdef __cplusplus
}
#endif
--- NEW FILE: pdp_mul.c ---
/*
* Pure Data Packet module.
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include "pdp.h"
#include "pdp_imagebase.h"
typedef struct pdp_mul_struct
{
t_pdp_imagebase x_base;
} t_pdp_mul;
static void pdp_mul_process(t_pdp_mul *x)
{
int p0 = pdp_base_get_packet(x, 0);
int p1 = pdp_base_get_packet(x, 1);
u32 mask = pdp_imagebase_get_chanmask(x);
pdp_imageproc_dispatch_2buf(&pdp_imageproc_mul_process, 0, mask, p0, p1);
}
static void pdp_mul_free(t_pdp_mul *x)
{
pdp_imagebase_free(x);
}
t_class *pdp_mul_class;
void *pdp_mul_new(void)
{
t_pdp_mul *x = (t_pdp_mul *)pd_new(pdp_mul_class);
/* super init */
pdp_imagebase_init(x);
pdp_base_add_pdp_inlet(x);
pdp_base_add_pdp_outlet(x);
pdp_base_set_process_method(x, (t_pdp_method)pdp_mul_process);
return (void *)x;
}
#ifdef __cplusplus
extern "C"
{
#endif
void pdp_mul_setup(void)
{
pdp_mul_class = class_new(gensym("pdp_mul"), (t_newmethod)pdp_mul_new,
(t_method)pdp_mul_free, sizeof(t_pdp_mul), 0, A_NULL);
pdp_imagebase_setup(pdp_mul_class);
}
#ifdef __cplusplus
}
#endif
--- NEW FILE: pdp_gain.c ---
/*
* Pure Data Packet module.
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include "pdp.h"
#include "pdp_imagebase.h"
typedef struct pdp_gain_struct
{
t_pdp_imagebase x_base;
void *x_gain;
} t_pdp_gain;
static void pdp_gain_process(t_pdp_gain *x)
{
int p = pdp_base_get_packet(x, 0);
u32 mask = pdp_imagebase_get_chanmask(x);
pdp_packet_image_set_chanmask(p, mask);
pdp_imageproc_dispatch_1buf(&pdp_imageproc_gain_process, x->x_gain, 0, p);
}
static void pdp_gain_gain(t_pdp_gain *x, t_floatarg f)
{
pdp_imageproc_gain_setgain(x->x_gain, f);
}
t_class *pdp_gain_class;
void pdp_gain_free(t_pdp_gain *x)
{
pdp_imagebase_free(x);
pdp_imageproc_gain_delete(x->x_gain);
}
void *pdp_gain_new(t_floatarg f)
{
t_pdp_gain *x = (t_pdp_gain *)pd_new(pdp_gain_class);
/* super init */
pdp_imagebase_init(x);
/* no arg, or zero -> gain = 1 */
if (f==0.0f) f = 1.0f;
/* io */
pdp_base_add_gen_inlet(x, gensym("float"), gensym("gain"));
pdp_base_add_pdp_outlet(x);
/* callbacks */
pdp_base_set_process_method(x, (t_pdp_method)pdp_gain_process);
x->x_gain = pdp_imageproc_gain_new();
pdp_gain_gain(x, f);
return (void *)x;
}
#ifdef __cplusplus
extern "C"
{
#endif
void pdp_gain_setup(void)
{
pdp_gain_class = class_new(gensym("pdp_gain"), (t_newmethod)pdp_gain_new,
(t_method)pdp_gain_free, sizeof(t_pdp_gain), 0, A_DEFFLOAT, A_NULL);
pdp_imagebase_setup(pdp_gain_class);
class_addmethod(pdp_gain_class, (t_method)pdp_gain_gain, gensym("gain"), A_DEFFLOAT, A_NULL);
}
#ifdef __cplusplus
}
#endif
--- NEW FILE: pdp_conv.c ---
/*
* Pure Data Packet module.
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include "pdp.h"
#include "pdp_imagebase.h"
typedef struct pdp_conv_struct
{
t_pdp_imagebase x_base;
unsigned int x_nbpasses;
bool x_horizontal;
bool x_vertical;
void *x_convolver_hor;
void *x_convolver_ver;
} t_pdp_conv;
static void pdp_conv_process(t_pdp_conv *x)
{
int p = pdp_base_get_packet(x, 0);
u32 mask = pdp_imagebase_get_chanmask(x);
if (x->x_vertical){
pdp_imageproc_conv_setnbpasses(x->x_convolver_ver, x->x_nbpasses);
pdp_imageproc_dispatch_1buf(&pdp_imageproc_conv_process, x->x_convolver_ver, mask, p);
}
if (x->x_horizontal){
pdp_imageproc_conv_setnbpasses(x->x_convolver_hor, x->x_nbpasses);
pdp_imageproc_dispatch_1buf(&pdp_imageproc_conv_process, x->x_convolver_hor, mask, p);
}
}
static void pdp_conv_passes(t_pdp_conv *x, t_floatarg f)
{
int passes = (int)f;
passes = passes < 0 ? 0 : passes;
x->x_nbpasses = passes;
}
static void pdp_conv_hor(t_pdp_conv *x, t_floatarg f)
{
int hor = (int)f;
x->x_horizontal = (hor != 0);
}
static void pdp_conv_ver(t_pdp_conv *x, t_floatarg f)
{
int ver = (int)f;
x->x_vertical = (ver != 0);
}
static void pdp_conv_free(t_pdp_conv *x)
{
pdp_imagebase_free(x);
pdp_imageproc_conv_delete(x->x_convolver_hor);
pdp_imageproc_conv_delete(x->x_convolver_ver);
}
/* setup hmask */
static void pdp_conv_hleft(t_pdp_conv *x, t_floatarg f)
{
pdp_imageproc_conv_setmin1(x->x_convolver_hor, f);
}
static void pdp_conv_hmiddle(t_pdp_conv *x, t_floatarg f)
{
pdp_imageproc_conv_setzero(x->x_convolver_hor, f);
}
static void pdp_conv_hright(t_pdp_conv *x, t_floatarg f)
{
pdp_imageproc_conv_setplus1(x->x_convolver_hor, f);
}
static void pdp_conv_hmask(t_pdp_conv *x, t_floatarg l, t_floatarg m, t_floatarg r)
{
pdp_conv_hleft(x, l);
pdp_conv_hmiddle(x, m);
pdp_conv_hright(x, r);
}
static void pdp_conv_vtop(t_pdp_conv *x, t_floatarg f)
{
pdp_imageproc_conv_setmin1(x->x_convolver_ver, f);
}
static void pdp_conv_vmiddle(t_pdp_conv *x, t_floatarg f)
{
pdp_imageproc_conv_setzero(x->x_convolver_ver, f);
}
static void pdp_conv_vbottom(t_pdp_conv *x, t_floatarg f)
{
pdp_imageproc_conv_setplus1(x->x_convolver_ver, f);
}
static void pdp_conv_vmask(t_pdp_conv *x, t_floatarg l, t_floatarg m, t_floatarg r)
{
pdp_conv_vtop(x, l);
pdp_conv_vmiddle(x, m);
pdp_conv_vbottom(x, r);
}
static void pdp_conv_mask(t_pdp_conv *x, t_floatarg l, t_floatarg m, t_floatarg r)
{
pdp_conv_hmask(x, l, m, r);
pdp_conv_vmask(x, l, m, r);
}
t_class *pdp_conv_class;
void *pdp_conv_new(void)
{
t_pdp_conv *x = (t_pdp_conv *)pd_new(pdp_conv_class);
/* super init */
pdp_imagebase_init(x);
/* inlets & outlets */
pdp_base_add_gen_inlet(x, gensym("float"), gensym("passes"));
pdp_base_add_pdp_outlet(x);
/* register */
pdp_base_set_process_method(x, (t_pdp_method)pdp_conv_process);
x->x_nbpasses = 1;
x->x_horizontal = true;
x->x_vertical = true;
x->x_convolver_hor = pdp_imageproc_conv_new();
x->x_convolver_ver = pdp_imageproc_conv_new();
pdp_imageproc_conv_setbordercolor(x->x_convolver_hor, 0);
pdp_imageproc_conv_setbordercolor(x->x_convolver_ver, 0);
pdp_imageproc_conv_setorientation(x->x_convolver_hor, PDP_IMAGEPROC_CONV_HORIZONTAL);
pdp_imageproc_conv_setorientation(x->x_convolver_ver, PDP_IMAGEPROC_CONV_VERTICAL);
pdp_conv_mask(x, .25,.5,.25);
return (void *)x;
}
#ifdef __cplusplus
extern "C"
{
#endif
void pdp_conv_setup(void)
{
pdp_conv_class = class_new(gensym("pdp_conv"), (t_newmethod)pdp_conv_new,
(t_method)pdp_conv_free, sizeof(t_pdp_conv), 0, A_NULL);
pdp_imagebase_setup(pdp_conv_class);
class_addmethod(pdp_conv_class, (t_method)pdp_conv_passes, gensym("passes"), A_DEFFLOAT, A_NULL);
class_addmethod(pdp_conv_class, (t_method)pdp_conv_hor, gensym("hor"), A_DEFFLOAT, A_NULL);
class_addmethod(pdp_conv_class, (t_method)pdp_conv_ver, gensym("ver"), A_DEFFLOAT, A_NULL);
class_addmethod(pdp_conv_class, (t_method)pdp_conv_hleft, gensym("hleft"), A_DEFFLOAT, A_NULL);
class_addmethod(pdp_conv_class, (t_method)pdp_conv_hmiddle, gensym("hmiddle"), A_DEFFLOAT, A_NULL);
class_addmethod(pdp_conv_class, (t_method)pdp_conv_hright, gensym("hright"), A_DEFFLOAT, A_NULL);
class_addmethod(pdp_conv_class, (t_method)pdp_conv_vtop, gensym("vtop"), A_DEFFLOAT, A_NULL);
class_addmethod(pdp_conv_class, (t_method)pdp_conv_vmiddle, gensym("vmiddle"), A_DEFFLOAT, A_NULL);
class_addmethod(pdp_conv_class, (t_method)pdp_conv_vbottom, gensym("vbottom"), A_DEFFLOAT, A_NULL);
class_addmethod(pdp_conv_class, (t_method)pdp_conv_vmask, gensym("vmask"), A_FLOAT, A_FLOAT, A_FLOAT, A_NULL);
class_addmethod(pdp_conv_class, (t_method)pdp_conv_hmask, gensym("hmask"), A_FLOAT, A_FLOAT, A_FLOAT, A_NULL);
class_addmethod(pdp_conv_class, (t_method)pdp_conv_mask, gensym("mask"), A_FLOAT, A_FLOAT, A_FLOAT, A_NULL);
}
#ifdef __cplusplus
}
#endif
--- NEW FILE: pdp_logic.c ---
/*
* Pure Data Packet module.
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include "pdp.h"
#include "pdp_imagebase.h"
typedef struct pdp_logic_struct
{
t_pdp_imagebase x_base;
void *x_mask;
} t_pdp_logic;
static void pdp_logic_process_and(t_pdp_logic *x)
{
int p0 = pdp_base_get_packet(x, 0);
int p1 = pdp_base_get_packet(x, 1);
u32 mask = pdp_imagebase_get_chanmask(x);
pdp_imageproc_dispatch_2buf(&pdp_imageproc_and_process, 0, mask, p0, p1);
}
static void pdp_logic_process_or(t_pdp_logic *x)
{
int p0 = pdp_base_get_packet(x, 0);
int p1 = pdp_base_get_packet(x, 1);
u32 mask = pdp_imagebase_get_chanmask(x);
pdp_imageproc_dispatch_2buf(&pdp_imageproc_or_process, 0, mask, p0, p1);
}
static void pdp_logic_process_xor(t_pdp_logic *x)
{
int p0 = pdp_base_get_packet(x, 0);
int p1 = pdp_base_get_packet(x, 1);
u32 mask = pdp_imagebase_get_chanmask(x);
pdp_imageproc_dispatch_2buf(&pdp_imageproc_xor_process, 0, mask, p0, p1);
}
static void pdp_logic_process_not(t_pdp_logic *x)
{
int p0 = pdp_base_get_packet(x, 0);
u32 mask = pdp_imagebase_get_chanmask(x);
pdp_imageproc_dispatch_1buf(&pdp_imageproc_not_process, 0, mask, p0);
}
static void pdp_logic_process_mask(t_pdp_logic *x)
{
int p0 = pdp_base_get_packet(x, 0);
u32 mask = pdp_imagebase_get_chanmask(x);
pdp_imageproc_dispatch_1buf(&pdp_imageproc_mask_process, x->x_mask, mask, p0);
}
static void pdp_logic_process_softthresh(t_pdp_logic *x)
{
int p0 = pdp_base_get_packet(x, 0);
u32 mask = pdp_imagebase_get_chanmask(x);
pdp_imageproc_dispatch_1buf(&pdp_imageproc_softthresh_process, x->x_mask, mask, p0);
}
static void pdp_logic_process_hardthresh(t_pdp_logic *x)
{
int p0 = pdp_base_get_packet(x, 0);
u32 mask = pdp_imagebase_get_chanmask(x);
pdp_imageproc_dispatch_1buf(&pdp_imageproc_hardthresh_process, x->x_mask, mask, p0);
}
static void pdp_logic_set_mask(t_pdp_logic *x, t_floatarg f)
{
/* using a pointer as a variable hmm? */
u32 mask = ((u32)f) & 0xffff;
x->x_mask = ((void * )mask);
}
static void pdp_logic_set_threshold(t_pdp_logic *x, t_floatarg f)
{
/* using a pointer as a variable hmm? */
if (f<0.0f) f = 0.0f;
if (f>1.0f) f = 1.0f;
x->x_mask = (void *)((u32)(((float)0x7fff) * f));
}
static void pdp_logic_set_depth(t_pdp_logic *x, t_floatarg f)
{
u32 mask;
int shift = (16 - ((int)f));
if (shift < 0) shift = 0;
if (shift > 16) shift = 16;
mask = ((0xffff)<<shift) & 0xffff;
x->x_mask = (void *)mask;
}
static void pdp_logic_free(t_pdp_logic *x)
{
/* remove process method from queue before deleting data */
pdp_imagebase_free(x);
}
t_class *pdp_logic_class;
/* common new method */
void *pdp_logic_new(void)
{
t_pdp_logic *x = (t_pdp_logic *)pd_new(pdp_logic_class);
/* super init */
pdp_imagebase_init(x);
/* outlet */
pdp_base_add_pdp_outlet(x);
x->x_mask = 0;
return (void *)x;
}
void *pdp_logic_new_and(void)
{
t_pdp_logic *x = pdp_logic_new();
/* init in/out */
pdp_base_add_pdp_inlet(x);
pdp_base_set_process_method(x, (t_pdp_method)pdp_logic_process_and);
return (void *)x;
}
void *pdp_logic_new_or(void)
{
t_pdp_logic *x = pdp_logic_new();
/* init in/out */
pdp_base_add_pdp_inlet(x);
pdp_base_set_process_method(x, (t_pdp_method)pdp_logic_process_or);
return (void *)x;
}
void *pdp_logic_new_xor(void)
{
t_pdp_logic *x = pdp_logic_new();
/* init in/out */
pdp_base_add_pdp_inlet(x);
pdp_base_set_process_method(x, (t_pdp_method)pdp_logic_process_xor);
return (void *)x;
}
void *pdp_logic_new_not(void)
{
t_pdp_logic *x = pdp_logic_new();
/* init in/out */
pdp_base_set_process_method(x, (t_pdp_method)pdp_logic_process_not);
return (void *)x;
}
void *pdp_logic_new_mask(void)
{
t_pdp_logic *x = pdp_logic_new();
/* init in/out */
pdp_base_add_gen_inlet(x, gensym("float"), gensym("mask"));
pdp_base_set_process_method(x, (t_pdp_method)pdp_logic_process_mask);
x->x_mask = (void *)0xffff;
return (void *)x;
}
void *pdp_logic_new_depth(void)
{
t_pdp_logic *x = pdp_logic_new();
/* init in/out */
pdp_base_add_gen_inlet(x, gensym("float"), gensym("depth"));
pdp_base_set_process_method(x, (t_pdp_method)pdp_logic_process_mask);
x->x_mask = (void *)0xffff;
return (void *)x;
}
void *pdp_logic_new_softthresh(t_floatarg f)
{
t_pdp_logic *x = pdp_logic_new();
/* init in/out */
pdp_base_add_gen_inlet(x, gensym("float"), gensym("threshold"));
pdp_base_set_process_method(x, (t_pdp_method)pdp_logic_process_softthresh);
pdp_logic_set_threshold(x,f);
return (void *)x;
}
void *pdp_logic_new_hardthresh(t_floatarg f)
{
t_pdp_logic *x = pdp_logic_new();
/* init in/out */
pdp_base_add_gen_inlet(x, gensym("float"), gensym("threshold"));
pdp_base_set_process_method(x, (t_pdp_method)pdp_logic_process_hardthresh);
pdp_logic_set_threshold(x,f);
return (void *)x;
}
#ifdef __cplusplus
extern "C"
{
#endif
void pdp_logic_setup(void)
{
pdp_logic_class = class_new(gensym("pdp_and"), (t_newmethod)pdp_logic_new_and,
(t_method)pdp_logic_free, sizeof(t_pdp_logic), 0, A_DEFFLOAT, A_NULL);
pdp_imagebase_setup(pdp_logic_class);
class_addcreator((t_newmethod)pdp_logic_new_or, gensym("pdp_or"), A_NULL);
class_addcreator((t_newmethod)pdp_logic_new_xor, gensym("pdp_xor"), A_NULL);
class_addcreator((t_newmethod)pdp_logic_new_not, gensym("pdp_not"), A_NULL);
class_addcreator((t_newmethod)pdp_logic_new_mask, gensym("pdp_bitmask"), A_NULL);
class_addcreator((t_newmethod)pdp_logic_new_depth, gensym("pdp_bitdepth"), A_NULL);
class_addcreator((t_newmethod)pdp_logic_new_softthresh, gensym("pdp_sthresh"), A_NULL);
class_addcreator((t_newmethod)pdp_logic_new_hardthresh, gensym("pdp_hthresh"), A_NULL);
class_addmethod(pdp_logic_class, (t_method)pdp_logic_set_mask, gensym("mask"), A_FLOAT, A_NULL);
class_addmethod(pdp_logic_class, (t_method)pdp_logic_set_depth, gensym("depth"), A_FLOAT, A_NULL);
class_addmethod(pdp_logic_class, (t_method)pdp_logic_set_threshold, gensym("threshold"), A_FLOAT, A_NULL);
}
#ifdef __cplusplus
}
#endif
--- NEW FILE: pdp_randmix.c ---
/*
* Pure Data Packet module.
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include "pdp.h"
#include "pdp_imagebase.h"
typedef struct pdp_randmix_struct
{
t_pdp_imagebase x_base;
void *x_randmixer;
} t_pdp_randmix;
void pdp_randmix_random(t_pdp_randmix *x, t_floatarg seed)
{
pdp_imageproc_randmix_setseed(x->x_randmixer, seed);
}
static void pdp_randmix_process(t_pdp_randmix *x)
{
int p0 = pdp_base_get_packet(x, 0);
int p1 = pdp_base_get_packet(x, 1);
u32 mask = pdp_imagebase_get_chanmask(x);
pdp_imageproc_dispatch_2buf(&pdp_imageproc_randmix_process, x->x_randmixer, mask, p0, p1);
}
static void pdp_randmix_threshold(t_pdp_randmix *x, t_floatarg f)
{
pdp_imageproc_randmix_setthreshold(x->x_randmixer, f);
}
static void pdp_randmix_free(t_pdp_randmix *x)
{
pdp_imagebase_free(x);
pdp_imageproc_randmix_delete(x->x_randmixer);
}
t_class *pdp_randmix_class;
void *pdp_randmix_new(void)
{
int i;
t_pdp_randmix *x = (t_pdp_randmix *)pd_new(pdp_randmix_class);
pdp_imagebase_init(x);
pdp_base_add_pdp_inlet(x);
pdp_base_add_gen_inlet(x, gensym("float"), gensym("threshold"));
pdp_base_set_process_method(x, (t_pdp_method)pdp_randmix_process);
pdp_base_add_pdp_outlet(x);
x->x_randmixer = pdp_imageproc_randmix_new();
pdp_randmix_threshold(x, 0.5f);
pdp_randmix_random(x, 0.0f);
return (void *)x;
}
#ifdef __cplusplus
extern "C"
{
#endif
void pdp_randmix_setup(void)
{
pdp_randmix_class = class_new(gensym("pdp_randmix"), (t_newmethod)pdp_randmix_new,
(t_method)pdp_randmix_free, sizeof(t_pdp_randmix), 0, A_NULL);
pdp_imagebase_setup(pdp_randmix_class);
class_addmethod(pdp_randmix_class, (t_method)pdp_randmix_threshold, gensym("threshold"), A_DEFFLOAT, A_NULL);
class_addmethod(pdp_randmix_class, (t_method)pdp_randmix_random, gensym("seed"), A_DEFFLOAT, A_NULL);
}
#ifdef __cplusplus
}
#endif
--- NEW FILE: pdp_bq.c ---
/*
* Pure Data Packet module.
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include "pdp.h"
#include "pdp_imagebase.h"
#include <math.h>
/* computes a transfer function:
*
* b0 + b1 z^(-1) + b2 z^(-2)
* T(z) = --------------------------
* 1 + a1 z^(-1) + a2 z^(-2)
*
*/
typedef struct pdp_bq_struct
{
t_pdp_imagebase x_base; //pdp_bq derives from pdp_base
/* state packets for bqt */
int x_packet1;
int x_packet2;
unsigned int x_nbpasses;
/* single direction */
unsigned int x_direction;
bool x_reset_on_formatchange;
void *x_biquad;
float x_coefs_a[3]; // a0, -a1, -a2
float x_coefs_b[3]; // b0, b1, b2
float x_state_u[2]; // u0, u1
float x_state_u_save[2]; // u0, u1 (for reset)
} t_pdp_bq;
/************************* COEFFICIENT METHODS ****************************/
static void pdp_bq_a0(t_pdp_bq *x, t_floatarg f){x->x_coefs_a[0] = f;}
static void pdp_bq_a1(t_pdp_bq *x, t_floatarg f){x->x_coefs_a[1] = -f;}
static void pdp_bq_a2(t_pdp_bq *x, t_floatarg f){x->x_coefs_a[2] = -f;}
static void pdp_bq_b0(t_pdp_bq *x, t_floatarg f){x->x_coefs_b[0] = f;}
static void pdp_bq_b1(t_pdp_bq *x, t_floatarg f){x->x_coefs_b[1] = f;}
static void pdp_bq_b2(t_pdp_bq *x, t_floatarg f){x->x_coefs_b[2] = f;}
static void pdp_bq_u0(t_pdp_bq *x, t_floatarg f){x->x_state_u_save[0] = f;}
static void pdp_bq_u1(t_pdp_bq *x, t_floatarg f){x->x_state_u_save[1] = f;}
static void pdp_bq_setcoefs(t_pdp_bq *x,
float a0, float a1, float a2,
float b0, float b1, float b2)
{
pdp_bq_a0(x,a0);
pdp_bq_a1(x,a1);
pdp_bq_a2(x,a2);
pdp_bq_b0(x,b0);
pdp_bq_b1(x,b1);
pdp_bq_b2(x,b2);
pdp_imageproc_bq_setcoef(x->x_biquad, x->x_coefs_a);
}
static void pdp_bq_setstate(t_pdp_bq *x, float u0, float u1)
{
pdp_bq_u0(x,u0);
pdp_bq_u1(x,u1);
pdp_imageproc_bq_setcoef(x->x_biquad, x->x_coefs_a);
}
/* reso lowpass */
static void pdp_bq_lpf(t_pdp_bq *x, t_floatarg f, t_floatarg Q)
{
float a0, a1, a2, b0, b1, b2, cs, sn, w, alpha;
w = 2.0 * M_PI * f;
cs = cos(w);
sn = sin(w);
alpha = sn*sinh(1.0f/(2.0f*Q));
b0 = (1.0 - cs)/2.0;
b1 = 1.0 - cs;
b2 = (1.0 - cs)/2.0;
a0 = (1.0 + alpha);
a1 = -2.0*cs;
a2 = 1.0 - alpha;
pdp_bq_setcoefs(x, a0, a1, a2, b0, b1, b2);
}
/* reso highpass */
static void pdp_bq_hpf(t_pdp_bq *x, t_floatarg f, t_floatarg Q)
{
float a0, a1, a2, b0, b1, b2, cs, sn, w, alpha;
w = 2.0 * M_PI * f;
cs = cos(w);
sn = sin(w);
alpha = sn*sinh(1.0f/(2.0f*Q));
b0 = (1.0 + cs)/2.0;
b1 = -1.0 - cs;
b2 = (1.0 + cs)/2.0;
a0 = (1.0 + alpha);
a1 = -2.0*cs;
a2 = 1.0 - alpha;
pdp_bq_setcoefs(x, a0, a1, a2, b0, b1, b2);
}
/* reso allpass */
static void pdp_bq_apf(t_pdp_bq *x, t_floatarg f, t_floatarg Q)
{
float a0, a1, a2, b0, b1, b2, cs, sn, w, alpha;
w = 2.0 * M_PI * f;
cs = cos(w);
sn = sin(w);
alpha = sn*sinh(1.0f/(2.0f*Q));
b0 = (1.0 - alpha);
b1 = -2.0 * cs;
b2 = (1.0 + alpha);
a0 = (1.0 + alpha);
a1 = -2.0*cs;
a2 = 1.0 - alpha;
pdp_bq_setcoefs(x, a0, a1, a2, b0, b1, b2);
}
/* reso band stop (notch) */
static void pdp_bq_bsf(t_pdp_bq *x, t_floatarg f, t_floatarg Q)
{
float a0, a1, a2, b0, b1, b2, cs, sn, w, alpha;
w = 2.0 * M_PI * f;
cs = cos(w);
sn = sin(w);
alpha = sn*sinh(1.0f/(2.0f*Q));
b0 = 1.0;
b1 = -2.0 * cs;
b2 = 1.0;
a0 = (1.0 + alpha);
a1 = -2.0*cs;
a2 = 1.0 - alpha;
pdp_bq_setcoefs(x, a0, a1, a2, b0, b1, b2);
}
static void pdp_bq_onep(t_pdp_bq *x, t_floatarg f)
{
float a0,a1,a2,b0,b1,b2;
if (f>1.0f) f = 1.0f;
if (f<0.0f) f = 0.0f;
a0 = 1.0f;
a1 = -(1.0f - f);
a2 = 0.0f;
b0 = f;
b1 = 0.0f;
b2 = 0.0f;
pdp_bq_setcoefs(x, a0, a1, a2, b0, b1, b2);
}
static void pdp_bq_twop(t_pdp_bq *x, t_floatarg f)
{
float f1;
float a0,a1,a2,b0,b1,b2;
if (f>1.0) f = 1.0;
if (f<0.0) f = 0.0;
f1 = 1.0 - f;
a0 = 1.0f;
a1 = -2.0f*f1;
a2 = f1*f1;
b0 = f*f;
b1 = 0.0f;
b2 = 0.0f;
pdp_bq_setcoefs(x, a0, a1, a2, b0, b1, b2);
}
/************************* PROCESS METHODS ****************************/
static void pdp_bqt_process(t_pdp_bq *x)
{
/* get received packets */
int p0 = pdp_base_get_packet(x, 0);
/* get channel mask */
u32 mask = pdp_imagebase_get_chanmask(x);
pdp_imageproc_dispatch_3buf(&pdp_imageproc_bqt_process, x->x_biquad,
mask, p0, x->x_packet1, x->x_packet2);
}
static void pdp_bq_process(t_pdp_bq *x)
{
/* get received packets */
int p0 = pdp_base_get_packet(x, 0);
/* get channel mask */
u32 mask = pdp_imagebase_get_chanmask(x);
pdp_imageproc_bq_setnbpasses(x->x_biquad, x->x_nbpasses);
pdp_imageproc_bq_setdirection(x->x_biquad, x->x_direction);
pdp_imageproc_dispatch_1buf(&pdp_imageproc_bq_process, x->x_biquad, mask, p0);
}
static void pdp_bqt_reset(t_pdp_bq *x)
{
pdp_imageproc_dispatch_1buf(&pdp_imageproc_zero_process, 0, -1, x->x_packet1);
pdp_imageproc_dispatch_1buf(&pdp_imageproc_zero_process, 0, -1, x->x_packet2);
}
static void pdp_bqt_preproc(t_pdp_bq *x)
{
/* get received packets */
int p0 = pdp_base_get_packet(x, 0);
/* check if state packets are compatible */
if (!(pdp_packet_image_compat(p0, x->x_packet1)
&& pdp_packet_image_compat(p0, x->x_packet1))){
/* if not, create new state packets by copying the input packets */
post("pdp_bqt: created new state packets");
pdp_packet_mark_unused(x->x_packet1);
pdp_packet_mark_unused(x->x_packet2);
x->x_packet1 = pdp_packet_clone_rw(p0);
x->x_packet2 = pdp_packet_clone_rw(p0);
/* reset */
if (x->x_reset_on_formatchange) pdp_bqt_reset(x);
}
}
/************************* CONFIG METHODS ****************************/
static void pdp_bq_passes(t_pdp_bq *x, t_floatarg f)
{
int passes = (int)f;
passes = passes < 0 ? 0 : passes;
x->x_nbpasses = passes;
}
static void pdp_bq_lr(t_pdp_bq *x, t_floatarg f)
{
if (f == 1.0f) x->x_direction |= PDP_IMAGEPROC_BIQUAD_LEFT2RIGHT;
if (f == 0.0f) x->x_direction &= ~PDP_IMAGEPROC_BIQUAD_LEFT2RIGHT;
}
static void pdp_bq_rl(t_pdp_bq *x, t_floatarg f)
{
if (f == 1.0f) x->x_direction |= PDP_IMAGEPROC_BIQUAD_RIGHT2LEFT;
if (f == 0.0f) x->x_direction &= ~PDP_IMAGEPROC_BIQUAD_RIGHT2LEFT;
}
static void pdp_bq_tb(t_pdp_bq *x, t_floatarg f)
{
if (f == 1.0f) x->x_direction |= PDP_IMAGEPROC_BIQUAD_TOP2BOTTOM;
if (f == 0.0f) x->x_direction &= ~PDP_IMAGEPROC_BIQUAD_TOP2BOTTOM;
}
static void pdp_bq_bt(t_pdp_bq *x, t_floatarg f)
{
if (f == 1.0f) x->x_direction |= PDP_IMAGEPROC_BIQUAD_BOTTOM2TOP;
if (f == 0.0f) x->x_direction &= ~PDP_IMAGEPROC_BIQUAD_BOTTOM2TOP;
}
static void pdp_bq_hor(t_pdp_bq *x, t_floatarg f)
{
pdp_bq_lr(x, f);
pdp_bq_rl(x, f);
}
static void pdp_bq_ver(t_pdp_bq *x, t_floatarg f)
{
pdp_bq_tb(x, f);
pdp_bq_bt(x, f);
}
/************************* DES/CONSTRUCTORS ****************************/
static void pdp_bq_free(t_pdp_bq *x)
{
pdp_imagebase_free(x);
pdp_imageproc_bq_delete(x->x_biquad);
pdp_packet_mark_unused(x->x_packet1);
pdp_packet_mark_unused(x->x_packet2);
}
void pdp_bq_init(t_pdp_bq *x)
{
x->x_packet1 = -1;
x->x_packet2 = -1;
x->x_nbpasses = 1;
x->x_reset_on_formatchange = true;
x->x_biquad = pdp_imageproc_bq_new();
pdp_bq_setstate(x, 0.0f, 0.0f);
pdp_bq_onep(x, 0.1f);
}
/* class pointers */
t_class *pdp_bq_class; /* biquad spacial processing */
t_class *pdp_bqt_class; /* biquad time processing */
void *pdp_bq_new(void)
{
t_pdp_bq *x = (t_pdp_bq *)pd_new(pdp_bq_class);
pdp_imagebase_init(x);
pdp_base_add_pdp_outlet(x);
pdp_base_set_process_method(x, (t_pdp_method)pdp_bq_process);
pdp_base_add_gen_inlet(x, gensym("float"), gensym("passes"));
pdp_bq_init(x);
return (void *)x;
}
void *pdp_bqt_new(void)
{
t_pdp_bq *x = (t_pdp_bq *)pd_new(pdp_bqt_class);
pdp_imagebase_init(x);
pdp_base_add_pdp_outlet(x);
pdp_base_set_preproc_method(x, (t_pdp_method)pdp_bqt_preproc);
pdp_base_set_process_method(x, (t_pdp_method)pdp_bqt_process);
pdp_bq_init(x);
return (void *)x;
}
#ifdef __cplusplus
extern "C"
{
#endif
/************************* CLASS CONSTRUCTORS ****************************/
void pdp_bq_coefmethods_setup(t_class *c)
{
/* raw coefficient methods */
class_addmethod(c, (t_method)pdp_bq_a1, gensym("a1"), A_FLOAT, A_NULL);
class_addmethod(c, (t_method)pdp_bq_a2, gensym("a2"), A_FLOAT, A_NULL);
class_addmethod(c, (t_method)pdp_bq_b0, gensym("b0"), A_FLOAT, A_NULL);
class_addmethod(c, (t_method)pdp_bq_b1, gensym("b1"), A_FLOAT, A_NULL);
class_addmethod(c, (t_method)pdp_bq_b2, gensym("b2"), A_FLOAT, A_NULL);
//class_addmethod(c, (t_method)pdp_bq_u1, gensym("u1"), A_FLOAT, A_NULL);
//class_addmethod(c, (t_method)pdp_bq_u2, gensym("u2"), A_FLOAT, A_NULL);
/* real pole filters */
class_addmethod(c, (t_method)pdp_bq_onep, gensym("onep"), A_FLOAT, A_NULL);
class_addmethod(c, (t_method)pdp_bq_twop, gensym("twop"), A_FLOAT, A_NULL);
/* resonnant pole filters */
class_addmethod(c, (t_method)pdp_bq_lpf, gensym("lpf"), A_FLOAT, A_FLOAT, A_NULL);
class_addmethod(c, (t_method)pdp_bq_hpf, gensym("hpf"), A_FLOAT, A_FLOAT, A_NULL);
class_addmethod(c, (t_method)pdp_bq_apf, gensym("apf"), A_FLOAT, A_FLOAT, A_NULL);
class_addmethod(c, (t_method)pdp_bq_bsf, gensym("bsf"), A_FLOAT, A_FLOAT, A_NULL);
}
void pdp_bq_setup(void)
{
/* setup spatial processing class */
pdp_bq_class = class_new(gensym("pdp_bq"), (t_newmethod)pdp_bq_new,
(t_method)pdp_bq_free, sizeof(t_pdp_bq), 0, A_NULL);
pdp_imagebase_setup(pdp_bq_class);
pdp_bq_coefmethods_setup(pdp_bq_class);
class_addmethod(pdp_bq_class, (t_method)pdp_bq_passes, gensym("passes"), A_FLOAT, A_NULL);
class_addmethod(pdp_bq_class, (t_method)pdp_bq_hor, gensym("hor"), A_FLOAT, A_NULL);
class_addmethod(pdp_bq_class, (t_method)pdp_bq_ver, gensym("ver"), A_FLOAT, A_NULL);
class_addmethod(pdp_bq_class, (t_method)pdp_bq_tb, gensym("tb"), A_FLOAT, A_NULL);
class_addmethod(pdp_bq_class, (t_method)pdp_bq_bt, gensym("bt"), A_FLOAT, A_NULL);
class_addmethod(pdp_bq_class, (t_method)pdp_bq_lr, gensym("lr"), A_FLOAT, A_NULL);
class_addmethod(pdp_bq_class, (t_method)pdp_bq_rl, gensym("rl"), A_FLOAT, A_NULL);
/* setup time processing class */
pdp_bqt_class = class_new(gensym("pdp_bqt"), (t_newmethod)pdp_bqt_new,
(t_method)pdp_bq_free, sizeof(t_pdp_bq), 0, A_NULL);
pdp_imagebase_setup(pdp_bqt_class);
pdp_bq_coefmethods_setup(pdp_bqt_class);
/* control */
class_addmethod(pdp_bqt_class, (t_method)pdp_bqt_reset, gensym("reset"), A_NULL);
}
#ifdef __cplusplus
}
#endif
--- NEW FILE: Makefile ---
current: all_modules
include ../../Makefile.config
PDP_MOD = pdp_add.o pdp_conv.o \
pdp_mix.o pdp_mul.o pdp_randmix.o \
pdp_bq.o pdp_noise.o \
pdp_gain.o pdp_zoom.o \
pdp_constant.o \
pdp_logic.o pdp_stateless.o pdp_plasma.o $(PDP_IMAGE_BASIC)
# build basic image processing modules (derived from base class)
all_modules: $(PDP_MOD)
clean:
rm -f *~
rm -f *.o
--- NEW FILE: pdp_constant.c ---
/*
* Pure Data Packet module.
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include "pdp.h"
#include "pdp_imagebase.h"
typedef struct pdp_constant_struct
{
t_pdp_imagebase x_base;
t_outlet *x_outlet0;
int x_packet0;
t_symbol *x_type;
unsigned int x_width;
unsigned int x_height;
void *x_constant;
} t_pdp_constant;
void pdp_constant_type(t_pdp_constant *x, t_symbol *s)
{
x->x_type = s;
}
void pdp_constant_value(t_pdp_constant *x, t_floatarg f)
{
if (f>1.0f) f = 1.0f;
if (f<-1.0f) f = -1.0f;
x->x_constant = (void *)((s32)(0x7fff * f));
}
static void pdp_constant_process(t_pdp_constant *x)
{
/* get channel mask */
u32 mask = pdp_imagebase_get_chanmask(x);
/* create new packet */
if (x->x_type == gensym("yv12")){x->x_packet0 = pdp_packet_new_image_YCrCb(x->x_width, x->x_height);}
else if (x->x_type == gensym("grey")){x->x_packet0 = pdp_packet_new_image_grey(x->x_width, x->x_height);}
else return;
/* this processes the packets using a pdp image processor */
pdp_imageproc_dispatch_1buf(&pdp_imageproc_constant_process, x->x_constant, mask, x->x_packet0);
pdp_imageproc_dispatch_1buf(&pdp_imageproc_constant_process, 0, ~mask, x->x_packet0);
return;
}
static void pdp_constant_postproc(t_pdp_constant *x)
{
pdp_packet_pass_if_valid(x->x_outlet0, &x->x_packet0);
}
static void pdp_constant_bang(t_pdp_constant *x)
{
pdp_base_bang(x);
}
static void pdp_constant_dim(t_pdp_constant *x, t_floatarg w, t_floatarg h)
{
x->x_width = pdp_imageproc_legalwidth((int)w);
x->x_height = pdp_imageproc_legalheight((int)h);
//post("dims %d %d", x->x_width, x->x_height);
}
static void pdp_constant_free(t_pdp_constant *x)
{
pdp_imagebase_free(x);
pdp_packet_mark_unused(x->x_packet0);
}
t_class *pdp_constant_class;
void *pdp_constant_new(void)
{
int i;
t_pdp_constant *x = (t_pdp_constant *)pd_new(pdp_constant_class);
/* super init */
pdp_imagebase_init(x);
/* in/out*/
pdp_base_add_gen_inlet(x, gensym("float"), gensym("value"));
x->x_outlet0 = pdp_base_add_pdp_outlet(x);
/* base callbacks */
pdp_base_disable_active_inlet(x);
pdp_base_set_process_method(x, (t_pdp_method)pdp_constant_process);
pdp_base_set_postproc_method(x, (t_pdp_method)pdp_constant_postproc);
/* data init */
x->x_packet0 = -1;
pdp_constant_dim(x, 320, 240);
pdp_constant_value(x, 0.0f);
pdp_constant_type(x, gensym("yv12"));
return (void *)x;
}
#ifdef __cplusplus
extern "C"
{
#endif
void pdp_constant_setup(void)
{
pdp_constant_class = class_new(gensym("pdp_constant"), (t_newmethod)pdp_constant_new,
(t_method)pdp_constant_free, sizeof(t_pdp_constant), 0, A_NULL);
pdp_imagebase_setup(pdp_constant_class);
class_addmethod(pdp_constant_class, (t_method)pdp_constant_value, gensym("value"), A_DEFFLOAT, A_NULL);
class_addmethod(pdp_constant_class, (t_method)pdp_constant_type, gensym("type"), A_SYMBOL, A_NULL);
class_addmethod(pdp_constant_class, (t_method)pdp_constant_dim, gensym("dim"), A_FLOAT, A_FLOAT, A_NULL);
class_addmethod(pdp_constant_class, (t_method)pdp_constant_bang, gensym("bang"), A_NULL);
}
#ifdef __cplusplus
}
#endif
--- NEW FILE: pdp_cheby.c ---
/*
* Pure Data Packet module.
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <stdio.h>
#include <gsl/gsl_math.h>
#include <gsl/gsl_chebyshev.h>
#include "pdp.h"
#include "pdp_imagebase.h"
typedef struct pdp_cheby_struct
{
t_pdp_imagebase x_base;
void *x_cheby;
int x_iterations;
int x_order;
gsl_cheb_series *x_cs;
gsl_function x_F;
float *x_vec;
int x_nbpoints;
} t_pdp_cheby;
static double pdp_cheby_mappingfunction(double f, void *params)
{
t_pdp_cheby *x = (t_pdp_cheby *)params;
int index;
/* if there's no array, return the identity function */
if (!x->x_vec) return f;
/* else interpolate the array */
index = ((f + 1) * 0.5) * (x->x_nbpoints - 1);
return x->x_vec[index];
}
static void pdp_cheby_coef(t_pdp_cheby *x, t_floatarg c, t_floatarg f)
{
pdp_imageproc_cheby_setcoef(x->x_cheby, (int)c, f);
}
static void pdp_cheby_approx(t_pdp_cheby *x, t_symbol *s)
{
int i;
t_garray *a;
/* check if array is valid */
if (!(a = (t_garray *)pd_findbyclass(s, garray_class))){
post("pdp_cheby: %s: no such array", s->s_name);
}
/* get data */
else if (!garray_getfloatarray(a, &x->x_nbpoints, &x->x_vec)){
post("pdp_cheby: %s: bad template", s->s_name);
}
else{
/* calculate approximation */
gsl_cheb_init (x->x_cs, &x->x_F, -1.0, 1.0);
/* propagate coefficients */
for (i=0; i<=x->x_order; i++){
pdp_cheby_coef(x, i, x->x_cs->c[i]);
}
}
x->x_vec = 0;
return;
}
static void pdp_cheby_process(t_pdp_cheby *x)
{
int p0 = pdp_base_get_packet(x, 0);
u32 mask = pdp_imagebase_get_chanmask(x);
pdp_imageproc_cheby_setnbpasses(x->x_cheby, x->x_iterations);
pdp_imageproc_dispatch_1buf(&pdp_imageproc_cheby_process, x->x_cheby, mask, p0);
}
static void pdp_cheby_reset(t_pdp_cheby *x)
{
int i;
for (i = 0; i <= x->x_order; i++)
pdp_imageproc_cheby_setcoef(x->x_cheby, i, 0);
}
static void pdp_cheby_iterations(t_pdp_cheby *x, t_floatarg f)
{
int i = (int)f;
if (i<0) i = 0;
x->x_iterations = i;
}
static void pdp_cheby_free(t_pdp_cheby *x)
{
pdp_imagebase_free(x);
pdp_imageproc_cheby_delete(x->x_cheby);
gsl_cheb_free(x->x_cs);
}
t_class *pdp_cheby_class;
void *pdp_cheby_new(t_floatarg f)
{
t_pdp_cheby *x = (t_pdp_cheby *)pd_new(pdp_cheby_class);
int order = (int)(f);
/* super init */
pdp_imagebase_init(x);
/* create i/o */
pdp_base_add_gen_inlet(x, gensym("float"), gensym("iterations"));
pdp_base_add_pdp_outlet(x);
/* setup callback */
pdp_base_set_process_method(x, (t_pdp_method)pdp_cheby_process);
/* data init */
x->x_cheby = pdp_imageproc_cheby_new(order);
x->x_iterations = 1;
if (order < 2) order = 2;
x->x_order = order;
/* init gls chebychev series object */
x->x_cs = gsl_cheb_alloc(order);
x->x_F.function = pdp_cheby_mappingfunction;
x->x_F.params = x;
x->x_vec = 0;
return (void *)x;
}
#ifdef __cplusplus
extern "C"
{
#endif
void pdp_cheby_setup(void)
{
pdp_cheby_class = class_new(gensym("pdp_cheby"), (t_newmethod)pdp_cheby_new,
(t_method)pdp_cheby_free, sizeof(t_pdp_cheby), 0, A_DEFFLOAT, A_NULL);
pdp_imagebase_setup(pdp_cheby_class);
class_addmethod(pdp_cheby_class, (t_method)pdp_cheby_coef, gensym("coef"), A_FLOAT, A_FLOAT, A_NULL);
class_addmethod(pdp_cheby_class, (t_method)pdp_cheby_iterations, gensym("iterations"), A_FLOAT, A_NULL);
class_addmethod(pdp_cheby_class, (t_method)pdp_cheby_reset, gensym("reset"), A_NULL);
class_addmethod(pdp_cheby_class, (t_method)pdp_cheby_approx, gensym("approx"), A_SYMBOL, A_NULL);
}
#ifdef __cplusplus
}
#endif
--- NEW FILE: README ---
This directory contains "normal" planar 16 bit unsigned image packet processors,
derived from the t_pdp_imagebase class defined in pdp_imagebase.h
Most modules are wrappers around monochrome bitmap processors (pdp_imageproc_*)
--- NEW FILE: pdp_zoom.c ---
/*
* Pure Data Packet module.
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include "pdp.h"
#include "pdp_imagebase.h"
typedef struct pdp_zoom_struct
{
t_pdp_imagebase x_base;
int x_packet1;
t_outlet *x_outlet0;
void *x_zoom;
int x_quality; //not used
} t_pdp_zoom;
static void pdp_zoom_process(t_pdp_zoom *x)
{
int p0 = pdp_base_get_packet(x, 0);
u32 mask = pdp_imagebase_get_chanmask(x);
pdp_imageproc_dispatch_2buf(&pdp_imageproc_resample_affinemap_process, x->x_zoom, mask, p0, x->x_packet1);
}
static void pdp_zoom_postproc(t_pdp_zoom *x)
{
/* delete source packet */
pdp_packet_mark_unused(pdp_base_move_packet(x, 0));
/* unregister and propagate if valid dest packet */
pdp_packet_pass_if_valid(x->x_outlet0, &x->x_packet1);
}
static void pdp_zoom_preproc(t_pdp_zoom *x)
{
int p = pdp_base_get_packet(x, 0);
t_pdp *header0 = pdp_packet_header(p);
if ((header0) && (PDP_IMAGE == header0->type)){
x->x_packet1 = pdp_packet_clone_rw(p);
}
}
static void pdp_zoom_zoom_x(t_pdp_zoom *x, t_floatarg f)
{
pdp_imageproc_resample_affinemap_setzoomx(x->x_zoom, f);
}
static void pdp_zoom_angle(t_pdp_zoom *x, t_floatarg f)
{
pdp_imageproc_resample_affinemap_setangle(x->x_zoom, f);
}
static void pdp_zoom_zoom_y(t_pdp_zoom *x, t_floatarg f)
{
pdp_imageproc_resample_affinemap_setzoomy(x->x_zoom, f);
}
static void pdp_zoom_zoom(t_pdp_zoom *x, t_floatarg f)
{
pdp_zoom_zoom_x(x, f);
pdp_zoom_zoom_y(x, f);
}
static void pdp_zoom_center_x(t_pdp_zoom *x, t_floatarg f)
{
pdp_imageproc_resample_affinemap_setcenterx(x->x_zoom, f);
}
static void pdp_zoom_center_y(t_pdp_zoom *x, t_floatarg f)
{
pdp_imageproc_resample_affinemap_setcentery(x->x_zoom, f);
}
static void pdp_zoom_center(t_pdp_zoom *x, t_floatarg fx, t_floatarg fy)
{
pdp_zoom_center_x(x, fx);
pdp_zoom_center_y(x, fy);
}
// not used
static void pdp_zoom_quality(t_pdp_zoom *x, t_floatarg f)
{
if (f==0) x->x_quality = 0;
if (f==1) x->x_quality = 1;
}
t_class *pdp_zoom_class;
void pdp_zoom_free(t_pdp_zoom *x)
{
pdp_imagebase_free(x);
pdp_imageproc_resample_affinemap_delete(x->x_zoom);
pdp_packet_mark_unused(x->x_packet1);
}
void pdp_zoom_init_common(t_pdp_zoom *x)
{
pdp_imagebase_init(x);
pdp_base_set_process_method(x, (t_pdp_method)pdp_zoom_process);
pdp_base_set_postproc_method(x, (t_pdp_method)pdp_zoom_postproc);
pdp_base_set_preproc_method(x, (t_pdp_method)pdp_zoom_preproc);
x->x_outlet0 = pdp_base_add_pdp_outlet(x);
x->x_packet1 = -1;
x->x_zoom = pdp_imageproc_resample_affinemap_new();
//quality is not used: all routines are "high quality" bilinear
//pdp_zoom_quality(x, 1);
pdp_zoom_center_x(x, 0.5f);
pdp_zoom_center_y(x, 0.5f);
}
void *pdp_zoom_new(t_floatarg zoom)
{
t_pdp_zoom *x = (t_pdp_zoom *)pd_new(pdp_zoom_class);
pdp_zoom_init_common(x);
pdp_base_add_gen_inlet(x, gensym("float"), gensym("zoom"));
if (zoom == 0.0f) zoom = 1.0f;
pdp_zoom_zoom(x, zoom);
pdp_zoom_angle(x, 0.0f);
return (void *)x;
}
void *pdp_zrot_new(t_floatarg zoom, t_floatarg angle)
{
t_pdp_zoom *x = (t_pdp_zoom *)pd_new(pdp_zoom_class);
pdp_zoom_init_common(x);
pdp_base_add_gen_inlet(x, gensym("float"), gensym("zoom"));
pdp_base_add_gen_inlet(x, gensym("float"), gensym("angle"));
if (zoom == 0.0f) zoom = 1.0f;
pdp_zoom_zoom(x, zoom);
pdp_zoom_angle(x, angle);
return (void *)x;
}
void *pdp_rotate_new(t_floatarg angle)
{
t_pdp_zoom *x = (t_pdp_zoom *)pd_new(pdp_zoom_class);
pdp_zoom_init_common(x);
pdp_base_add_gen_inlet(x, gensym("float"), gensym("angle"));
pdp_zoom_zoom(x, 1.0f);
pdp_zoom_angle(x, angle);
return (void *)x;
}
#ifdef __cplusplus
extern "C"
{
#endif
void pdp_zoom_setup(void)
{
pdp_zoom_class = class_new(gensym("pdp_zoom"), (t_newmethod)pdp_zoom_new,
(t_method)pdp_zoom_free, sizeof(t_pdp_zoom), 0, A_DEFFLOAT, A_NULL);
class_addcreator((t_newmethod)pdp_zrot_new, gensym("pdp_zrot"), A_DEFFLOAT, A_DEFFLOAT, A_NULL);
class_addcreator((t_newmethod)pdp_rotate_new, gensym("pdp_rotate"), A_DEFFLOAT, A_NULL);
pdp_imagebase_setup(pdp_zoom_class);
class_addmethod(pdp_zoom_class, (t_method)pdp_zoom_quality, gensym("quality"), A_FLOAT, A_NULL);
class_addmethod(pdp_zoom_class, (t_method)pdp_zoom_center_x, gensym("centerx"), A_FLOAT, A_NULL);
class_addmethod(pdp_zoom_class, (t_method)pdp_zoom_center_y, gensym("centery"), A_FLOAT, A_NULL);
class_addmethod(pdp_zoom_class, (t_method)pdp_zoom_center, gensym("center"), A_FLOAT, A_FLOAT, A_NULL);
class_addmethod(pdp_zoom_class, (t_method)pdp_zoom_zoom_x, gensym("zoomx"), A_FLOAT, A_NULL);
class_addmethod(pdp_zoom_class, (t_method)pdp_zoom_zoom_y, gensym("zoomy"), A_FLOAT, A_NULL);
class_addmethod(pdp_zoom_class, (t_method)pdp_zoom_zoom, gensym("zoom"), A_FLOAT, A_NULL);
class_addmethod(pdp_zoom_class, (t_method)pdp_zoom_angle, gensym("angle"), A_FLOAT, A_NULL);
}
#ifdef __cplusplus
}
#endif
--- NEW FILE: pdp_stateless.c ---
/*
* Pure Data Packet module. Some stateless image operations.
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include "pdp.h"
#include "pdp_imagebase.h"
typedef struct pdp_stateless_struct
{
t_pdp_imagebase x_base;
} t_pdp_stateless;
static void pdp_stateless_process_abs(t_pdp_stateless *x)
{
int p0 = pdp_base_get_packet(x, 0);
u32 mask = pdp_imagebase_get_chanmask(x);
pdp_imageproc_dispatch_1buf(&pdp_imageproc_abs_process, 0, mask, p0);
}
static void pdp_stateless_process_hardthresh(t_pdp_stateless *x)
{
int p0 = pdp_base_get_packet(x, 0);
u32 mask = pdp_imagebase_get_chanmask(x);
pdp_imageproc_dispatch_1buf(&pdp_imageproc_hardthresh_process, 0, mask, p0);
}
static void pdp_stateless_process_zthresh(t_pdp_stateless *x)
{
int p0 = pdp_base_get_packet(x, 0);
u32 mask = pdp_imagebase_get_chanmask(x);
pdp_imageproc_dispatch_1buf(&pdp_imageproc_zthresh_process, 0, mask, p0);
}
static void pdp_stateless_process_positive(t_pdp_stateless *x)
{
int p0 = pdp_base_get_packet(x, 0);
u32 mask = pdp_imagebase_get_chanmask(x);
pdp_imageproc_dispatch_1buf(&pdp_imageproc_ispositive_process, 0, mask, p0);
}
static void pdp_stateless_process_sign(t_pdp_stateless *x)
{
int p0 = pdp_base_get_packet(x, 0);
u32 mask = pdp_imagebase_get_chanmask(x);
pdp_imageproc_dispatch_1buf(&pdp_imageproc_sign_process, 0, mask, p0);
}
static void pdp_stateless_process_flip_tb(t_pdp_stateless *x)
{
int p0 = pdp_base_get_packet(x, 0);
u32 mask = pdp_imagebase_get_chanmask(x);
pdp_imageproc_dispatch_1buf(&pdp_imageproc_flip_tb_process, 0, mask, p0);
}
static void pdp_stateless_process_flip_lr(t_pdp_stateless *x)
{
int p0 = pdp_base_get_packet(x, 0);
u32 mask = pdp_imagebase_get_chanmask(x);
pdp_imageproc_dispatch_1buf(&pdp_imageproc_flip_lr_process, 0, mask, p0);
}
static void pdp_stateless_free(t_pdp_stateless *x)
{
/* remove process method from queue before deleting data */
pdp_imagebase_free(x);
}
t_class *pdp_stateless_class;
/* common new method */
void *pdp_stateless_new(void)
{
t_pdp_stateless *x = (t_pdp_stateless *)pd_new(pdp_stateless_class);
/* super init */
pdp_imagebase_init(x);
/* outlet */
pdp_base_add_pdp_outlet(x);
return (void *)x;
}
void *pdp_stateless_new_abs(void)
{
t_pdp_stateless *x = pdp_stateless_new();
/* init in/out */
pdp_base_set_process_method(x, (t_pdp_method)pdp_stateless_process_abs);
return (void *)x;
}
void *pdp_stateless_new_zthresh(void)
{
t_pdp_stateless *x = pdp_stateless_new();
/* init in/out */
pdp_base_set_process_method(x, (t_pdp_method)pdp_stateless_process_zthresh);
return (void *)x;
}
void *pdp_stateless_new_positive(void)
{
t_pdp_stateless *x = pdp_stateless_new();
/* init in/out */
pdp_base_set_process_method(x, (t_pdp_method)pdp_stateless_process_positive);
return (void *)x;
}
void *pdp_stateless_new_sign(void)
{
t_pdp_stateless *x = pdp_stateless_new();
/* init in/out */
pdp_base_set_process_method(x, (t_pdp_method)pdp_stateless_process_sign);
return (void *)x;
}
void *pdp_stateless_new_flip_tb(void)
{
t_pdp_stateless *x = pdp_stateless_new();
/* init in/out */
pdp_base_set_process_method(x, (t_pdp_method)pdp_stateless_process_flip_tb);
return (void *)x;
}
void *pdp_stateless_new_flip_lr(void)
{
t_pdp_stateless *x = pdp_stateless_new();
/* init in/out */
pdp_base_set_process_method(x, (t_pdp_method)pdp_stateless_process_flip_lr);
return (void *)x;
}
#ifdef __cplusplus
extern "C"
{
#endif
void pdp_stateless_setup(void)
{
pdp_stateless_class = class_new(gensym("pdp_abs"), (t_newmethod)pdp_stateless_new_abs,
(t_method)pdp_stateless_free, sizeof(t_pdp_stateless), 0, A_NULL);
pdp_imagebase_setup(pdp_stateless_class);
class_addcreator((t_newmethod)pdp_stateless_new_zthresh, gensym("pdp_zthresh"), A_NULL);
class_addcreator((t_newmethod)pdp_stateless_new_positive, gensym("pdp_positive"), A_NULL);
class_addcreator((t_newmethod)pdp_stateless_new_sign, gensym("pdp_sign"), A_NULL);
class_addcreator((t_newmethod)pdp_stateless_new_flip_tb, gensym("pdp_flip_tb"), A_NULL);
class_addcreator((t_newmethod)pdp_stateless_new_flip_lr, gensym("pdp_flip_lr"), A_NULL);
/* future extensions */
//class_addcreator((t_newmethod)pdp_stateless_new_garble, gensym("pdp_garble"), A_NULL);
}
#ifdef __cplusplus
}
#endif
--- NEW FILE: pdp_add.c ---
/*
* Pure Data Packet module.
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include "pdp.h"
#include "pdp_imagebase.h"
typedef struct pdp_add_struct
{
/* a pdp derived class has the t_pdp_imagebase data member as first entry */
/* it contains the pd object and the data members for the pdp_base class */
t_pdp_imagebase x_base;
} t_pdp_add;
/* the process method */
static void pdp_add_process(t_pdp_add *x)
{
/* get received packets */
int p0, p1;
/* get channel mask */
int mask = pdp_imagebase_get_chanmask(x);
/* this processes the packets using a pdp image processor */
/* replace this with your own processing code */
/* for raw packet acces: use pdp_pacjet_header() and pdp_packet_data() */
p0 = pdp_base_get_packet(x,0);
p1 = pdp_base_get_packet(x,1);
pdp_imageproc_dispatch_2buf(&pdp_imageproc_add_process, 0, mask, p0, p1);
}
static void pdp_add_free(t_pdp_add *x)
{
/* free super: this is mandatory
(it stops the thread if there is one running and frees all packets) */
pdp_imagebase_free(x);
/* if you have allocated more packets
this is the place to free them with pdp_mark_unused */
}
t_class *pdp_add_class;
void *pdp_add_new(void)
{
/* allocate */
t_pdp_add *x = (t_pdp_add *)pd_new(pdp_add_class);
/* init super: this is mandatory */
pdp_imagebase_init(x);
/* set the pdp processing method */
pdp_base_set_process_method(x, (t_pdp_method)pdp_add_process);
/* create additional cold (readonly) pdp inlets (there is already one pdp inlet) */
pdp_base_add_pdp_inlet(x);
/* create a pdp_outlet */
pdp_base_add_pdp_outlet(x);
return (void *)x;
}
#ifdef __cplusplus
extern "C"
{
#endif
void pdp_add_setup(void)
{
/* create a standard pd class */
pdp_add_class = class_new(gensym("pdp_add"), (t_newmethod)pdp_add_new,
(t_method)pdp_add_free, sizeof(t_pdp_add), 0, A_NULL);
/* inherit pdp base class methods */
pdp_imagebase_setup(pdp_add_class);
}
#ifdef __cplusplus
}
#endif
--- NEW FILE: pdp_mix.c ---
/*
* Pure Data Packet module.
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include "pdp.h"
#include "pdp_imagebase.h"
typedef struct pdp_mix_struct
{
t_pdp_imagebase x_base;
t_outlet *x_outlet0;
t_outlet *x_outlet1;
void *x_mixer;
int x_extrapolate;
} t_pdp_mix;
static void pdp_mix_process(t_pdp_mix *x)
{
int p0 = pdp_base_get_packet(x, 0);
int p1 = pdp_base_get_packet(x, 1);
u32 mask = pdp_imagebase_get_chanmask(x);
pdp_imageproc_dispatch_2buf(&pdp_imageproc_mix_process, x->x_mixer, mask, p0, p1);
}
static void pdp_mix_mix(t_pdp_mix *x, t_floatarg f)
{
float f2;
if (!x->x_extrapolate){
if (f < 0.0f) f = 0.0f;
if (f > 1.0f) f = 1.0f;
}
f2 = (1.0f - f);
pdp_imageproc_mix_setleftgain(x->x_mixer, f2);
pdp_imageproc_mix_setrightgain(x->x_mixer, f);
}
static void pdp_mix_mix1(t_pdp_mix *x, t_floatarg f)
{
pdp_imageproc_mix_setleftgain(x->x_mixer, f);
}
static void pdp_mix_mix2(t_pdp_mix *x, t_floatarg f2)
{
pdp_imageproc_mix_setrightgain(x->x_mixer, f2);
}
static void pdp_mix_extrapolate(t_pdp_mix *x, t_floatarg f)
{
if (f == 0.0f) x->x_extrapolate = 0;
if (f == 1.0f) x->x_extrapolate = 1;
}
static void pdp_mix_free(t_pdp_mix *x)
{
pdp_imagebase_free(x);
pdp_imageproc_mix_delete(x->x_mixer);
}
t_class *pdp_mix_class;
t_class *pdp_mix2_class;
void *pdp_mix_common_init(t_pdp_mix *x)
{
int i;
pdp_imagebase_init(x);
pdp_base_add_pdp_inlet(x);
pdp_base_add_pdp_outlet(x);
pdp_base_set_process_method(x, (t_pdp_method)pdp_mix_process);
x->x_extrapolate = 0;
x->x_mixer = pdp_imageproc_mix_new();
pdp_mix_mix(x, 0.0f);
return (void *)x;
}
void *pdp_mix_new(t_floatarg mix)
{
t_pdp_mix *x = (t_pdp_mix *)pd_new(pdp_mix_class);
pdp_mix_common_init(x);
pdp_base_add_gen_inlet(x, gensym("float"), gensym("mix"));
if (mix == 0.0f) mix = 0.5f;
pdp_mix_mix(x, mix);
return (void *)x;
}
void *pdp_mix2_new(t_floatarg mix1, t_floatarg mix2)
{
t_pdp_mix *x = (t_pdp_mix *)pd_new(pdp_mix2_class);
pdp_mix_common_init(x);
pdp_base_add_gen_inlet(x, gensym("float"), gensym("mix1"));
pdp_base_add_gen_inlet(x, gensym("float"), gensym("mix2"));
if ((mix1 == 0.0f) && (mix2 == 0.0f)) mix1 = mix2 = 0.5f;
pdp_mix_mix1(x, mix1);
pdp_mix_mix2(x, mix2);
return (void *)x;
}
#ifdef __cplusplus
extern "C"
{
#endif
void pdp_mix_setup(void)
{
pdp_mix_class = class_new(gensym("pdp_mix"), (t_newmethod)pdp_mix_new,
(t_method)pdp_mix_free, sizeof(t_pdp_mix), 0, A_DEFFLOAT, A_NULL);
pdp_imagebase_setup(pdp_mix_class);
class_addmethod(pdp_mix_class, (t_method)pdp_mix_mix, gensym("mix"), A_DEFFLOAT, A_NULL);
class_addmethod(pdp_mix_class, (t_method)pdp_mix_extrapolate, gensym("extrapolate"), A_DEFFLOAT, A_NULL);
pdp_mix2_class = class_new(gensym("pdp_mix2"), (t_newmethod)pdp_mix2_new,
(t_method)pdp_mix_free, sizeof(t_pdp_mix), 0, A_DEFFLOAT, A_DEFFLOAT, A_NULL);
pdp_imagebase_setup(pdp_mix2_class);
class_addmethod(pdp_mix2_class, (t_method)pdp_mix_mix1, gensym("mix1"), A_DEFFLOAT, A_NULL);
class_addmethod(pdp_mix2_class, (t_method)pdp_mix_mix2, gensym("mix2"), A_DEFFLOAT, A_NULL);
class_addmethod(pdp_mix2_class, (t_method)pdp_mix_extrapolate, gensym("extrapolate"), A_DEFFLOAT, A_NULL);
}
#ifdef __cplusplus
}
#endif
Update of /cvsroot/pure-data/externals/pdp/modules/matrix_basic
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv6756/modules/matrix_basic
Added Files:
Makefile README clusterstuff.c pdp_mat_lu.c pdp_mat_mul.c
pdp_mat_vec.c
Log Message:
checking in pdp 0.12.4 from http://zwizwa.fartit.com/pd/pdp/pdp-0.12.4.tar.gz
--- NEW FILE: pdp_mat_mul.c ---
/*
* Pure Data Packet module. Matrix multiplication module
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
//#include <gsl/gsl_block.h>
//#include <gsl/gsl_vector.h>
//#include <gsl/gsl_matrix.h>
//#include <gsl/gsl_blas.h>
#include "pdp.h"
#include "pdp_base.h"
typedef struct pdp_mat_mm_struct
{
t_pdp_base x_base;
CBLAS_TRANSPOSE_t x_T0;
CBLAS_TRANSPOSE_t x_T1;
int x_M0;
int x_M1;
float x_scale_r;
float x_scale_i;
} t_pdp_mat_mm;
static void pdp_mat_mm_rscale(t_pdp_mat_mm *x, t_floatarg r)
{
x->x_scale_r = r;
x->x_scale_i = 0.0f;
}
static void pdp_mat_mm_cscale(t_pdp_mat_mm *x, t_floatarg r, t_floatarg i)
{
x->x_scale_r = r;
x->x_scale_i = i;
}
/* matrix multilpy */
static void pdp_mat_mv_process_mul(t_pdp_mat_mm *x)
{
int pA = pdp_base_get_packet(x, 0);
int pB = pdp_base_get_packet(x, 1);
int p0, p1, pR;
/* determine which one is the vector */
if (pdp_packet_matrix_isvector(pA)){
p0 = pB;
p1 = pA;
}
else {
p1 = pB;
p0 = pA;
}
pR = pdp_packet_new_matrix_product_result(x->x_T0, CblasNoTrans, p0, p1);
if (-1 != pR){
pdp_packet_matrix_setzero(pR);
if (pdp_packet_matrix_blas_mv(x->x_T0, p0, p1, pR, x->x_scale_r, x->x_scale_i)){
//post("pdp_packet_matrix_blas_mm failed");
pdp_packet_mark_unused(pR);
pR = -1;
}
}
else {
//post("pdp_packet_new_matrix_product_result failed");
}
/* replace with result */
pdp_base_set_packet(x, 0, pR);
}
/* matrix vector multilpy */
static void pdp_mat_mm_process_mul(t_pdp_mat_mm *x)
{
int pA = pdp_base_get_packet(x, 0);
int pB = pdp_base_get_packet(x, 1);
int p0, p1, pR;
p0 = (x->x_M0) ? pB : pA;
p1 = (x->x_M1) ? pB : pA;
pR = pdp_packet_new_matrix_product_result(x->x_T0, x->x_T1, p0, p1);
if (-1 != pR){
pdp_packet_matrix_setzero(pR);
if (pdp_packet_matrix_blas_mm(x->x_T0, x->x_T1, p0, p1, pR, x->x_scale_r, x->x_scale_i)){
//post("pdp_packet_matrix_blas_mm failed");
pdp_packet_mark_unused(pR);
pR = -1;
}
}
else {
//post("pdp_packet_new_matrix_product_result failed");
}
/* replace with result */
pdp_base_set_packet(x, 0, pR);
}
/* matrix macc */
static void pdp_mat_mm_process_mac(t_pdp_mat_mm *x)
{
int pC = pdp_base_get_packet(x, 0);
int pA = pdp_base_get_packet(x, 1);
int pB = pdp_base_get_packet(x, 2);
int p0, p1;
p0 = (x->x_M0) ? pB : pA;
p1 = (x->x_M1) ? pB : pA;
if (pdp_packet_matrix_blas_mm(x->x_T0, x->x_T1, p0, p1, pC, x->x_scale_r, x->x_scale_i)){
//post("pdp_packet_matrix_blas_mm failed");
pdp_base_set_packet(x, 0, -1); // delete packet
}
}
static void pdp_mat_mm_free(t_pdp_mat_mm *x)
{
/* remove process method from queue before deleting data */
pdp_base_free(x);
}
t_class *pdp_mat_mm_class;
/* common new method */
void *pdp_mat_mm_new(void)
{
int i;
t_pdp_mat_mm *x = (t_pdp_mat_mm *)pd_new(pdp_mat_mm_class);
/* super init */
pdp_base_init(x);
/* outlet */
pdp_base_add_pdp_outlet(x);
return (void *)x;
}
static int pdp_mat_mm_setup_routing_M0(t_pdp_mat_mm *x, t_symbol *s0)
{
if ('A' == s0->s_name[0]){x->x_M0 = 0;} else if ('B' == s0->s_name[0]) {x->x_M0 = 1;} else return 0;
if ((gensym("A") == s0) || (gensym("B") == s0)) x->x_T0 = CblasNoTrans;
else if ((gensym("A^T") == s0) || (gensym("B^T") == s0)) x->x_T0 = CblasConjTrans;
else if ((gensym("A^H") == s0) || (gensym("B^H") == s0)) x->x_T0 = CblasConjTrans;
else return 0;
return 1;
}
static int pdp_mat_mm_setup_routing_M1(t_pdp_mat_mm *x, t_symbol *s1)
{
if ('A' == s1->s_name[0]){x->x_M1 = 0;} else if ('B' == s1->s_name[0]) {x->x_M1 = 1;} else return 0;
/* setup second matrix transpose operation */
if ((gensym("A") == s1) || (gensym("B") == s1)) x->x_T1 = CblasNoTrans;
else if ((gensym("A^T") == s1) || (gensym("B^T") == s1)) x->x_T1 = CblasConjTrans;
else if ((gensym("A^H") == s1) || (gensym("B^H") == s1)) x->x_T1 = CblasConjTrans;
else return 0;
return 1;
}
static int pdp_mat_mm_setup_scaling(t_pdp_mat_mm *x, t_symbol *scale)
{
int success = 1;
/* setup scaling inlet */
if ((gensym ("rscale") == scale) || (gensym("r") == scale)){
pdp_base_add_gen_inlet(x, gensym("float"), gensym("rscale"));
}
else if ((gensym ("cscale") == scale) || (gensym("c") == scale)){
pdp_base_add_gen_inlet(x, gensym("list"), gensym("cscale"));
}
else if (gensym ("") != scale) success = 0;
return success;
}
void *pdp_mat_mm_new_mul_common(t_symbol *s0, t_symbol *s1, t_symbol *scale, int ein)
{
t_pdp_mat_mm *x = pdp_mat_mm_new();
/* add extra pdp inlets */
while (ein--) pdp_base_add_pdp_inlet(x);
/* setup routing */
if (!pdp_mat_mm_setup_routing_M0(x, s0)) goto error;
if (!pdp_mat_mm_setup_routing_M1(x, s1)) goto error;
if (!pdp_mat_mm_setup_scaling(x, scale)) goto error;
/* default scale = 1 */
pdp_mat_mm_cscale(x, 1.0f, 0.0f);
return (void *)x;
error:
pd_free((void *)x);
return 0;
}
void *pdp_mat_mv_new_mul_common(t_symbol *s0, t_symbol *scale, int ein)
{
t_pdp_mat_mm *x = pdp_mat_mm_new();
/* add extra pdp inlets */
while (ein--) pdp_base_add_pdp_inlet(x);
/* setup routing */
if (!pdp_mat_mm_setup_routing_M0(x, s0)) goto error;
if (!pdp_mat_mm_setup_scaling(x, scale)) goto error;
/* default scale = 1 */
pdp_mat_mm_cscale(x, 1.0f, 0.0f);
return (void *)x;
error:
pd_free((void *)x);
return 0;
}
void *pdp_mat_mm_new_mul(t_symbol *s0, t_symbol *s1, t_symbol *scale)
{
t_pdp_mat_mm *x = pdp_mat_mm_new_mul_common(s0, s1, scale, 1);
if(x){
pdp_base_set_process_method(x, (t_pdp_method)pdp_mat_mm_process_mul);
pdp_base_readonly_active_inlet(x);
}
return x;
}
void *pdp_mat_mv_new_mul(t_symbol *s0, t_symbol *scale)
{
t_pdp_mat_mm *x = pdp_mat_mv_new_mul_common(s0, scale, 1);
if(x){
pdp_base_set_process_method(x, (t_pdp_method)pdp_mat_mv_process_mul);
pdp_base_readonly_active_inlet(x);
}
return x;
}
void *pdp_mat_mm_new_mac(t_symbol *s0, t_symbol *s1, t_symbol *scale)
{
t_pdp_mat_mm *x = pdp_mat_mm_new_mul_common(s0, s1, scale, 2);
if (x){
pdp_base_set_process_method(x, (t_pdp_method)pdp_mat_mm_process_mac);
}
return x;
}
#ifdef __cplusplus
extern "C"
{
#endif
void pdp_mat_mul_setup(void)
{
pdp_mat_mm_class = class_new(gensym("pdp_m_mm"), (t_newmethod)pdp_mat_mm_new_mul,
(t_method)pdp_mat_mm_free, sizeof(t_pdp_mat_mm), 0, A_SYMBOL, A_SYMBOL, A_DEFSYMBOL, A_NULL);
pdp_base_setup(pdp_mat_mm_class);
class_addcreator((t_newmethod)pdp_mat_mm_new_mac, gensym("pdp_m_+=mm"),
A_SYMBOL, A_SYMBOL, A_DEFSYMBOL, A_NULL);
class_addcreator((t_newmethod)pdp_mat_mv_new_mul, gensym("pdp_m_mv"),
A_SYMBOL, A_DEFSYMBOL, A_NULL);
class_addmethod(pdp_mat_mm_class, (t_method)pdp_mat_mm_rscale, gensym("rscale"), A_FLOAT, A_NULL);
class_addmethod(pdp_mat_mm_class, (t_method)pdp_mat_mm_cscale, gensym("cscale"), A_FLOAT, A_FLOAT, A_NULL);
}
#ifdef __cplusplus
}
#endif
--- NEW FILE: pdp_mat_vec.c ---
/*
* Pure Data Packet module. Vector modules.
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
//#include <gsl/gsl_block.h>
//#include <gsl/gsl_vector.h>
//#include <gsl/gsl_matrix.h>
//#include <gsl/gsl_blas.h>
#include "pdp.h"
#include "pdp_base.h"
typedef struct pdp_mat_vec_struct
{
t_pdp_base x_base;
int x_type;
t_outlet *x_out;
int x_accept_list;
int x_list_size;
t_atom *x_list;
} t_pdp_mat_vec;
#define GETFLOAT(x) ((x)->a_type == A_FLOAT ? (x)->a_w.w_float : 0.0f)
#define GETDOUBLE(x) (double)GETFLOAT(x)
static void pdp_mat_vec_list_in(t_pdp_mat_vec *x, t_symbol *s, int argc, t_atom *argv)
{
int i;
int vp = -1;
int f;
int dim = argc;
if (!x->x_accept_list) return; //check if this handler is enabled
if (!argc) return; //reject empty list
switch(x->x_type){
case PDP_MATRIX_TYPE_CFLOAT:
if (argc & 1) return; //reject odd nb elements
dim >>= 1; //halve dimension
case PDP_MATRIX_TYPE_RFLOAT:
vp = pdp_packet_new_matrix(dim, 1, x->x_type);
if (-1 != vp){
float *data = (float *)pdp_packet_data(vp);
for (i=0; i<argc; i++) data[i] = GETFLOAT(&argv[i]);
}
break;
case PDP_MATRIX_TYPE_CDOUBLE:
if (argc & 1) return; //reject odd nb elements
dim >>= 1; //halve dimension
case PDP_MATRIX_TYPE_RDOUBLE:
vp = pdp_packet_new_matrix(dim, 1, x->x_type);
if (-1 != vp){
double *data = (double *)pdp_packet_data(vp);
for (i=0; i<argc; i++) data[i] = GETDOUBLE(&argv[i]);
}
break;
default:
break;
}
if (-1 != vp){
/* store vector packet */
pdp_base_set_packet(x, 0, vp);
pdp_base_bang(x);
}
}
static void pdp_mat_vec_list_out(t_pdp_mat_vec *x)
{
int p = pdp_base_move_packet(x, 0);
int type = pdp_packet_matrix_get_type(p);
int outlist_size;
float *fdata = 0;
double *ddata = 0;
int i;
/* check if it's a vector */
gsl_vector *m = (gsl_vector *)pdp_packet_matrix_get_gsl_vector(p, type);
if (!pdp_packet_matrix_isvector(p)) return;
/* get list size */
outlist_size = m->size;
if ((type == PDP_MATRIX_TYPE_CFLOAT)
|| (type == PDP_MATRIX_TYPE_CDOUBLE))
outlist_size <<= 1;
/* realloc list if necessary */
if (outlist_size > x->x_list_size){
free(x->x_list);
x->x_list = (t_atom *)pdp_alloc(sizeof(t_atom) * outlist_size);
x->x_list_size = outlist_size;
}
/* copy data */
switch(type){
case PDP_MATRIX_TYPE_RFLOAT:
case PDP_MATRIX_TYPE_CFLOAT:
fdata = (float *)pdp_packet_data(p);
for (i=0; i<outlist_size; i++)
SETFLOAT(&x->x_list[i], fdata[i]);
break;
case PDP_MATRIX_TYPE_RDOUBLE:
case PDP_MATRIX_TYPE_CDOUBLE:
ddata = (double *)pdp_packet_data(p);
for (i=0; i<outlist_size; i++)
SETFLOAT(&x->x_list[i], (float)ddata[i]);
break;
}
/* dispose of vector packet and output list */
pdp_packet_mark_unused(p);
outlet_list(x->x_out, &s_list, outlist_size, x->x_list);
}
static void pdp_mat_vec_free(t_pdp_mat_vec *x)
{
/* remove process method from queue before deleting data */
pdp_base_free(x);
/* delete list */
if (x->x_list) pdp_dealloc (x->x_list);
}
t_class *pdp_mat_vec_class;
/* common new methods */
t_pdp_mat_vec *pdp_mat_vec_base_new(void)
{
t_pdp_mat_vec *x = (t_pdp_mat_vec *)pd_new(pdp_mat_vec_class);
pdp_base_init(x);
x->x_type = PDP_MATRIX_TYPE_CFLOAT;
x->x_accept_list = 0;
x->x_list_size = 0;
x->x_list = 0;
return x;
}
void *pdp_mat_vec_list2vec_new(t_symbol *type)
{
t_pdp_mat_vec *x = pdp_mat_vec_base_new();
pdp_base_disable_active_inlet(x);
pdp_base_add_pdp_outlet(x);
x->x_accept_list = 1;
if ((gensym ("") == type) || (gensym ("double/real") == type)) x->x_type = PDP_MATRIX_TYPE_RDOUBLE;
else if (gensym ("double/complex") == type) x->x_type = PDP_MATRIX_TYPE_CDOUBLE;
else if (gensym ("float/real") == type) x->x_type = PDP_MATRIX_TYPE_RFLOAT;
else if (gensym ("float/complex") == type) x->x_type = PDP_MATRIX_TYPE_CFLOAT;
else {
pd_free((t_pd *)x);
x = 0;
}
return (void *)x;
}
void *pdp_mat_vec_vec2list_new(t_symbol *type)
{
t_pdp_mat_vec *x = pdp_mat_vec_base_new();
x->x_out = outlet_new((t_object *)x, &s_anything);
pdp_base_set_postproc_method(x,(t_pdp_method)pdp_mat_vec_list_out);
pdp_base_readonly_active_inlet(x);
return (void *)x;
}
#ifdef __cplusplus
extern "C"
{
#endif
void pdp_mat_vec_setup(void)
{
pdp_mat_vec_class = class_new(gensym("pdp_m_list2vec"), (t_newmethod)pdp_mat_vec_list2vec_new,
(t_method)pdp_mat_vec_free, sizeof(t_pdp_mat_vec), 0, A_DEFSYMBOL, A_NULL);
pdp_base_setup(pdp_mat_vec_class);
class_addcreator((t_newmethod)pdp_mat_vec_vec2list_new, gensym("pdp_m_vec2list"), A_NULL);
class_addlist(pdp_mat_vec_class, (t_method)pdp_mat_vec_list_in);
}
#ifdef __cplusplus
}
#endif
--- NEW FILE: Makefile ---
current: all_modules
include ../../Makefile.config
PDP_MOD = $(PDP_MATRIX_BASIC)
all_modules: $(PDP_MOD)
clean:
rm -f *~
rm -f *.o
--- NEW FILE: pdp_mat_lu.c ---
/*
* Pure Data Packet module. LU decomposition module.
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
//#include <gsl/gsl_block.h>
//#include <gsl/gsl_vector.h>
//#include <gsl/gsl_matrix.h>
//#include <gsl/gsl_blas.h>
#include "pdp.h"
#include "pdp_base.h"
typedef struct pdp_mat_LU_struct
{
t_pdp_base x_base;
} t_pdp_mat_LU;
static void pdp_mat_LU_process_LU_inverse(t_pdp_mat_LU *x)
{
int p = pdp_base_get_packet(x, 0);
int p_LU = pdp_packet_matrix_LU_to_inverse(p);
pdp_base_set_packet(x, 0, p_LU); // replace packet
}
static void pdp_mat_LU_process_LU(t_pdp_mat_LU *x)
{
int p = pdp_base_get_packet(x, 0);
int p_LU = pdp_packet_matrix_LU(p);
pdp_base_set_packet(x, 0, p_LU); // replace packet
}
static void pdp_mat_LU_process_LU_solve(t_pdp_mat_LU *x)
{
int p0 = pdp_base_get_packet(x, 0);
int p1 = pdp_base_get_packet(x, 1);
int pvr, pm, pv;
/* determine which is vector and which is matrix */
if (pdp_packet_matrix_ismatrix(p0) && pdp_packet_matrix_isvector(p1)){
pm = p0;
pv = p1;
}
else {
pm = p1;
pv = p0;
}
/* create the result vector */
pvr = pdp_packet_matrix_LU_solve(pm, pv);
/* replace the active packet */
pdp_base_set_packet(x, 0, pvr);
}
static void pdp_mat_LU_free(t_pdp_mat_LU *x)
{
/* remove process method from queue before deleting data */
pdp_base_free(x);
}
t_class *pdp_mat_LU_class;
/* common new methods */
t_pdp_mat_LU *pdp_mat_LU_base_new(void)
{
t_pdp_mat_LU *x = (t_pdp_mat_LU *)pd_new(pdp_mat_LU_class);
pdp_base_init(x);
pdp_base_add_pdp_outlet(x);
return x;
}
void *pdp_mat_LU_inverse_new(void)
{
t_pdp_mat_LU *x = pdp_mat_LU_base_new();
pdp_base_set_process_method(x,(t_pdp_method)pdp_mat_LU_process_LU_inverse);
pdp_base_readonly_active_inlet(x);
return (void *)x;
}
void *pdp_mat_LU_new(void)
{
t_pdp_mat_LU *x = pdp_mat_LU_base_new();
pdp_base_set_process_method(x,(t_pdp_method)pdp_mat_LU_process_LU);
pdp_base_readonly_active_inlet(x);
return (void *)x;
}
void *pdp_mat_LU_solve_new(void)
{
t_pdp_mat_LU *x = pdp_mat_LU_base_new();
pdp_base_set_process_method(x,(t_pdp_method)pdp_mat_LU_process_LU_solve);
pdp_base_readonly_active_inlet(x);
pdp_base_add_pdp_inlet(x);
return (void *)x;
}
#ifdef __cplusplus
extern "C"
{
#endif
void pdp_mat_lu_setup(void)
{
pdp_mat_LU_class = class_new(gensym("pdp_m_LU_inverse"), (t_newmethod)pdp_mat_LU_inverse_new,
(t_method)pdp_mat_LU_free, sizeof(t_pdp_mat_LU), 0, A_NULL);
pdp_base_setup(pdp_mat_LU_class);
class_addcreator((t_newmethod)pdp_mat_LU_new, gensym("pdp_m_LU"), A_NULL);
class_addcreator((t_newmethod)pdp_mat_LU_solve_new, gensym("pdp_m_LU_solve"), A_NULL);
}
#ifdef __cplusplus
}
#endif
--- NEW FILE: README ---
This directory contains "normal" matrix packet processors,
derived from the t_pdp_base class defined in pdp_base.h
Most modules are wrappers around Gnu Scientific Library (gsl) calls
--- NEW FILE: clusterstuff.c ---
/*
* Pure Data Packet module.
* Copyright (c) 2003 by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include "pdp.h"
#include "pdp_base.h"
#include <math.h>
struct _pdp_histo;
typedef void (*t_histo_proc)(struct _pdp_histo *);
/* the cluster struct */
typedef struct _cluster
{
float N;
float cx;
float cy;
} t_cluster;
typedef struct _pdp_histo
{
t_object x_obj;
t_int x_logN;
t_symbol *x_array_sym;
t_float x_scale;
t_int x_debug;
t_int x_sample_size; /* pointcloud size */
t_int x_nb_clusters; /* nb of clusters */
t_cluster *x_cluster; /* cluster data (for tracking) */
t_histo_proc x_process_method; /* what to do with the histogram */
t_outlet *x_outlet0;
t_outlet *x_outlet1;
/* the packet */
int x_packet0;
/* packet data */
short int *x_data;
int x_width;
int x_height;
int x_nb_pixels;
/* histo data for processor: these are stored on the stack */
int *x_histo;
int *x_pixel_offset;
} t_pdp_histo;
// join 2 clusters. clear the second one
static void cluster_join(t_cluster *cA, t_cluster *cB)
{
float scale = 1.0f / (cA->N + cB->N);
cA->cx = (cA->N * cA->cx + cB->N * cB->cx) * scale;
cA->cy = (cA->N * cA->cy + cB->N * cB->cy) * scale;
cA->N += cB->N;
cB->N = 0.0f;
}
static void cluster_copy(t_cluster *cA, t_cluster *cB)
{
cA->cx = cB->cx;
cA->cy = cB->cy;
cA->N = cB->N;
}
static void cluster_clear(t_cluster *c)
{
c->N = 0.0f;
}
static void cluster_new(t_cluster *c, float x, float y)
{
c->N = 1.0f;
c->cx = x;
c->cy = y;
}
static float cluster_dsquared(t_cluster *cA, t_cluster *cB)
{
float dx = cA->cx - cB->cx;
float dy = cA->cy - cB->cy;
return dx*dx + dy*dy;
}
static int round_up_2log(int i)
{
int l = 0;
i--;
while (i) {
i >>= 1;
l++;
}
//post("log is %d, 2^n is %d", l, 1 << l);
l = (l < 16) ? l : 15;
return l;
}
static void compute_clusters(t_pdp_histo *x)
{
t_cluster c[x->x_sample_size];
int i;
float scalex = 1.0f / (float)(x->x_width);
float scaley = 1.0f / (float)(x->x_height);
int nb_clusters = x->x_sample_size;
/* build the cluster data struct */
for (i=0; i<x->x_sample_size; i++)
cluster_new(c+i,
((float)(x->x_pixel_offset[i] % x->x_width)) * scalex,
((float)(x->x_pixel_offset[i] / x->x_width)) * scaley);
/* the clustering loop */
while (nb_clusters > x->x_nb_clusters){
/* initialize cA, cB, d */
int cA=0;
int cB=1;
float d = cluster_dsquared(c+0, c+1);
int i,j;
/* find the closest 2 clusters:
scan the distance matrix above the diagonal */
for (i=2; i<nb_clusters; i++){
for (j=0; j<i; j++){
float dij = cluster_dsquared(c+i, c+j);
if (dij < d){
cA = j;
cB = i;
d = dij;
}
}
}
/* join the two clusters (cA < cB) */
cluster_join (c+cA, c+cB);
/* reduce the distance matrix by moving
the last element to the empty spot cB */
nb_clusters--;
cluster_copy (c+cB, c+nb_clusters);
}
/* copy cluster data */
if (!x->x_cluster){
int size = sizeof(t_cluster) * x->x_nb_clusters;
x->x_cluster = (t_cluster *)pdp_alloc(size);
memcpy(x->x_cluster, c, size);
}
/* or perform tracking */
else{
int i,j;
/* find best matches for the first couple of clusters */
for (i=0; i<x->x_nb_clusters - 1; i++){
int closest = 0;
float d_min = cluster_dsquared(x->x_cluster+i, c);
/* get closest cluster */
for (j=1; j<nb_clusters; j++){
float dj = cluster_dsquared(x->x_cluster+i, c+j);
if (dj < d_min){
closest = j;
d_min = dj;
}
}
/* replace reference cluster with closest match */
cluster_copy(x->x_cluster+i, c+closest);
/* shrink matrix (like above) */
nb_clusters--;
cluster_copy(c+closest, c+nb_clusters);
}
/* copy the last cluster */
cluster_copy(x->x_cluster + x->x_nb_clusters - 1, c);
}
/* print the clusters */
post("clusters:");
post("\tN\tcx\tcy");
for (i=0; i<x->x_nb_clusters; i++){
post("\t%d\t%0.2f\t%0.2f",
(int)x->x_cluster[i].N,
x->x_cluster[i].cx,
x->x_cluster[i].cy);
}
}
static void dump_to_array(t_pdp_histo *x)
{
float *vec;
int nbpoints;
t_garray *a;
int i;
int *histo = x->x_histo;
int N = 1 << (x->x_logN);
float scale = 1.0f / (float)(x->x_nb_pixels);
/* dump to array if possible */
if (!x->x_array_sym){
}
/* check if array is valid */
else if (!(a = (t_garray *)pd_findbyclass(x->x_array_sym, garray_class))){
post("pdp_histo: %s: no such array", x->x_array_sym->s_name);
}
/* get data */
else if (!garray_getfloatarray(a, &nbpoints, &vec)){
post("pdp_histo: %s: bad template", x->x_array_sym->s_name);
}
/* scale and dump in array */
else{
N = (nbpoints < N) ? nbpoints : N;
for (i=0; i<N; i++) vec[i] = (float)(histo[i]) * scale * x->x_scale;
//garray_redraw(a);
}
}
static void get_sampleset(t_pdp_histo *x, int log_tmp_size, int threshold)
{
int N = 1 << log_tmp_size;
int mask = N-1;
int index, nbpoints, i;
t_atom a[2];
float scalex = 1.0f / (float)(x->x_width);
float scaley = 1.0f / (float)(x->x_height);
t_symbol *s = gensym("list");
/* store the offsets of the points in a in an oversized array
the oversizing is to eliminate a division and to limit the
searching for a free location after a random index is generated */
int offset[N];
/* float versions of the coordinates */
float fx[x->x_sample_size];
float fy[x->x_sample_size];
float max_x, min_x, max_y, min_y;
/* reset the array */
memset(offset, -1, N * sizeof(int));
/* get the coordinates of the tempsize brightest points
and store them in a random location in the hash */
for (i=0; i<x->x_nb_pixels; i++){
if (x->x_data[i] >= threshold){
/* get a random index */
int ri = random();
//int ri = 0;
/* find an empty spot to store it */
while (-1 != offset[ri & mask]) ri++;
offset[ri & mask] = i;
}
}
/* repack the array to get the requested
sample size at the start */
index = 0;
nbpoints = 0;
while (nbpoints < x->x_sample_size){
while (-1 == offset[index]) index++; // ffwd to next nonepty slot
offset[nbpoints++] = offset[index++]; // move slot
}
/* mark output packet samples */
memset(x->x_data, 0, 2*x->x_nb_pixels);
for (i=0; i<x->x_sample_size; i++){
x->x_data[offset[i]] = 0x7fff;
}
/* send packet to left outlet */
pdp_pass_if_valid(x->x_outlet0, &x->x_packet0);
/* run the clustering algo */
x->x_pixel_offset = offset;
compute_clusters(x);
}
static void get_brightest(t_pdp_histo *x)
{
int i;
int *histo = x->x_histo;
int N = 1 << (x->x_logN);
int index, nsamps;
/* check requested size */
if (x->x_sample_size > x->x_nb_pixels){
post("WARNING: more samples requested than pixels in image");
x->x_sample_size = x->x_nb_pixels;
}
/* find limiting index */
index = N;
nsamps = 0;
while (nsamps < x->x_sample_size){
index--;
nsamps += histo[index];
}
/* status report */
if (x->x_debug){
post("found %d samples between h[%d] and h[%d]", nsamps, index, N-1);
}
/* get a representative set from the candidates
the tempbuf is the rounded log of the nb of samples + 1
so it is at least 50% sparse */
get_sampleset(x, round_up_2log(nsamps) + 1, index << (15-x->x_logN));
}
static void _pdp_histo_perform(t_pdp_histo *x)
{
short int *pp;
int N = 1 << x->x_logN;
int nbpixels = x->x_width * x->x_height, i;
int histo[N];
/* init */
for (i=0; i<N; i++) histo[i] = 0;
/* build histo */
for (i=0; i<nbpixels; i++){
int index = x->x_data[i] >> (15 - x->x_logN);
if (index < 0) index = 0; /* negative -> zero */
histo[index]++;
}
/* save the histo stack location */
x->x_histo = histo;
/* print it */
if (x->x_debug){
post("histogram:");
for (i=0; i<N; i++){
fprintf(stderr, "%d\t", histo[i]);
if (!(i % 10)) post("");
}
post("");
}
/* call the processor */
x->x_process_method(x);
}
// packet is an image/*/* packet or invalid */
static void pdp_histo_perform(t_pdp_histo *x)
{
t_pdp *header0 = pdp_packet_header(x->x_packet0);
void *data0 = pdp_packet_data(x->x_packet0);
if (!header0 || !data0) return;
x->x_width = header0->info.image.width;
x->x_height = header0->info.image.height;
x->x_nb_pixels = x->x_width * x->x_height;
x->x_data = data0;
_pdp_histo_perform(x);
}
static void pdp_histo_input_0(t_pdp_histo *x, t_symbol *s, t_floatarg f)
{
int packet = (int)f;
/* register */
if (s == gensym("register_ro")){
/* replace if not compatible or we are not interpolating */
pdp_packet_mark_unused(x->x_packet0);
x->x_packet0 = pdp_packet_convert_rw(packet, pdp_gensym("image/grey/*"));
}
if (s == gensym("process")){
pdp_histo_perform(x);
}
}
static void pdp_histo_samplesize(t_pdp_histo *x, t_floatarg f)
{
int i = (int)f;
if (i >= x->x_nb_clusters ) x->x_sample_size = i;
}
static void pdp_histo_clusters(t_pdp_histo *x, t_floatarg f)
{
int i = (int)f;
if (i>=2 && i<= x->x_sample_size){
x->x_nb_clusters = i;
if (x->x_cluster) pdp_dealloc(x->x_cluster);
x->x_cluster = 0;
}
}
static void pdp_histo_scale(t_pdp_histo *x, t_floatarg f){x->x_scale = f;}
static void pdp_histo_size(t_pdp_histo *x, t_floatarg f)
{
int i = (int)f;
if (i < 1) return;
x->x_logN = round_up_2log(i);
}
static void pdp_histo_array(t_pdp_histo *x, t_symbol *s)
{
//post("setting symbol %x", s);
x->x_array_sym = s;
}
static void pdp_histo_free(t_pdp_histo *x)
{
pdp_packet_mark_unused(x->x_packet0);
if (x->x_cluster) pdp_dealloc(x->x_cluster);
}
t_class *pdp_histo_class;
void *pdp_histo_new(t_floatarg f)
{
t_pdp_histo *x = (t_pdp_histo *)pd_new(pdp_histo_class);
if (f == 0.0f) f = 64;
pdp_histo_size(x, f);
x->x_packet0 = -1;
x->x_debug = 0;
x->x_sample_size = 16;
x->x_nb_clusters = 3;
x->x_cluster = 0;
return (void *)x;
}
void *pdp_histo_array_new(t_symbol *s, t_float f, t_float f2)
{
t_pdp_histo *x = (t_pdp_histo *)pdp_histo_new(f);
if (f2 == 0.0f) f2 = 1.0f;
pdp_histo_scale(x, f2);
pdp_histo_array(x, s);
x->x_process_method = dump_to_array;
return (void *)x;
}
void *pdp_histo_sample_new(t_float nbsamples, t_float histosize)
{
t_pdp_histo *x;
if (histosize == 0.0f) histosize = 256.0f;
x = (t_pdp_histo *)pdp_histo_new(histosize);
if (nbsamples == 0.0f) nbsamples = 16.0f;
pdp_histo_samplesize(x, nbsamples);
x->x_process_method = get_brightest;
x->x_outlet0 = outlet_new(&x->x_obj, gensym("anything"));
//x->x_outlet1 = outlet_new(&x->x_obj, gensym("anything"));
inlet_new((t_object *)x, (t_pd *)&x->x_obj, gensym("float"), gensym("nbpoints"));
return (void *)x;
}
#ifdef __cplusplus
extern "C"
{
#endif
void pdp_histo_setup(void)
{
pdp_histo_class = class_new(gensym("pdp_histo"), (t_newmethod)pdp_histo_array_new,
(t_method)pdp_histo_free, sizeof(t_pdp_histo), 0, A_DEFSYMBOL, A_DEFFLOAT, A_DEFFLOAT, A_NULL);
class_addcreator((t_newmethod)pdp_histo_sample_new, gensym("pdp_pointcloud"), A_DEFFLOAT, A_DEFFLOAT, A_NULL);
class_addmethod(pdp_histo_class, (t_method)pdp_histo_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL);
class_addmethod(pdp_histo_class, (t_method)pdp_histo_size, gensym("size"), A_FLOAT, A_NULL);
class_addmethod(pdp_histo_class, (t_method)pdp_histo_size, gensym("scale"), A_FLOAT, A_NULL);
class_addmethod(pdp_histo_class, (t_method)pdp_histo_array, gensym("array"), A_SYMBOL, A_NULL);
class_addmethod(pdp_histo_class, (t_method)pdp_histo_samplesize, gensym("nbpoints"), A_FLOAT, A_NULL);
class_addmethod(pdp_histo_class, (t_method)pdp_histo_clusters, gensym("nbclusters"), A_FLOAT, A_NULL);
}
#ifdef __cplusplus
}
#endif
Update of /cvsroot/pure-data/externals/pdp/modules/image_special
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv6756/modules/image_special
Added Files:
Makefile README pdp_array.c pdp_chrot.c pdp_cog.c
pdp_grey2mask.c pdp_histo.c pdp_scale.c pdp_scan.c
pdp_scanxy.c pdp_scope.c
Log Message:
checking in pdp 0.12.4 from http://zwizwa.fartit.com/pd/pdp/pdp-0.12.4.tar.gz
--- NEW FILE: pdp_histo.c ---
/*
* Pure Data Packet module.
* Copyright (c) 2003 by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include "pdp.h"
#include "pdp_base.h"
#include <math.h>
struct _pdp_histo;
typedef void (*t_histo_proc)(struct _pdp_histo *);
typedef struct _pdp_histo
{
t_object x_obj;
t_int x_logN;
t_symbol *x_array_sym;
t_float x_scale;
t_int x_debug;
t_int x_sample_size; /* pointcloud size */
t_histo_proc x_process_method; /* what to do with the histogram */
t_outlet *x_outlet0;
int x_matrix_output;
/* the packet */
int x_packet0;
/* packet data */
short int *x_data;
int x_width;
int x_height;
int x_nb_pixels;
/* histo data for processor: these are stored on the stack */
int *x_histo;
} t_pdp_histo;
static int round_up_2log(int i)
{
int l = 0;
i--;
while (i) {
i >>= 1;
l++;
}
//post("log is %d, 2^n is %d", l, 1 << l);
l = (l < 16) ? l : 15;
return l;
}
static void dump_to_array(t_pdp_histo *x)
{
float *vec;
int nbpoints;
t_garray *a;
int i;
int *histo = x->x_histo;
int N = 1 << (x->x_logN);
float scale = 1.0f / (float)(x->x_nb_pixels);
/* dump to array if possible */
if (!x->x_array_sym){
}
/* check if array is valid */
else if (!(a = (t_garray *)pd_findbyclass(x->x_array_sym, garray_class))){
post("pdp_histo: %s: no such array", x->x_array_sym->s_name);
}
/* get data */
else if (!garray_getfloatarray(a, &nbpoints, &vec)){
post("pdp_histo: %s: bad template", x->x_array_sym->s_name);
}
/* scale and dump in array */
else{
N = (nbpoints < N) ? nbpoints : N;
for (i=0; i<N; i++) vec[i] = (float)(histo[i]) * scale * x->x_scale;
//garray_redraw(a);
}
}
static void get_sampleset(t_pdp_histo *x, int log_tmp_size, int threshold)
{
int N = 1 << log_tmp_size;
int mask = N-1;
int index, nbpoints, i;
t_atom a[2];
double scalex = 1.0f / (double)(x->x_width);
double scaley = 1.0f / (double)(x->x_height);
t_symbol *s = gensym("list");
int matrix_packet;
double *mat_data;
/* store the offsets of the points in a in an oversized array
the oversizing is to eliminate a division and to limit the
searching for a free location after a random index is generated */
int offset[N];
/* reset the array */
memset(offset, -1, N * sizeof(int));
/* get the coordinates of the tempsize brightest points
and store them in a random location in the hash */
for (i=0; i<x->x_nb_pixels; i++){
if (x->x_data[i] >= threshold){
/* get a random index */
int ri = random();
//int ri = 0;
/* find an empty spot to store it */
while (-1 != offset[ri & mask]) ri++;
offset[ri & mask] = i;
}
}
/* repack the array to get the requested
sample size at the start */
index = 0;
nbpoints = 0;
while (nbpoints < x->x_sample_size){
while (-1 == offset[index]) index++; // ffwd to next nonepty slot
offset[nbpoints++] = offset[index++]; // move slot
}
/* MATRIX OUTPUT */
if (x->x_matrix_output){
matrix_packet = pdp_packet_new_matrix(x->x_sample_size, 2, PDP_MATRIX_TYPE_RDOUBLE);
mat_data = pdp_packet_data(matrix_packet);
if (mat_data){
/* build the cluster data struct */
for (i=0; i<x->x_sample_size; i++){
mat_data[2*i] = ((double)(offset[i] % x->x_width)) * scalex;
mat_data[2*i+1] = ((double)(offset[i] / x->x_width)) * scaley;
}
pdp_pass_if_valid(x->x_outlet0, &matrix_packet);
pdp_packet_mark_unused(x->x_packet0);
x->x_packet0 = -1;
}
}
/* IMAGE OUTPUT */
else {
/* get rw copy */
pdp_packet_replace_with_writable(&x->x_packet0);
x->x_data = pdp_packet_data(x->x_packet0);
/* mark output packet samples */
if (x->x_data){
memset(x->x_data, 0, 2*x->x_nb_pixels);
for (i=0; i<x->x_sample_size; i++){
x->x_data[offset[i]] = 0x7fff;
}
}
/* send packet to left outlet */
pdp_pass_if_valid(x->x_outlet0, &x->x_packet0);
}
}
static void get_brightest(t_pdp_histo *x)
{
int i;
int *histo = x->x_histo;
int N = 1 << (x->x_logN);
int index, nsamps;
/* check requested size */
if (x->x_sample_size > x->x_nb_pixels){
post("WARNING: more samples requested than pixels in image");
x->x_sample_size = x->x_nb_pixels;
}
/* find limiting index */
index = N;
nsamps = 0;
while (nsamps < x->x_sample_size){
index--;
nsamps += histo[index];
}
/* status report */
if (x->x_debug){
post("found %d samples between h[%d] and h[%d]", nsamps, index, N-1);
}
/* get a representative set from the candidates
the tempbuf is the rounded log of the nb of samples + 1
so it is at least 50% sparse */
get_sampleset(x, round_up_2log(nsamps) + 1, index << (15-x->x_logN));
}
static void _pdp_histo_perform(t_pdp_histo *x)
{
short int *pp;
int N = 1 << x->x_logN;
int nbpixels = x->x_width * x->x_height, i;
int histo[N];
/* init */
for (i=0; i<N; i++) histo[i] = 0;
/* build histo */
for (i=0; i<nbpixels; i++){
int index = x->x_data[i] >> (15 - x->x_logN);
if (index < 0) index = 0; /* negative -> zero */
histo[index]++;
}
/* save the histo stack location */
x->x_histo = histo;
/* print it */
if (x->x_debug){
post("histogram:");
for (i=0; i<N; i++){
fprintf(stderr, "%d\t", histo[i]);
if (!(i % 10)) post("");
}
post("");
}
/* call the processor */
x->x_process_method(x);
}
// packet is an image/*/* packet or invalid */
static void pdp_histo_perform(t_pdp_histo *x)
{
t_pdp *header0 = pdp_packet_header(x->x_packet0);
void *data0 = pdp_packet_data(x->x_packet0);
if (!header0 || !data0) return;
x->x_width = header0->info.image.width;
x->x_height = header0->info.image.height;
x->x_nb_pixels = x->x_width * x->x_height;
x->x_data = data0;
_pdp_histo_perform(x);
}
static void pdp_histo_input_0(t_pdp_histo *x, t_symbol *s, t_floatarg f)
{
int packet = (int)f;
/* register */
if (s == gensym("register_rw")){
/* replace if not compatible or we are not interpolating */
pdp_packet_mark_unused(x->x_packet0);
x->x_packet0 = pdp_packet_convert_ro(packet, pdp_gensym("image/grey/*"));
}
if (s == gensym("process")){
pdp_histo_perform(x);
}
}
static void pdp_histo_samplesize(t_pdp_histo *x, t_floatarg f)
{
int i = (int)f;
if (i > 0) x->x_sample_size = i;
}
static void pdp_histo_scale(t_pdp_histo *x, t_floatarg f){x->x_scale = f;}
static void pdp_histo_size(t_pdp_histo *x, t_floatarg f)
{
int i = (int)f;
if (i < 1) return;
x->x_logN = round_up_2log(i);
}
static void pdp_histo_array(t_pdp_histo *x, t_symbol *s)
{
//post("setting symbol %x", s);
x->x_array_sym = s;
}
static void pdp_histo_free(t_pdp_histo *x)
{
pdp_packet_mark_unused(x->x_packet0);
}
t_class *pdp_histo_class;
void *pdp_histo_new(t_floatarg f)
{
t_pdp_histo *x = (t_pdp_histo *)pd_new(pdp_histo_class);
if (f == 0.0f) f = 64;
pdp_histo_size(x, f);
x->x_packet0 = -1;
x->x_debug = 0;
x->x_sample_size = 16;
return (void *)x;
}
void *pdp_histo_array_new(t_symbol *s, t_float f, t_float f2)
{
t_pdp_histo *x = (t_pdp_histo *)pdp_histo_new(f);
if (f2 == 0.0f) f2 = 1.0f;
pdp_histo_scale(x, f2);
pdp_histo_array(x, s);
x->x_process_method = dump_to_array;
return (void *)x;
}
void *pdp_histo_sample_new(t_float nbsamples, t_float histosize)
{
t_pdp_histo *x;
if (histosize == 0.0f) histosize = 256.0f;
x = (t_pdp_histo *)pdp_histo_new(histosize);
if (nbsamples == 0.0f) nbsamples = 16.0f;
pdp_histo_samplesize(x, nbsamples);
x->x_process_method = get_brightest;
x->x_outlet0 = outlet_new(&x->x_obj, gensym("anything"));
x->x_matrix_output = 0;
inlet_new((t_object *)x, (t_pd *)&x->x_obj, gensym("float"), gensym("nbpoints"));
return (void *)x;
}
void *pdp_histo_sample_matrix_new(t_float nbsamples, t_float histosize)
{
t_pdp_histo *x = pdp_histo_sample_new(nbsamples, histosize);
if (x) x->x_matrix_output = 1;
return (void *)x;
}
#ifdef __cplusplus
extern "C"
{
#endif
void pdp_histo_setup(void)
{
pdp_histo_class = class_new(gensym("pdp_histo"), (t_newmethod)pdp_histo_array_new,
(t_method)pdp_histo_free, sizeof(t_pdp_histo), 0, A_DEFSYMBOL, A_DEFFLOAT, A_DEFFLOAT, A_NULL);
class_addcreator((t_newmethod)pdp_histo_sample_new, gensym("pdp_pointcloud"), A_DEFFLOAT, A_DEFFLOAT, A_NULL);
class_addcreator((t_newmethod)pdp_histo_sample_matrix_new, gensym("pdp_pointcloud_matrix"), A_DEFFLOAT, A_DEFFLOAT, A_NULL);
class_addmethod(pdp_histo_class, (t_method)pdp_histo_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL);
class_addmethod(pdp_histo_class, (t_method)pdp_histo_size, gensym("size"), A_FLOAT, A_NULL);
class_addmethod(pdp_histo_class, (t_method)pdp_histo_size, gensym("scale"), A_FLOAT, A_NULL);
class_addmethod(pdp_histo_class, (t_method)pdp_histo_array, gensym("array"), A_SYMBOL, A_NULL);
class_addmethod(pdp_histo_class, (t_method)pdp_histo_samplesize, gensym("nbpoints"), A_FLOAT, A_NULL);
}
#ifdef __cplusplus
}
#endif
--- NEW FILE: pdp_scale.c ---
/*
* Pure Data Packet module.
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include "pdp.h"
#include "pdp_resample.h"
typedef struct pdp_scale_struct
{
t_object x_obj;
t_float x_f;
t_outlet *x_outlet0;
int x_packet0;
int x_packet1;
int x_dropped;
int x_queue_id;
unsigned int x_width;
unsigned int x_height;
int x_quality;
} t_pdp_scale;
static void pdp_scale_process_yv12(t_pdp_scale *x)
{
t_pdp *header0 = pdp_packet_header(x->x_packet0);
t_pdp *header1 = pdp_packet_header(x->x_packet1);
void *data0 = pdp_packet_data (x->x_packet0);
void *data1 = pdp_packet_data (x->x_packet1);
unsigned int src_w = header0->info.image.width;
unsigned int src_h = header0->info.image.height;
unsigned int dst_w = header1->info.image.width;
unsigned int dst_h = header1->info.image.height;
short int *src_image = (short int *)data0;
short int *dst_image = (short int *)data1;
unsigned int src_size = src_w*src_h;
unsigned int src_voffset = src_size;
unsigned int src_uoffset = src_size + (src_size>>2);
unsigned int dst_size = dst_w*dst_h;
unsigned int dst_voffset = dst_size;
unsigned int dst_uoffset = dst_size + (dst_size>>2);
if (x->x_quality){
pdp_resample_scale_bilin(src_image, dst_image, src_w, src_h, dst_w, dst_h);
pdp_resample_scale_bilin(src_image+src_voffset, dst_image+dst_voffset, src_w>>1, src_h>>1, dst_w>>1, dst_h>>1);
pdp_resample_scale_bilin(src_image+src_uoffset, dst_image+dst_uoffset, src_w>>1, src_h>>1, dst_w>>1, dst_h>>1);
}
else{
pdp_resample_scale_nn(src_image, dst_image, src_w, src_h, dst_w, dst_h);
pdp_resample_scale_nn(src_image+src_voffset, dst_image+dst_voffset, src_w>>1, src_h>>1, dst_w>>1, dst_h>>1);
pdp_resample_scale_nn(src_image+src_uoffset, dst_image+dst_uoffset, src_w>>1, src_h>>1, dst_w>>1, dst_h>>1);
}
return;
}
static void pdp_scale_process_grey(t_pdp_scale *x)
{
t_pdp *header0 = pdp_packet_header(x->x_packet0);
t_pdp *header1 = pdp_packet_header(x->x_packet1);
void *data0 = pdp_packet_data (x->x_packet0);
void *data1 = pdp_packet_data (x->x_packet1);
unsigned int src_w = header0->info.image.width;
unsigned int src_h = header0->info.image.height;
unsigned int dst_w = header1->info.image.width;
unsigned int dst_h = header1->info.image.height;
short int *src_image = (short int *)data0;
short int *dst_image = (short int *)data1;
if (x->x_quality) pdp_resample_scale_bilin(src_image, dst_image, src_w, src_h, dst_w, dst_h);
else pdp_resample_scale_nn(src_image, dst_image, src_w, src_h, dst_w, dst_h);
return;
}
static void pdp_scale_sendpacket(t_pdp_scale *x)
{
/* delete source packet */
pdp_packet_mark_unused(x->x_packet0);
x->x_packet0 = -1;
/* unregister and propagate if valid dest packet */
pdp_packet_pass_if_valid(x->x_outlet0, &x->x_packet1);
}
static void pdp_scale_process(t_pdp_scale *x)
{
t_pdp_procqueue *q = pdp_queue_get_queue();
t_pdp *header0 = pdp_packet_header(x->x_packet0);
/* check data packets */
if ((header0) && (PDP_IMAGE == header0->type)){
/* if dims are equal, just send the packet */
if ((header0->info.image.width == x->x_width)
&& (header0->info.image.height == x->x_height)){
x->x_packet1 = x->x_packet0;
x->x_packet0 = -1;
pdp_scale_sendpacket(x);
return;
}
/* type hub */
switch(header0->info.image.encoding){
case PDP_IMAGE_YV12:
x->x_packet1 = pdp_packet_new_image_YCrCb(x->x_width, x->x_height);
if(x->x_packet1 == -1){
post("pdp_scale: can't allocate packet");
return;
}
pdp_procqueue_add(q, x, pdp_scale_process_yv12, pdp_scale_sendpacket, &x->x_queue_id);
break;
case PDP_IMAGE_GREY:
x->x_packet1 = pdp_packet_new_image_grey(x->x_width, x->x_height);
if(x->x_packet1 == -1){
post("pdp_scale: can't allocate packet");
return;
}
pdp_procqueue_add(q, x, pdp_scale_process_grey, pdp_scale_sendpacket, &x->x_queue_id);
break;
default:
break;
/* don't know the type, so dont process */
}
}
}
static void pdp_scale_input_0(t_pdp_scale *x, t_symbol *s, t_floatarg f)
{
int p = (int)f;
int passes, i;
if (s== gensym("register_rw")) x->x_dropped = pdp_packet_copy_ro_or_drop(&x->x_packet0, p);
if ((s == gensym("process")) && (-1 != x->x_packet0) && (!x->x_dropped)){
/* add the process method and callback to the process queue */
pdp_scale_process(x);
}
}
static void pdp_scale_width(t_pdp_scale *x, t_floatarg f)
{
int i = (int)f;
if (i < 32) i = 32;
x->x_width = i;
}
static void pdp_scale_height(t_pdp_scale *x, t_floatarg f)
{
int i = (int)f;
if (i < 32) i = 32;
x->x_height = i;
}
static void pdp_scale_dim(t_pdp_scale *x, t_floatarg w, t_floatarg h)
{
pdp_scale_width(x, w);
pdp_scale_height(x, h);
}
static void pdp_scale_quality(t_pdp_scale *x, t_floatarg f)
{
if (f==0) x->x_quality = 0;
if (f==1) x->x_quality = 1;
}
t_class *pdp_scale_class;
void pdp_scale_free(t_pdp_scale *x)
{
t_pdp_procqueue *q = pdp_queue_get_queue();
pdp_procqueue_finish(q, x->x_queue_id);
pdp_packet_mark_unused(x->x_packet0);
pdp_packet_mark_unused(x->x_packet1);
}
void *pdp_scale_new(t_floatarg fw, t_floatarg fh)
{
t_pdp_scale *x = (t_pdp_scale *)pd_new(pdp_scale_class);
x->x_outlet0 = outlet_new(&x->x_obj, &s_anything);
x->x_packet0 = -1;
x->x_packet1 = -1;
x->x_queue_id = -1;
if ((fw != 0.0f) && (fh != 0.0f)) pdp_scale_dim(x, fw, fh);
else pdp_scale_dim(x, 320, 240);
pdp_scale_quality(x, 1);
return (void *)x;
}
#ifdef __cplusplus
extern "C"
{
#endif
void pdp_scale_setup(void)
{
pdp_scale_class = class_new(gensym("pdp_scale"), (t_newmethod)pdp_scale_new,
(t_method)pdp_scale_free, sizeof(t_pdp_scale), 0, A_DEFFLOAT, A_DEFFLOAT, A_NULL);
class_addmethod(pdp_scale_class, (t_method)pdp_scale_quality, gensym("quality"), A_FLOAT, A_NULL);
class_addmethod(pdp_scale_class, (t_method)pdp_scale_width, gensym("width"), A_FLOAT, A_NULL);
class_addmethod(pdp_scale_class, (t_method)pdp_scale_height, gensym("height"), A_FLOAT, A_NULL);
class_addmethod(pdp_scale_class, (t_method)pdp_scale_dim, gensym("dim"), A_FLOAT, A_FLOAT, A_NULL);
class_addmethod(pdp_scale_class, (t_method)pdp_scale_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL);
}
#ifdef __cplusplus
}
#endif
--- NEW FILE: pdp_scanxy.c ---
/*
* Pure Data Packet module.
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include "pdp.h"
#include <math.h>
typedef struct pdp_scanxy_struct
{
t_object x_obj;
t_float x_f;
t_outlet *x_outlet0;
t_outlet *x_outlet1;
int x_packet0;
int x_packet1;
int x_interpolate;
} t_pdp_scanxy;
static t_int *pdp_scanxy_perform(t_int *w)
{
t_pdp_scanxy *x = (t_pdp_scanxy *)(w[1]);
t_int n = (t_int)(w[2]);
t_float *inx = (float *)(w[3]);
t_float *iny = (float *)(w[4]);
t_float *out = (float *)(w[5]);
/* check if valid image */
if (-1 == x->x_packet0){
while (n--) *out++ = 0;
return (w+6);
}
else{
t_pdp *header0 = pdp_packet_header(x->x_packet0);
short int *data0 = (short int *)pdp_packet_data (x->x_packet0);
short int *data1 = (short int *)pdp_packet_data (x->x_packet1);
int width = (float)header0->info.image.width;
int height = (float)header0->info.image.height;
int i;
float scale = 1.0f / 32767.0f;
float scalein = 0x10000;
if (x->x_interpolate && (-1 != x->x_packet1)){
float a_old = 1.0f;
float a_new = 0.0f;
float a_inc = 1.0f / (float)n;
float old, new;
while(n--){
int xxx = ((((int)(scalein * *inx++)) & 0xffff) * width) >> 16;
int yyy = ((((int)(scalein * *iny++)) & 0xffff) * height) >> 16;
int offset = yyy*width+xxx;
new = ((float)(data0[offset])) * scale;
old = ((float)(data1[offset])) * scale;
*out++ = a_old * old + a_new * new;
a_new += a_inc;
a_old -= a_inc;
}
pdp_packet_mark_unused(x->x_packet1);
x->x_packet1 = -1;
}
else{
while(n--){
int xxx = ((((int)(scalein * *inx++)) & 0xffff) * width) >> 16;
int yyy = ((((int)(scalein * *iny++)) & 0xffff) * height) >> 16;
int offset = yyy*width+xxx;
*out++ = ((float)(data0[offset])) * scale;
}
}
return (w+6);
}
}
static void pdp_scanxy_input_0(t_pdp_scanxy *x, t_symbol *s, t_floatarg f)
{
int packet = (int)f;
/* register */
if (s== gensym("register_ro")){
t_pdp *header = pdp_packet_header(packet);
if (!header) return;
if (PDP_IMAGE != header->type) return;
if ((header->info.image.encoding != PDP_IMAGE_YV12) && (header->info.image.encoding != PDP_IMAGE_GREY)) return;
/* replace if not compatible or we are not interpolating */
if (!x->x_interpolate || (!pdp_packet_image_compat(x->x_packet0, packet))){
pdp_packet_mark_unused(x->x_packet0);
x->x_packet0 = pdp_packet_copy_ro(packet);
}
/* otherwize keep the old one */
else{
pdp_packet_mark_unused(x->x_packet1);
x->x_packet1 = x->x_packet0;
x->x_packet0 = pdp_packet_copy_ro(packet);
}
}
/* pass packet */
if (s== gensym("process")){
//if (-1 != x->x_packet0) outlet_pdp (x->x_outlet0, x->x_packet0);
}
}
static void pdp_scanxy_dsp (t_pdp_scanxy *x, t_signal **sp)
{
dsp_add(pdp_scanxy_perform, 5, x, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec);
}
static void pdp_scanxy_interpolate(t_pdp_scanxy *x, t_floatarg f)
{
if (0.0 == f){
x->x_interpolate = 0;
pdp_packet_mark_unused(x->x_packet1);
}
if (1.0 == f) x->x_interpolate = 1;
}
static void pdp_scanxy_free(t_pdp_scanxy *x)
{
pdp_packet_mark_unused(x->x_packet0);
}
t_class *pdp_scanxy_class;
void *pdp_scanxy_new(void)
{
t_pdp_scanxy *x = (t_pdp_scanxy *)pd_new(pdp_scanxy_class);
inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("signal"), gensym("signal"));
x->x_outlet1 = outlet_new(&x->x_obj, &s_signal);
x->x_packet0 = -1;
x->x_packet1 = -1;
pdp_scanxy_interpolate(x, 0);
return (void *)x;
}
#ifdef __cplusplus
extern "C"
{
#endif
void pdp_scanxy_setup(void)
{
pdp_scanxy_class = class_new(gensym("pdp_scanxy~"), (t_newmethod)pdp_scanxy_new,
(t_method)pdp_scanxy_free, sizeof(t_pdp_scanxy), 0, A_NULL);
CLASS_MAINSIGNALIN(pdp_scanxy_class, t_pdp_scanxy, x_f);
class_addmethod(pdp_scanxy_class, (t_method)pdp_scanxy_interpolate, gensym("interpolate"), A_FLOAT, A_NULL);
class_addmethod(pdp_scanxy_class, (t_method)pdp_scanxy_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL);
class_addmethod(pdp_scanxy_class, (t_method)pdp_scanxy_dsp, gensym("dsp"), A_NULL);
}
#ifdef __cplusplus
}
#endif
--- NEW FILE: pdp_grey2mask.c ---
/*
* Pure Data Packet module.
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/* this module converts a greyscale image or the luma channel of a colour image
to a colour image intensity mask, usable for multiplication */
#include "pdp.h"
#include "pdp_resample.h"
typedef struct pdp_grey2mask_struct
{
t_object x_obj;
t_float x_f;
t_outlet *x_outlet0;
int x_packet0;
int x_dropped;
int x_queue_id;
} t_pdp_grey2mask;
static void pdp_grey2mask_process_grey(t_pdp_grey2mask *x)
{
t_pdp *header = pdp_packet_header(x->x_packet0);
short int *data = (short int *)pdp_packet_data (x->x_packet0);
t_pdp *newheader = 0;
short int *newdata = 0;
int newpacket = -1;
unsigned int w = header->info.image.width;
unsigned int h = header->info.image.height;
unsigned int size = w*h;
unsigned int totalnbpixels = size;
unsigned int u_offset = size;
unsigned int v_offset = size + (size>>2);
unsigned int row, col;
newpacket = pdp_packet_new_image_YCrCb(w, h);
newheader = pdp_packet_header(newpacket);
newdata = (short int *)pdp_packet_data(newpacket);
/* copy luma channel */
memcpy(newdata, data, size * sizeof(s16));
/* subsample luma -> chroma channel */
pdp_resample_halve(data, newdata+u_offset, w, h);
/* copy this to the other chroma channel */
memcpy(newdata+v_offset, newdata+u_offset, (size>>2)*sizeof(s16));
/* delete source packet and replace with new packet */
pdp_packet_mark_unused(x->x_packet0);
x->x_packet0 = newpacket;
return;
}
static void pdp_grey2mask_process_yv12(t_pdp_grey2mask *x)
{
/* process only the luminance channel */
pdp_grey2mask_process_grey(x);
}
static void pdp_grey2mask_process(t_pdp_grey2mask *x)
{
int encoding;
t_pdp *header = 0;
/* check if image data packets are compatible */
if ( (header = pdp_packet_header(x->x_packet0))
&& (PDP_IMAGE == header->type)){
/* pdp_grey2mask_process inputs and write into active inlet */
switch(pdp_packet_header(x->x_packet0)->info.image.encoding){
case PDP_IMAGE_YV12:
pdp_grey2mask_process_yv12(x);
break;
case PDP_IMAGE_GREY:
pdp_grey2mask_process_grey(x);
break;
default:
/* don't know the type, so dont pdp_grey2mask_process */
break;
}
}
}
static void pdp_grey2mask_sendpacket(t_pdp_grey2mask *x)
{
/* unregister and propagate if valid packet */
pdp_packet_pass_if_valid(x->x_outlet0, &x->x_packet0);
}
static void pdp_grey2mask_input_0(t_pdp_grey2mask *x, t_symbol *s, t_floatarg f)
{
int p = (int)f;
if (s== gensym("register_ro")) x->x_dropped = pdp_packet_copy_ro_or_drop(&x->x_packet0, p);
if ((s == gensym("process")) && (-1 != x->x_packet0) && (!x->x_dropped)){
/* add the process method and callback to the process queue */
//pdp_queue_add(x, pdp_grey2mask_process, pdp_grey2mask_sendpacket, &x->x_queue_id);
// since the process method creates a packet, this is not processed in the thread
// $$$TODO: fix this
pdp_grey2mask_process(x);
pdp_grey2mask_sendpacket(x);
}
}
static void pdp_grey2mask_free(t_pdp_grey2mask *x)
{
t_pdp_procqueue *q = pdp_queue_get_queue();
pdp_procqueue_finish(q, x->x_queue_id);
pdp_packet_mark_unused(x->x_packet0);
}
t_class *pdp_grey2mask_class;
void *pdp_grey2mask_new(void)
{
int i;
t_pdp_grey2mask *x = (t_pdp_grey2mask *)pd_new(pdp_grey2mask_class);
x->x_outlet0 = outlet_new(&x->x_obj, &s_anything);
x->x_packet0 = -1;
x->x_queue_id = -1;
return (void *)x;
}
#ifdef __cplusplus
extern "C"
{
#endif
void pdp_grey2mask_setup(void)
{
pdp_grey2mask_class = class_new(gensym("pdp_grey2mask"), (t_newmethod)pdp_grey2mask_new,
(t_method)pdp_grey2mask_free, sizeof(t_pdp_grey2mask), 0, A_NULL);
class_addmethod(pdp_grey2mask_class, (t_method)pdp_grey2mask_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL);
}
#ifdef __cplusplus
}
#endif
--- NEW FILE: pdp_scan.c ---
/*
* Pure Data Packet module.
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include "pdp.h"
#include "pdp_mmx.h"
#include <math.h>
#define PDP_SCAN_COSTABLE_SIZE 1024
static float pdp_cos[PDP_SCAN_COSTABLE_SIZE];
typedef struct pdp_scan_struct
{
t_object x_obj;
t_float x_f;
t_outlet *x_outlet0;
t_outlet *x_outlet1;
float x_centerx;
float x_centery;
float x_sizeh;
float x_sizev;
int x_packet0;
int x_packet1;
int x_interpolate;
} t_pdp_scan;
static t_int *pdp_scan_perform(t_int *w)
{
t_pdp_scan *x = (t_pdp_scan *)(w[1]);
t_int n = (t_int)(w[2]);
t_float *in = (float *)(w[3]);
t_float *out = (float *)(w[4]);
/* check if valid image */
if (-1 == x->x_packet0){
while (n--) *out++ = 0;
return (w+5);
}
else{
t_pdp *header0 = pdp_packet_header(x->x_packet0);
short int *data0 = (short int *)pdp_packet_data (x->x_packet0);
short int *data1 = (short int *)pdp_packet_data (x->x_packet1);
int width = (float)header0->info.image.width;
float widthm1 = (float)header0->info.image.width - 1;
float heightm1 = (float)header0->info.image.height - 1;
int i;
float scale = 1.0f / 32767.0f;
if (x->x_interpolate && (-1 != x->x_packet1)){
float a_old = 1.0f;
float a_new = 0.0f;
float a_inc = 1.0f / (float)n;
float old, new;
while(n--){
float phase = *in++;
int iphase = (int)(phase * PDP_SCAN_COSTABLE_SIZE);
float c = pdp_cos[iphase & (PDP_SCAN_COSTABLE_SIZE - 1)];
float s = pdp_cos[(iphase - (PDP_SCAN_COSTABLE_SIZE>>1)) & (PDP_SCAN_COSTABLE_SIZE - 1)];
int xxx = (int)((x->x_centerx + x->x_sizeh * c) * widthm1);
int yyy = (int)((x->x_centery + x->x_sizev * c) * heightm1);
int offset = yyy*width+xxx;
new = ((float)(data0[offset])) * scale;
old = ((float)(data1[offset])) * scale;
*out++ = a_old * old + a_new * new;
a_new += a_inc;
a_old -= a_inc;
}
pdp_packet_mark_unused(x->x_packet1);
x->x_packet1 = -1;
}
else{
while(n--){
float phase = *in++;
int iphase = (int)(phase * PDP_SCAN_COSTABLE_SIZE);
float c = pdp_cos[iphase & (PDP_SCAN_COSTABLE_SIZE - 1)];
float s = pdp_cos[(iphase - (PDP_SCAN_COSTABLE_SIZE>>1)) & (PDP_SCAN_COSTABLE_SIZE - 1)];
int xxx = (int)((x->x_centerx + x->x_sizeh * c) * widthm1);
int yyy = (int)((x->x_centery + x->x_sizev * c) * heightm1);
*out++ = ((float)(data0[yyy*width+xxx])) * scale;
}
}
return (w+5);
}
}
static void pdp_scan_input_0(t_pdp_scan *x, t_symbol *s, t_floatarg f)
{
int packet = (int)f;
/* register */
if (s== gensym("register_ro")){
t_pdp *header = pdp_packet_header(packet);
if (!header) return;
if (PDP_IMAGE != header->type) return;
if ((header->info.image.encoding != PDP_IMAGE_YV12) && (header->info.image.encoding != PDP_IMAGE_GREY)) return;
/* replace if not compatible or we are not interpolating */
if (!x->x_interpolate || (!pdp_packet_image_compat(x->x_packet0, packet))){
pdp_packet_mark_unused(x->x_packet0);
x->x_packet0 = pdp_packet_copy_ro(packet);
}
/* otherwize keep the old one */
else{
pdp_packet_mark_unused(x->x_packet1);
x->x_packet1 = x->x_packet0;
x->x_packet0 = pdp_packet_copy_ro(packet);
}
}
/* pass packet */
if (s== gensym("process")){
//if (-1 != x->x_packet0) outlet_pdp (x->x_outlet0, x->x_packet0);
}
}
static void pdp_scan_dsp (t_pdp_scan *x, t_signal **sp)
{
dsp_add(pdp_scan_perform, 4, x, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec);
}
static void pdp_scan_interpolate(t_pdp_scan *x, t_floatarg f)
{
if (0.0 == f){
x->x_interpolate = 0;
pdp_packet_mark_unused(x->x_packet1);
}
if (1.0 == f) x->x_interpolate = 1;
}
static void pdp_scan_free(t_pdp_scan *x)
{
pdp_packet_mark_unused(x->x_packet0);
}
t_class *pdp_scan_class;
void *pdp_scan_new(void)
{
t_pdp_scan *x = (t_pdp_scan *)pd_new(pdp_scan_class);
//x->x_outlet0 = outlet_new(&x->x_obj, &s_anything);
x->x_outlet1 = outlet_new(&x->x_obj, &s_signal);
x->x_packet0 = -1;
x->x_packet1 = -1;
x->x_centerx = 0.5f;
x->x_centery = 0.5f;
x->x_sizeh = 0.3;
x->x_sizev = 0.3;
pdp_scan_interpolate(x, 0);
return (void *)x;
}
#ifdef __cplusplus
extern "C"
{
#endif
void pdp_scan_setup(void)
{
int i;
for (i=0; i<PDP_SCAN_COSTABLE_SIZE; i++)
pdp_cos[i] = cos((double)(i) * 2 * M_PI / PDP_SCAN_COSTABLE_SIZE);
pdp_scan_class = class_new(gensym("pdp_scan~"), (t_newmethod)pdp_scan_new,
(t_method)pdp_scan_free, sizeof(t_pdp_scan), 0, A_NULL);
CLASS_MAINSIGNALIN(pdp_scan_class, t_pdp_scan, x_f);
class_addmethod(pdp_scan_class, (t_method)pdp_scan_interpolate, gensym("interpolate"), A_FLOAT, A_NULL);
class_addmethod(pdp_scan_class, (t_method)pdp_scan_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL);
class_addmethod(pdp_scan_class, (t_method)pdp_scan_dsp, gensym("dsp"), A_NULL);
}
#ifdef __cplusplus
}
#endif
--- NEW FILE: Makefile ---
current: all_modules
include ../../Makefile.config
PDP_MOD = pdp_chrot.o pdp_grey2mask.o pdp_scale.o pdp_scan.o \
pdp_scanxy.o pdp_scope.o \
pdp_cog.o pdp_array.o $(PDP_IMAGE_SPECIAL)
# build special case image (and sound) processing modules
all_modules: $(PDP_MOD)
clean:
rm -f *~
rm -f *.o
--- NEW FILE: pdp_cog.c ---
/*
* Pure Data Packet module.
* Copyright (c) 2003 by Johannes Taelman <johannes.taelman(a)rug.ac.be>
* API updates by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include "pdp.h"
#include "pdp_base.h"
#include <math.h>
typedef struct pdp_cog_struct
{
t_object x_obj;
t_float x_f;
t_outlet *x_outlet0;
t_outlet *x_outlet1;
t_outlet *x_outlet2;
t_outlet *x_outlet3;
t_outlet *x_outlet4;
int x_packet0;
int x_threshold;
int x_do_thresholding;
} t_pdp_cog;
static void _pdp_cog_perform(t_pdp_cog *x, int width, int height, short int *data0)
{
short int *pp;
int nbpixels;
int y;
int h,v;
int rowsums[width];
int columnsums[height];
float vsum,vvar,vcog,vstd;
float hsum,hvar,hcog,hstd;
pp=data0;
nbpixels=width*height;
for (h=0;h<width;h++)
columnsums[h]=0;
/* create column & row sums from thresholded data */
if (x->x_do_thresholding){
for (v=0;v<height;v++){
int rs=0;
for (h=0;h<width;h++){
int d=*pp++;
d=(d>x->x_threshold) ? d : ((d<-x->x_threshold)?(-d):0);
columnsums[h]+= d;
rs+=d;
}
rowsums[v]=rs;
}
}
/* don't perform thresholding */
else{
for (v=0;v<height;v++){
int rs=0;
for (h=0;h<width;h++){
int d=*pp++;
columnsums[h]+= d;
rs+=d;
}
rowsums[v]=rs;
}
}
/* compute vertical mean and standard dev */
vsum=1;
vvar=height*height/4;
vcog=height/2;
for (v=0;v<height;v++){
float d=rowsums[v];
vsum+=d;
vcog+=d*v;
}
vcog/=vsum;
for (v=0;v<height;v++){
float d=rowsums[v];
float f=v-vcog;
vvar+=d*f*f;
}
vstd=sqrt(vvar/vsum)/height;
/* compute horizontal meaan and standard dev */
hsum=1;
hvar=width*width/4;
hcog=width/2;
for (h=0;h<width;h++){
float d=columnsums[h];
hsum+=d;
hcog+=d*h;
}
hcog/=hsum;
for (h=0;h<width;h++){
float d=columnsums[h];
float f=h-hcog;
hvar+=d*f*f;
}
hstd=sqrt(hvar/hsum)/width;
/* pass it on */
outlet_float(x->x_outlet4,vstd);
outlet_float(x->x_outlet3,hstd);
outlet_float(x->x_outlet2,vcog/height);
outlet_float(x->x_outlet1,hcog/width);
outlet_float(x->x_outlet0,(1.0f / (float)(0x7fff)) * hsum/(height*width));
}
// packet is an image/*/* packet or invalid */
static void pdp_cog_perform(t_pdp_cog *x)
{
t_pdp *header0 = pdp_packet_header(x->x_packet0);
void *data0 = pdp_packet_data(x->x_packet0);
if (!header0 || !data0) return;
_pdp_cog_perform(x,
header0->info.image.width,
header0->info.image.height,
data0);
}
static void pdp_cog_input_0(t_pdp_cog *x, t_symbol *s, t_floatarg f)
{
int packet = (int)f;
/* register */
if (s == gensym("register_ro")){
/* replace if not compatible or we are not interpolating */
pdp_packet_mark_unused(x->x_packet0);
x->x_packet0 = pdp_packet_convert_ro(packet, pdp_gensym("image/*/*"));
}
if (s == gensym("process")){
pdp_cog_perform(x);
}
}
static void pdp_cog_threshold(t_pdp_cog *x, t_floatarg f)
{
x->x_threshold=(int) (f * ((float) 0x7fff));
}
static void pdp_cog_free(t_pdp_cog *x)
{
pdp_packet_mark_unused(x->x_packet0);
}
t_class *pdp_cog_class;
void *pdp_cog_new(void)
{
t_pdp_cog *x = (t_pdp_cog *)pd_new(pdp_cog_class);
x->x_outlet0 = outlet_new(&x->x_obj, &s_float);
x->x_outlet1 = outlet_new(&x->x_obj, &s_float);
x->x_outlet2 = outlet_new(&x->x_obj, &s_float);
x->x_outlet3 = outlet_new(&x->x_obj, &s_float);
x->x_outlet4 = outlet_new(&x->x_obj, &s_float);
x->x_packet0 = -1;
x->x_do_thresholding = 0;
return (void *)x;
}
void *pdp_cog_abs_thresh_new(t_floatarg f)
{
t_pdp_cog *x = (t_pdp_cog *)pdp_cog_new();
inlet_new((void *)x, &x->x_obj.ob_pd, gensym("float"),gensym("threshold"));
pdp_cog_threshold(x, f);
x->x_do_thresholding = 1;
return (void *)x;
}
#ifdef __cplusplus
extern "C"
{
#endif
void pdp_cog_setup(void)
{
pdp_cog_class = class_new(gensym("pdp_cog"), (t_newmethod)pdp_cog_new,
(t_method)pdp_cog_free, sizeof(t_pdp_cog), 0,A_NULL);
class_addcreator((t_newmethod)pdp_cog_abs_thresh_new, gensym("pdp_cog_abs_thresh"), A_DEFFLOAT, A_NULL);
class_addmethod(pdp_cog_class, (t_method)pdp_cog_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL);
class_addmethod(pdp_cog_class, (t_method)pdp_cog_threshold, gensym("threshold"),A_DEFFLOAT, A_NULL);
}
#ifdef __cplusplus
}
#endif
--- NEW FILE: README ---
This directory contains image processors that don't fit into the basic and io categories.
--- NEW FILE: pdp_array.c ---
/*
* Pure Data Packet module.
* Copyright (c) 2003 by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <math.h>
#include "pdp.h"
#include "pdp_base.h"
typedef struct _pdp_array
{
t_object x_obj;
t_symbol *x_array_sym;
t_outlet *x_outlet; // for array->pdp
t_int x_rows;
/* the packet */
int x_packet0;
} t_pdp_array;
static void pdp_array_bang(t_pdp_array *x)
{
post("not implemented");
}
static void pdp_array_input_0(t_pdp_array *x, t_symbol *s, t_floatarg f)
{
int packet = (int)f;
/* register */
if (s == gensym("register_ro")){
/* replace if not compatible or we are not interpolating */
pdp_packet_mark_unused(x->x_packet0);
x->x_packet0 = pdp_packet_convert_ro(packet, pdp_gensym("image/grey/*"));
}
/* process */
if (s == gensym("process")){
float *vec;
int nbpoints;
t_garray *a;
t_pdp *header = pdp_packet_header(x->x_packet0);
short int *data = pdp_packet_data(x->x_packet0);
if (!header || !data) return;
/* dump to array if possible */
if (!x->x_array_sym){
}
/* check if array is valid */
else if (!(a = (t_garray *)pd_findbyclass(x->x_array_sym, garray_class))){
post("pdp_array: %s: no such array", x->x_array_sym->s_name);
}
/* get data */
else if (!garray_getfloatarray(a, &nbpoints, &vec)){
post("pdp_array: %s: bad template", x->x_array_sym->s_name);
}
/* scale and dump in array */
else{
int i;
int w = header->info.image.width;
int h = header->info.image.height;
int N = w*h;
N = (nbpoints < N) ? nbpoints : N;
/* scan rows */
if (x->x_rows){
for (i=0; i<N; i++)
vec[i] = (float)data[i] * (1.0f / (float)0x8000);
}
/* scan columns */
else{
for (i=0; i<N; i++) {
int x = i / h;
int y = i % h;
vec[i] = (float)data[x+(h-y-1)*w] * (1.0f / (float)0x8000);
}
}
//garray_redraw(a);
}
}
}
static void pdp_array_array(t_pdp_array *x, t_symbol *s)
{
//post("setting symbol %x", s);
x->x_array_sym = s;
x->x_packet0 = -1;
}
static void pdp_array_free(t_pdp_array *x)
{
pdp_packet_mark_unused(x->x_packet0);
}
t_class *pdp_array2grey_class;
t_class *pdp_grey2array_class;
void *pdp_array2grey_new(t_symbol *s, t_symbol *r)
{
t_pdp_array *x = (t_pdp_array *)pd_new(pdp_array2grey_class);
pdp_array_array(x, s);
return (void *)x;
}
void *pdp_grey2array_new(t_symbol *s, t_symbol *r)
{
t_pdp_array *x = (t_pdp_array *)pd_new(pdp_grey2array_class);
pdp_array_array(x, s);
if (r == gensym("rows")){
x->x_rows = 1;
post("pdp_grey2array: scanning rows");
}
else {
x->x_rows = 0;
post("pdp_grey2array: scanning columns");
}
return (void *)x;
}
#ifdef __cplusplus
extern "C"
{
#endif
void pdp_array_setup(void)
{
pdp_array2grey_class = class_new(gensym("pdp_array2grey"),
(t_newmethod)pdp_array2grey_new,
(t_method)pdp_array_free,
sizeof(t_pdp_array),
0, A_DEFSYMBOL, A_DEFSYMBOL, A_NULL);
pdp_grey2array_class = class_new(gensym("pdp_grey2array"),
(t_newmethod)pdp_grey2array_new,
(t_method)pdp_array_free,
sizeof(t_pdp_array),
0, A_DEFSYMBOL, A_DEFSYMBOL, A_NULL);
/* packet input */
class_addmethod(pdp_grey2array_class,
(t_method)pdp_array_input_0,
gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL);
/* bang method */
class_addmethod(pdp_array2grey_class,
(t_method)pdp_array_bang, gensym("bang"), A_NULL);
/* bookkeeping */
class_addmethod(pdp_array2grey_class, (t_method)pdp_array_array,
gensym("array"), A_SYMBOL, A_NULL);
class_addmethod(pdp_grey2array_class, (t_method)pdp_array_array,
gensym("array"), A_SYMBOL, A_NULL);
}
#ifdef __cplusplus
}
#endif
--- NEW FILE: pdp_scope.c ---
/*
* Pure Data Packet module.
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include "pdp.h"
#include <string.h>
#define BUFSIZE 2048
typedef struct pdp_scope_data
{
short int random_seed[4];
}t_pdp_scope_data;
typedef struct pdp_scope_struct
{
t_object x_obj;
t_float x_f;
t_outlet *x_outlet0;
t_pdp_scope_data *x_data;
int x_packet0;
int x_queue_id;
int x_pdp_image_type;
unsigned int x_width;
unsigned int x_height;
float *x_buffer;
int x_needle;
} t_pdp_scope;
void pdp_scope_type(t_pdp_scope *x, t_symbol *s)
{
if (gensym("yv12") == s) {x->x_pdp_image_type = PDP_IMAGE_YV12; return;}
if (gensym("grey") == s) {x->x_pdp_image_type = PDP_IMAGE_GREY; return;}
x->x_pdp_image_type = -1;
}
static void pdp_scope_createpacket_yv12(t_pdp_scope *x)
{
t_pdp *header;
unsigned int w = x->x_width;
unsigned int h = x->x_height;
unsigned int size = w*h;
unsigned int totalnbpixels = size + (size >> 1);
unsigned int packet_size = totalnbpixels << 1;
x->x_packet0 = pdp_packet_new_image_YCrCb(w, h);
if(x->x_packet0 == -1){
post("pdp_scope: can't allocate packet");
return;
}
header = pdp_packet_header(x->x_packet0);
memset(pdp_packet_data(x->x_packet0), 0, packet_size);
}
static void pdp_scope_generate_yv12(t_pdp_scope *x)
{
unsigned int w = x->x_width;
unsigned int h = x->x_height;
unsigned int size = w*h;
unsigned int totalnbpixels = size + (size >> 1);
short int *data = (short int *) pdp_packet_data(x->x_packet0);
unsigned int i;
int offset = x->x_needle;
int val;
unsigned int y;
float fh2 = (float)(h/2);
if (!data) return;
for (i=0; i<w; i++){
y = (h/2) + (int)(fh2 * -x->x_buffer[(offset - w + i) & (BUFSIZE - 1)]);
if (y>=h) y = h-1;
data[i + y*w] = 0x7fff;
}
return;
}
static void pdp_scope_createpacket_grey(t_pdp_scope *x)
{
t_pdp *header;
short int *data;
unsigned int w = x->x_width;
unsigned int h = x->x_height;
unsigned int size = w*h;
unsigned int totalnbpixels = size;
unsigned int packet_size = totalnbpixels << 1;
/* create new packet */
x->x_packet0 = pdp_packet_new_image_grey(w,h);
if(x->x_packet0 == -1){
post("pdp_scope: can't allocate packet");
return;
}
header = pdp_packet_header(x->x_packet0);
data = (short int *) pdp_packet_data(x->x_packet0);
memset(pdp_packet_data(x->x_packet0), 0, packet_size);
}
static void pdp_scope_generate_grey(t_pdp_scope *x)
{
unsigned int w = x->x_width;
unsigned int h = x->x_height;
unsigned int totalnbpixels = x->x_width * x->x_height;
short int *data = (short int *) pdp_packet_data(x->x_packet0);
unsigned int i;
int offset = x->x_needle;
int val;
unsigned int y;
float fh2 = (float)(h/2);
if (!data) return;
for (i=0; i<w; i++){
y = (h/2) + (int)(fh2 * -x->x_buffer[(offset - w + i) & (BUFSIZE - 1)]);
if (y>=h) y = h-1;
data[i + y*w] = 0x7fff;
}
return;
}
static void pdp_scope_sendpacket(t_pdp_scope *x)
{
/* propagate if valid */
pdp_packet_pass_if_valid(x->x_outlet0, &x->x_packet0);
}
static void pdp_scope_bang(t_pdp_scope *x)
{
int encoding;
/* if we have an active packet, don't do anything */
if (-1 != x->x_packet0) return;
switch(x->x_pdp_image_type){
case PDP_IMAGE_YV12:
pdp_scope_createpacket_yv12(x); // don't create inside thread!!!
pdp_scope_generate_yv12(x);
pdp_scope_sendpacket(x);
//pdp_queue_add(x, pdp_scope_generate_yv12, pdp_scope_sendpacket, &x->x_queue_id);
break;
case PDP_IMAGE_GREY:
pdp_scope_createpacket_grey(x); // don't create inside thread!!!
pdp_scope_generate_grey(x);
pdp_scope_sendpacket(x);
//pdp_queue_add(x, pdp_scope_generate_grey, pdp_scope_sendpacket, &x->x_queue_id);
break;
default:
break;
}
/* release the packet */
}
static void pdp_scope_dim(t_pdp_scope *x, t_floatarg w, t_floatarg h)
{
if (w<32.0f) w = 32.0f;
if (h<32.0f) h = 32.0f;
x->x_width = (unsigned int)w;
x->x_height = (unsigned int)h;
}
static void pdp_scope_free(t_pdp_scope *x)
{
/* remove callback from process queue */
t_pdp_procqueue *q = pdp_queue_get_queue();
pdp_procqueue_finish(q, x->x_queue_id);
/* tidy up */
pdp_packet_mark_unused(x->x_packet0);
pdp_dealloc(x->x_data);
}
static t_int *pdp_scope_perform(t_int *w)
{
t_float *in = (float *)(w[3]);
t_pdp_scope *x = (t_pdp_scope *)(w[1]);
t_int n = (t_int)(w[2]);
t_int i;
t_int offset = x->x_needle;
for (i=0; i<n; i++)
x->x_buffer[(offset+i)&(BUFSIZE-1)] = in[i];
x->x_needle = (offset + n ) & (BUFSIZE - 1);
return (w+4);
}
static void pdp_scope_dsp(t_pdp_scope *x, t_signal **sp)
{
dsp_add(pdp_scope_perform, 3, x, sp[0]->s_n, sp[0]->s_vec);
}
t_class *pdp_scope_class;
void *pdp_scope_new(void)
{
int i;
t_pdp_scope *x = (t_pdp_scope *)pd_new(pdp_scope_class);
x->x_outlet0 = outlet_new(&x->x_obj, &s_anything);
x->x_packet0 = -1;
x->x_queue_id = -1;
x->x_width = 320;
x->x_height = 240;
x->x_f = 0.0;
x->x_data = (t_pdp_scope_data *)pdp_alloc(sizeof(t_pdp_scope_data));
pdp_scope_type(x, gensym("yv12"));
x->x_buffer = (float *)pdp_alloc(sizeof(float) * BUFSIZE);
x->x_needle = 0;
return (void *)x;
}
#ifdef __cplusplus
extern "C"
{
#endif
void pdp_scope_setup(void)
{
pdp_scope_class = class_new(gensym("pdp_scope~"), (t_newmethod)pdp_scope_new,
(t_method)pdp_scope_free, sizeof(t_pdp_scope), 0, A_NULL);
CLASS_MAINSIGNALIN(pdp_scope_class, t_pdp_scope, x_f);
class_addmethod(pdp_scope_class, (t_method)pdp_scope_type, gensym("type"), A_SYMBOL, A_NULL);
class_addmethod(pdp_scope_class, (t_method)pdp_scope_dim, gensym("dim"), A_FLOAT, A_FLOAT, A_NULL);
class_addmethod(pdp_scope_class, (t_method)pdp_scope_bang, gensym("bang"), A_NULL);
class_addmethod(pdp_scope_class, (t_method)pdp_scope_dsp, gensym("dsp"), 0);
}
#ifdef __cplusplus
}
#endif
--- NEW FILE: pdp_chrot.c ---
/*
* Pure Data Packet module.
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include "pdp.h"
#include "pdp_base.h"
#include <math.h>
typedef struct pdp_chrot_struct
{
t_pdp_base x_base;
float x_matrix[4];
void *x_crot2d;
} t_pdp_chrot;
static void pdp_chrot_process(t_pdp_chrot *x)
{
int packet;
t_pdp *header;
void *data;
unsigned int w,h,size,v_offset;
short int *idata;
/* get packet & info */
packet = pdp_base_get_packet(x, 0);
header = pdp_packet_header(packet);
data = pdp_packet_data (packet);
/* only process if we have a vlid yv12 image */
if ((header) && (PDP_IMAGE == header->type) && (PDP_IMAGE_YV12 == header->info.image.encoding)){
w = header->info.image.width;
h = header->info.image.height;
size = w*h;
v_offset = size;
idata = (short int *)data;
/* color rotation for 2 colour planes */
pdp_imageproc_crot2d_process(x->x_crot2d, idata + v_offset, w>>1, h>>1);
}
return;
}
static void pdp_chrot_setelement(t_pdp_chrot *x, int element, float f)
{
x->x_matrix[element] = f;
}
static void pdp_chrot_angle_radians(t_pdp_chrot *x, t_floatarg angle)
{
float c = cos(angle);
float s = sin(angle);
pdp_chrot_setelement(x, 0, c);
pdp_chrot_setelement(x, 1, s);
pdp_chrot_setelement(x, 2, -s);
pdp_chrot_setelement(x, 3, c);
pdp_imageproc_crot2d_setmatrix(x->x_crot2d, x->x_matrix);
}
static void pdp_chrot_angle_degrees(t_pdp_chrot *x, t_floatarg angle)
{
pdp_chrot_angle_radians(x, (angle * (M_PI / 180.f)));
}
static void pdp_chrot_free(t_pdp_chrot *x)
{
pdp_base_free(x);
pdp_imageproc_crot2d_delete(x->x_crot2d);
}
t_class *pdp_chrot_class;
void *pdp_chrot_new(t_floatarg f)
{
t_pdp_chrot *x = (t_pdp_chrot *)pd_new(pdp_chrot_class);
pdp_base_init(x);
pdp_base_add_gen_inlet(x, gensym("float"), gensym("angle"));
pdp_base_add_pdp_outlet(x);
pdp_base_set_process_method(x, (t_pdp_method)pdp_chrot_process);
x->x_crot2d = pdp_imageproc_crot2d_new();
pdp_chrot_angle_radians(x, 0.0f);
return (void *)x;
}
#ifdef __cplusplus
extern "C"
{
#endif
void pdp_chrot_setup(void)
{
pdp_chrot_class = class_new(gensym("pdp_chrot"), (t_newmethod)pdp_chrot_new,
(t_method)pdp_chrot_free, sizeof(t_pdp_chrot), 0, A_DEFFLOAT, A_NULL);
pdp_base_setup(pdp_chrot_class);
class_addmethod(pdp_chrot_class, (t_method)pdp_chrot_angle_degrees, gensym("angle"), A_DEFFLOAT, A_NULL);
}
#ifdef __cplusplus
}
#endif
Update of /cvsroot/pure-data/externals/pdp/modules
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv6756/modules
Added Files:
Makefile README
Log Message:
checking in pdp 0.12.4 from http://zwizwa.fartit.com/pd/pdp/pdp-0.12.4.tar.gz
--- NEW FILE: README ---
This file describes the protocol used for communicating packets.
See include/pdp.h and the sources in this directory for more info.
There are 3 kinds of pdp messages:
[pdp register_ro <packet_id>]
[pdp register_rw <packet_id>]
[pdp process]
Together they form the pdp protocol. An object can receive a packet
by catching the 3 kinds of messages:
When a register_ro message is received, the object can call
pdp_packet_copy_ro(packet) to reserve a read only copy for itself.
The same goes for handling the register_rw message. You can
reserve a read/write copy by using pdp_packet_copy_rw(packet)
When a process message is received, the object is allowed to start
processing the packet data end send the resulting packet(s) out.
To send out a packet, use the pdp_packet_pass_if_valid(outlet, &packet)
method. It passes a packet, and sets the reference to -1 (the undefined
packet id).
If you want to write pdp externs, consider using the pdp_base object
to derive your object from. Have a look at pdp_add, pdp_gain, pdp_noise
to see how to do this.
--- NEW FILE: Makefile ---
# build subdirs
current:
make -C generic
make -C image_basic
make -C image_io
make -C image_special
make -C matrix_basic
make -C test
clean:
make -C generic clean
make -C image_basic clean
make -C image_io clean
make -C image_special clean
make -C matrix_basic clean
make -C test clean
rm -f *~
rm -f *.o
Update of /cvsroot/pure-data/externals/pdp/include
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv6756/include
Added Files:
Makefile pdp.h pdp_ascii.h pdp_base.h pdp_bitmap.h pdp_comm.h
pdp_compat.h pdp_config.h pdp_config.h.in pdp_control.h
pdp_debug.h pdp_dpd_base.h pdp_dpd_command.h pdp_image.h
pdp_imagebase.h pdp_imageproc.h pdp_internals.h pdp_list.h
pdp_list_macros.h pdp_llconv.h pdp_matrix.h pdp_mem.h
pdp_mmx.h pdp_net.h pdp_packet.h pdp_pd.h pdp_png.h pdp_post.h
pdp_queue.h pdp_resample.h pdp_symbol.h pdp_type.h
pdp_type.h_old pdp_types.h pdp_xvideo.h pdp_xwindow.h
pwc-ioctl.h
Log Message:
checking in pdp 0.12.4 from http://zwizwa.fartit.com/pd/pdp/pdp-0.12.4.tar.gz
--- NEW FILE: pdp_list.h ---
/*
* Pure Data Packet header file. List class
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/* the pdp list is composed of atoms.
the default atom is a pointer.
lists can be recursed into trees.
note: all functions that return t_pdp_word and don't take a type argument
obviously don't perform any type checking. if you have heterogenous lists,
you should use atom iterators or direct access.
functions starting with "pdp_tree" recurse through sublists.
functions starting with "pdp_list" stay at the top level.
*/
#ifndef PDP_LIST_H
#define PDP_LIST_H
struct _pdp_list;
struct _pdp_atom;
/* THE LIST OBJECT */
typedef enum {
/* generic atoms */
a_undef = 0,
a_pointer,
a_float,
a_int,
a_symbol,
a_packet,
a_list,
a_atom_pointer,
/* forth atoms */
a_forthword, /* forth word operating on a stack */
a_vmword, /* forth word operating on a virtual machine */
a_vmmacro /* forth word operating on vm, manipilating current def */
} t_pdp_word_type;
typedef union _pdp_word
{
void* w_pointer;
float w_float;
int w_int;
struct _pdp_symbol* w_symbol;
int w_packet;
struct _pdp_list* w_list;
struct _pdp_atom* w_atom_pointer;
} t_pdp_word;
/* a list element */
typedef struct _pdp_atom
{
struct _pdp_atom *next;
t_pdp_word w;
t_pdp_word_type t;
} t_pdp_atom;
/* a list container */
typedef struct _pdp_list
{
int elements;
t_pdp_atom *first;
t_pdp_atom *last;
} t_pdp_list;
/* CONVENTION: trees stacks and lists.
* all operations with "list" in them operate on flat lists. all the
items contained in the list are either pure atoms (floats, ints, or symbols)
or references (packets, pointers, lists)
* all operations with "tree" in them, operate on recursive lists (trees)
all sublists of the list (tree) are owned by the parent list, so you can't
build trees from references to other lists.
* stacks are trees (the forth can have tree's on a stack, or have recursive stacks)
(WAS: stacks are by definition flat lists, so they can not contains sublists)
*/
typedef void (*t_pdp_atom_method)(t_pdp_atom *);
typedef void (*t_pdp_word_method)(t_pdp_word);
typedef void (*t_pdp_pword_method)(t_pdp_word *);
typedef void (*t_pdp_free_method)(void *);
/* creation / destruction */
t_pdp_atom* pdp_atom_new (void);
void pdp_atom_free (t_pdp_atom *);
t_pdp_list* pdp_list_new (int elements);
void pdp_list_free (t_pdp_list *l);
void pdp_list_clear (t_pdp_list *l);
void pdp_tree_free (t_pdp_list *l);
void pdp_tree_clear (t_pdp_list *l);
/* call a free method on all pointers in a tree */
void pdp_tree_strip_pointers (t_pdp_list *l, t_pdp_free_method f);
/* strip all packets from a tree. i.e. call pdp_packet_mark_unused on them */
void pdp_tree_strip_packets (t_pdp_list *l);
/* copy a tree, and copy all packets readonly */
t_pdp_list *pdp_tree_copy_ro(t_pdp_list *l);
t_pdp_list* pdp_tree_from_cstring(char *chardef, char **nextchar);
/* check type syntax of list */
int pdp_tree_check_syntax(t_pdp_list *list, t_pdp_list *syntax);
t_pdp_atom *pdp_atom_from_cstring(char *chardef, char **nextchar);
//void pdp_atom_from_cstring(t_pdp_atom *a, char *string);
/* traversal routines (map functions) */
/* use these in conjunction with gcc local functions
if there's ever a portability problem: add a void* data argument to implement closures */
void pdp_list_apply (t_pdp_list *l, t_pdp_atom_method am);
void pdp_tree_apply (t_pdp_list *l, t_pdp_atom_method am);
void pdp_list_apply_word_method (t_pdp_list *l, t_pdp_word_type t, t_pdp_word_method wm);
void pdp_tree_apply_word_method (t_pdp_list *l, t_pdp_word_type t, t_pdp_word_method wm);
void pdp_list_apply_pword_method (t_pdp_list *l, t_pdp_word_type t, t_pdp_pword_method pwm);
void pdp_tree_apply_pword_method (t_pdp_list *l, t_pdp_word_type t, t_pdp_pword_method pwm);
/* copy: (reverse) copies a list. */
/* list copy is flat. pointers and packets are copied. so you need to
ensure reference consistency yourself. */
t_pdp_list* pdp_list_copy (t_pdp_list *l);
t_pdp_list* pdp_list_copy_reverse (t_pdp_list *l);
t_pdp_list* pdp_tree_copy (t_pdp_list *l);
t_pdp_list* pdp_tree_copy_reverse (t_pdp_list *l);
/* cat: this makes a copy of the second list and adds it at the end of the first one */
void pdp_list_cat (t_pdp_list *l, t_pdp_list *tail);
/* information */
int pdp_list_contains (t_pdp_list *l, t_pdp_word_type t, t_pdp_word w);
int pdp_list_size (t_pdp_list *l);
void pdp_list_print (t_pdp_list *l);
void pdp_atom_print (t_pdp_atom *a);
/* access */
void pdp_list_add (t_pdp_list *l, t_pdp_word_type t, t_pdp_word w);
void pdp_list_add_back (t_pdp_list *l, t_pdp_word_type t, t_pdp_word w);
void pdp_list_add_to_set (t_pdp_list *l, t_pdp_word_type t, t_pdp_word w);
void pdp_list_remove (t_pdp_list *l, t_pdp_word_type t, t_pdp_word w);
void pdp_list_add_atom(t_pdp_list *l, t_pdp_atom *a);
void pdp_list_add_back_atom(t_pdp_list *l, t_pdp_atom *a);
/* these don't do error checking. out of bound == error */
t_pdp_atom *pdp_list_pop_atom (t_pdp_list *l);
t_pdp_word pdp_list_pop (t_pdp_list *l);
t_pdp_word pdp_list_index (t_pdp_list *l, int index);
void pdp_list_pop_push (t_pdp_list *source, t_pdp_list *dest);
/* some aliases */
#define pdp_list_add_front pdp_list_add
#define pdp_list_push pdp_list_add
#define pdp_list_queue pdp_list_add_end
#define pdp_list_unqueue pdp_list_pop
/* util */
void pdp_list_reverse(t_pdp_list *l);
/* generic atom iterator */
#define PDP_ATOM_IN(list,atom) for (atom = list->first ; atom ; atom = atom->next)
/* fast single type iterators */
/* generic */
#define PDP_WORD_IN(list, atom, word, type) for (atom=list->first ;atom && ((word = atom -> w . type) || 1); atom=atom->next)
/* type specific */
#define PDP_POINTER_IN(list, atom, x) PDP_WORD_IN(list, atom, x, w_pointer)
#define PDP_INT_IN(list, atom, x) PDP_WORD_IN(list, atom, x, w_int)
#define PDP_FLOAT_IN(list, atom, x) PDP_WORD_IN(list, atom, x, w_float)
#define PDP_SYMBOL_IN(list, atom, x) PDP_WORD_IN(list, atom, x, w_symbol)
#define PDP_PACKET_IN(list, atom, x) PDP_WORD_IN(list, atom, x, w_packet)
#define PDP_LIST_IN(list, atom, x) PDP_WORD_IN(list, atom, x, w_list)
/* some macros for the pointer type */
#define pdp_list_add_pointer(l,p) pdp_list_add(l, a_pointer, ((t_pdp_word)((void *)(p))))
#define pdp_list_add_back_pointer(l,p) pdp_list_add_back(l, a_pointer, ((t_pdp_word)((void *)(p))))
#define pdp_list_add_pointer_to_set(l,p) pdp_list_add_to_set(l, a_pointer, ((t_pdp_word)((void *)(p))))
#define pdp_list_remove_pointer(l,p) pdp_list_remove(l, a_pointer, ((t_pdp_word)((void *)(p))))
#define pdp_list_contains_pointer(l,p) pdp_list_contains(l, a_pointer, ((t_pdp_word)((void *)(p))))
/* atom access */
#define PDP_LIST_ATOM_0(x) ((x)->first)
#define PDP_LIST_ATOM_1(x) ((x)->first->next)
#define PDP_LIST_ATOM_2(x) ((x)->first->next->next)
#define PDP_LIST_ATOM_3(x) ((x)->first->next->next->next)
#define PDP_LIST_ATOM_4(x) ((x)->first->next->next->next->next)
/* array like setters */
static inline void pdp_atom_set(t_pdp_atom *a, t_pdp_word_type t, t_pdp_word w) {a->t = t; a->w = w;}
static inline void pdp_list_set_0(t_pdp_list *l, t_pdp_word_type t, t_pdp_word w) {pdp_atom_set(l->first, t, w);}
static inline void pdp_list_set_1(t_pdp_list *l, t_pdp_word_type t, t_pdp_word w) {pdp_atom_set(l->first->next, t, w);}
static inline void pdp_list_set_2(t_pdp_list *l, t_pdp_word_type t, t_pdp_word w) {pdp_atom_set(l->first->next->next, t, w);}
/* evaluator (tiny lisp) */
typedef t_pdp_list* (*t_pdp_list_evaluator_function)(t_pdp_list *);
#endif
--- NEW FILE: pdp_mmx.h ---
/*
* Pure Data Packet. Header file for mmx routines.
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#ifndef PDP_MMX_H
#define PDP_MMX_H
#ifdef __cplusplus
extern "C"
{
#endif
/****************************** 16 bit signed (pixel) routines ***************************************/
/* pack: gain is 8.8 fixed point */
void pixel_pack_s16u8_y(short int *input_pixels,
unsigned char *output_pixels,
int nb_pixels_div_8);
void pixel_pack_s16u8_uv(short int *input_pixels,
unsigned char *output_pixels,
int nb_pixels_div_8);
/* unpack: gain is not used -> full scale unpack */
void pixel_unpack_u8s16_y(unsigned char *input_pixels,
short int *output_pixels,
int nb_pixels_div_8);
void pixel_unpack_u8s16_uv(unsigned char *input_pixels,
short int *output_pixels,
int nb_pixels_div_8);
/* gain */
/* gain = integer */
/* shift is down shift count */
void pixel_gain_s16(short int *image,
int nb_4pixel_vectors,
short int gain[4],
unsigned long long *shift);
/* mix: left = gain_left * left + gain_right * right / gains are s.15 fixed point */
void pixel_mix_s16(short int *left,
short int *right,
int nb_4pixel_vectors,
short int gain_left[4],
short int gain_right[4]);
void pixel_randmix_s16(short int *left,
short int *right,
int nb_4pixel_vectors,
short int random_seed[4],
short int threshold[4]);
void pixel_rand_s16(short int *image,
int nb_4pixel_vectors,
short int random_seed[4]);
void pixel_add_s16(short int *left,
short int *right,
int nb_4pixel_vectors);
void pixel_mul_s16(short int *left,
short int *right,
int nb_4pixel_vectors);
/* affine transfo */
void pixel_affine_s16(short int *buf,
int nb_4pixel_vectors,
short int gain[4],
short int offset[4]);
/* conv */
void pixel_conv_hor_s16(short int *pixel_array,
int nb_4_pixel_vectors,
short int border[4],
short int mask[12]);
void pixel_conv_ver_s16(short int *pixel_array,
int nb_4_pixel_vectors,
int row_byte_size,
short int border[4],
short int mask[12]);
/* biquad */
void pixel_biquad_vertb_s16(short int *pixel_array,
int nb_4x4_pixblocks,
int linewidth,
short int coef[20],
short int state[8]);
void pixel_biquad_verbt_s16(short int *pixel_array,
int nb_4x4_pixblocks,
int linewidth,
short int coef[20],
short int state[8]);
void pixel_biquad_horlr_s16(short int *pixel_array,
int nb_4x4_pixblocks,
int linewidth,
short int coef[20],
short int state[8]);
void pixel_biquad_horrl_s16(short int *pixel_array,
int nb_4x4_pixblocks,
int linewidth,
short int coef[20],
short int state[8]);
void pixel_biquad_time_s16(short int *pixel_array,
short int *state_array1,
short int *state_array2,
short int *coefs,
int nb_4_pix_vectors);
/********************************** PLANAR COLOUR OPERATIONS ***************************************/
/* color rotation for 3 colour planes */
void pixel_crot3d_s16(short int *pixel_array,
int nb_4pixel_vectors_per_plane,
short int *row_encoded_vector_matrix);
/* color rotation for 2 colour planes */
void pixel_crot2d_s16(short int *pixel_array,
int nb_4pixel_vectors_per_plane,
short int *row_encoded_vector_matrix);
/********************************** RESAMPLE OPERATIONS *******************************************/
// affine transformation (called linear map, but that's flou terminology)
void pixel_resample_linmap_s16(void *x);
/********************************** POLYNOMIAL OPERATIONS *****************************************/
// chebychev polynomial
void pixel_cheby_s16_3plus(short int *buf, int nb_8pixel_vectors, int orderplusone, short int *coefs);
#ifdef __cplusplus
}
#endif
#endif //PDP_MMX_H
--- NEW FILE: pdp_matrix.h ---
/*
* Pure Data Packet system implementation. matrix packet interface
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#ifndef PDP_MATRIX_H
#define PDP_MATRIX_H
#include <stdio.h>
#include <gsl/gsl_block.h>
#include <gsl/gsl_vector.h>
#include <gsl/gsl_matrix.h>
#include <gsl/gsl_blas.h>
#include <gsl/gsl_linalg.h>
#include "pdp_types.h"
#define gsl_rows size1
#define gsl_columns size2
typedef struct _matrix
{
/* meta data */
u32 type; /* float/double real/complex */
u32 rows;
u32 columns;
/* gsl structures: these will be cast to the correct type on use */
gsl_block block; /* gsl block meta data */
gsl_vector vector; /* gsl vector meta data */
gsl_matrix matrix; /* gsl matrix meta data */
gsl_permutation perm; /* permutation data for storing an LU decomposition */
int signum; /* sign of permutation matrix */
} t_matrix;
#define PDP_MATRIX 7
#define PDP_MATRIX_TYPE_RFLOAT 1
#define PDP_MATRIX_TYPE_CFLOAT 2
#define PDP_MATRIX_TYPE_RDOUBLE 3
#define PDP_MATRIX_TYPE_CDOUBLE 4
int pdp_packet_matrix_isvalid(int p);
int pdp_packet_matrix_isvector(int p);
int pdp_packet_matrix_ismatrix(int p);
int pdp_packet_new_matrix(u32 rows, u32 columns, u32 type);
int pdp_packet_new_matrix_product_result(CBLAS_TRANSPOSE_t TransA, CBLAS_TRANSPOSE_t TransB, int pA, int pB);
void pdp_packet_matrix_setzero(int p);
/* getters: returns 0 if type is incorrect */
void *pdp_packet_matrix_get_gsl_matrix(int p, u32 type);
void *pdp_packet_matrix_get_gsl_vector(int p, u32 type);
int pdp_packet_matrix_get_type(int p);
/* type transparent matrix operations */
/* blas wrappers */
/* C += scale op(A) op(B) */
int pdp_packet_matrix_blas_mm(CBLAS_TRANSPOSE_t TransA, CBLAS_TRANSPOSE_t TransB,
int pA, int pB, int pC,
float scale_r, float scale_i);
/* c += scale op(A) b */
int pdp_packet_matrix_blas_mv(CBLAS_TRANSPOSE_t TransA,
int pA, int pb, int pc,
float scale_r, float scale_i);
/* other gsl wrappers */
int pdp_packet_matrix_LU(int p_matrix);
int pdp_packet_matrix_LU_to_inverse(int p_matrix);
int pdp_packet_matrix_LU_solve(int p_matrix, int p_vector);
#endif
--- NEW FILE: pdp_type.h ---
/*
* Pure Data Packet system implementation. Type handling interface
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/* COMMENTS
Since version 0.11 all packets have an (optional) high level type description.
This can be thought of as their mime type. It has several uses:
* automatic type conversion
* better reuse strategy for non pure packets
* debugging
The description is text-encoded, in the following form:
type/subtype/subsubtype/..
This is implemented using t_pdp_symbol.
Type descriptors can have wildcards. This is to give some freedom to a desired
type conversion. The following are all compatible:
*/
// image/grey/320x240
// image/*/320x240
// image/*/*
/*
>From a user pov, the type conversion is centralized. A single object (pdp_convert)
can do most of the conversions.
Type conversion implementation has to be done decentralized. It is subdivided into
two steps: inter-type and intra-type conversions.
Intra-type is the full responsability of each type implementation and can be handled
in a decentralized way (at linkage the type central intra-converter is registered
at the pdp framework.
Inter-type conversion is harder to do decentralized, therefore each new type should
provide some conversions to the basic built in types. (internal image, bitmap or matrix
types.
The point of this whole business is to
* enable automatic conversion from anything to a desired type for operators that combine objects.
i.e. pdp_add but receive incompatible objects.
* enable manual anything to anything conversion using a pdp_convert object, i.e. have a consistent
packet conversion api for users.
The solution is type conversion programs. A program's behaviour is specified as follows:
* the program is registered with a source and destination (result) template
* it is passed a packet and a destination template
* it can assume the source packet complies to the program's registerd source template
* it should convert the packet to a packet that will comply to it's registered destination template
* if for some reason a conversion fails, an invalid packet (handle == -1) should be returned
about type templates:
* they are hierarchical, with subtypes separated by a '/' character
* they can contain a wildcard '*', meaning that a certain level in the type hierarchy is:
- a don't care value, when the wildcard is used
-> as a destination template in a requested conversion
-> as a source template in a conversion program's specification
- uspecified, when the wildcard is used
-> as a destination template in a conversion program's specification
NOTE:
a wildcard can't be used in a source template for a conversion request
this assymetry requires there be 2 kinds of template matching mechanisms:
- source type description (without wildcards) to conversion program source template matching
- destination type description (with wildcards) to conversion program destination template matching
since a packet's type description cannot have wildcards, a symmetric matching (both sides have
wildcards) can be used for matching.
*/
/*
implementation:
there are 2 lists with conversion progams:
* the global list, containing all registered programs.
* the cached list, containing all recently used registered programs, or combinations thereof
if there is no cached, perfectly matching rule, a new one will be created, and added to
the head of the conversion list.
all conversion methods should keep their hands off the source packet. it is treated as readonly.
this is to ensure a more flexible operation (i.e. be able to put the conversion at the register_ro
level)
TODO: add a breadth first search algorithm to do multiple stage conversion.
*/
#ifndef PDP_TYPE_H
#define PDP_TYPE_H
#include "pdp_symbol.h"
#include "pdp_list.h"
/* the conversion method accepts a packet (which is freed) and a destination wildcard
and produces a new packet, or the invalid packet if the conversion failed */
typedef int (*t_pdp_conversion_method)(int, t_pdp_symbol *);
/* a conversion program is alist of conversion methods */
typedef t_pdp_list t_pdp_conversion_program;
/* a conversion has source and dest wildcards, and a conversion program */
typedef struct _pdp_conversion
{
t_pdp_symbol *src_pattern; // source type pattern
t_pdp_symbol *dst_pattern; // destination type pattern
t_pdp_conversion_program *program; // the conversion program for this conversion
} t_pdp_conversion;
/* all symbols are C style */
#ifdef __cplusplus
extern "C"
{
#endif
/* pdp_packet methods */
t_pdp_symbol *pdp_packet_get_description(int packet);
int pdp_packet_convert_ro(int packet, t_pdp_symbol *dest_pattern);
int pdp_packet_convert_rw(int packet, t_pdp_symbol *dest_pattern);
/* pdp_conversion_program methods */
void pdp_conversion_program_free(t_pdp_conversion_program *program);
t_pdp_conversion_program *pdp_conversion_program_new(t_pdp_conversion_method method, ...);
t_pdp_conversion_program *pdp_conversion_program_copy(t_pdp_conversion_program *program);
void pdp_conversion_program_add(t_pdp_conversion_program *program, t_pdp_conversion_program *tail);
/* pdp_type (central type object) methods */
int pdp_type_description_match(t_pdp_symbol *description, t_pdp_symbol *pattern);
void pdp_type_register_conversion (t_pdp_symbol *src_pattern, t_pdp_symbol *dst_pattern, t_pdp_conversion_program *program);
void pdp_type_register_cached_conversion (t_pdp_symbol *src_pattern, t_pdp_symbol *dst_pattern, t_pdp_conversion_program *program);
//t_pdp_symbol *pdp_type_gendesc(char *desc); //generate a type description (with description list attached)
t_pdp_list *pdp_type_to_list(t_pdp_symbol *type);
/* pdp's (threadsafe) symbol */
t_pdp_symbol *pdp_gensym(char *s);
#ifdef __cplusplus
}
#endif
#endif
--- NEW FILE: pwc-ioctl.h ---
#ifndef PWC_IOCTL_H
#define PWC_IOCTL_H
/* (C) 2001-2002 Nemosoft Unv. webcam(a)smcc.demon.nl
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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* This is pwc-ioctl.h belonging to PWC 8.6 */
/*
Changes
2001/08/03 Alvarado Added ioctl constants to access methods for
changing white balance and red/blue gains
*/
/* These are private ioctl() commands, specific for the Philips webcams.
They contain functions not found in other webcams, and settings not
specified in the Video4Linux API.
The #define names are built up like follows:
VIDIOC VIDeo IOCtl prefix
PWC Philps WebCam
G optional: Get
S optional: Set
... the function
*/
/* The frame rate is encoded in the video_window.flags parameter using
the upper 16 bits, since some flags are defined nowadays. The following
defines provide a mask and shift to filter out this value.
In 'Snapshot' mode the camera freezes its automatic exposure and colour
balance controls.
*/
#define PWC_FPS_SHIFT 16
#define PWC_FPS_MASK 0x00FF0000
#define PWC_FPS_FRMASK 0x003F0000
#define PWC_FPS_SNAPSHOT 0x00400000
struct pwc_probe
{
char name[32];
int type;
};
/* pwc_whitebalance.mode values */
#define PWC_WB_INDOOR 0
#define PWC_WB_OUTDOOR 1
#define PWC_WB_FL 2
#define PWC_WB_MANUAL 3
#define PWC_WB_AUTO 4
/* Used with VIDIOCPWC[SG]AWB (Auto White Balance).
Set mode to one of the PWC_WB_* values above.
*red and *blue are the respective gains of these colour components inside
the camera; range 0..65535
When 'mode' == PWC_WB_MANUAL, 'manual_red' and 'manual_blue' are set or read;
otherwise undefined.
'read_red' and 'read_blue' are read-only.
*/
struct pwc_whitebalance
{
int mode;
int manual_red, manual_blue; /* R/W */
int read_red, read_blue; /* R/O */
};
/*
'control_speed' and 'control_delay' are used in automatic whitebalance mode,
and tell the camera how fast it should react to changes in lighting, and
with how much delay. Valid values are 0..65535.
*/
struct pwc_wb_speed
{
int control_speed;
int control_delay;
};
/* Used with VIDIOCPWC[SG]LED */
struct pwc_leds
{
int led_on; /* Led on-time; range = 0..25000 */
int led_off; /* Led off-time; range = 0..25000 */
};
/* Restore user settings */
#define VIDIOCPWCRUSER _IO('v', 192)
/* Save user settings */
#define VIDIOCPWCSUSER _IO('v', 193)
/* Restore factory settings */
#define VIDIOCPWCFACTORY _IO('v', 194)
/* You can manipulate the compression factor. A compression preference of 0
means use uncompressed modes when available; 1 is low compression, 2 is
medium and 3 is high compression preferred. Of course, the higher the
compression, the lower the bandwidth used but more chance of artefacts
in the image. The driver automatically chooses a higher compression when
the preferred mode is not available.
*/
/* Set preferred compression quality (0 = uncompressed, 3 = highest compression) */
#define VIDIOCPWCSCQUAL _IOW('v', 195, int)
/* Get preferred compression quality */
#define VIDIOCPWCGCQUAL _IOR('v', 195, int)
/* This is a probe function; since so many devices are supported, it
becomes difficult to include all the names in programs that want to
check for the enhanced Philips stuff. So in stead, try this PROBE;
it returns a structure with the original name, and the corresponding
Philips type.
To use, fill the structure with zeroes, call PROBE and if that succeeds,
compare the name with that returned from VIDIOCGCAP; they should be the
same. If so, you can be assured it is a Philips (OEM) cam and the type
is valid.
*/
#define VIDIOCPWCPROBE _IOR('v', 199, struct pwc_probe)
/* Set AGC (Automatic Gain Control); int < 0 = auto, 0..65535 = fixed */
#define VIDIOCPWCSAGC _IOW('v', 200, int)
/* Get AGC; int < 0 = auto; >= 0 = fixed, range 0..65535 */
#define VIDIOCPWCGAGC _IOR('v', 200, int)
/* Set shutter speed; int < 0 = auto; >= 0 = fixed, range 0..65535 */
#define VIDIOCPWCSSHUTTER _IOW('v', 201, int)
/* Color compensation (Auto White Balance) */
#define VIDIOCPWCSAWB _IOW('v', 202, struct pwc_whitebalance)
#define VIDIOCPWCGAWB _IOR('v', 202, struct pwc_whitebalance)
/* Auto WB speed */
#define VIDIOCPWCSAWBSPEED _IOW('v', 203, struct pwc_wb_speed)
#define VIDIOCPWCGAWBSPEED _IOR('v', 203, struct pwc_wb_speed)
/* LEDs on/off/blink; int range 0..65535 */
#define VIDIOCPWCSLED _IOW('v', 205, struct pwc_leds)
#define VIDIOCPWCGLED _IOR('v', 205, struct pwc_leds)
/* Contour (sharpness); int < 0 = auto, 0..65536 = fixed */
#define VIDIOCPWCSCONTOUR _IOW('v', 206, int)
#define VIDIOCPWCGCONTOUR _IOR('v', 206, int)
/* Backlight compensation; 0 = off, otherwise on */
#define VIDIOCPWCSBACKLIGHT _IOW('v', 207, int)
#define VIDIOCPWCGBACKLIGHT _IOR('v', 207, int)
/* Flickerless mode; = 0 off, otherwise on */
#define VIDIOCPWCSFLICKER _IOW('v', 208, int)
#define VIDIOCPWCGFLICKER _IOR('v', 208, int)
/* Dynamic noise reduction; 0 off, 3 = high noise reduction */
#define VIDIOCPWCSDYNNOISE _IOW('v', 209, int)
#define VIDIOCPWCGDYNNOISE _IOR('v', 209, int)
#endif
--- NEW FILE: Makefile ---
current:
clean:
rm -f *~
--- NEW FILE: pdp_config.h.in ---
/* include/pdp_config.h.in. Generated from configure.ac by autoheader. */
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have the `gslcblas' library (-lgslcblas). */
#undef HAVE_LIBGSLCBLAS
/* Define to 1 if you have the `m' library (-lm). */
#undef HAVE_LIBM
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* build pdp_glx */
#undef HAVE_PDP_GLX
/* gsl support */
#undef HAVE_PDP_GSL
/* build png support */
#undef HAVE_PDP_PNG
/* build pdp_qt */
#undef HAVE_PDP_QT
/* readline needed for console support */
#undef HAVE_PDP_READLINE
/* build pdp_sdl */
#undef HAVE_PDP_SDL
/* build pdp_v4l */
#undef HAVE_PDP_V4L
/* experimental vforth dsp engine */
#undef HAVE_PDP_VFORTH
/* build X11 support */
#undef HAVE_PDP_X
/* build pdp_xv */
#undef HAVE_PDP_XV
/* enable forced pwc v4l support */
#undef HAVE_PWCV4L
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* "disable debugging support" */
#undef PDP_DEBUG
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
--- NEW FILE: pdp_queue.h ---
/*
* Pure Data Packet - processor queue interface
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#ifndef PDP_QUEUE_H
#define PDP_QUEUE_H
#include "pdp_pd.h"
#include <pthread.h>
/********************* general purpose pd process queue class *********************/
typedef void (*t_pdpmethod)(void *client);
/* the process queue data record */
typedef struct process_queue_struct
{
void *x_owner; /* the object we are dealing with */
t_pdpmethod x_process; /* the process method */
t_pdpmethod x_callback; /* the function to be called when finished */
int *x_queue_id; /* place to store the queue id for task */
} t_process_queue_item;
/* a pd process queue object */
typedef struct _pd_queue
{
/* clock members */
t_clock *pdp_clock;
double deltime;
/* some bookkeeping vars */
long long ticks;
long long packets;
/* queue members */
t_process_queue_item *q; /* queue */
int mask;
int head; /* last entry in queue + 1 */
int tail; /* first entry in queque */
int curr; /* the object currently processed in other thread */
/* pthread vars */
pthread_mutex_t mut;
pthread_cond_t cond_dataready;
pthread_cond_t cond_processingdone;
pthread_t thread_id;
/* toggle for thread usage */
int use_thread;
} t_pdp_procqueue;
/* all symbols are C-style */
#ifdef __cplusplus
extern "C"
{
#endif
/* returns 1 if full, 0 if there's space available */
int pdp_procqueue_full(t_pdp_procqueue *q);
void pdp_procqueue_flush(t_pdp_procqueue *q);
void pdp_procqueue_wait(t_pdp_procqueue *q);
void pdp_procqueue_finish(t_pdp_procqueue *q, int index);
void pdp_procqueue_add(t_pdp_procqueue *q, void *owner, void *process, void *callback, int *queue_id);
void pdp_procqueue_use_thread(t_pdp_procqueue* q, int t);
void pdp_procqueue_init(t_pdp_procqueue *q, double milliseconds, int logsize);
/********************* interface to pdp process queue singleton *********************/
/* processor queue methods, callable from main pd thread */
/* get the default queue */
t_pdp_procqueue *pdp_queue_get_queue(void);
#if 1
/* add a method to the processing queue */
void pdp_queue_add(void *owner, void *process, void *callback, int *queue_id);
/* halt main tread until processing is done */
void pdp_queue_wait(void);
/* halt main tread until processing is done and remove
callback from queue(for destructors) */
void pdp_queue_finish(int queue_id);
#endif
/* misc signals to pdp */
void pdp_control_notify_drop(int packet);
#ifdef __cplusplus
}
#endif
#endif
--- NEW FILE: pdp_list_macros.h ---
#ifndef __PDP_LIST_MACROS__
#define __PDP_LIST_MACROS__
/* some additional (short named) list macros mainly for manipulationg
argument lists. needs to be included locally. */
/* reading a list */
#define FIRST(l) ((l)->first)
#define SIZE(l) ((l)->elements)
#define NEXT(a) ((a)->next)
#define N(a) (a = a->next)
#define FLOAT(a) ((a)->t == a_float ? (a)->w.w_float : 0.0f)
#define PACKET(a) ((a)->t == a_packet ? (a)->w.w_packet : -1)
#define INT(a) ((a)->t == a_int ? (a)->w.w_packet : 0)
/* creating a list, and adding stuff to the end (queueing) */
#define LIST(n) pdp_list_new(n)
#define LFREE(l) pdp_list_free(l)
#define QFLOAT(l, x) pdp_list_add_back(l, a_float, ((t_pdp_word)(float)(x)))
#define QINT(l, x) pdp_list_add_back(l, a_int, ((t_pdp_word)(int)(x)))
#define QPACKET(l, x) pdp_list_add_back(l, a_packet,((t_pdp_word)(int)(x)))
#endif
--- NEW FILE: pdp_comm.h ---
/*
* Pure Data Packet system implementation.
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/* this file contains misc communication methods */
#ifndef PDP_COMM_H
#define PDP_COMM_H
#include "pdp_symbol.h"
#include "pdp_list.h"
/* all symbols are C style */
#ifdef __cplusplus
extern "C"
{
#endif
/* pdp's pd symbols for communication
don't use these directly!!
use the macros instead, in case
this is proven to be too much of a hack.. */
extern t_symbol s_pdp;
extern t_symbol s_register_ro;
extern t_symbol s_register_rw;
extern t_symbol s_process;
extern t_symbol s_dpd;
extern t_symbol s_inspect;
extern t_symbol s_accumulate;
extern t_symbol s_chanmask;
#define S_PDP &s_pdp
#define S_REGISTER_RO &s_register_ro
#define S_REGISTER_RW &s_register_rw
#define S_PROCESS &s_process
#define S_DPD &s_dpd
#define S_INSPECT &s_inspect
#define S_ACCUMULATE &s_accumulate
#define S_CHANMASK &s_chanmask
/* utility methods */
/* if packet is valid, mark it unused and send it to an outlet */
void pdp_packet_pass_if_valid(t_outlet *outlet, int *packet);
/* if source packet is valid, release dest packet and move src->dest */
void pdp_packet_replace_if_valid(int *dpacket, int *spacket);
/* copy_ro if dest packet if invalid, else drop source
(don't copy) + send drop notif to pdp system
returns 1 if dropped, 0 if copied */
int pdp_packet_copy_ro_or_drop(int *dpacket, int spacket);
int pdp_packet_convert_ro_or_drop(int *dpacket, int spacket, t_pdp_symbol *type_template);
/* copy_rw if dest packit is invalid, else drop source
(don't copy) + send drop notif to pdp system
returns 1 if dropped, zero if copied */
int pdp_packet_copy_rw_or_drop(int *dpacket, int spacket);
int pdp_packet_convert_rw_or_drop(int *dpacket, int spacket, t_pdp_symbol *type_template);
/* pd and pdp conversion stuff */
void pd_atom_to_pdp_atom(t_atom *pdatom, t_pdp_atom *pdpatom);
/* send pdp lists and atoms */
void outlet_pdp_atom(t_outlet *out, struct _pdp_atom *a);
void outlet_pdp_list(t_outlet *out, struct _pdp_list *l);
/* send a packet to an outlet: it is only legal to call this on a "passing packet"
or a "read only packet".
this means it is illegal to change a packet after you have passed it to others,
since this would mess up all read only references to the packet.
*/
/* this seems like a nice place to hide a comment on the notion of read/write in pdp
which packets are writable? all packets with exactly 1 user. this includes all packets
aquired with pdp_packet_*_rw or a constructor, and all packets that are not registered
after being sent out by outlet_pdp.
which packets are readable? all packets */
void outlet_pdp(t_outlet *out, int packetid);
/* send an accumulation (context) packet to an outlet. this is for usage in the dpd
base class. */
void outlet_dpd(t_outlet *out, int packetid);
#ifdef __cplusplus
}
#endif
#endif
--- NEW FILE: pdp_xvideo.h ---
/*
* Pure Data Packet header file: xwindow glue code
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
// x stuff
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/extensions/Xv.h>
#include <X11/extensions/Xvlib.h>
// image formats for communication with the X Server
#define FOURCC_YV12 0x32315659 /* YV12 YUV420P */
#define FOURCC_YUV2 0x32595559 /* YUV2 YUV422 */
#define FOURCC_I420 0x30323449 /* I420 Intel Indeo 4 */
/* xvideo class */
typedef struct _pdp_xvideo
{
t_pdp_xdisplay *xdpy;
t_pdp_xwindow *xwin;
//Display *dpy;
//int screen;
//Window win;
int xv_format;
int xv_port;
XvImage *xvi;
unsigned char *data;
unsigned int width;
unsigned int height;
int last_encoding;
int initialized;
} t_pdp_xvideo;
/* cons */
void pdp_xvideo_init(t_pdp_xvideo *x);
t_pdp_xvideo *pdp_xvideo_new(void);
/* des */
void pdp_xvideo_cleanup(t_pdp_xvideo* x);
void pdp_xvideo_free(t_pdp_xvideo* x);
/* open an xv port (and create XvImage) */
int pdp_xvideo_open_on_display(t_pdp_xvideo *x, t_pdp_xdisplay *d);
/* close xv port (and delete XvImage */
void pdp_xvideo_close(t_pdp_xvideo* x);
/* display a packet */
void pdp_xvideo_display_packet(t_pdp_xvideo *x, t_pdp_xwindow *w, int packet);
--- NEW FILE: pdp_bitmap.h ---
/*
* Pure Data Packet system implementation. 8 bit image packet interface
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/*
This file contains methods for the image packets
pdp_packet_new_* methods are several image packet constructors
It also contains some pdp_type_ methods, for type checking
and conversion.
*/
#ifndef PDP_BITMAP_H
#define PDP_BITMAP_H
/* bitmap data packet */
typedef struct _bitmap
{
/* standard images */
unsigned int encoding; /* image encoding (fourcc data format) */
unsigned int width; /* image width in pixels */
unsigned int height; /* image height in pixels */
unsigned int bpp; /* bits per pixel (0 == standard) */
} t_bitmap;
/* supported encodings (fourcc) */
/* special */
#define PDP_BITMAP_RGB 0x32424752
#define PDP_BITMAP_RGBA 0x41424752
#define PDP_BITMAP_GREY 0x59455247
/* packet yuv */
#define PDP_BITMAP_YUY2 0x32595559
#define PDP_BITMAP_UYVY 0x59565955
/* planar yuv */
#define PDP_BITMAP_I420 0x30323449
#define PDP_BITMAP_YV12 0x32315659
/* all symbols are C style */
#ifdef __cplusplus
extern "C"
{
#endif
/* bitmap constructors*/
int pdp_packet_new_bitmap_yv12(u32 width, u32 height);
int pdp_packet_new_bitmap_grey(u32 width, u32 height);
int pdp_packet_new_bitmap_rgb(u32 width, u32 height);
int pdp_packet_new_bitmap_rgba(u32 width, u32 height);
int pdp_packet_new_bitmap(int type, u32 width, u32 height);
/* utility methids */
void pdp_packet_bitmap_flip_top_bottom(int packet);
/* get description */
t_pdp_symbol *pdp_packet_bitmap_get_description(int packet);
/* get subheader */
t_bitmap *pdp_packet_bitmap_info(int packet);
bool pdp_packet_bitmap_isvalid(int packet);
#ifdef __cplusplus
}
#endif
#endif
--- NEW FILE: pdp_dpd_base.h ---
/*
* Pure Data Packet header file. DPD base class
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/* dpd base class for context based processors (for pd-fying standard stack based serial languages)
not all of pdp is used here, but the class is derived from the pdp base class to enable mixing
standard pdp (data flow packet processing) and dpd (context based serial languages)
dpd is short for "upside down pdp". the name stems from the observation
of opengl code in pd (like in gem) having an upside down feel when looking
through dataflow eyes. i.e.: the target (window context) is on top, while
the objects (geos) are at the bottom connected by a chain of geometric transforms
the principles of dpd are simple:
* there is only one main packet, received on the left inlet.
* this packet is called the "context" and is produced by and returned to a top context source/sink
* additional pd messages and pdp packets can be received on the cold inlets
* as opposed to pdp, no copies are made of this context packet, all operations on it are accumulative.
* the protocol is different because fanout is prohibited (so no ro/rw registering)
* the only exception for fanout are inspectors, which have precedence over normal processors
* all processors and inspectors for a single context type must use the pdp thread, to preserve execution order
*/
#include "pdp_base.h"
#define PDP_DPD_MAX_CONTEXT_OUTLETS 4
typedef struct pdp_dpd_base_struct
{
t_pdp_base b_base; /* pdp base class */
int b_nb_context_outlets;
t_outlet *b_context_outlet[PDP_DPD_MAX_CONTEXT_OUTLETS]; /* dpd outlets */
int b_outlet_enable[PDP_DPD_MAX_CONTEXT_OUTLETS]; /* dpd outlets */
t_pdp_method b_accum_method[PDP_DPD_MAX_CONTEXT_OUTLETS]; /* accumulation methods for each outlet */
t_pdp_method b_accum_callback[PDP_DPD_MAX_CONTEXT_OUTLETS]; /* pd callback methods for each outlet */
//int b_accum_queue_id[PDP_DPD_MAX_CONTEXT_OUTLETS]; /* accumulator queue id's */
t_pdp_method b_inspector_method; /* pdp thread inspector callback */
t_pdp_method b_inspector_callback; /* main thread inspector callback */
//int b_inspector_queue_id;
t_pdp_method b_cleanup_method; /* queued after propagation is done */
t_pdp_method b_cleanup_callback; /* queued after propagation is done */
//int b_cleanup_queue_id;
t_pdp_method b_complete_notify; /* method called after packet output is done */
t_pdp_newmethod b_command_factory_method; /* command factory method */
int b_context_packet; /* the current context packet */
int b_dpd_active_inlet_disabled;
} t_pdp_dpd_base;
#ifdef __cplusplus
extern "C"
{
#endif
/* bang method (propagate context to outlets & register callbacks)
mainly for context source/sinks
it is not registered as a pd message by default ! */
void pdp_dpd_base_bang(void *x);
/* get/set the context packet */
int pdp_dpd_base_get_context_packet(void *x);
void pdp_dpd_base_set_context_packet(void *x, int p);
int pdp_dpd_base_move_context_packet(void *x);
/* add a context outlet and it's corresponding accumulation (process) and callback method */
t_outlet *pdp_dpd_base_add_outlet(void *x, t_pdp_method accum_method, t_pdp_method accum_callback);
/* add a cleanup callback (called after all propagation is finished) for sources/sinks */
void pdp_dpd_base_add_cleanup(void *x, t_pdp_method cleanup_method, t_pdp_method accum_callback);
/* add an inspector callback */
void pdp_dpd_base_add_inspector(void *x, t_pdp_method inspector_method);
/* destructor */
void pdp_dpd_base_free(void *x);
/* init method */
void pdp_dpd_base_init(void *x);
/* disable dpd active inlet */
void pdp_dpd_base_disable_active_inlet(void *x);
/* enable/disable outlet */
void pdp_dpd_base_enable_outlet(void *x, int outlet, int toggle);
/* register notify method (called from the end of pdp_dpd_base_bang) */
void pdp_dpd_base_register_complete_notify(void *x, t_pdp_method method);
/* register a command init (factory) method
this method should return a command object to place in the queue */
void pdp_dpd_base_register_command_factory_method(void *x, t_pdp_newmethod command_factory_method);
/* class setup method */
void pdp_dpd_base_setup(t_class *class);
/* add a command to the process queue */
void pdp_dpd_base_queue_command(void *x, void *c, t_pdp_method process,
t_pdp_method callback, int *id);
/* get/set the queue instance (thread) used for scheduling */
#define pdp_dpd_base_set_queue pdp_base_set_queue
#define pdp_dpd_base_get_queue pdp_base_get_queue
#define pdp_dpd_base_queue_wait pdp_base_queue_wait
#ifdef __cplusplus
}
#endif
--- NEW FILE: pdp_imagebase.h ---
/*
* Pure Data Packet image processor base class header file.
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/*
This file contains the specification of the pdp base class. It is derived
from t_object, the basic pd object (like any other pd extern). Have a look
at pdp_add, pdp_gain and pdp_noise to see how to use this.
*/
#include "pdp_base.h"
typedef struct
{
t_pdp_base x_obj;
u32 b_channel_mask; // channel mask
} t_pdp_imagebase;
/* setup base class. call this in your derived class setup method */
void pdp_imagebase_setup(t_class *c);
/* base class constructor/destructor. call this in your base class constructor/destructor */
void pdp_imagebase_init(void *x);
void pdp_imagebase_free(void *x);
/* getters for image base class data */
u32 pdp_imagebase_get_chanmask(void *x);
--- NEW FILE: pdp_llconv.h ---
/*
* Pure Data Packet system implementation. : low level format conversion code
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/* this file contains low level conversion code
it is a wrapper around some machine code routines padded
with some extra c code */
/* don't rely too much on the calling conventions here
this is mainly to tuck away "ugly" parts of the code
that come up in several places */
#ifndef PDP_LLCONV_H
#define PDP_LLCONV_H
/* all symbols are C style */
#ifdef __cplusplus
extern "C"
{
#endif
/* raw image formats (RIF) descriptions used for low level conversion routines
format: RIF_[component names and order]_[data arganization]_[data type]
component names: R(red), G(green), B(blue), Y(chroma), V(chroma red), U(chroma blue)
component type: [S/U][nb bits] ex: S16, U8
data organization: [P/P[samplefrequency]] ex: P(packed) P411(planar, 2nd and 3rd 2x2 subsampled)
*/
enum RIF {
RIF_YVU__P411_U8,
RIF_YUV__P411_U8,
RIF_YVU__P411_S16,
RIF_YVU__P444_S16,
RIF_YUYV_P____U8,
RIF_RGB__P____U8,
RIF_RGBA_P____U8,
RIF_RGB__P444_S16,
RIF_GREY______S16,
RIF_GREY______U8,
RIF_BGR__P____U8,
RIF_BGRA_P____U8
};
/* pdp_llconv is NOT thread safe !*/
/* gain = 1.0 means maximal */
/* low level convert 2 images */
void pdp_llconv(void *src, int stype, void *dest, int dtype, int w, int h);
#ifdef __cplusplus
}
#endif
#endif
--- NEW FILE: pdp_config.h ---
/* include/pdp_config.h. Generated by configure. */
/* include/pdp_config.h.in. Generated from configure.ac by autoheader. */
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Define to 1 if you have the `gslcblas' library (-lgslcblas). */
#define HAVE_LIBGSLCBLAS 1
/* Define to 1 if you have the `m' library (-lm). */
#define HAVE_LIBM 1
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
/* build pdp_glx */
#define HAVE_PDP_GLX 1
/* gsl support */
#define HAVE_PDP_GSL 1
/* build png support */
#define HAVE_PDP_PNG 1
/* build pdp_qt */
#define HAVE_PDP_QT 1
/* readline needed for console support */
/* #undef HAVE_PDP_READLINE */
/* build pdp_sdl */
/* #undef HAVE_PDP_SDL */
/* build pdp_v4l */
/* #undef HAVE_PDP_V4L */
/* experimental vforth dsp engine */
/* #undef HAVE_PDP_VFORTH */
/* build X11 support */
#define HAVE_PDP_X 1
/* build pdp_xv */
#define HAVE_PDP_XV 1
/* enable forced pwc v4l support */
/* #undef HAVE_PWCV4L */
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT ""
/* Define to the full name of this package. */
#define PACKAGE_NAME ""
/* Define to the full name and version of this package. */
#define PACKAGE_STRING ""
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME ""
/* Define to the version of this package. */
#define PACKAGE_VERSION ""
/* "disable debugging support" */
#define PDP_DEBUG 0
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
--- NEW FILE: pdp_base.h ---
/*
* Pure Data Packet base class header file.
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/*
This file contains the specification of the pdp base class. It is derived
from t_object, the basic pd object (like any other pd extern). Have a look
at pdp_add, pdp_gain and pdp_noise to see how to use this.
*/
#define MAX_NB_PDP_BASE_INLETS 4
#define MAX_NB_PDP_BASE_OUTLETS 4
#include "pdp_pd.h"
#include "pdp_symbol.h"
#include "pdp_types.h"
#include "pdp_queue.h"
#include "pdp_comm.h"
#include "pdp_compat.h"
#include "pdp_packet.h"
typedef void (*t_pdp_method)(void *);
typedef void* (*t_pdp_newmethod)(void *);
typedef struct
{
t_object x_obj;
int b_inlets; // the number of pdp inlets
int b_outlets; // the number of pdp outlets
// registers to store incoming packets
int b_packet[MAX_NB_PDP_BASE_INLETS];
int b_packet_next[MAX_NB_PDP_BASE_INLETS];
t_pdp_symbol *b_type_template[MAX_NB_PDP_BASE_INLETS];
int b_queue_id; // task id in process queue (for callback cancelling)
//int b_dropped; // indicate if a packet was dropped during register_rw cycle
// wil the default (left) active inlet accept pdp messages ?
int b_active_inlet_enabled;
int b_active_inlet_readonly;
// the process callbacks
t_pdp_method b_process_method; // called in pdp thread
t_pdp_method b_preproc_method; // called before thread (for packet alloc and checking)
t_pdp_method b_postproc_method; // called after thread (for outlet stuff other than default active packet->out0)
// packet outlets
t_outlet *b_outlet[MAX_NB_PDP_BASE_OUTLETS];
u32 b_channel_mask; // channel mask
int b_thread_enabled; // thread enable switch
t_pdp_procqueue *b_q; // queue object
} t_pdp_base;
/* setup base class. call this in your derived class setup method */
void pdp_base_setup(t_class *c);
/* base class constructor/destructor. call this in your base class constructor/destructor */
void pdp_base_init(void *x);
void pdp_base_free(void *x);
/* register processing callbacks */
void pdp_base_set_process_method(void *x, t_pdp_method m); //process callback (called from pdp thread)
void pdp_base_set_preproc_method(void *x, t_pdp_method m); //pre-process callback (called before process from pd thread)
void pdp_base_set_postproc_method(void *x, t_pdp_method m); //post-process callback (called after process from pd thread)
/* configure inlets/outlets */
void pdp_base_add_pdp_inlet(void *x);
t_outlet *pdp_base_add_pdp_outlet(void *x);
void pdp_base_disable_active_inlet(void *x); //use this for pdp generators
void pdp_base_readonly_active_inlet(void *x); //use this for pdp converters ("out of place" processing)
void pdp_base_add_gen_inlet(void *x, t_symbol *from, t_symbol *to); // generic inlet
/* bang method */
void pdp_base_bang(void *x);
/* move delayed passive packets in place */
void pdp_base_movepassive(void *x);
/* packet manipulation methods
0 active inlet (left) if enabled
>0 additional pdp inlets created with pdp_base_add_pdp_inlet */
int pdp_base_get_packet(void *x, int inlet); // get the packet from an inlet
int pdp_base_move_packet(void *x, int inlet); // same as get, but it removes the reference in the base class
void pdp_base_set_packet(void *x, int inlet, int packet); // set (replace) the active packet (will be sent to outlet)
/* getters for base class data */
u32 pdp_base_get_chanmask(void *x);
t_object *pdp_base_get_object(void *x);
/* thread control */
void pdp_base_disable_thread(void *x);
/* type control */
void pdp_base_set_type_template(void *x, int inlet, t_pdp_symbol *type_template);
/* queue control */
void pdp_base_queue_wait(void *x);
void pdp_base_set_queue(void *x, t_pdp_procqueue *q);
t_pdp_procqueue *pdp_base_get_queue(void *x);
--- NEW FILE: pdp_control.h ---
#ifndef __PDP_CONTROL_H__
#define __PDP_CONTROL_H__
#include "pdp_pd.h"
struct _pdp_control;
typedef void (t_pdp_control_method_notify)(struct _pdp_control *x);
void pdp_control_notify_broadcast(t_pdp_control_method_notify *notify);
void pdp_control_addmethod(t_method m, t_symbol *s);
#endif
--- NEW FILE: pdp_imageproc.h ---
/*
* Pure Data Packet. Header file for image processing routines (used in modules).
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/* this is a c wrapper around platform specific (mmx) code */
#include "pdp_types.h"
#ifndef PDP_IMAGEPROC_H
#define PDP_IMAGEPROC_H
#ifdef __cplusplus
extern "C"
{
#endif
/* the basic allocation unit, for stack alignment */
typedef long long t_pdp_imageproc_stackword;
/* convert byte size to nb of stack words */
#define PDP_IMAGEPROC_NB_STACKWORDS(x) (((x-1)/sizeof(t_pdp_imageproc_stackword))+1)
/* the packet types should be the same for the dispatchers. packet0 is the dominant packet */
/* image processing dispatchers */
void pdp_imageproc_dispatch_1buf(void (*process_routine)(void*, u32, u32, s16*), void *x, u32 chanmask, int packet0);
void pdp_imageproc_dispatch_2buf(void (*process_routine)(void*, u32, u32, s16*, s16 *), void *x, u32 chanmask, int packet0, int packet1);
void pdp_imageproc_dispatch_3buf(void (*process_routine)(void*, u32, u32, s16*, s16 *, s16*), void *x, u32 chanmask, int packet0, int packet1, int packet2);
/* get legal image dimensions */
/* this is a fix for the dimension problem */
/* some imageproc implementations require the dims to be a multiple of some square */
u32 pdp_imageproc_legalwidth(int i);
u32 pdp_imageproc_legalheight(int i);
u32 pdp_imageproc_legalwidth_round_down(int i);
u32 pdp_imageproc_legalheight_round_down(int i);
/****************************** 16 bit signed (pixel) routines ***************************************/
// mix 2 images
void *pdp_imageproc_mix_new(void);
int pdp_imageproc_mix_nb_stackwords(void);
void pdp_imageproc_mix_delete(void *x);
void pdp_imageproc_mix_setleftgain(void *x, float gain);
void pdp_imageproc_mix_setrightgain(void *x, float gain);
void pdp_imageproc_mix_process(void *x, u32 width, u32 height, s16 *image, s16 *image2);
// random mix 2 images
// note: random number generator can be platform specific
// however, it should be seeded. (same seed produces the same result)
// threshold = 0 -> left image
// threshold = 1 -> right image
void *pdp_imageproc_randmix_new(void);
int pdp_imageproc_randmix_nb_stackwords(void);
void pdp_imageproc_randmix_delete(void *x);
void pdp_imageproc_randmix_setthreshold(void *x, float threshold);
void pdp_imageproc_randmix_setseed(void *x, float seed);
void pdp_imageproc_randmix_process(void *x, u32 width, u32 height, s16 *image, s16 *image2);
// produce a random image
// note: random number generator can be platform specific
// however, it should be seeded. (same seed produces the same result)
void *pdp_imageproc_random_new(void);
void pdp_imageproc_random_delete(void *x);
void pdp_imageproc_random_setseed(void *x, float seed);
void pdp_imageproc_random_process(void *x, u32 width, u32 height, s16 *image);
// produce a plasma image
// note: random number generator can be platform specific
// however, it should be seeded. (same seed produces the same result)
void *pdp_imageproc_plasma_new(void);
void pdp_imageproc_plasma_delete(void *x);
void pdp_imageproc_plasma_setseed(void *x, float seed);
void pdp_imageproc_plasma_setturbulence(void *x, float seed);
void pdp_imageproc_plasma_process(void *x, u32 width, u32 height, s16 *image);
// apply a gain to an image
void *pdp_imageproc_gain_new(void);
void pdp_imageproc_gain_delete(void *x);
void pdp_imageproc_gain_setgain(void *x, float gain);
void pdp_imageproc_gain_process(void *x, u32 width, u32 height, s16 *image);
// add two images
void pdp_imageproc_add_process(void *x, u32 width, u32 height, s16 *image, s16 *image2);
// mul two images
void pdp_imageproc_mul_process(void *x, u32 width, u32 height, s16 *image, s16 *image2);
// 3x1 or 1x3 in place convolution
// orientation
#define PDP_IMAGEPROC_CONV_HORIZONTAL 0
#define PDP_IMAGEPROC_CONV_VERTICAL 1
void *pdp_imageproc_conv_new(void);
void pdp_imageproc_conv_delete(void *x);
void pdp_imageproc_conv_setmin1(void *x, float val);
void pdp_imageproc_conv_setzero(void *x, float val);
void pdp_imageproc_conv_setplus1(void *x, float val);
void pdp_imageproc_conv_setbordercolor(void *x, float intensity);
void pdp_imageproc_conv_setorientation(void *x, u32 val);
void pdp_imageproc_conv_setnbpasses(void *x, u32 val);
void pdp_imageproc_conv_process(void *x, u32 width, u32 height, s16 *image);
// colour rotation for 2 colour planes ($$$TODO: change interface)
// matrix is column encoded
void *pdp_imageproc_crot2d_new(void);
void pdp_imageproc_crot2d_delete(void *x);
void pdp_imageproc_crot2d_setmatrix(void *x, float *matrix);
void pdp_imageproc_crot2d_process(void *x, s16 *image, u32 width, u32 height);
// colour rotation for 3 colour planes ($$$TODO: change interface)
void *pdp_imageproc_crot3d_new(void);
void pdp_imageproc_crot3d_delete(void *x);
void pdp_imageproc_crot3d_setmatrix(void *x, float *matrix);
void pdp_imageproc_crot3d_process(void *x, s16 *image, u32 width, u32 height);
// biquad space
// directions
#define PDP_IMAGEPROC_BIQUAD_TOP2BOTTOM (1<<0)
#define PDP_IMAGEPROC_BIQUAD_BOTTOM2TOP (1<<1)
#define PDP_IMAGEPROC_BIQUAD_LEFT2RIGHT (1<<2)
#define PDP_IMAGEPROC_BIQUAD_RIGHT2LEFT (1<<3)
void *pdp_imageproc_bq_new(void);
void pdp_imageproc_bq_delete(void *x);
void pdp_imageproc_bq_setcoef(void *x, float *coef); // a0,a1,a2,b0,b1,b2
void pdp_imageproc_bq_setnbpasses(void *x, u32 nbpasses);
void pdp_imageproc_bq_setdirection(void *x, u32 direction);
void pdp_imageproc_bq_process(void *x, u32 width, u32 height, s16* image);
// biquad time
//void *pdp_imageproc_bqt_new(void);
//void pdp_imageproc_bqt_delete(void *x);
//void pdp_imageproc_bqt_setcoef(void *x, float *coef); // a0,a1,a2,b0,b1,b2
void pdp_imageproc_bqt_process(void *x, u32 width, u32 height, s16 *image, s16 *state0, s16 *state1);
// zoom object
void *pdp_imageproc_resample_affinemap_new(void);
void pdp_imageproc_resample_affinemap_delete(void *x);
void pdp_imageproc_resample_affinemap_setcenterx(void *x, float f);
void pdp_imageproc_resample_affinemap_setcentery(void *x, float f);
void pdp_imageproc_resample_affinemap_setzoomx(void *x, float f);
void pdp_imageproc_resample_affinemap_setzoomy(void *x, float f);
void pdp_imageproc_resample_affinemap_setangle(void *x, float f);
void pdp_imageproc_resample_affinemap_process(void *x, u32 width, u32 height, s16 *srcimage, s16 *dstimage);
//chebyshev poly
void *pdp_imageproc_cheby_new(int order);
void pdp_imageproc_cheby_delete(void *x);
void pdp_imageproc_cheby_setcoef(void *x, u32 n, float f);
void pdp_imageproc_cheby_setnbpasses(void *x, u32 n);
void pdp_imageproc_cheby_process(void *x, u32 width, u32 height, s16 *image);
//logic ops
void pdp_imageproc_xor_process(void *x, u32 width, u32 height, s16 *image, s16 *image2);
void pdp_imageproc_or_process(void *x, u32 width, u32 height, s16 *image, s16 *image2);
void pdp_imageproc_and_process(void *x, u32 width, u32 height, s16 *image, s16 *image2);
void pdp_imageproc_mask_process(void *x, u32 width, u32 height, s16 *image);
void pdp_imageproc_not_process(void *x, u32 width, u32 height, s16 *image);
void pdp_imageproc_hardthresh_process(void *x, u32 width, u32 height, s16 *image);
void pdp_imageproc_softthresh_process(void *x, u32 width, u32 height, s16 *image);
//other stateles operators
void pdp_imageproc_abs_process(void *x, u32 width, u32 height, s16 *image);
void pdp_imageproc_zthresh_process(void *x, u32 width, u32 height, s16 *image);
void pdp_imageproc_plasma_process(void *x, u32 width, u32 height, s16 *image);
void pdp_imageproc_ispositive_process(void *x, u32 width, u32 height, s16 *image);
void pdp_imageproc_sign_process(void *x, u32 width, u32 height, s16 *image);
void pdp_imageproc_flip_lr_process(void *dummy, u32 width, u32 height, s16 *image);
void pdp_imageproc_flip_tb_process(void *dummy, u32 width, u32 height, s16 *image);
//set to zero
void pdp_imageproc_zero_process(void *x, u32 width, u32 height, s16 *image);
void pdp_imageproc_constant_process(void *x, u32 width, u32 height, s16 *image);
#ifdef __cplusplus
}
#endif
#endif //PDP_IMAGEPROC_H
--- NEW FILE: pdp_mem.h ---
/*
* Pure Data Packet header file: memory allocation
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#ifndef _PDP_MEM_H_
#define _PDP_MEM_H_
#include <pthread.h>
/* a wrapper around malloc and free to keep track of pdp's memory usage */
void *pdp_alloc(int size);
void pdp_dealloc(void *stuff);
/* fast allocator object (for lists and atoms) */
#define PDP_FASTALLOC_BLOCK_ELEMENTS 4096
typedef struct _pdp_fastalloc
{
unsigned int atom_size;
unsigned int block_elements;
pthread_mutex_t mut;
struct _fastalloc *freelist;
} t_pdp_fastalloc;
void *pdp_fastalloc_new_atom(t_pdp_fastalloc *x);
void pdp_fastalloc_save_atom(t_pdp_fastalloc *x, void *atom);
t_pdp_fastalloc *pdp_fastalloc_new(unsigned int size);
#endif
--- NEW FILE: pdp_type.h_old ---
/*
* Pure Data Packet system implementation. Type handling interface
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/* COMMENTS
Since version 0.11 all packets have an (optional) high level type description.
This can be thought of as their mime type. It has several uses:
* automatic type conversion
* better reuse strategy for non pure packets
* debugging
The description is text-encoded, in the following form:
type/subtype/subsubtype/..
This is implemented using t_pdp_symbol.
Type descriptors can have wildcards. This is to give some freedom to a desired
type conversion. The following are all compatible:
*/
// image/grey/320x240
// image/*/320x240
// image/*/*
/*
>From a user pov, the type conversion is centralized. A single object (pdp_convert)
can do most of the conversions.
Type conversion implementation has to be done decentralized. It is subdivided into
two steps: inter-type and intra-type conversions.
Intra-type is the full responsability of each type implementation and can be handled
in a decentralized way (at linkage the type central intra-converter is registered
at the pdp framework.
Inter-type conversion is harder to do decentralized, therefore each new type should
provide some conversions to the basic built in types. (internal image, bitmap or matrix
types.
The point of this whole business is to
* enable automatic conversion from anything to a desired type for operators that combine objects.
i.e. pdp_add but receive incompatible objects.
* enable manual anything to anything conversion using a pdp_convert object, i.e. have a consistent
package conversion api for users.
The solution is type conversion programs. A program's behaviour is specified as follows:
* the program is registered with a source and destination (result) template
* it is passed a packet and a destination template
* it can assume the source packet complies to the program's registerd source template
* it should convert the packet to a packet that will comply to it's registered destination template
* if for some reason a conversion fails, an invalid packet (handle == -1) should be returned
about type templates:
* they are hierarchical, with subtypes separated by a '/' character
* they can contain a wildcard '*', meaning that a certain level in the type hierarchy is:
- a don't care value, when the wildcard is used
-> as a destination template in a requested conversion
-> as a source template in a conversion program's specification
- uspecified, when the wildcard is used
-> as a destination template in a conversion program's specification
NOTE:
a wildcard can't be used in a source template for a conversion request
this assymetry requires there be 2 kinds of template matching mechanisms:
- source type description (without wildcards) to conversion program source template matching
- destination type description (with wildcards) to conversion program destination template matching
since a packet's type description cannot have wildcards, a symmetric matching (both sides have
wildcards) can be used for matching.
*/
/*
implementation:
there are 2 lists with conversion progams:
* the global list, containing all registered programs.
* the cached list, containing all recently used registered programs, or combinations thereof
if there is no cached, perfectly matching rule, a new one will be created, and added to
the head of the conversion list.
all conversion methods should keep their hand's off the source packet. it is treated as readonly.
this is to ensure a more flexible operation (i.e. be able to put the conversion at the register_ro
level) this will need a bit more logic in running the conversion program though..
*/
#ifndef PDP_TYPE_H
#define PDP_TYPE_H
/* the conversion method accepts a packet (which is freed) and a destination wildcard
and produces a new packet, or the invalid packet if the conversion failed */
typedef int (*t_pdp_conversion_method)(int, t_pdp_symbol *);
/* a conversion program is alist of conversion methods */
typedef struct _pdp_conversion_program
{
t_pdp_conversion_method method; // conversion method
struct _pdp_conversion_program *next; // next method in program
} t_pdp_conversion_program;
/* a conversion has source and dest wildcards, and a conversion program */
typedef struct _pdp_conversion
{
t_pdp_symbol *src_pattern; // source type pattern
t_pdp_symbol *dst_pattern; // destination type pattern
t_pdp_conversion_program *program; // the conversion program for this conversion
struct _pdp_conversion *next; // next conversion program record
} t_pdp_conversion;
/* all symbols are C style */
#ifdef __cplusplus
extern "C"
{
#endif
/* pdp_packet methods */
t_pdp_symbol *pdp_packet_get_description(int packet);
int pdp_packet_convert_ro(int packet, t_pdp_symbol *dest_pattern);
int pdp_packet_convert_rw(int packet, t_pdp_symbol *dest_pattern);
/* pdp_conversion_program methods */
void pdp_conversion_program_free(t_pdp_conversion_program *program);
t_pdp_conversion_program *pdp_conversion_program_new(t_pdp_conversion_method method, ...);
t_pdp_conversion_program *pdp_conversion_program_copy(t_pdp_conversion_program *program);
void pdp_conversion_program_add(t_pdp_conversion_program *program, t_pdp_conversion_program *tail);
/* pdp_type (central type object) methods */
int pdp_type_description_match(t_pdp_symbol *description, t_pdp_symbol *pattern);
void pdp_type_register_conversion (t_pdp_symbol *src_pattern, t_pdp_symbol *dst_pattern, t_pdp_conversion_program *program);
void pdp_type_register_cached_conversion (t_pdp_symbol *src_pattern, t_pdp_symbol *dst_pattern, t_pdp_conversion_program *program);
//t_pdp_symbol *pdp_type_gendesc(char *desc); //generate a type description (with description list attached)
t_pdp_list *pdp_type_to_list(t_pdp_symbol *type);
/* pdp's (threadsafe) symbol */
t_pdp_symbol *pdp_gensym(char *s);
#ifdef __cplusplus
}
#endif
#endif
--- NEW FILE: pdp_compat.h ---
/*
please don't use any of these. for backwards compatibility only
*/
#ifndef PDP_COMPAT_H
#define PDP_COMPAT_H
void pdp_pass_if_valid(t_outlet *outlet, int *packet);
void pdp_replace_if_valid(int *dpacket, int *spacket);
#endif
--- NEW FILE: pdp_internals.h ---
/*
* Pure Data Packet internal header file.
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/* this file contains prototypes for "private" pdp methods.
DON'T CALL THESE FROM OUTSIDE OF PDP! unless you really
know what you are doing.
*/
#ifndef PDP_INTERNALS_H
#define PDP_INTERNALS_H
#ifdef __cplusplus
extern "C"
{
#endif
/* INTERNAL SYSTEM METHODS */
/* set/unset main pdp thread usage */
void pdp_queue_use_thread(int t);
/* INTERNAL PACKET METHODS */
/* create a new packet, reuse if possible.
ONLY USE THIS IN A TYPE SPECIFIC CONSTRUCTOR! */
int pdp_packet_new(unsigned int datatype, unsigned int datasize);
#ifdef __cplusplus
}
#endif
#endif
--- NEW FILE: pdp_pd.h ---
/* pdp_pd.h wrapper */
#ifndef _M_PD_H_
#define _M_PD_H_
#include "m_pd.h"
#endif
--- NEW FILE: pdp_types.h ---
/*
* Pure Data Packet header file. Scalar type definitions.
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/* some typedefs and utility classes */
#ifndef PDP_TYPES_H
#define PDP_TYPES_H
typedef signed char s8;
typedef signed short s16;
typedef signed long s32;
typedef signed long long s64;
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned long u32;
typedef unsigned long long u64;
#ifndef __cplusplus
typedef int bool;
#define true 1;
#define false 0;
#endif
typedef struct _pdp t_pdp;
typedef void (*t_pdp_packet_method1)(t_pdp *); /* dst */
typedef void (*t_pdp_packet_method2)(t_pdp *, t_pdp *); /* dst, src */
/* generic packet subheader */
//typedef unsigned char t_raw[PDP_SUBHEADER_SIZE];
typedef unsigned int t_raw;
#endif
--- NEW FILE: pdp_symbol.h ---
/*
* Pure Data Packet system implementation. : symbol and namespace stuff
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#ifndef _PDP_SYMBOL_
#define _PDP_SYMBOL_
/* pdp's symbols are derived from pd's symbols
there is one symbol hash. each symbol has
a meaning in several name spaces.
* forth words
* type description lists (for accelerating type matching)
*/
#include "pdp_list.h"
/* the pdp symbol type */
typedef struct _pdp_symbol
{
/* next */
struct _pdp_symbol *s_next;
/* the symbol name */
char *s_name;
/* forth symbol->atom */
struct _pdp_atom s_forth;
/* packet handling cache */
struct _pdp_list *s_type; // a parsed type description: a/b/c -> (a,b,c)
struct _pdp_list *s_reusefifo; // packet pool fifo for this type
} t_pdp_symbol;
#ifdef __cplusplus
extern "C"
{
#endif
/* namespace stuff */
int pdp_symbol_set_typelist(t_pdp_symbol *s, struct _pdp_list *typelist);
/* get symbol from char */
t_pdp_symbol *pdp_gensym(char *s);
/* iterate over all symbols */
typedef void (*t_pdp_symbol_iterator)(t_pdp_symbol *s);
void pdp_symbol_apply_all(t_pdp_symbol_iterator ir);
// don't use these directly, use the macros
extern t_pdp_symbol _pdp_sym_wildcard;
extern t_pdp_symbol _pdp_sym_float;
extern t_pdp_symbol _pdp_sym_int;
extern t_pdp_symbol _pdp_sym_symbol;
extern t_pdp_symbol _pdp_sym_packet;
extern t_pdp_symbol _pdp_sym_pointer;
extern t_pdp_symbol _pdp_sym_list;
extern t_pdp_symbol _pdp_sym_invalid;
extern t_pdp_symbol _pdp_sym_question_mark;
extern t_pdp_symbol _pdp_sym_atom;
extern t_pdp_symbol _pdp_sym_null;
extern t_pdp_symbol _pdp_sym_quote_start;
extern t_pdp_symbol _pdp_sym_quote_end;
extern t_pdp_symbol _pdp_sym_return;
extern t_pdp_symbol _pdp_sym_nreturn;
extern t_pdp_symbol _pdp_sym_defstart;
extern t_pdp_symbol _pdp_sym_defend;
extern t_pdp_symbol _pdp_sym_if;
extern t_pdp_symbol _pdp_sym_then;
extern t_pdp_symbol _pdp_sym_local;
extern t_pdp_symbol _pdp_sym_forth;
extern t_pdp_symbol _pdp_sym_call;
extern t_pdp_symbol _pdp_sym_push;
extern t_pdp_symbol _pdp_sym_pop;
#ifdef __cplusplus
}
#endif
// these symbols are used a lot in critical parts
// optimize later
#define PDP_SYM_WILDCARD &_pdp_sym_wildcard
#define PDP_SYM_FLOAT &_pdp_sym_float
#define PDP_SYM_INT &_pdp_sym_int
#define PDP_SYM_SYMBOL &_pdp_sym_symbol
#define PDP_SYM_PACKET &_pdp_sym_packet
#define PDP_SYM_POINTER &_pdp_sym_pointer
#define PDP_SYM_LIST &_pdp_sym_list
#define PDP_SYM_INVALID &_pdp_sym_invalid
#define PDP_SYM_QUESTION_MARK &_pdp_sym_question_mark
#define PDP_SYM_ATOM &_pdp_sym_atom
#define PDP_SYM_NULL &_pdp_sym_null
#define PDP_SYM_QUOTE_START &_pdp_sym_quote_start
#define PDP_SYM_QUOTE_END &_pdp_sym_quote_end
#define PDP_SYM_RETURN &_pdp_sym_return
#define PDP_SYM_NRETURN &_pdp_sym_nreturn
#define PDP_SYM_DEF_START &_pdp_sym_defstart
#define PDP_SYM_DEF_END &_pdp_sym_defend
#define PDP_SYM_IF &_pdp_sym_if
#define PDP_SYM_THEN &_pdp_sym_then
#define PDP_SYM_LOCAL &_pdp_sym_local
#define PDP_SYM_FORTH &_pdp_sym_forth
#define PDP_SYM_CALL &_pdp_sym_call
#define PDP_SYM_PUSH &_pdp_sym_push
#define PDP_SYM_POP &_pdp_sym_pop
#endif
--- NEW FILE: pdp_debug.h ---
#ifndef __PDP_DEBUG_H_
#define __PDP_DEBUG_H_
#include "pdp_config.h" // needed for PDP_DEBUG define
void pdp_assert_hook (char *condition, char *file, int line);
#if PDP_DEBUG
#define PDP_ASSERT(x) if (!(x)) {pdp_assert_hook(#x, __FILE__, __LINE__);}
#else
#define PDP_ASSERT(x)
#endif
#endif //__PDP_DEBUG_H_
--- NEW FILE: pdp_xwindow.h ---
/*
* Pure Data Packet header file: xwindow glue code
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
// x stuff
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include "pdp_list.h"
#include "pdp_mem.h"
/* x display class */
typedef struct _pdp_xdisplay
{
Display *dpy; // the display connection
int screen; // the screen
t_pdp_list *windowlist; // all windows belonging to this connection
// this contains (id, eventlist)
int dragbutton;
} t_pdp_xdisplay;
/* cons */
t_pdp_xdisplay *pdp_xdisplay_new(char *dpy_string);
/* des */
void pdp_xdisplay_free(t_pdp_xdisplay *d);
struct _pdp_xwindow;
void pdp_xdisplay_register_window(t_pdp_xdisplay *d, struct _pdp_xwindow *w);
void pdp_xdisplay_unregister_window(t_pdp_xdisplay *d, struct _pdp_xwindow *w);
/* x window class */
typedef struct _pdp_xwindow
{
//Display *dpy;
//int screen;
t_pdp_xdisplay *xdisplay; // the display object
Window win; // window reference
GC gc; // graphics context
Atom WM_DELETE_WINDOW;
int winwidth; // dim states
int winheight;
int winxoffset;
int winyoffset;
int initialized;
int autocreate;
char lastbut; // last button pressed (for drag)
//t_symbol *dragbutton;
float cursor;
} t_pdp_xwindow;
/* cons */
void pdp_xwindow_init(t_pdp_xwindow *b);
t_pdp_xwindow *pdp_xwindow_new(void);
/* des */
void pdp_xwindow_cleanup(t_pdp_xwindow *b);
void pdp_xwindow_free(t_pdp_xwindow *b);
/* move the pointer */
void pdp_xwindow_warppointer(t_pdp_xwindow *xwin, int x, int y);
/* fullscreen message */
void pdp_xwindow_fullscreen(t_pdp_xwindow *xwin);
/* resize window */
void pdp_xwindow_resize(t_pdp_xwindow *b, int width, int height);
/* resize window */
void pdp_xwindow_moveresize(t_pdp_xwindow *b, int xoffset, int yoffset, int width, int height);
/* fill a tile of the screen */
void pdp_xwindow_tile(t_pdp_xwindow *xwin, int x_tiles, int y_tiles, int i, int j);
/* move window */
void pdp_xwindow_move(t_pdp_xwindow *xwin, int xoffset, int yoffset);
/* receive events */
t_pdp_list *pdp_xwindow_get_eventlist(t_pdp_xwindow *xwin);
/* enable/disable cursor */
void pdp_xwindow_cursor(t_pdp_xwindow *b, int flag);
/* create xwindow. return code != NULL on succes */
int pdp_xwindow_create_on_display(t_pdp_xwindow *b, t_pdp_xdisplay *d);
/* close window */
void pdp_xwindow_close(t_pdp_xwindow *b);
/* set title */
void pdp_xwindow_title(t_pdp_xwindow *xwin, char *title);
--- NEW FILE: pdp_resample.h ---
/*
* Pure Data Packet header file. - image resampling prototypes
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#ifndef PDP_RESAMPLE_H
#define PDP_RESAMPLE_H
#include "pdp_types.h"
/* image resampling methods */
void pdp_resample_scale_bilin(s16 *src_image, s16 *dst_image, s32 src_w, s32 src_h, s32 dst_w, s32 dst_h);
void pdp_resample_scale_nn(s16 *src_image, s16 *dst_image, s32 src_w, s32 src_h, s32 dst_w, s32 dst_h);
/* USE pdp_imageproc_resample_affinemap
void pdp_resample_zoom_tiled_bilin(s16 *src_image, s16 *dst_image, s32 w, s32 h,
float zoom_x, float zoom_y, float center_x_relative, float center_y_relative);
*/
//void pdp_resample_zoom_tiled_nn(s16 *src_image, s16 *dst_image, s32 w, s32 h, float zoom_x, float zoom_y);
/* power of 2 resamplers */
void pdp_resample_halve(s16 *src_image, s16 *dst_image, s32 src_w, s32 src_h);
void pdp_resample_double(s16 *src_image, s16 *dst_image, s32 src_w, s32 src_h);
/* core routines */
//s32 pdp_resample_bilin(s16 *image, s32 width, s32 height, s32 virt_x, s32 virt_y);
#endif
--- NEW FILE: pdp_png.h ---
/*
* Pure Data Packet header file. png glue code.
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#ifndef __PDP_PNG_H__
#define __PDP_PNG_H__
int pdp_packet_bitmap_save_png_file(int packet, char *filename);
int pdp_packet_bitmap_from_png_file(char *filename);
#endif
--- NEW FILE: pdp_packet.h ---
/*
* Pure Data Packet system implementation: Packet Manager Interface
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/*
This file contains the pdp packet manager interface specification.
It is an implementation of the "Object Pool" pattern with lazy instantiation
and lazy destruction.
The pool is a growable array. It can only grow larger. Packets are represented
by an integer, which is an index in this array.
The standard "pure" packets (the ones which use a flat memory buffer) have recovery
for resource depletion (main memory). If an out of memory condition is met
on allocation of a new package, the garbage collector kicks in and frees unused
packets until the out of memory condition is solved. Since an out of memory
condition can be fatal for other parts of the program, pdp also supports a
memory limit, to ensure some kind of safety margin.
The "not so pure" packets should resolve resource conflicts in their own factory method,
since the constructor is responsible for allocating external resources. The standard
way to do this is to allocate a packet, free it's resources and allocate a new packet
until the resource allocation succeeds. Especially for these kinds of packets, the
pdp pool supports an explicit reuse method. This returns a valid packet if it can reuse
one (based on the high level type description).
Packets that don't have memory managing methods defined in the packet class
(Standard packets) are treated as a header concatenated with a flat memory buffer, and
can be copied and cloned without problems. So, if a packet contains pointers to other
data or code, it can't be a pure packet.
The interface to the packet manager contains the following managing methods:
* pdp_packet_new: create a new packet or reuse a previous one
* pdp_packet_mark_unused: release a packet
* pdp_packet_copy_ro: register a packet for read only use
* pdp_packet_copy_rw: register a packet for read/write use (this creates a copy if necessary)
* pdp_packet_clone_rw: create a new packet using a template, but don't copy the data
And two methods for raw data access
* pdp_packet_header: retreive the header of the packet
* pdp_packet_data: retreive the data buffer of the packet (only for static packets)
All the methods declared in this header are supposed to be thread safe, so you
can call them from the pd and pdp thread.
*/
#ifndef PDP_PACKET_H
#define PDP_PACKET_H
#include "pdp_symbol.h"
#include "pdp_types.h"
// this is legacy stuff: images are basic types
#include "pdp_image.h"
#include "pdp_bitmap.h"
#define PDP_HEADER_SIZE 256
/* all symbols are C-style */
#ifdef __cplusplus
extern "C"
{
#endif
typedef int (*t_pdp_factory_method)(t_pdp_symbol *); //returns bool success
/* packet class header */
typedef struct _pdp_class
{
/* packet manips: non-pure data packets (using external resources) must define these */
t_pdp_packet_method1 wakeup; /* called before returning a reused packet (rc:0->1) */
t_pdp_packet_method2 copy; /* copy data from source packet to destination packet */
t_pdp_packet_method1 cleanup; /* free packet's resources (destructor) */
t_pdp_packet_method1 sleep; /* mark_unused notify: called when refcount reaches zero */
t_pdp_symbol *type; /* type template for packet class */
t_pdp_factory_method create; /* the constructor: create a packet with uninitialized data */
}t_pdp_class;
/* TODO:
implement garbage collection for fobs.
(fobs are forth object dictionaries, but for the gc these count as lists)
*/
#define PDP_GC_COLOUR_GREY 0 /* 0 == default: object is reachable */
#define PDP_GC_COLOUR_WHITE 1
#define PDP_GC_COLOUR_BLACK 2
/* packet object header */
struct _pdp
{
/* meta info */
unsigned int type; /* main datatype of this object */
t_pdp_symbol *desc; /* high level type description (sort of a mime type) */
unsigned int size; /* datasize including header */
unsigned int flags; /* packet flags */
/* reference count */
unsigned int users; /* nb users of this object, readonly if > 1 */
/* class object */
t_pdp_class *theclass; /* if zero, the packet is a pure packet (just data, no member functions) */
u32 pad[10]; /* LATER: reserve bytes to provide compatibility with future extensions */
union /* each packet type has a unique subheader */
{
t_raw raw; /* raw subheader (for extensions unkown to pdp core system) */
struct _image image; /* (nonstandard internal) 16 bit signed planar bitmap image format */
struct _bitmap bitmap; /* (standard) bitmap image (fourcc coded) */
//t_ca ca; /* cellular automaton state data */
//t_ascii ascii; /* ascii packet */
} info;
};
/* pdp data packet type id */
#define PDP_IMAGE 1 /* 16bit signed planar scanline encoded image packet */
//RESERVED: #define PDP_CA 2 /* 1bit toroidial shifted scanline encoded cellular automaton */
//RESERVED: #define PDP_ASCII 3 /* ascii packet */
//RESERVED: #define PDP_TEXTURE 4 /* opengl texture object */
//RESERVED: #define PDP_3DCONTEXT 5 /* opengl render context */
#define PDP_BITMAP 6 /* 8bit image packet (fourcc coded??) */
//RESERVED: #define PDP_MATRIX 7 /* floating point/double matrix/vector packet (from gsl) */
#define PDP_FOB 8 /* small c->forth object wrapper */
/* PACKET FLAGS */
#define PDP_FLAG_DONOTCOPY (1<<0) /* don't copy the packet on register_rw, instead return an invalid packet */
/* class methods */
t_pdp_class *pdp_class_new(t_pdp_symbol *type, t_pdp_factory_method create);
#if 0
void pdp_class_addmethod(t_pdp_class *c, t_pdp_symbol *name, t_pdp_attribute_method method,
struct _pdp_list *in_spec, struct _pdp_list *out_spec);
#endif
/* packet factory method + registration */
int pdp_factory_newpacket(t_pdp_symbol *type);
#if 0
/* send a message to a packet (packet polymorphy)
this returns NULL on failure, or a return list
the return list should be freed by the caller */
int pdp_packet_op(t_pdp_symbol *operation, struct _pdp_list *stack);
#endif
/* debug */
void pdp_packet_print_debug(int packet);
/* hard coded packet methods */
int pdp_packet_copy_ro(int handle); /* get a read only copy */
int pdp_packet_copy_rw(int handle); /* get a read/write copy */
int pdp_packet_clone_rw(int handle); /* get an empty read/write packet of the same type (only copy header) */
void pdp_packet_mark_unused(int handle); /* indicate that you're done with the packet */
void pdp_packet_delete(int packet); /* like mark_unused, but really delete when refcount == 0 */
t_pdp* pdp_packet_header(int handle); /* get packet header */
void* pdp_packet_subheader(int handle); /* get packet subheader */
void* pdp_packet_data(int handle); /* get packet raw data */
int pdp_packet_data_size(int handle); /* get packet raw data size */
int pdp_packet_compat(int packet0, int packet1);
int pdp_packet_reuse(t_pdp_symbol *description);
int pdp_packet_create(unsigned int datatype, unsigned int datasize); /* create a new packet, don't reuse */
int pdp_packet_writable(int packet); /* returns true if packet is writable */
void pdp_packet_replace_with_writable(int *packet); /* replaces a packet with a writable copy */
//void pdp_packet_mark_unused_atomic(int *handle); /* mark unused + set reference to -1 (for thread synchro) */
/* pool stuff */
int pdp_pool_collect_garbage(void); /* free all unused packets */
void pdp_pool_set_max_mem_usage(int max); /* set max mem usage */
#ifdef __cplusplus
}
#endif
#endif
--- NEW FILE: pdp_net.h ---
#ifndef __PDP_UDP_H_
#define __PDP_UDP_H_
/*
* Pure Data Packet header: UDP protocol for raw packets
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/*
This file contains the specification of the pdp UDP transport protocol.
It is a very basic binary protocol, not very fool proof.
The protocol:
A header packet is transmitted first. This contains mime type information,
and the size of and number of packets to be received.
The connection id:
Currently it is just a random number from the libc rand() function
this should be accurate enough.
*/
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <pthread.h>
#include <netdb.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/* some defs */
#define MAX_UDP_PACKET 1472
#define RESEND_MAX_CHUNKS ((MAX_UDP_PACKET - sizeof(t_pdp_udp_header))/sizeof(unsigned int))
#define PDP_UDP_VERSION 1
/* a pdp udp packet is prepended with this header */
typedef struct _pdp_udp_header
{
char signature[4]; /* must be "PDP" */;
unsigned int version; /* protocol version */
unsigned int connection_id; /* the 'connection' id */
unsigned int sequence_number; /* sequence number. negative: control packet: body contains meta info */
} t_pdp_udp_header;
/* the data part for a new connection */
#define PDP_UDP_NEW -1 /* start a new transmission */
typedef struct _pdp_udp_new
{
unsigned int data_size; /* the size of the packets */
unsigned int nb_chunks; /* number of chunks in pdp to be transmitted */
unsigned int chunk_size; /* the maximum chunk size */
char type[0]; /* the packet type */
// the tail part is the mime type, for creation and reassembly
} t_pdp_udp_newpacket;
#define PDP_UDP_DONE -2 /* transmission is done */
#define PDP_UDP_RESEND -3 /* request retransmission of certain chunks. empty: transmission ok */
#define PDP_UDP_ACKNEW -4 /* acknowledge reception of new packet header */
/* receiver and sender classes (transport layer) */
#define PDP_UDP_BUFSIZE 0xF000
/* RECEIVER */
typedef struct _pdp_udp_receiver
{
// buffer for receiving
t_pdp_udp_header x_header; //pdp over udp header
char x_buf[PDP_UDP_BUFSIZE]; //send buffer
unsigned int x_zero_terminator; // to prevent runaway strings
unsigned int x_buf_size; //size of the received data in the buffer (excluding the header)
// buffer for sending
t_pdp_udp_header x_resend_header; // header of the resend packet
unsigned int x_resend_chunks[RESEND_MAX_CHUNKS]; // body contains the chunks to resend
unsigned int x_resend_udp_packet_size;
// transmission info
unsigned int x_connection_id;
unsigned int x_nb_chunks;
unsigned int x_chunk_size;
unsigned int *x_chunk_list;
char *x_data_type;
unsigned int x_data_size;
void *x_data;
struct sockaddr_in x_source_socket;
int x_sslen;
int x_receive_finished;
int x_packet_transferred;
int x_socket; //socket used for sending
struct sockaddr_in x_sa; //address struct
} t_pdp_udp_receiver;
/* setup */
t_pdp_udp_receiver *pdp_udp_receiver_new(int port);
void pdp_udp_receiver_free(t_pdp_udp_receiver *x);
/* reset connection (wait for new packet) */
void pdp_udp_receiver_reset(t_pdp_udp_receiver *x);
/* receive, returns 1 on success, 0 on timeout, -1 on error */
int pdp_udp_receiver_receive(t_pdp_udp_receiver *x, unsigned int timeout_ms);
/* get meta & data */
char *pdp_udp_receiver_type(t_pdp_udp_receiver *x);
unsigned int pdp_udp_receiver_size(t_pdp_udp_receiver *x);
void *pdp_udp_receiver_data(t_pdp_udp_receiver *x);
/* SENDER */
typedef struct _pdp_udp_sender
{
// desired udp packet size
unsigned int x_udp_payload_size;
// current packet && communication info
unsigned int x_connection_id;
char *x_data_type;
void *x_data;
unsigned int x_data_size;
unsigned int x_chunk_size;
unsigned int *x_chunk_list;
unsigned int x_nb_chunks;
unsigned int x_chunk_list_size;
// connection data
int x_socket; //socket used for sending
struct sockaddr_in x_sa; //address struct
unsigned int x_sleepgrain_us; //pause between sends (the poor man's flow control) (0 == no sleep)
unsigned int x_sleep_count;
unsigned int x_sleep_period;
unsigned int x_timeout_us;
// temp buffer for sending
t_pdp_udp_header x_header;
char x_buf[PDP_UDP_BUFSIZE];
unsigned int x_buf_size;
// temp buffer for receiving
t_pdp_udp_header x_resend_header;
unsigned int x_resend_chunks[RESEND_MAX_CHUNKS];
unsigned int x_resend_items;
} t_pdp_udp_sender;
/* some flow control variables */
void pdp_udp_sender_timeout_us(t_pdp_udp_sender *x, unsigned int timeout_us);
void pdp_udp_sender_sleepgrain_us(t_pdp_udp_sender *x, unsigned int sleepgrain_us);
void pdp_udp_sender_sleepperiod(t_pdp_udp_sender *x, unsigned int sleepperiod);
void pdp_udp_sender_udp_packet_size(t_pdp_udp_sender *x, unsigned int udp_packet_size);
/* setup */
t_pdp_udp_sender *pdp_udp_sender_new(void);
void pdp_udp_sender_free(t_pdp_udp_sender *x);
/* connect */
void pdp_udp_sender_connect(t_pdp_udp_sender *x, char *host, unsigned int port);
/* send, returns 1 on success, 0 on error */
int pdp_udp_sender_send(t_pdp_udp_sender *x, char* type, unsigned int size, void *data);
#endif
--- NEW FILE: pdp_dpd_command.h ---
/*
* Pure Data Packet header file. DPD command class
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/* this object implements a dpd command 'factory and recycling center' */
/* a small note on commands & dpd
dpd uses a different synchronization model than pdp.
in pdp, objects only pass once the process method in the process thread
has finished.
in dpd a context packet propagates a context trough an tree of objects,
depth first, following the pd messages. it is possible to send a list of
contexts trough a tree before the actual processing starts. therefore,
each time a context passes trough an object, a new command object (or memento)
needs to be created that saves the state of the rendering context. the command
factory class can be used to create these commands.
the dpd base class queues a command object and calls the registered method
on the object instead of the dpd object. so a command object is in fact
a delegate of the dpd object in question.
*/
#ifndef PDP_DPD_COMMAND
#define PDP_DPD_COMMAND
#include "pdp_types.h"
/* COMMAND BASE CLASS */
typedef struct _pdp_dpd_command
{
struct _pdp_dpd_command *next;
u32 used;
} t_pdp_dpd_command;
/* COMMAND LIST (COMMAND FACTORY) CLASS */
typedef struct _pdp_dpd_commandfactory
{
u32 nb_commands;
u32 command_size;
t_pdp_dpd_command *command;
} t_pdp_dpd_commandfactory;
/* COMMAND LIST METHODS */
void pdp_dpd_commandfactory_init(t_pdp_dpd_commandfactory *x, u32 size);
void pdp_dpd_commandfactory_free(t_pdp_dpd_commandfactory *x);
t_pdp_dpd_command *pdp_dpd_commandfactory_get_new_command(t_pdp_dpd_commandfactory *x);
/* COMMAND METHODS */
void pdp_dpd_command_suicide(void *);
#endif
--- NEW FILE: pdp.h ---
/*
* Pure Data Packet header file.
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#ifndef PDP_H
#define PDP_H
/* header and subheader size in bytes */
#include <string.h>
#include <stdlib.h>
#include "pdp_pd.h"
/* config stuff */
#include "pdp_config.h"
/* debug stuff */
#include "pdp_debug.h"
/* some typedefs */
#include "pdp_types.h"
/* pdp's symbol handling */
#include "pdp_symbol.h"
/* the list object */
#include "pdp_list.h"
/* memory management */
#include "pdp_mem.h"
/* console messages */
#include "pdp_post.h"
/* PDP_IMAGE COMPONENTS */
/* header and methods for the built in image packet type */
#include "pdp_image.h"
/* low level image processing and high level dispatching routines */
#include "pdp_imageproc.h"
/* low level image conversion routines */
#include "pdp_llconv.h"
/* low level image resampling routines */
#include "pdp_resample.h"
/* PDP_BITMAP COMPONENTS */
/* header and methods for the built in bitmap packet type */
#include "pdp_bitmap.h"
/* PDP_MATRIX COMPONENTS */
#include "pdp_matrix.h"
/* PDP SYSTEM COMPONENTS */
/* packet pool stuff */
#include "pdp_packet.h"
/* processing queue object */
#include "pdp_queue.h"
/* several communication helper methods (pd specific) */
#include "pdp_comm.h"
/* type handling subsystem */
#include "pdp_type.h"
/* dpd command stuff */
#include "pdp_dpd_command.h"
/* BACKWARDS COMPAT STUFF */
#include "pdp_compat.h"
#endif
/*
PDP CORE API OVERVIEW
pdp_packet_* : packet methods, first argument is packet id
new: construct a raw packet (depreciated)
new_*: construct packet of specific type/subtype/...
mark_unused: release
mark_passing: conditional release (release on first copy ro/rw)
copy_ro: readonly (shared) copy
copy_rw: private copy
clone_rw: private copy (copies only meta data, not the content)
header: get the raw header (t_pdp *)
data: get the raw data (void *)
pass_if_valid: send a packet to pd outlet, if it is valid
replace_if_valid delete packet and replace with new one, if new is valid
copy_ro_or_drop: copy readonly, or don't copy if dest slot is full + send drop notify
copy_rw_or_drop: same, but private copy
get_description: retrieve type info
convert_ro: same as copy_ro, but with an automatic conversion matching a type template
convert_rw: same as convert_ro, but producing a private copy
pdp_pool_* : packet pool methods
collect_garbage: manually free all unused resources in packet pool
pdp_queue_* : processing queue methods
add: add a process method + callback
finish: wait until a specific task is done
wait: wait until processing queue is done
pdp_control_* : central pdp control hub methods
notify_drop: notify that a packet has been dropped
pdp_type_* : packet type mediator methods
description_match: check if two type templates match
register_conversion: register a type conversion program
NOTE: it is advised to derive your module from the pdp base class defined in pdp_base.h
instead of communicating directly with the pdp core
*/
--- NEW FILE: pdp_image.h ---
/*
* Pure Data Packet system implementation. Image packet interface
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/*
This file contains methods for the image packets
pdp_packet_new_* methods are several image packet constructors
It also contains some pdp_type_ methods, for type checking
and conversion.
*/
#ifndef PDP_IMAGE_H
#define PDP_IMAGE_H
#include "pdp_symbol.h"
#include "pdp_types.h"
/* image subheader */
typedef struct _image
{
/* standard images */
unsigned int encoding; /* image encoding (data format) */
unsigned int width; /* image width in pixels */
unsigned int height; /* image height in pixels */
unsigned int depth; /* number of colour planes if PDP_IMAGE_MCHP */
unsigned int chanmask; /* channel bitmask to mask out inactive channels (0 == not used) */
} t_image;
/* image encodings */
#define PDP_IMAGE_YV12 1 /* 24bbp: 16 bit Y plane followed by 16 bit 2x2 subsampled V and U planes.*/
#define PDP_IMAGE_GREY 2 /* 16bbp: 16 bit Y plane */
#define PDP_IMAGE_MCHP 4 /* generic 16bit multi channel planar (16 bit 3D tensor) */
/* slice synchro information */
#define PDP_IMAGE_SLICE_FIRST (1<<0)
#define PDP_IMAGE_SLICE_LAST (1<<1)
#define PDP_IMAGE_SLICE_BODY (1<<2)
/* all symbols are C style */
#ifdef __cplusplus
extern "C"
{
#endif
/* validate and compat check */
bool pdp_packet_image_isvalid(int packet);
bool pdp_packet_image_compat(int packet0, int packet1);
/* short cuts to create specific packets */
int pdp_packet_new_image(u32 encoding, u32 width, u32 height);
int pdp_packet_new_image_YCrCb(u32 width, u32 height);
int pdp_packet_new_image_grey(u32 width, u32 height);
int pdp_packet_new_image_mchp(u32 width, u32 height, u32 depth);
#define pdp_packet_new_image_multi pdp_packet_new_image_mchp
/* get info */
t_pdp_symbol *pdp_packet_image_get_description(int packet);
t_image *pdp_packet_image_info(int packet);
/* set props */
void pdp_packet_image_set_chanmask(int packet, unsigned int chanmask);
#ifdef __cplusplus
}
#endif
#endif
--- NEW FILE: pdp_ascii.h ---
/*
* Pure Data Packet header file. ascii packet type.
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#ifndef PDP_H
#define PDP_H
/* ascii data packet */
typedef struct
{
unsigned int encoding; /* image encoding (data format) */
unsigned int width; /* image width in pixels */
unsigned int height; /* image height in pixels */
} t_ascii;
/* ascii encodings */
#define PDP_ASCII_BW 1 /* 8 bit per character black and white.*/
#define PDP_ASCII_IBM 2 /* 16 bit per character colour (8 bit character, 8 bit colour, like good old text framebuffers.*/
#define PDP_ASCII_RGB 3 /* 64 bit per character colour (8 bit character, 3x8 bit RGB */
#endif
--- NEW FILE: pdp_post.h ---
/*
* Pure Data Packet header file. pdp logging.
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#ifndef _PDP_POST_H_
#define _PDP_POST_H_
/* write a message to log (console) */
void pdp_post_n(char *fmt, ...);
void pdp_post(char *fmt, ...);
#endif
Update of /cvsroot/pure-data/externals/pdp/modules/generic
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv6756/modules/generic
Added Files:
Makefile README pdp_convert.c pdp_del.c pdp_description.c
pdp_inspect.c pdp_loop.c pdp_rawin.c pdp_rawout.c pdp_reg.c
pdp_route.c pdp_snap.c pdp_trigger.c pdp_udp_receive.c
pdp_udp_send.c
Log Message:
checking in pdp 0.12.4 from http://zwizwa.fartit.com/pd/pdp/pdp-0.12.4.tar.gz
--- NEW FILE: pdp_convert.c ---
/*
* Pure Data Packet module.
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include "pdp.h"
typedef struct pdp_convert_struct
{
t_object x_obj;
t_symbol *x_type_mask;
t_outlet *x_outlet0;
int x_packet0;
} t_pdp_convert;
static void pdp_convert_type_mask(t_pdp_convert *x, t_symbol *s)
{
x->x_type_mask = s;
}
static void pdp_convert_input_0(t_pdp_convert *x, t_symbol *s, t_floatarg f)
{
int p = (int)f;
int passes, i;
if (s== gensym("register_ro")){
pdp_packet_mark_unused(x->x_packet0);
if (x->x_type_mask->s_name[0])
x->x_packet0 = pdp_packet_convert_ro(p, pdp_gensym(x->x_type_mask->s_name));
else
x->x_packet0 = pdp_packet_copy_ro(p);
}
if ((s == gensym("process")) && (-1 != x->x_packet0)){
pdp_packet_pass_if_valid(x->x_outlet0, &x->x_packet0);
}
}
t_class *pdp_convert_class;
void pdp_convert_free(t_pdp_convert *x)
{
pdp_packet_mark_unused(x->x_packet0);
}
void *pdp_convert_new(t_symbol *s)
{
t_pdp_convert *x = (t_pdp_convert *)pd_new(pdp_convert_class);
x->x_type_mask = s;
x->x_outlet0 = outlet_new(&x->x_obj, &s_anything);
x->x_packet0 = -1;
return (void *)x;
}
#ifdef __cplusplus
extern "C"
{
#endif
void pdp_convert_setup(void)
{
pdp_convert_class = class_new(gensym("pdp_convert"), (t_newmethod)pdp_convert_new,
(t_method)pdp_convert_free, sizeof(t_pdp_convert), 0, A_DEFSYMBOL, A_NULL);
class_addmethod(pdp_convert_class, (t_method)pdp_convert_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL);
class_addsymbol(pdp_convert_class, (t_method)pdp_convert_type_mask);
}
#ifdef __cplusplus
}
#endif
--- NEW FILE: pdp_udp_receive.c ---
/*
* Pure Data Packet module.
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/* this module sends receives an udp packet stream and converts to pdp packet */
#include "pdp_net.h"
#include "pdp.h"
#include "pdp_resample.h"
#define D if(0)
typedef struct pdp_udp_receive_struct
{
t_object x_obj;
t_float x_f;
/* receiver object */
t_pdp_udp_receiver *x_receiver;
/* thread vars */
pthread_attr_t x_attr;
pthread_t x_thread;
int x_exit_thread;
/* packet queue */
int x_index;
int x_packet[2];
/* polling clock */
t_clock *x_clock;
/* outlet */
t_outlet *x_outlet0;
} t_pdp_udp_receive;
static void clock_tick(t_pdp_udp_receive *x)
{
/* poll for new packet */
pdp_pass_if_valid(x->x_outlet0, &x->x_packet[!x->x_index]);
clock_delay(x->x_clock, 1.0f);
}
static void *receive_thread(void *threaddata)
{
t_pdp_udp_receive *x = (t_pdp_udp_receive *)threaddata;
t_pdp *pdp_header = 0;
void *pdp_data = 0;
int tmp_packet = -1;
char *type = 0;
unsigned int size = 0;
/* listen for packets */
while (!x->x_exit_thread){
switch(pdp_udp_receiver_receive(x->x_receiver, 100)){
case -1:
/* error */
goto exit;
case 0:
/* timeout */
continue;
case 1:
/* data ready */
break;
}
/* create a new packet */
type = pdp_udp_receiver_type(x->x_receiver);
tmp_packet = pdp_factory_newpacket(pdp_gensym(type));
pdp_header = pdp_packet_header(tmp_packet);
pdp_data = pdp_packet_data(tmp_packet);
/* check if we were able to create the pdp packet */
if (!(pdp_header && pdp_data)){
post("pdp_netreceive: can't create packet (type %s)", type);
pdp_udp_receiver_reset(x->x_receiver);
continue;
}
/* check size */
size = pdp_udp_receiver_size(x->x_receiver);
if ((pdp_header->size - PDP_HEADER_SIZE) != size){
pdp_packet_mark_unused(tmp_packet);
tmp_packet = -1;
post("pdp_netreceive: invalid packet size %d (pdp packet size = %d)",
size, pdp_header->size - PDP_HEADER_SIZE);
continue;
}
/* copy the data */
memcpy(pdp_data, pdp_udp_receiver_data(x->x_receiver), size);
/* copy the packet into queue */
x->x_index ^= 1;
pdp_packet_mark_unused(x->x_packet[x->x_index]);
x->x_packet[x->x_index] = tmp_packet;
}
exit:
post("thread exiting");
return 0;
}
static void pdp_udp_receive_free(t_pdp_udp_receive *x)
{
int i;
void* retval;
x->x_exit_thread = 1; // wait for thread to finish
pthread_join(x->x_thread, &retval);
pdp_udp_receiver_free(x->x_receiver);
pdp_packet_mark_unused(x->x_packet[0]);
pdp_packet_mark_unused(x->x_packet[1]);
}
t_class *pdp_udp_receive_class;
void *pdp_udp_receive_new(t_floatarg fport)
{
int i;
int port;
struct hostent *hp;
t_pdp_udp_receive *x = (t_pdp_udp_receive *)pd_new(pdp_udp_receive_class);
x->x_outlet0 = outlet_new(&x->x_obj, &s_anything);
x->x_packet[0] = -1;
x->x_packet[1] = -1;
x->x_index = 0;
port = (fport == 0.0f) ? 7777 : fport;
x->x_receiver = pdp_udp_receiver_new(port);
/* setup thread stuff & create thread */
x->x_exit_thread = 0;
pthread_attr_init(&x->x_attr);
pthread_attr_setschedpolicy(&x->x_attr, SCHED_OTHER);
pthread_create(&x->x_thread, &x->x_attr, receive_thread, x);
/* setup the clock */
x->x_clock = clock_new(x, (t_method)clock_tick);
clock_delay(x->x_clock, 0);
post("pdp_netreceive: WARNING: experimental object");
return (void *)x;
}
#ifdef __cplusplus
extern "C"
{
#endif
void pdp_udp_receive_setup(void)
{
pdp_udp_receive_class = class_new(gensym("pdp_netreceive"), (t_newmethod)pdp_udp_receive_new,
(t_method)pdp_udp_receive_free, sizeof(t_pdp_udp_receive), 0, A_DEFFLOAT, A_NULL);
}
#ifdef __cplusplus
}
#endif
--- NEW FILE: pdp_loop.c ---
/*
* Pure Data Packet module.
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/*
pdp_loop: a looping packet delay line
messages:
record x: start recording at position x (default = 0)
stop: stop recording
float: output packet at position
bang: output next packet
rewind: rewind
loop: set looping mode
*/
#include "pdp.h"
#include "pdp_internals.h"
typedef struct pdp_loop_struct
{
t_object x_obj;
t_float x_f;
t_outlet *x_outlet0;
t_outlet *x_outlet1;
int *x_packet;
int x_order; /* size of the packet loop */
int x_play_head; /* next position to play back */
int x_record_head; /* next position to record to */
int x_loop;
int x_recording_frames; /* nb frames left to record */
//int x_recording_shot; /* single frame recording is on */
} t_pdp_loop;
static void pdp_loop_input_0(t_pdp_loop *x, t_symbol *s, t_floatarg f)
{
int in;
int out;
int packet;
/* if recording is off, ignore packet */
if ((!x->x_recording_frames)) return;
/* store a packet on register ro */
if (s == gensym("register_ro")){
/* delete old & store new */
in = x->x_record_head; //% x->x_order;
pdp_packet_mark_unused(x->x_packet[in]);
packet = pdp_packet_copy_ro((int)f);
x->x_packet[in] = packet;
/* advance head & decrease record counter */
x->x_recording_frames--;
x->x_record_head++;
/* turn off recording if we are at the end */
if (x->x_record_head == x->x_order) x->x_recording_frames = 0;
}
}
static void pdp_loop_bang(t_pdp_loop *x){
int out;
int packet;
out = x->x_play_head;
/* don't play if we're at the end of the sequence and looping is disabled */
if ((!x->x_loop) && (out >= x->x_order)) return;
/* wrap index */
out %= x->x_order;
/* output the current packet */
packet = x->x_packet[out];
outlet_float(x->x_outlet1, (float)out); // output location
if (-1 != packet) outlet_pdp(x->x_outlet0, packet); // output packet
/* advance playback head */
x->x_play_head++;
}
static void pdp_loop_reset(t_pdp_loop *x)
{
int i;
for (i=0; i<x->x_order; i++) {
pdp_packet_mark_unused(x->x_packet[i]);
x->x_packet[i] = -1;
}
x->x_play_head = 0;
x->x_record_head = 0;
}
static void pdp_loop_record(t_pdp_loop *x, t_floatarg fstart, t_floatarg fdur)
{
int istart = (int)fstart;
int idur = (int)fdur;
istart %= x->x_order;
if (istart<0) istart+= x->x_order;
if (idur <= 0) idur = x->x_order - istart;
x->x_record_head = istart;
x->x_recording_frames = idur;
}
static void pdp_loop_store(t_pdp_loop *x, t_floatarg f)
{
int i = (int)f;
i %= x->x_order;
if (i<0) i+= x->x_order;
x->x_record_head = i;
x->x_recording_frames = 1;
}
static void pdp_loop_seek(t_pdp_loop *x, t_floatarg f)
{
int i = (int)f;
i %= x->x_order;
if (i<0) i+= x->x_order;
x->x_play_head = i;
}
static void pdp_loop_seek_hot(t_pdp_loop *x, t_floatarg f)
{
pdp_loop_seek(x, f);
pdp_loop_bang(x);
}
static void pdp_loop_stop(t_pdp_loop *x)
{
x->x_recording_frames = 0;
}
static void pdp_loop_loop(t_pdp_loop *x, t_floatarg f)
{
if (f == 0.0f) x->x_loop = 0;
if (f == 1.0f) x->x_loop = 1;
}
static void pdp_loop_free(t_pdp_loop *x)
{
pdp_loop_reset(x);
pdp_dealloc (x->x_packet);
}
static int pdp_loop_realsize(float f)
{
int order = (int)f;
if (order <= 2) order = 2;
return order;
}
static void pdp_loop_resize(t_pdp_loop *x, t_floatarg f)
{
int i;
int order = pdp_loop_realsize(f);
int *newloop;
/* if size didn't change, do nothing */
if (x->x_order == order) return;
/* create new array */
newloop = (int *)pdp_alloc(sizeof(int) * order);
/* extend it */
if (x->x_order < order){
/* copy old packets */
for (i=0; i<x->x_order; i++) newloop[i] = x->x_packet[i];
/* loop extend the rest */
for (i=x->x_order; i<order; i++) newloop[i] = pdp_packet_copy_ro(x->x_packet[i % x->x_order]);
}
/* or shrink it */
else {
/* copy part of old packets */
for (i=0; i<order; i++) newloop[i] = x->x_packet[i];
/* delete the other part of old packets */
for (i=order; i<x->x_order; i++) pdp_packet_mark_unused(x->x_packet[i]);
/* adjust heads */
x->x_play_head %= order;
x->x_record_head %= order;
}
/* delete old line & store new */
pdp_dealloc (x->x_packet);
x->x_packet = newloop;
x->x_order = order;
}
t_class *pdp_loop_class;
void *pdp_loop_new(t_floatarg f)
{
int i;
int order = pdp_loop_realsize(f);
t_pdp_loop *x = (t_pdp_loop *)pd_new(pdp_loop_class);
x->x_order = order;
x->x_packet = (int *)pdp_alloc(sizeof(int)*order);
for(i=0; i<order; i++) x->x_packet[i] = -1;
x->x_play_head = 0;
x->x_record_head = 0;
x->x_recording_frames = 0;
inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("seek"));
x->x_outlet0 = outlet_new(&x->x_obj, &s_anything);
x->x_outlet1 = outlet_new(&x->x_obj, &s_anything);
x->x_loop = 1;
return (void *)x;
}
#ifdef __cplusplus
extern "C"
{
#endif
void pdp_loop_setup(void)
{
pdp_loop_class = class_new(gensym("pdp_loop"), (t_newmethod)pdp_loop_new,
(t_method)pdp_loop_free, sizeof(t_pdp_loop), 0, A_DEFFLOAT, A_NULL);
class_addmethod(pdp_loop_class, (t_method)pdp_loop_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL);
class_addmethod(pdp_loop_class, (t_method)pdp_loop_record, gensym("record"), A_DEFFLOAT, A_DEFFLOAT, A_NULL);
class_addmethod(pdp_loop_class, (t_method)pdp_loop_store, gensym("store"), A_DEFFLOAT, A_NULL);
class_addmethod(pdp_loop_class, (t_method)pdp_loop_reset, gensym("reset"), A_NULL);
class_addmethod(pdp_loop_class, (t_method)pdp_loop_bang, gensym("bang"), A_NULL);
class_addmethod(pdp_loop_class, (t_method)pdp_loop_stop, gensym("stop"), A_NULL);
class_addmethod(pdp_loop_class, (t_method)pdp_loop_seek, gensym("seek"), A_DEFFLOAT, A_NULL);
class_addmethod(pdp_loop_class, (t_method)pdp_loop_resize, gensym("size"), A_FLOAT, A_NULL);
class_addmethod(pdp_loop_class, (t_method)pdp_loop_loop, gensym("loop"), A_FLOAT, A_NULL);
class_addfloat(pdp_loop_class, (t_method)pdp_loop_seek_hot);
}
#ifdef __cplusplus
}
#endif
--- NEW FILE: Makefile ---
current: all_modules
include ../../Makefile.config
PDP_MOD = pdp_reg.o pdp_del.o pdp_snap.o pdp_trigger.o \
pdp_route.o pdp_inspect.o pdp_loop.o pdp_description.o pdp_convert.o \
pdp_udp_send.o pdp_udp_receive.o pdp_rawin.o pdp_rawout.o
# build generic modules
all_modules: $(PDP_MOD)
clean:
rm -f *~
rm -f *.o
--- NEW FILE: pdp_udp_send.c ---
/*
* Pure Data Packet module.
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/* this module sends a pure packet out as an udp packet stream */
#include "pdp_net.h"
#include "pdp.h"
#include "pdp_resample.h"
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <pthread.h>
#include <netdb.h>
#define DD if(0) // print DROP debug info
#define D if(0) // print extra connection debug info
#define V if(0) // be verbose (parameter setting feedback)
typedef struct pdp_udp_send_struct
{
t_object x_obj;
t_float x_f;
/* sender object */
t_pdp_udp_sender *x_sender;
/* pthread vars */
pthread_mutex_t x_mut;
pthread_cond_t x_cond_data_ready;
pthread_cond_t x_cond_send_done;
pthread_t x_thread;
int x_exit_thread;
// drop info
unsigned int x_drop;
t_outlet *x_outlet0;
// packet queue
int x_nb_packets;
int x_read_packet;
int x_write_packet;
int *x_packet;
} t_pdp_udp_send;
/* some synchro code */
static int _wait_for_feeder(t_pdp_udp_send *x)
{
/* only use locking when there is no data */
if (x->x_packet[x->x_read_packet] == -1){
/* signal sending is done */
pthread_mutex_lock(&x->x_mut);
pthread_cond_signal(&x->x_cond_send_done);
/* wait until there is an item in the queue */
while((x->x_packet[x->x_read_packet] == -1) && (!x->x_exit_thread)){
pthread_cond_wait(&x->x_cond_data_ready, &x->x_mut);
}
pthread_mutex_unlock(&x->x_mut);
/* check if we need to stop the thread */
if (x->x_exit_thread) return 0;
}
return !x->x_exit_thread;
}
static void _signal_sender(t_pdp_udp_send *x)
{
pthread_mutex_lock(&x->x_mut);
pthread_cond_signal(&x->x_cond_data_ready);
pthread_mutex_unlock(&x->x_mut);
}
static void _wait_until_done(t_pdp_udp_send *x)
{
pthread_mutex_lock(&x->x_mut);
while (x->x_packet[x->x_read_packet] != -1){
pthread_cond_wait(&x->x_cond_send_done, &x->x_mut);
}
pthread_mutex_unlock(&x->x_mut);
}
static void _remove_packet_from_queue(t_pdp_udp_send *x)
{
}
static void *send_thread(void *threaddata)
{
t_pdp_udp_send *x = (t_pdp_udp_send *)threaddata;
/* main thread loop */
/* get a pdp packet from queue */
/* send header packet and make sure it has arrived */
/* send a chunk burst */
/* send done packet and get the resend list */
/* repeat until send list is empty */
while (_wait_for_feeder(x)){
t_pdp *header;
void *data;
/* check if we have a valid pdp packet */
if ((!(header = pdp_packet_header(x->x_packet[x->x_read_packet])))
||(!(data = pdp_packet_data(x->x_packet[x->x_read_packet])))
||(0 == header->desc)) goto remove; /* nothing to transmit */
/* send it */
pdp_udp_sender_send(x->x_sender,
header->desc->s_name,
header->size - PDP_HEADER_SIZE, data);
remove:
/* remove packet from queue */
pdp_packet_mark_unused(x->x_packet[x->x_read_packet]);
x->x_packet[x->x_read_packet] = -1;
x->x_read_packet++;
x->x_read_packet %= x->x_nb_packets;
}
return 0;
}
static void pdp_udp_send_input_0(t_pdp_udp_send *x, t_symbol *s, t_floatarg f)
{
int p = (int)f;
int my_p;
int transferred = 0;
if (s== gensym("register_ro")){
// check if packet can be stored in the queue
// this is possible if the current write location does not contain a packet
if (x->x_packet[x->x_write_packet] == -1){
// get the packet outside of the lock
my_p = pdp_packet_copy_ro(p);
// add to queue (do we really need to lock here?>
//pthread_mutex_lock(&x->x_mut); // LOCK
x->x_packet[x->x_write_packet] = my_p;
x->x_write_packet++;
x->x_write_packet %= x->x_nb_packets;
transferred = 1;
//pthread_mutex_unlock(&x->x_mut); // UNLOCK
}
// signal sender if transfer succeded
if (transferred) _signal_sender(x);
// else send a float indicating the number of drops so far
else{
x->x_drop++;
//outlet_float(x->x_outlet0, (float)x->x_drop);
DD post ("pdp_netsend: DROP: queue full");
}
}
}
/* some flow control hacks */
static void pdp_udp_send_timeout(t_pdp_udp_send *x, float f)
{
if (f < 0.0f) f = 0.0f;
pdp_udp_sender_timeout_us(x->x_sender, 1000.0f * f);
}
static void pdp_udp_send_sleepgrain(t_pdp_udp_send *x, float f)
{
if (f < 0.0f) f = 0.0f;
pdp_udp_sender_sleepgrain_us(x->x_sender, 1000.0f * f);
}
static void pdp_udp_send_sleepperiod(t_pdp_udp_send *x, float f)
{
if (f < 0.0f) f = 0.0f;
pdp_udp_sender_sleepperiod(x->x_sender, f);
}
static void pdp_udp_send_udpsize(t_pdp_udp_send *x, float f)
{
if (f < 0.0f) f = 0.0f;
pdp_udp_sender_udp_packet_size(x->x_sender, f);
}
static void pdp_udp_send_connect(t_pdp_udp_send *x, t_symbol *shost, t_float fport)
{
unsigned int port;
struct hostent *hp;
/* suspend until sending thread is finished */
_wait_until_done(x);
/* set target address */
port = (fport == 0.0f) ? 7777 : fport;
if (shost == gensym("")) shost = gensym("127.0.0.1");
/* connect */
pdp_udp_sender_connect(x->x_sender, shost->s_name, port);
}
static void pdp_udp_send_free(t_pdp_udp_send *x)
{
int i;
void* retval;
_wait_until_done(x); // send all remaining packets
x->x_exit_thread = 1; // .. and wait for thread to finish
_signal_sender(x);
pthread_join(x->x_thread, &retval);
pdp_udp_sender_free(x->x_sender);
for (i=0; i<x->x_nb_packets; i++) pdp_packet_mark_unused(x->x_packet[i]);
pdp_dealloc(x->x_packet);
}
t_class *pdp_udp_send_class;
void *pdp_udp_send_new(void)
{
int i;
pthread_attr_t attr;
t_pdp_udp_send *x = (t_pdp_udp_send *)pd_new(pdp_udp_send_class);
x->x_sender = pdp_udp_sender_new();
//x->x_outlet0 = outlet_new(&x->x_obj, &s_anything);
x->x_nb_packets = 4;
x->x_packet = malloc(sizeof(int)*x->x_nb_packets);
for (i=0; i<x->x_nb_packets; i++) x->x_packet[i] = -1;
x->x_read_packet = 0;
x->x_write_packet = 0;
x->x_drop = 0;
/* setup thread stuff & create thread */
x->x_exit_thread = 0;
pthread_mutex_init(&x->x_mut, NULL);
pthread_cond_init(&x->x_cond_data_ready, NULL);
pthread_cond_init(&x->x_cond_send_done, NULL);
pthread_attr_init(&attr);
//pthread_attr_setschedpolicy(&attr, SCHED_OTHER);
pthread_create(&x->x_thread, &attr, send_thread, x);
post("pdp_netsend: WARNING: experimental object");
return (void *)x;
}
#ifdef __cplusplus
extern "C"
{
#endif
void pdp_udp_send_setup(void)
{
pdp_udp_send_class = class_new(gensym("pdp_netsend"), (t_newmethod)pdp_udp_send_new,
(t_method)pdp_udp_send_free, sizeof(t_pdp_udp_send), 0, A_NULL);
class_addmethod(pdp_udp_send_class, (t_method)pdp_udp_send_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL);
class_addmethod(pdp_udp_send_class, (t_method)pdp_udp_send_sleepgrain, gensym("sleepgrain"), A_FLOAT, A_NULL);
class_addmethod(pdp_udp_send_class, (t_method)pdp_udp_send_sleepperiod, gensym("sleepperiod"), A_FLOAT, A_NULL);
class_addmethod(pdp_udp_send_class, (t_method)pdp_udp_send_udpsize, gensym("udpsize"), A_FLOAT, A_NULL);
class_addmethod(pdp_udp_send_class, (t_method)pdp_udp_send_timeout, gensym("timeout"), A_FLOAT, A_NULL);
class_addmethod(pdp_udp_send_class, (t_method)pdp_udp_send_connect, gensym("connect"), A_SYMBOL, A_FLOAT, A_NULL);
}
#ifdef __cplusplus
}
#endif
--- NEW FILE: pdp_rawin.c ---
/*
* Pure Data Packet module. packet forth console
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <time.h>
#include <fcntl.h>
#include "pdp_pd.h"
#include "pdp_debug.h"
#include "pdp_list.h"
#include "pdp_comm.h"
#include "pdp_post.h"
#include "pdp_packet.h"
#define PERIOD 1.0f
#define D if (1)
/* raw input from a unix pipe */
typedef struct rawin_struct
{
/* pd */
t_object x_obj;
t_outlet *x_outlet;
t_outlet *x_sync_outlet;
t_clock *x_clock;
/* comm */
t_pdp_list *x_queue; // packet queue
/* thread */
pthread_mutex_t x_mut;
pthread_attr_t x_attr;
pthread_t x_thread;
/* sync */
int x_giveup; // 1-> terminate reader thread
int x_active; // 1-> reader thread is launched
int x_done; // 1-> reader thread has exited
/* config */
t_symbol *x_pipe;
t_pdp_symbol *x_type;
} t_rawin;
static inline void lock(t_rawin *x){pthread_mutex_lock(&x->x_mut);}
static inline void unlock(t_rawin *x){pthread_mutex_unlock(&x->x_mut);}
static void rawin_close(t_rawin *x);
static void tick(t_rawin *x)
{
/* send all packets in queue to outlet */
lock(x);
while (x->x_queue->elements){
outlet_pdp_atom(x->x_outlet, x->x_queue->first);
pdp_list_pop(x->x_queue); // pop stale reference
}
unlock(x);
clock_delay(x->x_clock, PERIOD);
/* check if thread is done */
if (x->x_done) rawin_close(x);
}
static void move_current_to_queue(t_rawin *x, int packet)
{
lock(x);
pdp_list_add_back(x->x_queue, a_packet, (t_pdp_word)packet);
unlock(x);
}
static void *rawin_thread(void *y)
{
int pipe;
int packet = -1;
t_rawin *x = (t_rawin *)y;
int period_sec;
int period_usec;
//D pdp_post("pipe: %s", x->x_pipe->s_name);
//D pdp_post("type: %s", x->x_type->s_name);
/* open pipe */
if (-1 == (pipe = open(x->x_pipe->s_name, O_RDONLY|O_NONBLOCK))){
perror(x->x_pipe->s_name);
goto exit;
}
/* main loop (packets) */
while(1){
void *data = 0;
int left = -1;
/* create packet */
if (-1 != packet){
pdp_post("WARNING: deleting stale packet");
pdp_packet_mark_unused(packet);
}
packet = pdp_factory_newpacket(x->x_type);
if (-1 == packet){
pdp_post("ERROR: can't create packet. type = %s", x->x_type->s_name);
goto exit;
}
/* fill packet */
data = pdp_packet_data(packet);
left = pdp_packet_data_size(packet);
// D pdp_post("packet %d, data %x, size %d", packet, data, left);
/* inner loop: pipe reads */
while(left){
fd_set inset;
struct timeval tv = {0,10000};
/* check if we need to stop */
if (x->x_giveup){
pdp_packet_mark_unused(packet);
goto close;
}
/* select, with timeout */
FD_ZERO(&inset);
FD_SET(pipe, &inset);
if (-1 == select(pipe+1, &inset, NULL,NULL, &tv)){
pdp_post("select error");
goto close;
}
/* if ready, read, else retry */
if (FD_ISSET(pipe, &inset)){
int bytes = read(pipe, data, left);
if (!bytes){
/* if no bytes are read, pipe is closed */
goto close;
}
data += bytes;
left -= bytes;
}
}
/* move to queue */
move_current_to_queue(x, packet);
packet = -1;
}
close:
/* close pipe */
close(pipe);
exit:
x->x_done = 1;
return 0;
}
static void rawin_type(t_rawin *x, t_symbol *type)
{
x->x_type = pdp_gensym(type->s_name);
}
static void rawin_open(t_rawin *x, t_symbol *pipe)
{
/* save pipe name if not empty */
if (pipe->s_name[0]) {x->x_pipe = pipe;}
if (x->x_active) {
pdp_post("already open");
return;
}
/* start thread */
x->x_giveup = 0;
x->x_done = 0;
pthread_create(&x->x_thread, &x->x_attr, rawin_thread , x);
x->x_active = 1;
}
static void rawin_close(t_rawin *x)
{
if (!x->x_active) return;
/* stop thread: set giveup + wait */
x->x_giveup = 1;
pthread_join(x->x_thread, NULL);
x->x_active = 0;
/* notify */
outlet_bang(x->x_sync_outlet);
pdp_post("connection to %s closed", x->x_pipe->s_name);
}
static void rawin_free(t_rawin *x)
{
rawin_close(x);
clock_free(x->x_clock);
pdp_tree_strip_packets(x->x_queue);
pdp_tree_free(x->x_queue);
}
t_class *rawin_class;
static void *rawin_new(t_symbol *pipe, t_symbol *type)
{
t_rawin *x;
pdp_post("%s %s", pipe->s_name, type->s_name);
/* allocate & init */
x = (t_rawin *)pd_new(rawin_class);
x->x_outlet = outlet_new(&x->x_obj, &s_anything);
x->x_sync_outlet = outlet_new(&x->x_obj, &s_anything);
x->x_clock = clock_new(x, (t_method)tick);
x->x_queue = pdp_list_new(0);
x->x_active = 0;
x->x_giveup = 0;
x->x_done = 0;
x->x_type = pdp_gensym("image/YCrCb/320x240"); //default
x->x_pipe = gensym("/tmp/pdpraw"); // default
pthread_attr_init(&x->x_attr);
pthread_mutex_init(&x->x_mut, NULL);
clock_delay(x->x_clock, PERIOD);
/* args */
rawin_type(x, type);
if (pipe->s_name[0]) x->x_pipe = pipe;
return (void *)x;
}
#ifdef __cplusplus
extern "C"
{
#endif
void pdp_rawin_setup(void)
{
int i;
/* create a standard pd class: [pdp_rawin pipe type] */
rawin_class = class_new(gensym("pdp_rawin"), (t_newmethod)rawin_new,
(t_method)rawin_free, sizeof(t_rawin), 0, A_DEFSYMBOL, A_DEFSYMBOL, A_NULL);
/* add global message handler */
class_addmethod(rawin_class, (t_method)rawin_type, gensym("type"), A_SYMBOL, A_NULL);
class_addmethod(rawin_class, (t_method)rawin_open, gensym("open"), A_DEFSYMBOL, A_NULL);
class_addmethod(rawin_class, (t_method)rawin_close, gensym("close"), A_NULL);
}
#ifdef __cplusplus
}
#endif
--- NEW FILE: pdp_del.c ---
/*
* Pure Data Packet module.
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include "pdp.h"
typedef struct pdp_del_struct
{
t_object x_obj;
t_float x_f;
t_outlet *x_outlet0;
t_outlet **x_outlet;
int *x_packet;
int x_order;
int x_head;
int x_delay;
} t_pdp_del;
static void pdp_del_input_0(t_pdp_del *x, t_symbol *s, t_floatarg f)
{
int in;
int out;
int packet;
/* if this is a register_ro message or register_rw message, register with packet factory */
/* if this is a process message, start the processing + propagate stuff to outputs */
if (s == gensym("register_ro")){
in = (x->x_head % x->x_order);
//post("pdp_del: marking unused packed id=%d on loc %d", x->x_packet[0], in);
pdp_packet_mark_unused(x->x_packet[in]);
packet = pdp_packet_copy_ro((int)f);
// TODO TODO TODO !!!!
//pdp_packet_print_debug((int)f);
x->x_packet[in] = packet;
//post("pdp_del: writing packed id=%d on loc %d", packet, in);
}
else if (s == gensym("process")){
out = (((x->x_head + x->x_delay)) % x->x_order);
packet = x->x_packet[out];
pdp_packet_pass_if_valid(x->x_outlet0, &x->x_packet[out]);
/*
if (-1 != packet){
//post("pdp_del: packet %d has id %d", out, packet);
pdp_packet_mark_unused(packet);
outlet_pdp(x->x_outlet0, packet);
x->x_packet[out] = -1;
}
else {
//post("pdp_del: packet %d is empty", out);
}
*/
x->x_head = (x->x_head + x->x_order - 1) % x->x_order;
}
}
static void pdp_del_delay(t_pdp_del *x, t_floatarg fdel)
{
int del = (int)fdel;
if (del < 0) del = 0;
if (del >= x->x_order) del = x->x_order - 1;
x->x_delay = del;
}
static void pdp_del_reset(t_pdp_del *x)
{
int i;
for (i=0; i<x->x_order; i++) {
pdp_packet_mark_unused(x->x_packet[i]);
x->x_packet[i] = -1;
}
x->x_head = 0;
}
static void pdp_del_debug(t_pdp_del *x)
{
int i;
post ("order %d", x->x_order);
post ("delay %d", x->x_delay);
post ("head %d", x->x_head);
for (i=0; i<x->x_order; i++) {
post("%d ", x->x_packet[i]);
}
}
static void pdp_del_free(t_pdp_del *x)
{
pdp_del_reset(x);
pdp_dealloc (x->x_packet);
}
t_class *pdp_del_class;
void *pdp_del_new(t_floatarg forder, t_floatarg fdel)
{
int order = (int)forder;
int del;
int logorder;
int i;
t_pdp_del *x = (t_pdp_del *)pd_new(pdp_del_class);
del = order;
order++;
if (del < 0) del = 0;
if (order <= 2) order = 2;
//post("pdp_del: order = %d", order);
x->x_order = order;
x->x_packet = (int *)pdp_alloc(sizeof(int)*order);
for(i=0; i<order; i++) x->x_packet[i] = -1;
x->x_delay = del;
inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("delay"));
x->x_outlet0 = outlet_new(&x->x_obj, &s_anything);
return (void *)x;
}
#ifdef __cplusplus
extern "C"
{
#endif
void pdp_del_setup(void)
{
pdp_del_class = class_new(gensym("pdp_del"), (t_newmethod)pdp_del_new,
(t_method)pdp_del_free, sizeof(t_pdp_del), 0, A_DEFFLOAT, A_NULL);
class_addmethod(pdp_del_class, (t_method)pdp_del_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL);
class_addmethod(pdp_del_class, (t_method)pdp_del_delay, gensym("delay"), A_DEFFLOAT, A_NULL);
class_addmethod(pdp_del_class, (t_method)pdp_del_reset, gensym("reset"), A_NULL);
class_addmethod(pdp_del_class, (t_method)pdp_del_debug, gensym("_debug"), A_NULL);
}
#ifdef __cplusplus
}
#endif
--- NEW FILE: pdp_description.c ---
/*
* Pure Data Packet module.
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include "pdp.h"
typedef struct pdp_description_struct
{
t_object x_obj;
t_outlet *x_outlet;
} t_pdp_description;
static void pdp_description_input_pdp(t_pdp_description *x, t_symbol *s, t_floatarg f)
{
int p = (int)f;
t_symbol *rro = S_REGISTER_RO;
if (rro == s){
outlet_symbol(x->x_outlet, gensym(pdp_packet_get_description(p)->s_name));
}
}
static void pdp_description_input_dpd(t_pdp_description *x, t_symbol *s, t_floatarg f)
{
int p = (int)f;
t_symbol *ins = S_INSPECT;
if (ins == s){
outlet_symbol(x->x_outlet, gensym(pdp_packet_get_description(p)->s_name));
}
}
static void pdp_description_free(t_pdp_description *x)
{
}
t_class *pdp_description_class;
static void *pdp_description_new(t_symbol *s, int argc, t_atom *argv)
{
t_pdp_description *x = (t_pdp_description *)pd_new(pdp_description_class);
x->x_outlet = outlet_new(&x->x_obj, &s_symbol);
return (void *)x;
}
#ifdef __cplusplus
extern "C"
{
#endif
void pdp_description_setup(void)
{
pdp_description_class = class_new(gensym("pdp_description"), (t_newmethod)pdp_description_new,
(t_method)pdp_description_free, sizeof(t_pdp_description), 0, A_NULL);
class_addmethod(pdp_description_class, (t_method)pdp_description_input_pdp, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL);
class_addmethod(pdp_description_class, (t_method)pdp_description_input_dpd, gensym("dpd"), A_SYMBOL, A_DEFFLOAT, A_NULL);
}
#ifdef __cplusplus
}
#endif
--- NEW FILE: pdp_snap.c ---
/*
* Pure Data Packet module.
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include "pdp.h"
#include "pdp_internals.h"
typedef struct pdp_snap_struct
{
t_object x_obj;
t_float x_f;
t_outlet *x_outlet0;
int x_packet0;
bool x_snapnext;
} t_pdp_snap;
static void pdp_snap_bang(t_pdp_snap *x)
{
if (-1 != x->x_packet0)
outlet_pdp(x->x_outlet0, x->x_packet0);
}
static void pdp_snap_input_1(t_pdp_snap *x, t_symbol *s, t_floatarg f)
{
/* if this is a register_ro message or register_rw message, register with packet factory */
/* if this is a process message, start the processing + propagate stuff to outputs */
if (s == gensym("register_ro")){
if(x->x_snapnext) {
pdp_packet_mark_unused(x->x_packet0);
x->x_packet0 = pdp_packet_copy_ro((int)f);
x->x_snapnext = false;
}
}
}
static void pdp_snap_snap(t_pdp_snap *x)
{
x->x_snapnext = true;
}
static void pdp_snap_free(t_pdp_snap *x)
{
pdp_packet_mark_unused(x->x_packet0);
}
t_class *pdp_snap_class;
void *pdp_snap_new(void)
{
t_pdp_snap *x = (t_pdp_snap *)pd_new(pdp_snap_class);
inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("pdp"), gensym("pdp1"));
x->x_outlet0 = outlet_new(&x->x_obj, &s_anything);
x->x_packet0 = -1;
x->x_snapnext = false;
return (void *)x;
}
#ifdef __cplusplus
extern "C"
{
#endif
void pdp_snap_setup(void)
{
pdp_snap_class = class_new(gensym("pdp_snap"), (t_newmethod)pdp_snap_new,
(t_method)pdp_snap_free, sizeof(t_pdp_snap), 0, A_NULL);
class_addmethod(pdp_snap_class, (t_method)pdp_snap_bang, gensym("bang"), A_NULL);
class_addmethod(pdp_snap_class, (t_method)pdp_snap_snap, gensym("snap"), A_NULL);
class_addmethod(pdp_snap_class, (t_method)pdp_snap_input_1, gensym("pdp1"), A_SYMBOL, A_DEFFLOAT, A_NULL);
}
#ifdef __cplusplus
}
#endif
--- NEW FILE: pdp_trigger.c ---
/*
* Pure Data Packet module.
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include "pdp.h"
#include "pdp_internals.h"
/* adapted from the pd trigger object */
#define TR_BANG 0
#define TR_FLOAT 1
#define TR_SYMBOL 2
#define TR_POINTER 3
#define TR_LIST 4
#define TR_ANYTHING 5
#define TR_PDP 6
/*
$$$TODO: emplement so that it behaves like the standard trigger object
i.e. [trigger bang pdp pdp bang pdp]
register_ro and register_rw messages pass right trough,
since they're not action events, only configure events.
a bang is made equivalent to a process event.
*/
typedef struct triggerout
{
int u_type; /* outlet type from above */
t_outlet *u_outlet;
} t_triggerout;
typedef struct pdp_trigger_struct
{
t_object x_obj;
t_float x_f;
int x_n;
t_triggerout *x_vec;
} t_pdp_trigger;
static void pdp_trigger_input_pdp(t_pdp_trigger *x, t_symbol *s, t_floatarg f)
{
t_atom atom[2];
t_symbol *pdp = S_PDP;
t_symbol *prc = S_PROCESS;
t_triggerout *u;
int i;
for (i = x->x_n, u = x->x_vec + i; u--, i--;){
/* trigger bang outlet only when a process event is recieved */
if ((u->u_type == TR_BANG) && (s == prc)){
outlet_bang(u->u_outlet);
}
/* just pass the message if it is a pdp outlet */
if ((u->u_type) == TR_PDP){
SETSYMBOL(atom+0, s);
SETFLOAT(atom+1, f);
if (s == prc) outlet_anything(u->u_outlet, pdp, 1, atom);
else outlet_anything(u->u_outlet, pdp, 2, atom);
}
}
}
static void pdp_trigger_input_dpd(t_pdp_trigger *x, t_symbol *s, t_floatarg f)
{
t_atom atom[2];
t_symbol *dpd = S_DPD;
t_symbol *acc = S_ACCUMULATE;
t_triggerout *u;
int i;
int p = (int)f;
for (i = x->x_n, u = x->x_vec + i; u--, i--;){
/* trigger outlet only when an accumulate event is recieved */
if (s == acc){
/* output bang */
if (u->u_type == TR_BANG) outlet_bang(u->u_outlet);
/* output a complete dpd message if it is a pdp outlet */
if ((u->u_type) == TR_PDP){
outlet_dpd(u->u_outlet, p);
}
}
}
}
static void pdp_trigger_free(t_pdp_trigger *x)
{
pdp_dealloc(x->x_vec);
}
t_class *pdp_trigger_class;
static void *pdp_trigger_new(t_symbol *s, int argc, t_atom *argv)
{
t_pdp_trigger *x = (t_pdp_trigger *)pd_new(pdp_trigger_class);
t_atom defarg[2], *ap;
t_triggerout *u;
int i;
if (!argc)
{
argv = defarg;
argc = 2;
SETSYMBOL(&defarg[0], gensym("pdp"));
SETSYMBOL(&defarg[1], gensym("bang"));
}
x->x_n = argc;
x->x_vec = pdp_alloc(argc * sizeof(*x->x_vec));
for (i = 0, ap = argv, u = x->x_vec; i < argc; u++, ap++, i++)
{
t_atomtype thistype = ap->a_type;
char c;
if (thistype == TR_SYMBOL) c = ap->a_w.w_symbol->s_name[0];
else c = 0;
if (c == 'p')
u->u_type = TR_PDP,
u->u_outlet = outlet_new(&x->x_obj, &s_anything);
else if (c == 'b')
u->u_type = TR_BANG, u->u_outlet = outlet_new(&x->x_obj, &s_bang);
else
{
pd_error(x, "pdp_trigger: %s: bad type", ap->a_w.w_symbol->s_name);
u->u_type = TR_BANG, u->u_outlet = outlet_new(&x->x_obj, &s_bang);
}
}
return (void *)x;
}
#ifdef __cplusplus
extern "C"
{
#endif
void pdp_trigger_setup(void)
{
pdp_trigger_class = class_new(gensym("pdp_trigger"), (t_newmethod)pdp_trigger_new,
(t_method)pdp_trigger_free, sizeof(t_pdp_trigger), 0, A_GIMME, A_NULL);
class_addcreator((t_newmethod)pdp_trigger_new, gensym("pdp_t"), A_GIMME, 0);
class_addmethod(pdp_trigger_class, (t_method)pdp_trigger_input_pdp, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL);
class_addmethod(pdp_trigger_class, (t_method)pdp_trigger_input_dpd, gensym("dpd"), A_SYMBOL, A_DEFFLOAT, A_NULL);
}
#ifdef __cplusplus
}
#endif
--- NEW FILE: pdp_inspect.c ---
/*
* Pure Data Packet module.
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include "pdp.h"
/* adapted from the pd trigger object */
#define TR_BANG 0
#define TR_FLOAT 1
#define TR_SYMBOL 2
#define TR_POINTER 3
#define TR_LIST 4
#define TR_ANYTHING 5
#define TR_PDP 6
/*
$$$TODO: emplement so that it behaves like the standard trigger object
i.e. [trigger bang pdp pdp bang pdp]
register_ro and register_rw messages pass right trough,
since they're not action events, only configure events.
a bang is made equivalent to a process event.
*/
typedef struct pdp_inspect_struct
{
t_object x_obj;
t_float x_f;
t_outlet *x_outlet;
} t_pdp_inspect;
static void pdp_inspect_input_0(t_pdp_inspect *x, t_symbol *s, t_floatarg f)
{
t_atom atom[2];
t_symbol *pdp = gensym("pdp");
t_symbol *prc = gensym("process");
t_symbol *rro = gensym("register_ro");
int i;
/* if there is a reg_ro, shortcut the right outlet */
if (s == rro){
SETSYMBOL(atom+0, s);
SETFLOAT(atom+1, f);
outlet_anything(x->x_outlet, pdp, 2, atom);
SETSYMBOL(atom+0, prc);
outlet_anything(x->x_outlet, pdp, 1, atom);
}
}
static void pdp_inspect_free(t_pdp_inspect *x)
{
}
t_class *pdp_inspect_class;
static void *pdp_inspect_new(void)
{
t_pdp_inspect *x = (t_pdp_inspect *)pd_new(pdp_inspect_class);
x->x_outlet = outlet_new(&x->x_obj, &s_anything);
return (void *)x;
}
#ifdef __cplusplus
extern "C"
{
#endif
void pdp_inspect_setup(void)
{
pdp_inspect_class = class_new(gensym("pdp_inspect_ro"), (t_newmethod)pdp_inspect_new,
(t_method)pdp_inspect_free, sizeof(t_pdp_inspect), 0, A_GIMME, A_NULL);
class_addcreator((t_newmethod)pdp_inspect_new, gensym("pdp_t"), A_GIMME, 0);
class_addmethod(pdp_inspect_class, (t_method)pdp_inspect_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL);
}
#ifdef __cplusplus
}
#endif
--- NEW FILE: README ---
This directory contains generic packet processors (i.e. containers).
Should work with any packet type.
--- NEW FILE: pdp_rawout.c ---
/*
* Pure Data Packet module. packet forth console
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <time.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>
#include "pdp_pd.h"
#include "pdp_debug.h"
#include "pdp_list.h"
#include "pdp_comm.h"
#include "pdp_post.h"
#include "pdp_packet.h"
#define D if (1)
#define MAX_QUEUESIZE 4
#define PIPE_BLOCKSIZE 4096
/* raw input from a unix pipe */
typedef struct rawout_struct
{
/* pd */
t_object x_obj;
//t_outlet *x_outlet;
t_outlet *x_sync_outlet;
/* comm */
t_pdp_list *x_queue; // packet queue
/* thread */
pthread_mutex_t x_mut;
pthread_attr_t x_attr;
pthread_t x_thread;
/* sync */
int x_giveup; // 1-> terminate writer thread
int x_active; // 1-> writer thread is launched
int x_done; // 1-> writer thread has exited
/* config */
t_symbol *x_pipe;
t_pdp_symbol *x_type;
} t_rawout;
static inline void lock(t_rawout *x){pthread_mutex_lock(&x->x_mut);}
static inline void unlock(t_rawout *x){pthread_mutex_unlock(&x->x_mut);}
static void rawout_close(t_rawout *x);
static void pdp_in(t_rawout *x, t_symbol *s, t_float f)
{
/* save packet to pdp queue, if size is smaller than maxsize */
if (s == S_REGISTER_RO){
if (x->x_queue->elements < MAX_QUEUESIZE){
int p = (int)f;
p = pdp_packet_copy_ro(p);
if (p != -1){
lock(x);
pdp_list_add_back(x->x_queue, a_packet, (t_pdp_word)p);
unlock(x);
}
}
else {
pdp_post("pdp_rawout: dropping packet: (queue full)", MAX_QUEUESIZE);
}
}
/* check if thread is done */
if (x->x_done) rawout_close(x);
}
static void *rawout_thread(void *y)
{
int pipe;
int packet = -1;
t_rawout *x = (t_rawout *)y;
int period_sec;
int period_usec;
sigset_t sigvec; /* signal handling */
/* ignore pipe signal */
sigemptyset(&sigvec);
sigaddset(&sigvec,SIGPIPE);
pthread_sigmask(SIG_BLOCK, &sigvec, 0);
//D pdp_post("pipe: %s", x->x_pipe->s_name);
//D pdp_post("type: %s", x->x_type->s_name);
/* open pipe */
if (-1 == (pipe = open(x->x_pipe->s_name, O_WRONLY|O_NONBLOCK))){
perror(x->x_pipe->s_name);
goto exit;
}
/* main loop (packets) */
while(1){
void *data = 0;
int left = -1;
/* try again if queue is empty */
if (!x->x_queue->elements){
/* check if we need to stop */
if (x->x_giveup){
goto close;
}
else {
usleep(1000.0f); // sleep before polling again
continue;
}
}
/* get packet from queue */
lock(x);
packet = pdp_list_pop(x->x_queue).w_packet;
unlock(x);
/* send packet */
data = pdp_packet_data(packet);
left = pdp_packet_data_size(packet);
/* inner loop: pipe reads */
while(left){
fd_set outset;
struct timeval tv = {0,10000};
/* check if we need to stop */
if (x->x_giveup){
pdp_packet_mark_unused(packet);
goto close;
}
/* select, with timeout */
FD_ZERO(&outset);
FD_SET(pipe, &outset);
if (-1 == select(pipe+1, NULL, &outset, NULL, &tv)){
pdp_post("select error");
goto close;
}
/* if ready, read, else retry */
if (FD_ISSET(pipe, &outset)){
int bytes = write(pipe, data, left);
/* handle errors */
if (bytes <= 0){
perror(x->x_pipe->s_name);
if (bytes != EAGAIN) goto close;
}
/* or update pointers */
else{
data += bytes;
left -= bytes;
//pdp_post("left %d", left);
}
}
else {
//pdp_post("retrying write");
}
}
/* discard packet */
pdp_packet_mark_unused(packet);
}
close:
/* close pipe */
close(pipe);
exit:
x->x_done = 1;
return 0;
}
static void rawout_type(t_rawout *x, t_symbol *type)
{
x->x_type = pdp_gensym(type->s_name);
}
static void rawout_open(t_rawout *x, t_symbol *pipe)
{
/* save pipe name if not empty */
if (pipe->s_name[0]) {x->x_pipe = pipe;}
if (x->x_active) {
pdp_post("already open");
return;
}
/* start thread */
x->x_giveup = 0;
x->x_done = 0;
pthread_create(&x->x_thread, &x->x_attr, rawout_thread , x);
x->x_active = 1;
}
static void rawout_close(t_rawout *x)
{
if (!x->x_active) return;
/* stop thread: set giveup + wait */
x->x_giveup = 1;
pthread_join(x->x_thread, NULL);
x->x_active = 0;
/* notify */
outlet_bang(x->x_sync_outlet);
pdp_post("connection to %s closed", x->x_pipe->s_name);
}
static void rawout_free(t_rawout *x)
{
rawout_close(x);
pdp_tree_strip_packets(x->x_queue);
pdp_tree_free(x->x_queue);
}
t_class *rawout_class;
static void *rawout_new(t_symbol *pipe, t_symbol *type)
{
t_rawout *x;
pdp_post("%s %s", pipe->s_name, type->s_name);
/* allocate & init */
x = (t_rawout *)pd_new(rawout_class);
//x->x_outlet = outlet_new(&x->x_obj, &s_anything);
x->x_sync_outlet = outlet_new(&x->x_obj, &s_anything);
x->x_queue = pdp_list_new(0);
x->x_active = 0;
x->x_giveup = 0;
x->x_done = 0;
x->x_type = pdp_gensym("image/YCrCb/320x240"); //default
x->x_pipe = gensym("/tmp/pdpraw"); // default
pthread_attr_init(&x->x_attr);
pthread_mutex_init(&x->x_mut, NULL);
/* args */
rawout_type(x, type);
if (pipe->s_name[0]) x->x_pipe = pipe;
return (void *)x;
}
#ifdef __cplusplus
extern "C"
{
#endif
void pdp_rawout_setup(void)
{
int i;
/* create a standard pd class: [pdp_rawout pipe type] */
rawout_class = class_new(gensym("pdp_rawout"), (t_newmethod)rawout_new,
(t_method)rawout_free, sizeof(t_rawout), 0, A_DEFSYMBOL, A_DEFSYMBOL, A_NULL);
/* add global message handler */
class_addmethod(rawout_class, (t_method)pdp_in,
gensym("pdp"), A_SYMBOL, A_FLOAT, A_NULL);
class_addmethod(rawout_class, (t_method)rawout_type, gensym("type"), A_SYMBOL, A_NULL);
class_addmethod(rawout_class, (t_method)rawout_open, gensym("open"), A_DEFSYMBOL, A_NULL);
class_addmethod(rawout_class, (t_method)rawout_close, gensym("close"), A_NULL);
}
#ifdef __cplusplus
}
#endif
--- NEW FILE: pdp_route.c ---
/*
* Pure Data Packet module.
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include "pdp.h"
#include "pdp_internals.h"
// dynamic ????
#define PDP_ROUTE_MAX_NB_OUTLETS 100
typedef struct pdp_route_struct
{
t_object x_obj;
t_float x_f;
t_outlet *x_outlet[PDP_ROUTE_MAX_NB_OUTLETS];
int x_nb_outlets;
int x_route;
int x_route_next;
} t_pdp_route;
static void pdp_route_input_0(t_pdp_route *x, t_symbol *s, t_floatarg f)
{
t_atom atom[2];
t_symbol *pdp = gensym("pdp");
/* trigger on register_ro */
if (s == gensym("register_ro")){
x->x_route = x->x_route_next;
}
/* propagate the pdp message */
SETSYMBOL(atom+0, s);
SETFLOAT(atom+1, f);
outlet_anything(x->x_outlet[x->x_route], pdp, 2, atom);
}
static void pdp_route_input_0_dpd(t_pdp_route *x, t_symbol *s, t_floatarg f)
{
/* trigger on accumulate */
if (s == gensym("accumulate")){
x->x_route = x->x_route_next;
}
/* propagate the dpd message */
outlet_dpd(x->x_outlet[x->x_route], (int)f);
}
static void pdp_route_route(t_pdp_route *x, t_floatarg f)
{
int route = (int)f;
if (route < 0) route = 0;
if (route >= x->x_nb_outlets) route = x->x_nb_outlets - 1;
x->x_route_next = route;
}
static void pdp_route_free(t_pdp_route *x)
{
}
t_class *pdp_route_class;
void *pdp_route_new(t_floatarg f)
{
int nboutlets = (int)f;
int i;
t_pdp_route *x = (t_pdp_route *)pd_new(pdp_route_class);
if (nboutlets < 2) nboutlets = 2;
if (nboutlets >= PDP_ROUTE_MAX_NB_OUTLETS) nboutlets = PDP_ROUTE_MAX_NB_OUTLETS - 1;
inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("route"));
x->x_nb_outlets = nboutlets;
x->x_route = 0;
x->x_route_next = 0;
for (i=0; i<nboutlets; i++)
x->x_outlet[i] = outlet_new(&x->x_obj, &s_anything);
return (void *)x;
}
#ifdef __cplusplus
extern "C"
{
#endif
void pdp_route_setup(void)
{
pdp_route_class = class_new(gensym("pdp_route"), (t_newmethod)pdp_route_new,
(t_method)pdp_route_free, sizeof(t_pdp_route), 0, A_DEFFLOAT, A_NULL);
class_addmethod(pdp_route_class, (t_method)pdp_route_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL);
class_addmethod(pdp_route_class, (t_method)pdp_route_input_0_dpd, gensym("dpd"), A_SYMBOL, A_DEFFLOAT, A_NULL);
class_addmethod(pdp_route_class, (t_method)pdp_route_route, gensym("route"), A_DEFFLOAT, A_NULL);
}
#ifdef __cplusplus
}
#endif
--- NEW FILE: pdp_reg.c ---
/*
* Pure Data Packet module.
* Copyright (c) by Tom Schouten <pdp(a)zzz.kotnet.org>
*
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include "pdp.h"
#include "pdp_png.h"
#include "pdp_internals.h"
typedef struct pdp_reg_struct
{
t_object x_obj;
t_float x_f;
t_outlet *x_outlet0;
int x_packet0;
} t_pdp_reg;
static void pdp_reg_load_png(t_pdp_reg *x, t_symbol *s)
{
int packet;
//post("sym: %s", s->s_name);
packet = pdp_packet_bitmap_from_png_file(s->s_name);
if (-1 == packet){
post("pdp_reg: error loading png file %s", s->s_name);
}
else{
pdp_packet_mark_unused(x->x_packet0);
x->x_packet0 = packet;
}
}
static void pdp_reg_save_png(t_pdp_reg *x, t_symbol *s)
{
int newpacket = pdp_packet_convert_ro(x->x_packet0, pdp_gensym("bitmap/*/*"));
if (-1 == newpacket){
post("pdp_reg: nothing to save");
return;
}
if (!(pdp_packet_bitmap_save_png_file(newpacket, s->s_name))){
post("pdp_reg: error saving png file %s", s->s_name);
}
pdp_packet_mark_unused(newpacket);
}
static void pdp_reg_bang(t_pdp_reg *x)
{
if (-1 != x->x_packet0) outlet_pdp(x->x_outlet0, x->x_packet0);
}
static void pdp_reg_input_0(t_pdp_reg *x, t_symbol *s, t_floatarg f)
{
/* if this is a register_ro message or register_rw message, register with packet factory */
/* if this is a process message, start the processing + propagate stuff to outputs */
if (s == gensym("register_ro")){
pdp_packet_mark_unused(x->x_packet0);
x->x_packet0 = pdp_packet_copy_ro((int)f);
//post("in0ro: requested %d, got %d", (int)f, x->x_packet0);
}
else if (s == gensym("process")){
pdp_reg_bang(x);
}
}
static void pdp_reg_input_1(t_pdp_reg *x, t_symbol *s, t_floatarg f)
{
/* if this is a register_ro message or register_rw message, register with packet factory */
/* if this is a process message, start the processing + propagate stuff to outputs */
if (s == gensym("register_ro")){
pdp_packet_mark_unused(x->x_packet0);
x->x_packet0 = pdp_packet_copy_ro((int)f);
//post("in0ro: requested %d, got %d", (int)f, x->x_packet0);
}
}
static void pdp_reg_free(t_pdp_reg *x)
{
pdp_packet_mark_unused(x->x_packet0);
}
t_class *pdp_reg_class;
void *pdp_reg_new(void)
{
t_pdp_reg *x = (t_pdp_reg *)pd_new(pdp_reg_class);
inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("pdp"), gensym("pdp1"));
x->x_outlet0 = outlet_new(&x->x_obj, &s_anything);
x->x_packet0 = -1;
return (void *)x;
}
#ifdef __cplusplus
extern "C"
{
#endif
void pdp_reg_setup(void)
{
pdp_reg_class = class_new(gensym("pdp_reg"), (t_newmethod)pdp_reg_new,
(t_method)pdp_reg_free, sizeof(t_pdp_reg), 0, A_NULL);
class_addmethod(pdp_reg_class, (t_method)pdp_reg_bang, gensym("bang"), A_NULL);
class_addmethod(pdp_reg_class, (t_method)pdp_reg_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL);
class_addmethod(pdp_reg_class, (t_method)pdp_reg_input_1, gensym("pdp1"), A_SYMBOL, A_DEFFLOAT, A_NULL);
class_addmethod(pdp_reg_class, (t_method)pdp_reg_save_png, gensym("save_png"), A_SYMBOL, A_NULL);
class_addmethod(pdp_reg_class, (t_method)pdp_reg_load_png, gensym("load_png"), A_SYMBOL, A_NULL);
}
#ifdef __cplusplus
}
#endif