diff options
author | Pablo Martín <caedesv@users.sourceforge.net> | 2003-09-07 21:39:37 +0000 |
---|---|---|
committer | Pablo Martín <caedesv@users.sourceforge.net> | 2003-09-07 21:39:37 +0000 |
commit | 599a8e20c02fa48bab5102d15fab79dd6b631c95 (patch) | |
tree | 80e8760e6a8fdc7d9144370dc569b38232b2b315 /system/X11 | |
parent | b509942daafa671a5b5ede267b6e786619ce8173 (diff) |
Updating to last version of pdp 0.12.2
svn path=/trunk/externals/pdp/; revision=940
Diffstat (limited to 'system/X11')
-rw-r--r-- | system/X11/Makefile | 11 | ||||
-rw-r--r-- | system/X11/pdp_xwindow.c | 529 |
2 files changed, 540 insertions, 0 deletions
diff --git a/system/X11/Makefile b/system/X11/Makefile new file mode 100644 index 0000000..0001c49 --- /dev/null +++ b/system/X11/Makefile @@ -0,0 +1,11 @@ + +OBJECTS = pdp_xwindow.o + + +include ../../Makefile.config + +all: $(OBJECTS) + +clean: + rm -f *~ + rm -f *.o diff --git a/system/X11/pdp_xwindow.c b/system/X11/pdp_xwindow.c new file mode 100644 index 0000000..563ee21 --- /dev/null +++ b/system/X11/pdp_xwindow.c @@ -0,0 +1,529 @@ +/* + * Pure Data Packet system module. - x window glue code (fairly tied to pd and pdp) + * Copyright (c) by Tom Schouten <pdp@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 code is fairly tied to pd and pdp. serves mainly as reusable glue code +// for pdp_xv, pdp_glx, pdp_3d_windowcontext, ... + + +#include "pdp.h" +#include "pdp_xwindow.h" + +#define D if(0) + + +static void pdp_xwindow_overrideredirect(t_pdp_xwindow *xwin, int b) +{ + XSetWindowAttributes new_attr; + new_attr.override_redirect = b ? True : False; + XChangeWindowAttributes(xwin->dpy, xwin->win, CWOverrideRedirect, &new_attr); + //XFlush(xwin->dpy); + +} + + +void pdp_xwindow_moveresize(t_pdp_xwindow *xwin, int xoffset, int yoffset, int width, int height) +{ + + D post("_pdp_xwindow_moveresize"); + if ((width > 0) && (height > 0)){ + xwin->winwidth = width; + xwin->winheight = height; + xwin->winxoffset = xoffset; + xwin->winyoffset = yoffset; + + if (xwin->initialized){ + XMoveResizeWindow(xwin->dpy, xwin->win, xoffset, yoffset, width, height); + XFlush(xwin->dpy); + } + } +} + + +void pdp_xwindow_fullscreen(t_pdp_xwindow *xwin) +{ + XWindowAttributes rootwin_attr; + + D post("pdp_xwindow_fullscreen"); + + /* hmm.. fullscreen and xlib the big puzzle.. + if it looks like a hack it is a hack. */ + + if (xwin->initialized){ + + XGetWindowAttributes(xwin->dpy, RootWindow(xwin->dpy, xwin->screen), &rootwin_attr ); + + //pdp_xwindow_overrideredirect(xwin, 0); + pdp_xwindow_moveresize(xwin, 0, 0, rootwin_attr.width, rootwin_attr.height); + //pdp_xwindow_overrideredirect(xwin, 1); + //XRaiseWindow(xwin->dpy, xwin->win); + //pdp_xwindow_moveresize(xwin, 0, 0, rootwin_attr.width, rootwin_attr.height); + //pdp_xwindow_overrideredirect(xwin, 0); + + + + + } +} + + +void pdp_xwindow_tile(t_pdp_xwindow *xwin, int x_tiles, int y_tiles, int i, int j) +{ + XWindowAttributes rootwin_attr; + XSetWindowAttributes new_attr; + + D post("pdp_xwindow_fullscreen"); + + if (xwin->initialized){ + int tile_w; + int tile_h; + XGetWindowAttributes(xwin->dpy, RootWindow(xwin->dpy, xwin->screen), &rootwin_attr ); + + tile_w = rootwin_attr.width / x_tiles; + tile_h = rootwin_attr.height / y_tiles; + + xwin->winwidth = (x_tiles-1) ? rootwin_attr.width - (x_tiles-1)*tile_w : tile_w; + xwin->winheight = (y_tiles-1) ? rootwin_attr.height - (y_tiles-1)*tile_h : tile_h; + xwin->winxoffset = i * tile_w; + xwin->winyoffset = j * tile_h; + + //new_attr.override_redirect = True; + //XChangeWindowAttributes(xwin->dpy, xwin->win, CWOverrideRedirect, &new_attr ); + XMoveResizeWindow(xwin->dpy, xwin->win, xwin->winxoffset, xwin->winyoffset, xwin->winwidth, xwin->winheight); + + } +} + +/* resize window */ +void pdp_xwindow_resize(t_pdp_xwindow *xwin, int width, int height) +{ + D post("pdp_xwindow_resize"); + if ((width > 0) && (height > 0)){ + xwin->winwidth = width; + xwin->winheight = height; + if (xwin->initialized){ + XResizeWindow(xwin->dpy, xwin->win, width, height); + XFlush(xwin->dpy); + } + } + //_pdp_xwindow_moveresize(xwin, xwin->winxoffset, xwin->winyoffset, width, height); +} + +/* move window */ +void pdp_xwindow_move(t_pdp_xwindow *xwin, int xoffset, int yoffset) +{ + D post("pdp_xwindow_move"); + pdp_xwindow_moveresize(xwin, xoffset, yoffset, xwin->winwidth, xwin->winheight); +} + +/* send events to a pd outlet (don't call this outside the pd thread) */ +void pdp_xwindow_send_events(t_pdp_xwindow *xwin, t_outlet *outlet) +{ + + unsigned int i; + XEvent e; + XConfigureEvent *ce = (XConfigureEvent *)&e; + XButtonEvent *be = (XButtonEvent *)&e; + XMotionEvent *me = (XMotionEvent *)&e; + t_symbol *s; + t_atom atom[2]; + char nextdrag[]="drag0"; + char but='0'; + float inv_x = 1.0f / (float)(xwin->winwidth); + float inv_y = 1.0f / (float)(xwin->winheight); + int nbEvents = XEventsQueued(xwin->dpy, QueuedAlready); + + + +#if 0 + while (nbEvents && XPending(xwin->dpy)){ + XNextEvent(xwin->dpy, &e); + nbEvents--; + if (e.xany.window != xwin->win) { + XPutBackEvent(xwin->dpy, &e); + continue; + } +#else + + while (XPending(xwin->dpy)){ + XNextEvent(xwin->dpy, &e); + //if (e.xany.window != xwin->win) continue; +#endif + + switch(e.type){ + case ConfigureNotify: + xwin->winwidth = ce->width; + xwin->winheight = ce->height; + inv_x = 1.0f / (float)(xwin->winwidth); + inv_y = 1.0f / (float)(xwin->winheight); + break; + + case ClientMessage: + if ((Atom)e.xclient.data.l[0] == xwin->WM_DELETE_WINDOW) { + //post("pdp_xv: button disabled, please send a \"close\" message to close the window"); + //pdp_xv_kaboom(x); + //destroy = 1; + } + break; + + case ButtonPress: + //post("pdp_xv: press %f %f", inv_x * (float)be->x, inv_y * (float)be->y); + SETFLOAT(atom+0,inv_x * (float)be->x); + SETFLOAT(atom+1,inv_y * (float)be->y); + outlet_anything(outlet, gensym("press"), 2, atom); + switch(be->button){ + case Button1: outlet_anything(outlet, gensym("press1"), 2, atom); but='1'; break; + case Button2: outlet_anything(outlet, gensym("press2"), 2, atom); but='2'; break; + case Button3: outlet_anything(outlet, gensym("press3"), 2, atom); but='3'; break; + case Button4: outlet_anything(outlet, gensym("press4"), 2, atom); but='4'; break; + case Button5: outlet_anything(outlet, gensym("press5"), 2, atom); but='5'; break; + default: break; + } + nextdrag[4]=but; + xwin->dragbutton = gensym(nextdrag); + break; + + case ButtonRelease: + //post("pdp_xv: release %f %f", inv_x * (float)be->x, inv_y * (float)be->y); + SETFLOAT(atom+0,inv_x * (float)be->x); + SETFLOAT(atom+1,inv_y * (float)be->y); + outlet_anything(outlet, gensym("release"), 2, atom); + switch(be->button){ + case Button1: outlet_anything(outlet, gensym("release1"), 2, atom); break; + case Button2: outlet_anything(outlet, gensym("release2"), 2, atom); break; + case Button3: outlet_anything(outlet, gensym("release3"), 2, atom); break; + case Button4: outlet_anything(outlet, gensym("release4"), 2, atom); break; + case Button5: outlet_anything(outlet, gensym("release5"), 2, atom); break; + default: break; + } + + break; + case MotionNotify: + //post("pdp_xv: drag %f %f", inv_x * (float)be->x, inv_y * (float)be->y); + SETFLOAT(atom+0,inv_x * (float)be->x); + SETFLOAT(atom+1,inv_y * (float)be->y); + outlet_anything(outlet, gensym("drag"), 2, atom); + outlet_anything(outlet, xwin->dragbutton, 2, atom); + break; + + default: + //post("pdp_xv: unknown event"); + break; + } + + } + +} + + + +void pdp_xwindow_cursor(t_pdp_xwindow *xwin, t_floatarg f) +{ + if (!xwin->initialized) return; + + if (f == 0) { + static char data[] = {0}; + + Cursor cursor; + Pixmap blank; + XColor dummy; + + blank = XCreateBitmapFromData(xwin->dpy, xwin->win, data, 1, 1); + cursor = XCreatePixmapCursor(xwin->dpy, blank, blank, &dummy, + &dummy, 0, 0); + XFreePixmap(xwin->dpy, blank); + XDefineCursor(xwin->dpy, xwin->win,cursor); + } + else + XUndefineCursor(xwin->dpy, xwin->win); + + xwin->cursor = f; +} + +/* create xwindow */ +int pdp_xwindow_create_on_display(t_pdp_xwindow *xwin, Display *dpy) +{ + XEvent e; + unsigned int i; + + /* check if already opened */ + if( xwin->initialized ){ + post("pdp_xwindow_create_on_display: window already created"); + goto exit; + } + + xwin->dpy = dpy; + + /* create a window */ + xwin->screen = DefaultScreen(xwin->dpy); + + + xwin->win = XCreateSimpleWindow( + xwin->dpy, + RootWindow(xwin->dpy, xwin->screen), xwin->winxoffset, xwin->winyoffset, xwin->winwidth, xwin->winheight, 0, + BlackPixel(xwin->dpy, xwin->screen), + BlackPixel(xwin->dpy, xwin->screen)); + + + /* enable handling of close window event */ + xwin->WM_DELETE_WINDOW = XInternAtom(xwin->dpy, "WM_DELETE_WINDOW", True); + (void)XSetWMProtocols(xwin->dpy, xwin->win, &xwin->WM_DELETE_WINDOW, 1); + + if(!(xwin->win)){ + /* clean up mess */ + post("pdp_xwindow_create_on_display: could not create window. closing.\n"); + //XCloseDisplay(xwin->dpy); NOT OWNER + xwin->dpy = 0; + xwin->initialized = false; + goto exit; + } + + /* select input events */ + XSelectInput(xwin->dpy, xwin->win, StructureNotifyMask | ButtonPressMask | ButtonReleaseMask | MotionNotify | ButtonMotionMask); + //XSelectInput(xwin->dpy, xwin->win, StructureNotifyMask); + + + /* set window title */ + XStoreName(xwin->dpy, xwin->win, "pdp"); + + + /* map */ + XMapWindow(xwin->dpy, xwin->win); + + /* create graphics context */ + xwin->gc = XCreateGC(xwin->dpy, xwin->win, 0, 0); + + /* catch mapnotify */ + for(;;){ + XNextEvent(xwin->dpy, &e); + if (e.type == MapNotify) break; + } + + + /* we're done initializing */ + xwin->initialized = true; + + /* disable/enable cursor */ + pdp_xwindow_cursor(xwin, xwin->cursor); + + exit: + return xwin->initialized; + +} + +void pdp_xwindow_init(t_pdp_xwindow *xwin) +{ + xwin->dpy = 0; + xwin->screen = -1; + + xwin->winwidth = 320; + xwin->winheight = 240; + xwin->winxoffset = 0; + xwin->winyoffset = 0; + + xwin->initialized = 0; + + xwin->cursor = 0; + xwin->dragbutton = gensym("drag1"); + +} + + +void pdp_xwindow_close(t_pdp_xwindow *xwin) +{ + + XEvent e; + + if (xwin->initialized){ + XFreeGC(xwin->dpy, xwin->gc); + XDestroyWindow(xwin->dpy, xwin->win); + while(XPending(xwin->dpy)) XNextEvent(xwin->dpy, &e); + xwin->dpy = 0; + xwin->initialized = false; + } + +} + +void pdp_xwindow_free(t_pdp_xwindow *x) +{ + // close win + pdp_xwindow_close(x); + + // no more dynamic data to free +} + + + +// some more x specific stuff: XVideo + +static void pdp_xvideo_create_xvimage(t_pdp_xvideo *xvid, int width, int height) +{ + int i; + long size; + + //post("pdp_xvideo_create_xvimage"); + + xvid->width = width; + xvid->height = height; + size = (xvid->width * xvid->height + (((xvid->width>>1)*(xvid->height>>1))<<1)); + //post("create xvimage %d %d", xvid->width, xvid->height); + xvid->data = (unsigned char *)pdp_alloc(size); + for (i=0; i<size; i++) xvid->data[i] = i; + xvid->xvi = XvCreateImage(xvid->dpy, xvid->xv_port, xvid->xv_format, (char *)xvid->data, xvid->width, xvid->height); + xvid->last_encoding = -1; + if ((!xvid->xvi) || (!xvid->data)) post ("ERROR CREATING XVIMAGE"); + //post("created xvimag data:%x xvi:%x",xvid->data,xvid->xvi); + +} + +static void pdp_xvideo_destroy_xvimage(t_pdp_xvideo *xvid) +{ + if(xvid->data) pdp_dealloc(xvid->data); + if (xvid->xvi) XFree(xvid->xvi); + xvid->xvi = 0; + xvid->data = 0; +} + +void pdp_xvideo_display_packet(t_pdp_xvideo *xvid, t_pdp_xwindow *xwin, int packet) +{ + t_pdp *header = pdp_packet_header(packet); + void *data = pdp_packet_data(packet); + t_bitmap * bm = pdp_packet_bitmap_info(packet); + unsigned int width, height, encoding, size, nbpixels; + + /* some checks: only display when initialized and when pacet is bitmap YV12 */ + if (!xvid->initialized) return; + if (!header) return; + if (!bm) return; + + width = bm->width; + height = bm->height; + encoding = bm->encoding; + size = (width * height + (((width>>1)*(height>>1))<<1)); + nbpixels = width * height; + + if (PDP_BITMAP != header->type) return; + if (PDP_BITMAP_YV12 != encoding) return; + + /* check if xvimage needs to be recreated */ + if ((width != xvid->width) || (height != xvid->height)){ + //post("pdp_xv: replace image"); + pdp_xvideo_destroy_xvimage(xvid); + pdp_xvideo_create_xvimage(xvid, width, height); + } + + /* copy the data to the XvImage buffer */ + memcpy(xvid->data, data, size); + + /* display */ + XvPutImage(xvid->dpy,xvid->xv_port, xwin->win,xwin->gc,xvid->xvi, + 0,0,xvid->width,xvid->height, 0,0,xwin->winwidth,xwin->winheight); + XFlush(xvid->dpy); + + + +} + + + +void pdp_xvideo_close(t_pdp_xvideo* xvid) +{ + if (xvid->initialized){ + if (xvid->xvi) pdp_xvideo_destroy_xvimage(xvid); + XvUngrabPort(xvid->dpy, xvid->xv_port, CurrentTime); + xvid->xv_port = 0; + xvid->dpy = 0; + xvid->screen = -1; + xvid->last_encoding = -1; + xvid->initialized = false; + } +} + +void pdp_xvideo_free(t_pdp_xvideo* xvid) +{ + // close xvideo port (and delete XvImage) + pdp_xvideo_close(xvid); + + // no more dynamic data to free + +} + +void pdp_xvideo_init(t_pdp_xvideo *xvid) +{ + + xvid->dpy = 0; + xvid->screen = -1; + + xvid->xv_format = FOURCC_YV12; + xvid->xv_port = 0; + + xvid->width = 320; + xvid->height = 240; + + xvid->data = 0; + xvid->xvi = 0; + + xvid->initialized = 0; + xvid->last_encoding = -1; + +} + +int pdp_xvideo_open_on_display(t_pdp_xvideo *xvid, Display *dpy) +{ + unsigned int ver, rel, req, ev, err, i, j; + unsigned int adaptors; + int formats; + XvAdaptorInfo *ai; + + if (xvid->initialized) return 1; + if (!dpy) return 0; + xvid->dpy = dpy; + + if (Success != XvQueryExtension(xvid->dpy,&ver,&rel,&req,&ev,&err)) return 0; + + /* find + lock port */ + if (Success != XvQueryAdaptors(xvid->dpy,DefaultRootWindow(xvid->dpy),&adaptors,&ai)) + return 0; + for (i = 0; i < adaptors; i++) { + if ((ai[i].type & XvInputMask) && (ai[i].type & XvImageMask)) { + for (j=0; j < ai[i].num_ports; j++){ + if (Success != XvGrabPort(xvid->dpy,ai[i].base_id+j,CurrentTime)) { + //fprintf(stderr,"INFO: Xvideo port %ld on adapter %d: is busy, skipping\n",ai[i].base_id+j, i); + } + else { + xvid->xv_port = ai[i].base_id + j; + goto breakout; + } + } + } + } + + + breakout: + + XFree(ai); + if (0 == xvid->xv_port) return 0; + post("pdp_xvideo: grabbed port %d on adaptor %d", xvid->xv_port, i); + xvid->initialized = 1; + pdp_xvideo_create_xvimage(xvid, xvid->width, xvid->height); + return 1; +} + + |