aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/help-pdp_xcanvas.pd158
-rw-r--r--modules/pdp_xcanvas.c539
2 files changed, 697 insertions, 0 deletions
diff --git a/doc/help-pdp_xcanvas.pd b/doc/help-pdp_xcanvas.pd
new file mode 100644
index 0000000..ed78dac
--- /dev/null
+++ b/doc/help-pdp_xcanvas.pd
@@ -0,0 +1,158 @@
+#N canvas 121 0 828 668 10;
+#X obj 227 100 bng 15 250 50 0 empty empty empty 20 8 0 8 -262144 -1
+-1;
+#X msg 123 139 loop \$1;
+#X obj 124 117 tgl 15 0 empty empty empty 20 8 0 8 -262144 -1 -1 1
+1;
+#X msg 119 80 open \$1;
+#X obj 118 56 openpanel;
+#X obj 103 39 bng 15 250 50 0 empty empty empty 20 8 0 8 -262144 -1
+-1;
+#X msg 184 101 stop;
+#X obj 36 177 pdp_v4l;
+#X obj 36 145 metro 70;
+#X obj 83 104 bng 15 250 50 0 empty empty empty 20 8 0 8 -262144 -1
+-1;
+#X msg 40 105 stop;
+#X obj 716 529 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0
+1;
+#X obj 716 581 pdp_control;
+#X msg 716 554 thread \$1;
+#X floatatom 716 642 5 0 0 0 - - -;
+#X obj 716 613 route pdp_drop;
+#X text 35 641 written by Yves Degoyon ( ydegoyon@free.fr );
+#X floatatom 189 169 5 0 0 0 - - -;
+#X text 413 470 <-- you can move video sources by dragging them around
+;
+#X obj 470 99 bng 15 250 50 0 empty empty empty 20 8 0 8 -262144 -1
+-1;
+#X msg 366 138 loop \$1;
+#X obj 367 116 tgl 15 0 empty empty empty 20 8 0 8 -262144 -1 -1 0
+1;
+#X msg 362 79 open \$1;
+#X obj 361 55 openpanel;
+#X obj 346 38 bng 15 250 50 0 empty empty empty 20 8 0 8 -262144 -1
+-1;
+#X msg 427 100 stop;
+#X obj 283 178 pdp_v4l;
+#X obj 290 154 metro 70;
+#X obj 337 113 bng 15 250 50 0 empty empty empty 20 8 0 8 -262144 -1
+-1;
+#X msg 294 114 stop;
+#X floatatom 432 168 5 0 0 0 - - -;
+#X obj 735 96 bng 15 250 50 0 empty empty empty 20 8 0 8 -262144 -1
+-1;
+#X msg 631 135 loop \$1;
+#X obj 632 113 tgl 15 0 empty empty empty 20 8 0 8 -262144 -1 -1 0
+1;
+#X msg 627 76 open \$1;
+#X obj 626 52 openpanel;
+#X obj 611 35 bng 15 250 50 0 empty empty empty 20 8 0 8 -262144 -1
+-1;
+#X msg 692 97 stop;
+#X obj 695 134 metro 70;
+#X obj 548 176 pdp_v4l;
+#X obj 548 152 metro 70;
+#X obj 595 111 bng 15 250 50 0 empty empty empty 20 8 0 8 -262144 -1
+-1;
+#X msg 552 112 stop;
+#X floatatom 697 165 5 0 0 0 - - -;
+#X text 36 605 note : the maximum number of inputs is 10;
+#X text 36 618 ( easily hackable in the code );
+#X text 544 397 Change offsets of first video source;
+#X obj 548 351 pack f f;
+#X floatatom 549 312 5 0 0 0 - - -;
+#X floatatom 599 312 5 0 0 0 - - -;
+#X obj 589 331 t b f;
+#X text 564 294 X;
+#X text 609 293 Y;
+#X msg 548 375 offset 1 \$1 \$2;
+#X obj 81 315 loadbang;
+#X msg 172 514 select \$1 \$2;
+#X msg 278 513 drag \$1 \$2;
+#X msg 366 512 unselect;
+#X msg 84 399 cursor 1;
+#X msg 82 341 offset 2 320 0;
+#X msg 81 365 offset 3 256 240;
+#X obj 134 258 pdp_scale 320 240;
+#X obj 307 255 pdp_scale 320 240;
+#X obj 496 254 pdp_scale 320 240;
+#X obj 233 471 route press drag release;
+#X obj 187 138 metro 40;
+#X obj 431 137 metro 40;
+#X obj 121 177 pdp_yqt;
+#X obj 367 177 pdp_yqt;
+#X obj 632 174 pdp_yqt;
+#X obj 234 432 pdp_xcanvas 640 480 3;
+#X text 34 591 constructor : pdp_xcanvas <width> <height> <nb inputs>
+;
+#X text 35 565 pdp_xcanvas : displaying several video sources;
+#X text 35 578 pdp_xcanvas = pdp_canvas + pdp_xv;
+#X connect 0 0 65 0;
+#X connect 1 0 67 0;
+#X connect 2 0 1 0;
+#X connect 3 0 67 0;
+#X connect 4 0 3 0;
+#X connect 5 0 4 0;
+#X connect 6 0 65 0;
+#X connect 7 0 61 0;
+#X connect 8 0 7 0;
+#X connect 9 0 8 0;
+#X connect 10 0 8 0;
+#X connect 11 0 13 0;
+#X connect 12 0 15 0;
+#X connect 13 0 12 0;
+#X connect 15 0 14 0;
+#X connect 17 0 67 1;
+#X connect 19 0 66 0;
+#X connect 20 0 68 0;
+#X connect 21 0 20 0;
+#X connect 22 0 68 0;
+#X connect 23 0 22 0;
+#X connect 24 0 23 0;
+#X connect 25 0 66 0;
+#X connect 26 0 62 0;
+#X connect 27 0 26 0;
+#X connect 28 0 27 0;
+#X connect 29 0 27 0;
+#X connect 30 0 68 1;
+#X connect 31 0 38 0;
+#X connect 32 0 69 0;
+#X connect 33 0 32 0;
+#X connect 34 0 69 0;
+#X connect 35 0 34 0;
+#X connect 36 0 35 0;
+#X connect 37 0 38 0;
+#X connect 38 0 69 0;
+#X connect 39 0 63 0;
+#X connect 40 0 39 0;
+#X connect 41 0 40 0;
+#X connect 42 0 40 0;
+#X connect 43 0 69 1;
+#X connect 47 0 53 0;
+#X connect 48 0 47 0;
+#X connect 49 0 50 0;
+#X connect 50 0 47 0;
+#X connect 50 1 47 1;
+#X connect 53 0 70 0;
+#X connect 54 0 59 0;
+#X connect 54 0 60 0;
+#X connect 55 0 70 0;
+#X connect 56 0 70 0;
+#X connect 57 0 70 0;
+#X connect 58 0 70 0;
+#X connect 59 0 70 0;
+#X connect 60 0 70 0;
+#X connect 61 0 70 1;
+#X connect 62 0 70 2;
+#X connect 63 0 70 3;
+#X connect 64 0 55 0;
+#X connect 64 1 56 0;
+#X connect 64 2 57 0;
+#X connect 65 0 67 0;
+#X connect 66 0 68 0;
+#X connect 67 0 61 0;
+#X connect 68 0 62 0;
+#X connect 69 0 63 0;
+#X connect 70 0 58 0;
+#X connect 70 0 64 0;
diff --git a/modules/pdp_xcanvas.c b/modules/pdp_xcanvas.c
new file mode 100644
index 0000000..77bf7d5
--- /dev/null
+++ b/modules/pdp_xcanvas.c
@@ -0,0 +1,539 @@
+/*
+ * PiDiP module.
+ * Copyright (c) by Yves Degoyon (ydegoyon@free.fr)
+ *
+ * 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 is an object allowing juxtaposition of frames from two inlets
+ * Written by Yves Degoyon
+ */
+
+
+
+#include "pdp.h"
+#include "pdp_xwindow.h"
+#include <math.h>
+
+static char *pdp_xcanvas_version = "pdp_xcanvas: version 0.1, display for several video sources, written by Yves Degoyon (ydegoyon@free.fr)";
+
+#define MAX_CANVAS_INPUT 10
+#define PDP_XCANVAS_AUTOCREATE_RETRY 10
+
+typedef struct pdp_xcanvas_struct
+{
+ t_object x_obj;
+ t_float x_f;
+
+ t_int x_dropped;
+ t_int x_queue_id;
+
+ t_int x_opacket;
+
+ t_int x_current;
+ t_float x_xmouse;
+ t_float x_ymouse;
+
+ t_int *x_packets;
+ t_int *x_widths;
+ t_int *x_heights;
+ t_float *x_xoffsets;
+ t_float *x_yoffsets;
+ t_int *x_sizes;
+
+ t_int x_owidth;
+ t_int x_oheight;
+ t_int x_osize;
+ t_int x_nbinputs;
+
+ // X data
+ t_outlet *x_events;
+ t_pdp_xwindow x_xwin;
+ t_pdp_xvideo x_xvid;
+ Display *x_dpy;
+ t_symbol *x_display;
+ int x_initialized;
+
+} t_pdp_xcanvas;
+
+static Bool pdp_xcanvas_shm_completion_event(Display *dpy, XEvent *ev, XPointer arg)
+{
+ if(ev->type == XShmGetEventBase(dpy) + ShmCompletion ) {
+ return True;
+ } else {
+ return False;
+ }
+}
+
+static void pdp_canvas_create(t_pdp_xcanvas* x)
+{
+ int i;
+ if(x->x_initialized) return;
+
+ post("pdp_xcanvas: pdp_canvas_create");
+
+ x->x_xwin.winwidth = x->x_owidth;
+ x->x_xwin.winheight = x->x_oheight;
+ x->x_xvid.width = x->x_owidth;
+ x->x_xvid.height = x->x_oheight;
+
+ /* manually open a display */
+ if (NULL == (x->x_dpy = XOpenDisplay(x->x_display->s_name))){
+ post("pdp_xv: cant open display %s\n",x->x_display->s_name);
+ x->x_initialized = false;
+ return;
+ }
+
+ post("pdp_xcanvas: pdp_xvideo_create_on_display");
+
+ /* create a window on the display */
+ if (!(x->x_initialized = pdp_xwindow_create_on_display(&x->x_xwin, x->x_dpy))) goto exit_close_win;
+
+ post("pdp_xcanvas: pdp_xvideo_open_on_display");
+
+ /* open an xv port on the display */
+ if (!(x->x_initialized = pdp_xvideo_open_on_display(&x->x_xvid, x->x_dpy))) goto exit_close_dpy;
+
+ x->x_xwin.initialized = True;
+
+ /* done */
+ return;
+
+ /* cleanup exits */
+ exit_close_win:
+ pdp_xwindow_close(&x->x_xwin); // cose window
+ exit_close_dpy:
+ XCloseDisplay(x->x_dpy); // close display
+ x->x_dpy = 0;
+}
+
+static void pdp_xcanvas_destroy(t_pdp_xcanvas* x)
+{
+ if (x->x_initialized){
+ pdp_xvideo_close(&x->x_xvid); // close xvideo connection
+ pdp_xwindow_close(&x->x_xwin); // close the window
+ XCloseDisplay(x->x_dpy); // close the display connection
+ x->x_dpy = 0;
+ x->x_initialized = 0;
+ }
+}
+
+static void pdp_xcanvas_cursor(t_pdp_xcanvas *x, t_floatarg f)
+{
+ pdp_xwindow_cursor(&x->x_xwin, f);
+}
+
+static void pdp_xcanvas_process_yv12(t_pdp_xcanvas *x)
+{
+ t_int px, py, ppx, ppy, ii, nbs;
+ char *pY, *pU, *pV;
+ char *ppY, *ppU, *ppV;
+ t_pdp *oheader;
+ char *odata, *pdata;
+ t_pdp *iheader;
+ t_int mx, dx, my, dy;
+
+ if ( !x->x_initialized )
+ {
+ pdp_canvas_create( x ) ;
+ }
+
+ pY = (char *)x->x_xvid.xshmimage->data;
+ pV = (char *)(x->x_xvid.xshmimage->data+x->x_osize);
+ pU = (char *)(x->x_xvid.xshmimage->data+x->x_osize+(x->x_osize>>2));
+
+ // paint it black
+ for ( py=0; py<x->x_oheight; py++)
+ {
+ memset( pY+(py*x->x_owidth), 0, x->x_owidth );
+ memset( pU+((py>>1)*(x->x_owidth>>1)), -128, (x->x_owidth>>1) );
+ memset( pV+((py>>1)*(x->x_owidth>>1)), -128, (x->x_owidth>>1) );
+ }
+
+ for ( ii=0; ii<x->x_nbinputs; ii++)
+ {
+ if ( x->x_packets[ii] != -1 )
+ {
+ if ( x->x_xoffsets[ii] < -x->x_widths[ii] ) continue;
+ if ( x->x_xoffsets[ii] > x->x_owidth ) continue;
+ if ( x->x_yoffsets[ii] < -x->x_heights[ii] ) continue;
+ if ( x->x_yoffsets[ii] > x->x_oheight ) continue;
+
+ pdata = (char *)pdp_packet_data(x->x_packets[ii]);
+ ppY = pdata;
+ ppV = pdata+x->x_sizes[ii];
+ ppU = pdata+x->x_sizes[ii]+(x->x_sizes[ii]>>2);
+
+ if ( x->x_xoffsets[ii] < 0 )
+ {
+ mx = -x->x_xoffsets[ii];
+ dx = x->x_widths[ii]+x->x_xoffsets[ii];
+ }
+ else if ( x->x_xoffsets[ii] > x->x_owidth - x->x_widths[ii] )
+ {
+ mx = 0;
+ dx = x->x_owidth-x->x_xoffsets[ii];
+ }
+ else
+ {
+ mx = 0;
+ dx = x->x_widths[ii];
+ }
+
+ if ( x->x_yoffsets[ii] < 0 )
+ {
+ my = -x->x_yoffsets[ii];
+ dy = x->x_heights[ii]+x->x_yoffsets[ii]-1;
+ }
+ else if ( x->x_yoffsets[ii] > x->x_oheight - x->x_heights[ii] )
+ {
+ my = 0;
+ dy = x->x_oheight-x->x_yoffsets[ii]-1;
+ }
+ else
+ {
+ my = 0;
+ dy = x->x_heights[ii]-1;
+ }
+
+ for ( py=x->x_yoffsets[ii]+my; py<x->x_yoffsets[ii]+dy; py++)
+ {
+ memcpy( pY+(py*x->x_owidth)+(t_int)x->x_xoffsets[ii]+mx,
+ ppY+(py-(t_int)x->x_yoffsets[ii])*x->x_widths[ii]+mx, dx );
+ memcpy( pU+((py>>1)*(x->x_owidth>>1))+((t_int)(x->x_xoffsets[ii]+mx)>>1),
+ ppU+((py-(t_int)x->x_yoffsets[ii])>>1)*(x->x_widths[ii]>>1)+(mx>>1), (dx>>1) );
+ memcpy( pV+((py>>1)*(x->x_owidth>>1))+((t_int)(x->x_xoffsets[ii]+mx)>>1),
+ ppV+((py-(t_int)x->x_yoffsets[ii])>>1)*(x->x_widths[ii]>>1)+(mx>>1), (dx>>1) );
+ }
+ }
+ }
+ return;
+}
+
+static void pdp_xcanvas_display_packet(t_pdp_xcanvas *x)
+{
+ XEvent xevent;
+
+ /* receive events & output them */
+ pdp_xwindow_send_events(&x->x_xwin, x->x_events);
+
+ /* display */
+ XvShmPutImage(x->x_xvid.dpy, x->x_xvid.xv_port, x->x_xwin.win, x->x_xwin.gc, x->x_xvid.xshmimage,
+ 0, 0, x->x_xvid.width, x->x_xvid.height, 0, 0,
+ x->x_xwin.winwidth, x->x_xwin.winheight, True);
+ XIfEvent(x->x_xvid.dpy, &xevent, pdp_xcanvas_shm_completion_event, NULL);
+ XFlush(x->x_xvid.dpy);
+}
+
+static void pdp_xcanvas_process(t_pdp_xcanvas *x, t_int ni)
+{
+ int encoding;
+ t_pdp *header = 0;
+
+ /* check if image data packets are compatible */
+ if ( (header = pdp_packet_header(x->x_packets[ni]))
+ && (PDP_BITMAP == header->type)){
+
+ /* pdp_xcanvas_process inputs and write into active inlet */
+ switch(pdp_packet_header(x->x_packets[ni])->info.image.encoding){
+
+ case PDP_BITMAP_YV12:
+ pdp_queue_add(x, pdp_xcanvas_process_yv12, pdp_xcanvas_display_packet, &x->x_queue_id);
+ break;
+
+ default:
+ post( "pdp_xcanvas : unknow image type : %d",
+ pdp_packet_header(x->x_packets[ni])->info.image.encoding );
+ break;
+
+ }
+ }
+}
+
+static void pdp_xcanvas_offset(t_pdp_xcanvas *x, t_floatarg ni, t_floatarg xoffset, t_floatarg yoffset)
+{
+ if ( ( ni < 1 ) || ( ni > x->x_nbinputs ) )
+ {
+ post( "pdp_xcanvas : offset : wrong source : %d : must be between 1 and %d", ni, x->x_nbinputs );
+ return;
+ }
+ x->x_xoffsets[(int)ni-1] = xoffset;
+ x->x_yoffsets[(int)ni-1] = yoffset;
+}
+
+static void pdp_xcanvas_select(t_pdp_xcanvas *x, t_floatarg X, t_floatarg Y)
+{
+ t_int ii;
+
+ x->x_current = -1;
+ X = X*x->x_owidth;
+ Y = Y*x->x_oheight;
+ // post( "pdp_xcanvas : select %f %f", X, Y );
+ for ( ii=0; ii<x->x_nbinputs; ii++)
+ {
+ if ( x->x_packets[ii] != -1 )
+ {
+ if ( (X >= x->x_xoffsets[ii]) && ( X < x->x_xoffsets[ii] + x->x_widths[ii] )
+ && (Y >= x->x_yoffsets[ii]) && ( Y < x->x_yoffsets[ii] + x->x_heights[ii] )
+ )
+ {
+ x->x_current = ii;
+ x->x_xmouse = X;
+ x->x_ymouse = Y;
+ }
+ }
+ }
+}
+
+static void pdp_xcanvas_drag(t_pdp_xcanvas *x, t_floatarg X, t_floatarg Y)
+{
+ X = X*x->x_owidth;
+ Y = Y*x->x_oheight;
+ // post( "pdp_xcanvas : drag %f %f", X, Y );
+ if ( x->x_current != -1 )
+ {
+ x->x_xoffsets[ x->x_current ] += (X-x->x_xmouse);
+ x->x_yoffsets[ x->x_current ] += (Y-x->x_ymouse);
+ x->x_xmouse = X;
+ x->x_ymouse = Y;
+ }
+}
+
+static void pdp_xcanvas_unselect(t_pdp_xcanvas *x)
+{
+ x->x_current = -1;
+}
+
+static void pdp_xcanvas_input(t_pdp_xcanvas *x, t_symbol *s, t_floatarg f, t_int ni)
+{
+ t_pdp *header;
+ short int *data;
+
+ /* if this is a register_ro message or register_rw message, register with packet factory */
+
+ if (s== gensym("register_rw"))
+ {
+ /* release the packet */
+ if ( x->x_packets[ni] != -1 )
+ {
+ pdp_packet_mark_unused(x->x_packets[ni]);
+ x->x_packets[ni] = -1;
+ }
+ x->x_dropped = pdp_packet_convert_ro_or_drop(&x->x_packets[ni], (int)f, pdp_gensym("bitmap/yv12/*") );
+ if ( x->x_packets[ni] != -1 )
+ {
+ header = pdp_packet_header(x->x_packets[ni]);
+ x->x_widths[ni] = header->info.image.width;
+ x->x_heights[ni] = header->info.image.height;
+ x->x_sizes[ni] = x->x_widths[ni]*x->x_heights[ni];
+ }
+ }
+
+ if ((s == gensym("process")) && (-1 != x->x_packets[ni]) && (!x->x_dropped))
+ {
+ /* add the process method and callback to the process queue */
+ pdp_xcanvas_process(x, ni);
+ }
+}
+
+static void pdp_xcanvas_input0(t_pdp_xcanvas *x, t_symbol *s, t_floatarg f)
+{
+ pdp_xcanvas_input(x, s, f, 0);
+}
+
+static void pdp_xcanvas_input1(t_pdp_xcanvas *x, t_symbol *s, t_floatarg f)
+{
+ pdp_xcanvas_input(x, s, f, 1);
+}
+
+static void pdp_xcanvas_input2(t_pdp_xcanvas *x, t_symbol *s, t_floatarg f)
+{
+ pdp_xcanvas_input(x, s, f, 2);
+}
+
+static void pdp_xcanvas_input3(t_pdp_xcanvas *x, t_symbol *s, t_floatarg f)
+{
+ pdp_xcanvas_input(x, s, f, 3);
+}
+
+static void pdp_xcanvas_input4(t_pdp_xcanvas *x, t_symbol *s, t_floatarg f)
+{
+ pdp_xcanvas_input(x, s, f, 4);
+}
+
+static void pdp_xcanvas_input5(t_pdp_xcanvas *x, t_symbol *s, t_floatarg f)
+{
+ pdp_xcanvas_input(x, s, f, 5);
+}
+
+static void pdp_xcanvas_input6(t_pdp_xcanvas *x, t_symbol *s, t_floatarg f)
+{
+ pdp_xcanvas_input(x, s, f, 6);
+}
+
+static void pdp_xcanvas_input7(t_pdp_xcanvas *x, t_symbol *s, t_floatarg f)
+{
+ pdp_xcanvas_input(x, s, f, 7);
+}
+
+static void pdp_xcanvas_input8(t_pdp_xcanvas *x, t_symbol *s, t_floatarg f)
+{
+ pdp_xcanvas_input(x, s, f, 8);
+}
+
+static void pdp_xcanvas_input9(t_pdp_xcanvas *x, t_symbol *s, t_floatarg f)
+{
+ pdp_xcanvas_input(x, s, f, 9);
+}
+
+static void pdp_xcanvas_free(t_pdp_xcanvas *x)
+{
+ t_int ii;
+
+ pdp_queue_finish(x->x_queue_id);
+ for ( ii=0; ii<x->x_nbinputs; ii++)
+ {
+ pdp_packet_mark_unused(x->x_packets[ii]);
+ }
+ pdp_packet_mark_unused(x->x_opacket);
+ if ( x->x_packets ) freebytes( x->x_packets, x->x_nbinputs*sizeof(t_int) );
+ if ( x->x_widths ) freebytes( x->x_widths, x->x_nbinputs*sizeof(t_int) );
+ if ( x->x_heights ) freebytes( x->x_heights, x->x_nbinputs*sizeof(t_int) );
+ if ( x->x_sizes ) freebytes( x->x_sizes, x->x_nbinputs*sizeof(t_int) );
+ if ( x->x_xoffsets ) freebytes( x->x_xoffsets, x->x_nbinputs*sizeof(t_float) );
+ if ( x->x_yoffsets ) freebytes( x->x_yoffsets, x->x_nbinputs*sizeof(t_float) );
+ pdp_xcanvas_destroy(x);
+ pdp_xvideo_free(&x->x_xvid);
+ pdp_xwindow_free(&x->x_xwin);
+}
+
+t_class *pdp_xcanvas_class;
+
+void *pdp_xcanvas_new(t_symbol *s, int argc, t_atom *argv)
+{
+ t_pdp_xcanvas *x = (t_pdp_xcanvas *)pd_new(pdp_xcanvas_class);
+ t_int ii;
+ char *imes[32];
+
+ if ( argc != 3 )
+ {
+ post( "pdp_xcanvas : wrong constructor : pdp_xcanvas <width> <height> <nb inputs> (argc=%d)", argc);
+ return NULL;
+ }
+ if ( argv[0].a_type != A_FLOAT || argv[1].a_type != A_FLOAT ||
+ argv[2].a_type != A_FLOAT )
+ {
+ post( "pdp_xcanvas : wrong constructor : pdp_xcanvas <width> <height> <nb inputs>");
+ return NULL;
+ }
+
+ x->x_events = outlet_new(&x->x_obj, &s_anything);
+
+ x->x_owidth = ( (int) argv[0].a_w.w_float / 8 ) * 8; // round to a multiple of 8
+ x->x_oheight = ( (int) argv[1].a_w.w_float / 8 ) * 8; // round to a multiple of 8
+ x->x_osize = x->x_owidth*x->x_oheight;
+ x->x_nbinputs = (int) argv[2].a_w.w_float;
+
+ if ( x->x_owidth < 0 )
+ {
+ post( "pdp_xcanvas : wrong width : %d", x->x_owidth);
+ return NULL;
+ }
+ if ( x->x_oheight < 0 )
+ {
+ post( "pdp_xcanvas : wrong height : %d", x->x_oheight);
+ return NULL;
+ }
+ if ( x->x_nbinputs < 0 )
+ {
+ post( "pdp_xcanvas : wrong number of inputs : %d", x->x_nbinputs);
+ return NULL;
+ }
+ if ( x->x_nbinputs > MAX_CANVAS_INPUT )
+ {
+ post( "pdp_xcanvas : number of inputs is too high : %d : only %d supported",
+ x->x_nbinputs, MAX_CANVAS_INPUT);
+ return NULL;
+ }
+
+ post ( "pdp_xcanvas : new %dx%d canvas with %d inputs", x->x_owidth, x->x_oheight, x->x_nbinputs );
+
+ x->x_packets = ( t_int* ) getbytes( x->x_nbinputs*sizeof(t_int) );
+ x->x_widths = ( t_int* ) getbytes( x->x_nbinputs*sizeof(t_int) );
+ x->x_heights = ( t_int* ) getbytes( x->x_nbinputs*sizeof(t_int) );
+ x->x_sizes = ( t_int* ) getbytes( x->x_nbinputs*sizeof(t_int) );
+ x->x_xoffsets = ( t_float* ) getbytes( x->x_nbinputs*sizeof(t_float) );
+ x->x_yoffsets = ( t_float* ) getbytes( x->x_nbinputs*sizeof(t_float) );
+
+ x->x_opacket = pdp_packet_new_image_YCrCb( x->x_owidth, x->x_oheight );
+
+ for ( ii=0; ii<x->x_nbinputs; ii++)
+ {
+ sprintf( (char*)imes, "pdp%d", ii );
+ inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("pdp"), gensym((char*)imes) );
+ x->x_packets[ii] = -1;
+ x->x_xoffsets[ii] = 0.;
+ x->x_yoffsets[ii] = 0.;
+ }
+ x->x_current = -1;
+
+ pdp_xwindow_init(&x->x_xwin);
+ pdp_xvideo_init(&x->x_xvid);
+
+ x->x_display = gensym(":0");
+ x->x_dpy = 0;
+ x->x_initialized = 0;
+
+ return (void *)x;
+}
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+void pdp_xcanvas_setup(void)
+{
+ char *imes[32];
+
+ // post( pdp_xcanvas_version );
+ pdp_xcanvas_class = class_new(gensym("pdp_xcanvas"), (t_newmethod)pdp_xcanvas_new,
+ (t_method)pdp_xcanvas_free, sizeof(t_pdp_xcanvas), 0, A_GIMME, A_NULL);
+ class_sethelpsymbol( pdp_xcanvas_class, gensym("pdp_xcanvas.pd") );
+
+ class_addmethod(pdp_xcanvas_class, (t_method)pdp_xcanvas_input0, gensym("pdp0"), A_SYMBOL, A_DEFFLOAT, A_NULL);
+ class_addmethod(pdp_xcanvas_class, (t_method)pdp_xcanvas_input1, gensym("pdp1"), A_SYMBOL, A_DEFFLOAT, A_NULL);
+ class_addmethod(pdp_xcanvas_class, (t_method)pdp_xcanvas_input2, gensym("pdp2"), A_SYMBOL, A_DEFFLOAT, A_NULL);
+ class_addmethod(pdp_xcanvas_class, (t_method)pdp_xcanvas_input3, gensym("pdp3"), A_SYMBOL, A_DEFFLOAT, A_NULL);
+ class_addmethod(pdp_xcanvas_class, (t_method)pdp_xcanvas_input4, gensym("pdp4"), A_SYMBOL, A_DEFFLOAT, A_NULL);
+ class_addmethod(pdp_xcanvas_class, (t_method)pdp_xcanvas_input5, gensym("pdp5"), A_SYMBOL, A_DEFFLOAT, A_NULL);
+ class_addmethod(pdp_xcanvas_class, (t_method)pdp_xcanvas_input6, gensym("pdp6"), A_SYMBOL, A_DEFFLOAT, A_NULL);
+ class_addmethod(pdp_xcanvas_class, (t_method)pdp_xcanvas_input7, gensym("pdp7"), A_SYMBOL, A_DEFFLOAT, A_NULL);
+ class_addmethod(pdp_xcanvas_class, (t_method)pdp_xcanvas_input8, gensym("pdp8"), A_SYMBOL, A_DEFFLOAT, A_NULL);
+ class_addmethod(pdp_xcanvas_class, (t_method)pdp_xcanvas_input9, gensym("pdp9"), A_SYMBOL, A_DEFFLOAT, A_NULL);
+ class_addmethod(pdp_xcanvas_class, (t_method)pdp_xcanvas_offset, gensym("offset"), A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, A_NULL);
+ class_addmethod(pdp_xcanvas_class, (t_method)pdp_xcanvas_select, gensym("select"), A_DEFFLOAT, A_DEFFLOAT, A_NULL);
+ class_addmethod(pdp_xcanvas_class, (t_method)pdp_xcanvas_drag, gensym("drag"), A_DEFFLOAT, A_DEFFLOAT, A_NULL);
+ class_addmethod(pdp_xcanvas_class, (t_method)pdp_xcanvas_unselect, gensym("unselect"), A_NULL);
+ class_addmethod(pdp_xcanvas_class, (t_method)pdp_xcanvas_cursor, gensym("cursor"), A_FLOAT, A_NULL);
+
+}
+
+#ifdef __cplusplus
+}
+#endif