aboutsummaryrefslogtreecommitdiff
path: root/modules/pdp_xv.c
diff options
context:
space:
mode:
Diffstat (limited to 'modules/pdp_xv.c')
-rw-r--r--modules/pdp_xv.c646
1 files changed, 0 insertions, 646 deletions
diff --git a/modules/pdp_xv.c b/modules/pdp_xv.c
deleted file mode 100644
index fde5409..0000000
--- a/modules/pdp_xv.c
+++ /dev/null
@@ -1,646 +0,0 @@
-/*
- * Pure Data Packet module.
- * 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.
- *
- */
-
-/*
-
-pdp xvideo output
-
-*/
-
-// 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 */
-
-// pdp stuff
-#include "pdp.h"
-#include "pdp_llconv.h"
-
-
-/* initial image dimensions */
-#define PDP_XV_W 320
-#define PDP_XV_H 240
-
-#define PDP_XV_AUTOCREATE_RETRY 10
-
-
-typedef struct pdp_xv_struct
-{
- t_object x_obj;
- t_float x_f;
- t_outlet *x_outlet;
-
- int x_packet0;
- int x_queue_id;
- t_symbol *x_display;
-
- Display *x_dpy;
- int x_screen;
- Window x_win;
- GC x_gc;
- Atom x_WM_DELETE_WINDOW;
-
- int x_xv_format;
- int x_xv_port;
-
- int x_winwidth;
- int x_winheight;
-
- XvImage *x_xvi;
- unsigned char *x_data;
- unsigned int x_width;
- unsigned int x_height;
- int x_last_encoding;
-
- int x_initialized;
- int x_autocreate;
-
- float x_cursor;
- t_symbol *x_dragbutton;
-
-
-} t_pdp_xv;
-
-
-static int xv_init(t_pdp_xv *x)
-{
- unsigned int ver, rel, req, ev, err, i, j;
- unsigned int adaptors;
- int formats;
- XvAdaptorInfo *ai;
-
- if (Success != XvQueryExtension(x->x_dpy,&ver,&rel,&req,&ev,&err)) return 0;
-
- /* find + lock port */
- if (Success != XvQueryAdaptors(x->x_dpy,DefaultRootWindow(x->x_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(x->x_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 {
- x->x_xv_port = ai[i].base_id + j;
- goto breakout;
- }
- }
- }
- }
-
-
- breakout:
-
- XFree(ai);
- if (0 == x->x_xv_port) return 0;
- post("pdp_xv: grabbed port %d on adaptor %d", x->x_xv_port, i);
- return 1;
-}
-
-
-void pdp_xv_create_xvimage(t_pdp_xv *x)
-{
-
- long size = (x->x_width * x->x_height + (((x->x_width>>1)*(x->x_height>>1))<<1));
- //post("create xvimage %d %d", x->x_width, x->x_height);
- x->x_data = (unsigned char *)malloc(size);
- x->x_xvi = XvCreateImage(x->x_dpy, x->x_xv_port, x->x_xv_format, (char *)x->x_data, x->x_width, x->x_height);
- x->x_last_encoding = -1;
- if ((!x->x_xvi) || (!x->x_data)) post ("ERROR CREATING XVIMAGE");
- //post("created xvimag data:%x xvi:%x",x->x_data,x->x_xvi);
-
-}
-
-void pdp_xv_destroy_xvimage(t_pdp_xv *x)
-{
- if(x->x_data) free(x->x_data);
- if (x->x_xvi) XFree(x->x_xvi);
- x->x_xvi = 0;
- x->x_data = 0;
-}
-
-
-static void pdp_xv_cursor(t_pdp_xv *x, t_floatarg f)
-{
- if (!x->x_initialized) return;
-
- if (f == 0) {
- static char data[1] = {0};
-
- Cursor cursor;
- Pixmap blank;
- XColor dummy;
-
- blank = XCreateBitmapFromData(x->x_dpy, x->x_win, data, 1, 1);
- cursor = XCreatePixmapCursor(x->x_dpy, blank, blank, &dummy,
- &dummy, 0, 0);
- XFreePixmap(x->x_dpy, blank);
- XDefineCursor(x->x_dpy, x->x_win,cursor);
- }
- else
- XUndefineCursor(x->x_dpy, x->x_win);
-
- x->x_cursor = f;
-}
-
-
-static void pdp_xv_destroy(t_pdp_xv* x)
-{
- XEvent e;
-
- if (x->x_initialized){
- XFreeGC(x->x_dpy, x->x_gc);
- XDestroyWindow(x->x_dpy, x->x_win);
- while(XPending(x->x_dpy)) XNextEvent(x->x_dpy, &e);
- XvUngrabPort(x->x_dpy, x->x_xv_port, CurrentTime);
- pdp_xv_destroy_xvimage(x);
- XCloseDisplay(x->x_dpy);
- x->x_initialized = false;
-
- }
-
-}
-
-static void pdp_xv_resize(t_pdp_xv* x, t_floatarg width, t_floatarg height)
-{
- if (x->x_initialized && (width>0) && (height>0)){
- XResizeWindow(x->x_dpy, x->x_win, (unsigned int)width, (unsigned int)height);
- XFlush(x->x_dpy);
- }
-}
-
-static void pdp_xv_create(t_pdp_xv* x)
-{
- unsigned int *uintdata = (unsigned int *)(x->x_data);
- XEvent e;
- unsigned int i;
-
-
- if( x->x_initialized ){
- //post("pdp_xv: window already created");
- return;
- }
-
- 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;
- }
-
- /* init xvideo */
- if (xv_init(x)){
-
- pdp_xv_create_xvimage(x);
-
- }
-
- else {
- /* clean up mess */
- post("pdp_xv: ERROR: no xv port available. closing display.");
- XCloseDisplay(x->x_dpy);
- x->x_initialized = false;
- return;
- }
-
-
- /* create a window */
- x->x_screen = DefaultScreen(x->x_dpy);
-
-
- x->x_win = XCreateSimpleWindow(
- x->x_dpy,
- RootWindow(x->x_dpy, x->x_screen), 0, 0, x->x_winwidth, x->x_winheight, 0,
- BlackPixel(x->x_dpy, x->x_screen),
- BlackPixel(x->x_dpy, x->x_screen));
-
-
- /* enable handling of close window event */
- x->x_WM_DELETE_WINDOW = XInternAtom(x->x_dpy, "WM_DELETE_WINDOW", True);
- (void)XSetWMProtocols(x->x_dpy, x->x_win, &x->x_WM_DELETE_WINDOW, 1);
-
- if(!(x->x_win)){
- /* clean up mess */
- post("pdp_xv: could not create window\n");
- post("pdp_xv: unlocking xv port");
- XvUngrabPort(x->x_dpy, x->x_xv_port, CurrentTime);
- post("pdp_xv: freeing xvimage");
- pdp_xv_destroy_xvimage(x);
- post("pdp_xv: closing display");
- XCloseDisplay(x->x_dpy);
- x->x_initialized = false;
- return;
- }
-
- /* select input events */
- XSelectInput(x->x_dpy, x->x_win, StructureNotifyMask
- | ButtonPressMask | ButtonReleaseMask | MotionNotify | ButtonMotionMask);
-
-
- XMapWindow(x->x_dpy, x->x_win);
-
- x->x_gc = XCreateGC(x->x_dpy, x->x_win, 0, 0);
-
- for(;;){
- XNextEvent(x->x_dpy, &e);
- if (e.type == MapNotify) break;
- }
-
-
- /* we're done initializing */
- x->x_initialized = true;
-
- /* disable/enable cursor */
- pdp_xv_cursor(x, x->x_cursor);
-
-}
-
-void pdp_xv_copy_xvimage(t_pdp_xv *x, t_image *image, short int* data)
-{
- unsigned int width = image->width;
- unsigned int height = image->height;
- int encoding = image->encoding;
- unsigned int* uintdata;
- int i;
-
-
- /* 8bit y fulscale and 8bit u,v 2x2 subsampled */
- //static short int gain[4] = {0x0100, 0x0100, 0x0100, 0x0100};
- long size = (width * height + (((width>>1)*(height>>1))<<1));
- int nbpixels = width * height;
-
- /* check if xvimage needs to be recreated */
- if ((width != x->x_width) || (height != x->x_height)){
- //post("pdp_xv: replace image");
- x->x_width = width;
- x->x_height = height;
- pdp_xv_destroy_xvimage(x);
- pdp_xv_create_xvimage(x);
- }
-
-
- /* data holds a 16bit version of a the xvimage, so it needs to be converted */
-
-
-
- if (data) {
- /* convert 16bit -> 8bit */
- if(PDP_IMAGE_YV12 == encoding){
- pdp_llconv(data,RIF_YVU__P411_S16, x->x_data, RIF_YVU__P411_U8, x->x_width, x->x_height);
- x->x_last_encoding = PDP_IMAGE_YV12;
- }
- if(PDP_IMAGE_GREY == encoding){
- pdp_llconv(data,RIF_GREY______S16, x->x_data, RIF_GREY______U8, x->x_width, x->x_height);
- if (PDP_IMAGE_GREY != x->x_last_encoding) {
- post("pdp_xv: switching to greyscale");
- /* clear u&v planes if necessary */
- uintdata = (unsigned int *)&x->x_data[nbpixels];
- for(i=0; i < nbpixels>>3; i++) uintdata[i]=0x80808080;
- }
- x->x_last_encoding = PDP_IMAGE_GREY;
-
- }
- }
- else bzero(x->x_data, size);
-
-
-
-}
-
-static int pdp_xv_try_autocreate(t_pdp_xv *x)
-{
-
- if (x->x_autocreate){
- post("pdp_xv: autocreate window");
- pdp_xv_create(x);
- if (!(x->x_initialized)){
- x->x_autocreate--;
- if (!x->x_autocreate){
- post ("pdp_xv: autocreate failed %d times: disabled", PDP_XV_AUTOCREATE_RETRY);
- post ("pdp_xv: send [autocreate 1] message to re-enable");
- return 0;
- }
- }
- else return 1;
-
- }
- return 0;
-}
-
-static void pdp_xv_bang(t_pdp_xv *x);
-
-static void pdp_xv_process(t_pdp_xv *x)
-{
- t_pdp *header = pdp_packet_header(x->x_packet0);
- void *data = pdp_packet_data (x->x_packet0);
-
-
- if (-1 != x->x_queue_id) return;
-
- /* check if window is initialized */
- if (!(x->x_initialized)){
- if (!pdp_xv_try_autocreate(x)) return;
- }
-
- /* check data packet */
- if (!(header)) {
- post("pdp_xv: invalid packet header");
- return;
- }
- if (PDP_IMAGE != header->type) {
- post("pdp_xv: packet is not a PDP_IMAGE");
- return;
- }
- if ((PDP_IMAGE_YV12 != header->info.image.encoding)
- && (PDP_IMAGE_GREY != header->info.image.encoding)) {
- post("pdp_xv: packet is not a PDP_IMAGE_YV12/GREY");
- return;
- }
-
- /* copy the packet to the xvimage */
- pdp_xv_copy_xvimage(x, &header->info.image, (short int *)data);
-
-
- /* display the new image */
- pdp_xv_bang(x);
-
-
-}
-
-
-static void pdp_xv_random(t_pdp_xv *x)
-{
- unsigned int i;
- long *intdata = (long *)(x->x_data);
- for(i=0; i<x->x_width*x->x_height/4; i++) intdata[i]=random();
-}
-
-
-/* redisplays image */
-static void pdp_xv_bang_thread(t_pdp_xv *x)
-{
-
- unsigned int i;
- XEvent e;
- XConfigureEvent *ce = (XConfigureEvent *)&e;
- XButtonEvent *be = (XButtonEvent *)&e;
- XMotionEvent *me = (XMotionEvent *)&e;
- float inv_x, inv_y;
- t_symbol *s;
- t_atom atom[2];
- char nextdrag[]="drag0";
- char b='0';
-
- inv_x = 1.0f / (float)(x->x_winwidth);
- inv_y = 1.0f / (float)(x->x_winheight);
-
- while (XPending(x->x_dpy)){
-
- XNextEvent(x->x_dpy, &e);
-
- switch(e.type){
- case ConfigureNotify:
- x->x_winwidth = ce->width;
- x->x_winheight = ce->height;
- inv_x = 1.0f / (float)(x->x_winwidth);
- inv_y = 1.0f / (float)(x->x_winheight);
- break;
-
- case ClientMessage:
- if ((Atom)e.xclient.data.l[0] == x->x_WM_DELETE_WINDOW) {
- post("pdp_xv: button disabled, please send a \"close\" message to close the window");
- //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(x->x_outlet, gensym("press"), 2, atom);
- switch(be->button){
- case Button1: outlet_anything(x->x_outlet, gensym("press1"), 2, atom); b='1'; break;
- case Button2: outlet_anything(x->x_outlet, gensym("press2"), 2, atom); b='2'; break;
- case Button3: outlet_anything(x->x_outlet, gensym("press3"), 2, atom); b='3'; break;
- case Button4: outlet_anything(x->x_outlet, gensym("press4"), 2, atom); b='4'; break;
- case Button5: outlet_anything(x->x_outlet, gensym("press5"), 2, atom); b='5'; break;
- default: break;
- }
- nextdrag[4]=b;
- x->x_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(x->x_outlet, gensym("release"), 2, atom);
- switch(be->button){
- case Button1: outlet_anything(x->x_outlet, gensym("release1"), 2, atom); break;
- case Button2: outlet_anything(x->x_outlet, gensym("release2"), 2, atom); break;
- case Button3: outlet_anything(x->x_outlet, gensym("release3"), 2, atom); break;
- case Button4: outlet_anything(x->x_outlet, gensym("release4"), 2, atom); break;
- case Button5: outlet_anything(x->x_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(x->x_outlet, gensym("drag"), 2, atom);
- outlet_anything(x->x_outlet, x->x_dragbutton, 2, atom);
- break;
-
- default:
- //post("pdp_xv: unknown event");
- break;
- }
-
- }
-
- // THIS SEEMS TO CRASH ON VERY LARGE IMAGES..
- //post("start");
- //post("XvPutImage xvi:%x",x->x_xvi);
- XvPutImage(x->x_dpy,x->x_xv_port,x->x_win,x->x_gc,x->x_xvi,
- 0,0,x->x_width,x->x_height, 0,0,x->x_winwidth,x->x_winheight);
- //post("XFlush");
- XFlush(x->x_dpy);
-
- //post("end");
-
-
-
-
-}
-
-static void pdp_xv_bang_callback(t_pdp_xv *x)
-{
- /* release the packet if there is one */
- pdp_packet_mark_unused(x->x_packet0);
- x->x_packet0 = -1;}
-
-static void pdp_xv_bang(t_pdp_xv *x)
-{
-
- /* check if window is initialized */
- if (!(x->x_initialized)){
- if (!pdp_xv_try_autocreate(x)) return;
- }
-
-
- /* if previous queued method returned
- schedule a new one, else ignore */
- if (-1 == x->x_queue_id) {
- pdp_queue_add(x, pdp_xv_bang_thread, pdp_xv_bang_callback, &x->x_queue_id);
- }
-
-}
-
-static void pdp_xv_input_0(t_pdp_xv *x, t_symbol *s, t_floatarg f)
-{
-
- if (s == gensym("register_ro")) pdp_packet_copy_ro_or_drop(&x->x_packet0, (int)f);
- if (s == gensym("process")) pdp_xv_process(x);
-
-}
-
-
-static void pdp_xv_vga(t_pdp_xv *x)
-{
- pdp_xv_resize(x, 640, 480);
-}
-
-static void pdp_xv_autocreate(t_pdp_xv *x, t_floatarg f)
-{
- if (f != 0.0f) x->x_autocreate = PDP_XV_AUTOCREATE_RETRY;
- else x->x_autocreate = 0;
-}
-
-static void pdp_xv_display(t_pdp_xv *x, t_symbol *s)
-{
- pdp_queue_finish(x->x_queue_id);
- x->x_queue_id = -1;
- x->x_display = s;
- if (x->x_initialized){
- pdp_xv_destroy(x);
- pdp_xv_create(x);
- }
-}
-
-
-
-static void pdp_xv_free(t_pdp_xv *x)
-{
- pdp_queue_finish(x->x_queue_id);
-
- pdp_xv_destroy(x);
- pdp_packet_mark_unused(x->x_packet0);
-}
-
-t_class *pdp_xv_class;
-
-
-
-void *pdp_xv_new(void)
-{
- t_pdp_xv *x = (t_pdp_xv *)pd_new(pdp_xv_class);
- x->x_outlet = outlet_new(&x->x_obj, &s_anything);
-
-
- x->x_packet0 = -1;
- x->x_queue_id = -1;
- x->x_display = gensym(":0");
-
-
- x->x_dpy = 0;
- x->x_screen = -1;
-
- x->x_xv_format = FOURCC_YV12;
- x->x_xv_port = 0;
-
- x->x_winwidth = PDP_XV_W;
- x->x_winheight = PDP_XV_H;
-
- x->x_width = PDP_XV_W;
- x->x_height = PDP_XV_H;
-
- x->x_data = 0;
- x->x_xvi = 0;
-
- x->x_initialized = 0;
- pdp_xv_autocreate(x,1);
- x->x_last_encoding = -1;
-
- x->x_cursor = 0;
- x->x_dragbutton = gensym("drag1");
-
- //pdp_xv_create(x);
-
- return (void *)x;
-}
-
-
-
-
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-
-void pdp_xv_setup(void)
-{
-
-
- pdp_xv_class = class_new(gensym("pdp_xv"), (t_newmethod)pdp_xv_new,
- (t_method)pdp_xv_free, sizeof(t_pdp_xv), 0, A_NULL);
-
-
- class_addmethod(pdp_xv_class, (t_method)pdp_xv_bang, gensym("bang"), A_NULL);
- class_addmethod(pdp_xv_class, (t_method)pdp_xv_random, gensym("random"), A_NULL);
- class_addmethod(pdp_xv_class, (t_method)pdp_xv_create, gensym("open"), A_NULL);
- class_addmethod(pdp_xv_class, (t_method)pdp_xv_create, gensym("create"), A_NULL);
- class_addmethod(pdp_xv_class, (t_method)pdp_xv_autocreate, gensym("autocreate"), A_FLOAT, A_NULL);
- class_addmethod(pdp_xv_class, (t_method)pdp_xv_destroy, gensym("destroy"), A_NULL);
- class_addmethod(pdp_xv_class, (t_method)pdp_xv_destroy, gensym("close"), A_NULL);
- class_addmethod(pdp_xv_class, (t_method)pdp_xv_resize, gensym("dim"), A_FLOAT, A_FLOAT, A_NULL);
- class_addmethod(pdp_xv_class, (t_method)pdp_xv_resize, gensym("size"), A_FLOAT, A_FLOAT, A_NULL);
- class_addmethod(pdp_xv_class, (t_method)pdp_xv_display, gensym("display"), A_SYMBOL, A_NULL);
- class_addmethod(pdp_xv_class, (t_method)pdp_xv_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL);
- class_addmethod(pdp_xv_class, (t_method)pdp_xv_cursor, gensym("cursor"), A_FLOAT, A_NULL);
-
- /* some shortcuts for the lazy */
- class_addmethod(pdp_xv_class, (t_method)pdp_xv_vga, gensym("vga"), A_NULL);
-
-}
-
-#ifdef __cplusplus
-}
-#endif
-
-