diff options
Diffstat (limited to 'externals/gridflow/format')
-rw-r--r-- | externals/gridflow/format/aalib.c | 2 | ||||
-rw-r--r-- | externals/gridflow/format/dc1394.c | 2 | ||||
-rw-r--r-- | externals/gridflow/format/jpeg.c | 12 | ||||
-rw-r--r-- | externals/gridflow/format/main.rb | 33 | ||||
-rw-r--r-- | externals/gridflow/format/mpeg3.c | 4 | ||||
-rw-r--r-- | externals/gridflow/format/opengl.c | 181 | ||||
-rw-r--r-- | externals/gridflow/format/png.c | 2 | ||||
-rw-r--r-- | externals/gridflow/format/quartz.m | 2 | ||||
-rw-r--r-- | externals/gridflow/format/quicktimeapple.c | 2 | ||||
-rw-r--r-- | externals/gridflow/format/quicktimehw.c | 19 | ||||
-rw-r--r-- | externals/gridflow/format/sdl.c | 2 | ||||
-rw-r--r-- | externals/gridflow/format/videodev.c | 2 | ||||
-rw-r--r-- | externals/gridflow/format/x11.c | 418 |
13 files changed, 451 insertions, 230 deletions
diff --git a/externals/gridflow/format/aalib.c b/externals/gridflow/format/aalib.c index f014a632..cf029dfe 100644 --- a/externals/gridflow/format/aalib.c +++ b/externals/gridflow/format/aalib.c @@ -1,5 +1,5 @@ /* - $Id: aalib.c,v 1.1 2005-10-04 02:02:15 matju Exp $ + $Id: aalib.c,v 1.2 2006-03-15 04:37:46 matju Exp $ GridFlow Copyright (c) 2001,2002,2003 by Mathieu Bouchard diff --git a/externals/gridflow/format/dc1394.c b/externals/gridflow/format/dc1394.c index 1632bef7..5349c231 100644 --- a/externals/gridflow/format/dc1394.c +++ b/externals/gridflow/format/dc1394.c @@ -1,5 +1,5 @@ /* - $Id: dc1394.c,v 1.1 2005-10-04 02:02:15 matju Exp $ + $Id: dc1394.c,v 1.2 2006-03-15 04:37:46 matju Exp $ GridFlow Copyright (c) 2001,2002,2003,2004 by Mathieu Bouchard diff --git a/externals/gridflow/format/jpeg.c b/externals/gridflow/format/jpeg.c index e59d8e06..4363be52 100644 --- a/externals/gridflow/format/jpeg.c +++ b/externals/gridflow/format/jpeg.c @@ -1,5 +1,5 @@ /* - $Id: jpeg.c,v 1.1 2005-10-04 02:02:15 matju Exp $ + $Id: jpeg.c,v 1.2 2006-03-15 04:37:46 matju Exp $ GridFlow Copyright (c) 2001,2002,2003,2004 by Mathieu Bouchard @@ -42,6 +42,7 @@ struct FormatJPEG : Format { int fd; FILE *f; \decl Ruby frame (); + \decl void quality (short quality); \decl void initialize (Symbol mode, Symbol source, String filename); \grin 0 int }; @@ -108,6 +109,13 @@ static bool gfeof(FILE *f) { return Qnil; } +\def void quality (short quality) { + quality = min(max((int)quality,0),100); + // should the last arg ("baseline") be set to true ? + // and what is it for? is it for accuracy of the DC component? + jpeg_set_quality(&cjpeg,quality,false); +} + \def void initialize (Symbol mode, Symbol source, String filename) { rb_call_super(argc,argv); if (source!=SYM(file)) RAISE("usage: jpeg file <filename>"); @@ -121,7 +129,7 @@ static bool gfeof(FILE *f) { \classinfo { IEVAL(rself, - "install '#in:jpeg',1,1;@mode=6;" + "install '#io:jpeg',1,1;@mode=6;" "include GridFlow::EventIO; suffixes_are'jpeg','jpg'"); } \end class FormatJPEG diff --git a/externals/gridflow/format/main.rb b/externals/gridflow/format/main.rb index 6e31be75..1cac124f 100644 --- a/externals/gridflow/format/main.rb +++ b/externals/gridflow/format/main.rb @@ -1,5 +1,5 @@ =begin - $Id: main.rb,v 1.1 2005-10-04 02:02:15 matju Exp $ + $Id: main.rb,v 1.2 2006-03-15 04:37:46 matju Exp $ GridFlow Copyright (c) 2001,2002,2003,2004 by Mathieu Bouchard @@ -237,7 +237,7 @@ GridObject.subclass("#in",1,2) { def _0_set frame; check_file_open; @format.seek frame end def _0_reset; check_file_open; @format.seek 0; end def _1_grid(*a) send_out 0,:grid,*a end - def _0_load name; _0_open name; _0_bang; _0_close end + def _0_load(*a); _0_open(*a); _0_bang; _0_close end } GridObject.subclass("#out",1,1) { @@ -350,8 +350,7 @@ module EventIO else r.close STDOUT.reopen w - STDIN.reopen @stream - @stream = File.open filename, "r" + STDIN.reopen filename, "r" exec "gzip", "-dc" end end @@ -364,8 +363,7 @@ module EventIO else w.close STDIN.reopen r - STDOUT.reopen @stream - @stream = File.open filename, "w" + STDOUT.reopen filename, "w" exec "gzip", "-c" end end @@ -375,7 +373,7 @@ module EventIO when :in; "r" when :out; "w" else raise "bad mode" end - close + @stream.close if @stream case source when :file filename = args[0].to_s @@ -721,6 +719,27 @@ Format.subclass("#io:ppm",1,1) { end def _0_rgrid_flow(data) @stream.write @bp.pack(data) end def _0_rgrid_end; @stream.flush end + self +}.subclass("#io:tk",1,1) { + install_rgrid 0 + def initialize(mode) + if mode!=:out then raise "only #out" end + super(mode,:file,"/tmp/tk-#{$$}-#{object_id}.ppm") + GridFlow.gui "toplevel .#{object_id}\n" + GridFlow.gui "wm title . GridFlow/Tk\n" + GridFlow.gui "image create photo #{object_id} -width 320 -height 240\n" + GridFlow.gui "pack [label .#{object_id}.im -image #{object_id}]\n" + end + def _0_rgrid_end + super + @stream.seek 0,IO::SEEK_SET + GridFlow.gui "image create photo #{object_id} -file /tmp/tk-#{$$}-#{object_id}.ppm\n" + end + def delete + GridFlow.gui "destroy .#{object_id}\n" + GridFlow.gui "image delete #{object_id}\n" + end + alias close delete } Format.subclass("#io:targa",1,1) { diff --git a/externals/gridflow/format/mpeg3.c b/externals/gridflow/format/mpeg3.c index d6820ccd..c2b85192 100644 --- a/externals/gridflow/format/mpeg3.c +++ b/externals/gridflow/format/mpeg3.c @@ -1,5 +1,5 @@ /* - $Id: mpeg3.c,v 1.1 2005-10-04 02:02:15 matju Exp $ + $Id: mpeg3.c,v 1.2 2006-03-15 04:37:46 matju Exp $ GridFlow Copyright (c) 2001,2002,2003 by Mathieu Bouchard @@ -88,7 +88,7 @@ struct FormatMPEG3 : Format { } \classinfo { - IEVAL(rself,"install '#in:mpeg',1,1;@flags=4;" + IEVAL(rself,"install '#io:mpeg',1,1;@flags=4;" "@comment='Motion Picture Expert Group Format" " (using HeroineWarrior\\'s)';suffixes_are'mpg,mpeg'"); } diff --git a/externals/gridflow/format/opengl.c b/externals/gridflow/format/opengl.c new file mode 100644 index 00000000..39979f68 --- /dev/null +++ b/externals/gridflow/format/opengl.c @@ -0,0 +1,181 @@ +/* + $Id: opengl.c,v 1.1 2006-03-15 04:54:54 matju Exp $ + + GridFlow + Copyright (c) 2001,2002,2003,2004,2005 by Mathieu Bouchard + + 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. + + See file ../COPYING for further informations on licensing terms. + + 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. +*/ + +#include "../base/grid.h.fcs" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <sys/time.h> +#include <signal.h> +#ifdef MACOSX +#include <OpenGL/gl.h> +#include <OpenGL/glu.h> +#else +#include <GL/gl.h> +#include <GL/glu.h> +#include <GL/glut.h> +#endif +#include <setjmp.h> + +static bool in_use = false; + +\class FormatOpenGL < Format +struct FormatOpenGL : Format { + int window; + GLuint gltex; + P<BitPacking> bit_packing; + P<Dim> dim; + Pt<uint8> buf; + \decl void call (); + \decl void initialize (Symbol mode); + \decl void close (); + \decl void resize_window (int sx, int sy); + \grin 0 +}; + +static jmp_buf hack; +static void my_idle () { longjmp(hack,1); } + +\def void call () { + int32 sy = dim->get(0); + int32 sx = dim->get(1); + glEnable(GL_TEXTURE_2D); + if (!gltex) { + } + glTexSubImage2D(GL_TEXTURE_2D,0,0,0,sx,sy,GL_RGBA,GL_UNSIGNED_BYTE,buf); + glBindTexture(GL_TEXTURE_2D, gltex); + glBegin(GL_QUADS); + glColor3f(1.f,1.f,1.f); + glTexCoord2f(0.f,0.f); glVertex2f(0.f,0.f); + glTexCoord2f(1.f,0.f); glVertex2f( sx,0.f); + glTexCoord2f(1.f,1.f); glVertex2f( sx, sy); + glTexCoord2f(0.f,1.f); glVertex2f(0.f, sy); + glEnd(); + + //Here comes some (un)fair amount of arm-twisting + //This is for processing queued events and then "returning". + glutIdleFunc(my_idle); + if(!setjmp(hack)) glutMainLoop(); + //done + + IEVAL(rself,"@clock.delay 100"); +} + +\def void resize_window (int sx, int sy) {L + dim = new Dim(sy,sx,3); + char foo[666]; + sprintf(foo,"GridFlow/GL (%d,%d,3)",sy,sx); + if ((unsigned)window==0xDeadBeef) { + glutInitWindowSize(sx,sy); + window = glutCreateWindow(foo); + } else { + glutReshapeWindow(sx,sy); + } + if (buf) delete buf.p; + buf = ARRAY_NEW(uint8,sy*sx*4); + glViewport(0,0,sx,sy); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0,sx,sy,0,-99999,99999); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + if (gltex) glDeleteTextures(1, (GLuint*)&gltex); + glGenTextures(1, (GLuint*)&gltex); + glBindTexture(GL_TEXTURE_2D,gltex); + glPixelStorei(GL_UNPACK_ALIGNMENT,1); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); + glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE); + glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,sx,sy,0,GL_RGBA,GL_UNSIGNED_BYTE,NULL); + +} + +GRID_INLET(FormatOpenGL,0) { + if (in->dim->n != 3) + RAISE("expecting 3 dimensions: rows,columns,channels"); + if (in->dim->get(2) != 3) + RAISE("expecting 3 channels: red,green,blue (got %d)",in->dim->get(2)); + int sxc = in->dim->prod(1); + int sx = in->dim->get(1), osx = dim->get(1); + int sy = in->dim->get(0), osy = dim->get(0); + in->set_factor(sxc); + if (sx!=osx || sy!=osy) resize_window(0,0,sx,sy); +} GRID_FLOW { + int sxc = in->dim->prod(1); + int sx = in->dim->get(1); + int bypl = 4*sx; + int y = in->dex / sxc; + assert((in->dex % sxc) == 0); + assert((n % sxc) == 0); + for (; n>0; y++, data+=sxc, n-=sxc) bit_packing->pack(sx, data, buf+y*bypl); + } GRID_FINISH { +} GRID_END + +\def void close () { + IEVAL(rself,"@clock.unset"); + if (gltex) glDeleteTextures(1, (GLuint*)&gltex); + if (buf) delete buf.p; + in_use=false; + if ((unsigned)window!=0xDeadBeef) { + glutDestroyWindow(window); + window=0xDeadBeef; + } +} + +\def void initialize (Symbol mode) { + rb_call_super(argc,argv); + if (in_use) RAISE("only one #io:opengl object at a time; sorry"); + in_use=true; + if (mode!=SYM(out)) RAISE("write-only, sorry"); + gltex = 0; + glEnable(GL_TEXTURE_2D); + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + glDisable(GL_ALPHA_TEST); + glDisable(GL_CULL_FACE); + glDisable(GL_DITHER); + glDisable(GL_DEPTH_TEST); + glDisable(GL_LIGHTING); + window = 0xDeadBeef; + int dummy = 0; + glutInit(&dummy,0); + glutInitDisplayMode(GLUT_RGBA); + resize_window(0,0,320,240); + uint32 mask[3] = {0xff000000,0x00ff0000,0x0000ff00}; + bit_packing = new BitPacking(4,4,3,mask); + IEVAL(rself,"@clock = Clock.new self; @clock.delay 0"); + gfpost("@clock = Clock.new self"); +} + +\classinfo { + IEVAL(rself,"install '#io:opengl',1,1;@comment='Silicon Graphics OpenGL'"); +} +\end class FormatOpenGL +void startup_opengl () { + \startall +}
\ No newline at end of file diff --git a/externals/gridflow/format/png.c b/externals/gridflow/format/png.c index 69a0254e..5db0c254 100644 --- a/externals/gridflow/format/png.c +++ b/externals/gridflow/format/png.c @@ -1,5 +1,5 @@ /* - $Id: png.c,v 1.1 2005-10-04 02:02:15 matju Exp $ + $Id: png.c,v 1.2 2006-03-15 04:37:46 matju Exp $ GridFlow Copyright (c) 2001,2002,2003,2004 by Mathieu Bouchard diff --git a/externals/gridflow/format/quartz.m b/externals/gridflow/format/quartz.m index d7f2863a..9cb00078 100644 --- a/externals/gridflow/format/quartz.m +++ b/externals/gridflow/format/quartz.m @@ -1,5 +1,5 @@ /* - $Id: quartz.m,v 1.1 2005-10-04 02:15:31 matju Exp $ + $Id: quartz.m,v 1.2 2006-03-15 04:37:46 matju Exp $ GridFlow Copyright (c) 2001,2002,2003 by Mathieu Bouchard diff --git a/externals/gridflow/format/quicktimeapple.c b/externals/gridflow/format/quicktimeapple.c index 0664322e..2a485424 100644 --- a/externals/gridflow/format/quicktimeapple.c +++ b/externals/gridflow/format/quicktimeapple.c @@ -1,5 +1,5 @@ /* - $Id: quicktimeapple.c,v 1.1 2005-10-04 02:02:15 matju Exp $ + $Id: quicktimeapple.c,v 1.2 2006-03-15 04:37:46 matju Exp $ GridFlow Copyright (c) 2001,2002,2003,2004 by Mathieu Bouchard diff --git a/externals/gridflow/format/quicktimehw.c b/externals/gridflow/format/quicktimehw.c index 4ae77209..58f415a0 100644 --- a/externals/gridflow/format/quicktimehw.c +++ b/externals/gridflow/format/quicktimehw.c @@ -1,8 +1,8 @@ /* - $Id: quicktimehw.c,v 1.1 2005-10-04 02:02:15 matju Exp $ + $Id: quicktimehw.c,v 1.2 2006-03-15 04:37:46 matju Exp $ GridFlow - Copyright (c) 2001,2002,2003 by Mathieu Bouchard + Copyright (c) 2001,2002,2003,2004,2005,2006 by Mathieu Bouchard This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -21,18 +21,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#define QUICKTIMEHW_INCLUDE_HERE #include "../base/grid.h.fcs" #include <stdlib.h> #include <string.h> #include <errno.h> -#include <quicktime/quicktime.h> -#include <quicktime/colormodels.h> - -#include <quicktime/lqt_version.h> -#ifdef LQT_VERSION -#include <quicktime/lqt.h> -#include <quicktime/lqt_codecinfo.h> -#endif \class FormatQuickTimeHW < Format struct FormatQuickTimeHW : Format { @@ -218,6 +211,8 @@ GRID_INLET(FormatQuickTimeHW,0) { \end ruby ); +//#define L fprintf(stderr,"%s:%d in %s\n",__FILE__,__LINE__,__PRETTY_FUNCTION__); + #ifdef LQT_VERSION lqt_registry_init(); int n = lqt_get_num_video_codecs(); @@ -225,6 +220,10 @@ GRID_INLET(FormatQuickTimeHW,0) { Ruby fourccs = rb_hash_new(); for (int i=0; i<n; i++) { const lqt_codec_info_t *s = lqt_get_video_codec_info(i); + if (!s->name) { + fprintf(stderr,"[#in quicktime]: skipping codec with null name!\n"); + continue; + } Ruby name = rb_str_new2(s->name); Ruby f = rb_ary_new2(s->num_fourccs); for (int j=0; j<s->num_fourccs; j++) { diff --git a/externals/gridflow/format/sdl.c b/externals/gridflow/format/sdl.c index 628f71ee..32ba64a5 100644 --- a/externals/gridflow/format/sdl.c +++ b/externals/gridflow/format/sdl.c @@ -1,5 +1,5 @@ /* - $Id: sdl.c,v 1.1 2005-10-04 02:02:15 matju Exp $ + $Id: sdl.c,v 1.2 2006-03-15 04:37:46 matju Exp $ GridFlow Copyright (c) 2001,2002,2003,2004 by Mathieu Bouchard diff --git a/externals/gridflow/format/videodev.c b/externals/gridflow/format/videodev.c index e907eaa9..0f458408 100644 --- a/externals/gridflow/format/videodev.c +++ b/externals/gridflow/format/videodev.c @@ -1,5 +1,5 @@ /* - $Id: videodev.c,v 1.1 2005-10-04 02:02:15 matju Exp $ + $Id: videodev.c,v 1.2 2006-03-15 04:37:46 matju Exp $ GridFlow Copyright (c) 2001,2002,2003,2004 by Mathieu Bouchard diff --git a/externals/gridflow/format/x11.c b/externals/gridflow/format/x11.c index 62041f06..9237a6b6 100644 --- a/externals/gridflow/format/x11.c +++ b/externals/gridflow/format/x11.c @@ -1,8 +1,8 @@ /* - $Id: x11.c,v 1.1 2005-10-04 02:02:15 matju Exp $ + $Id: x11.c,v 1.2 2006-03-15 04:37:46 matju Exp $ GridFlow - Copyright (c) 2001,2002,2003 by Mathieu Bouchard + Copyright (c) 2001,2002,2003,2004,2005 by Mathieu Bouchard This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -19,8 +19,9 @@ 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. -*/ + Note: some of the code was adapted from PDP's (the XVideo stuff). +*/ #include "../base/grid.h.fcs" #include <ctype.h> #include <stdio.h> @@ -28,66 +29,67 @@ #include <string.h> #include <errno.h> #include <sys/time.h> - #include <X11/Xlib.h> #include <X11/Xutil.h> #include <X11/StringDefs.h> - -/* X11 Error Handler type */ -typedef int (*XEH)(Display *, XErrorEvent *); - #ifdef HAVE_X11_SHARED_MEMORY #include <sys/ipc.h> #include <sys/shm.h> #include <X11/extensions/XShm.h> #endif +#ifdef HAVE_X11_XVIDEO +#include <X11/extensions/Xv.h> +#include <X11/extensions/Xvlib.h> +#endif + +#undef L +#define L gfpost("%s:%d in %s",__FILE__,__LINE__,__PRETTY_FUNCTION__); + +/* X11 Error Handler type */ +typedef int (*XEH)(Display *, XErrorEvent *); \class FormatX11 < Format struct FormatX11 : Format { - template <class T> void frame_by_type (T bogus); /* at the Display/Screen level */ Display *display; /* connection to xserver */ Visual *visual; /* screen properties */ Window root_window; Colormap colormap; /* for 256-color mode */ - long black,white; /* color numbers in default colormap */ short depth; - bool use_shm; /* should use shared memory? */ + int transfer; /* 0=plain 1=xshm 2=xvideo */ bool use_stripes; /* use alternate conversion in 256-color mode */ - /* at the Window level */ - int autodraw; /* how much to send to the display at once */ Window window; /* X11 window number */ Window parent; /* X11 window number of the parent */ GC imagegc; /* X11 graphics context (like java.awt.Graphics) */ XImage *ximage; /* X11 image descriptor */ - char *name; /* window name (for use by window manager) */ Pt<uint8> image; /* the real data (that XImage binds to) */ bool is_owner; - int pos_x, pos_y; - + int32 pos[2]; P<BitPacking> bit_packing; P<Dim> dim; bool lock_size; bool override_redirect; - #ifdef HAVE_X11_SHARED_MEMORY XShmSegmentInfo *shm_info; /* to share memory with X11/Unix */ #endif - - Atom wmProtocolsAtom; - Atom wmDeleteAtom; - - FormatX11 () : use_stripes(false), - autodraw(1), window(0), ximage(0), name(0), image(Pt<uint8>()), is_owner(true), +#ifdef HAVE_X11_XVIDEO + int xv_format; + int xv_port; + XvImage *xvi; + unsigned char *data; + int last_encoding; +#endif + FormatX11 () : transfer(0), use_stripes(false), + window(0), ximage(0), image(Pt<uint8>()), is_owner(true), dim(0), lock_size(false), override_redirect(false) #ifdef HAVE_X11_SHARED_MEMORY , shm_info(0) #endif {} - + template <class T> void frame_by_type (T bogus); void show_section(int x, int y, int sx, int sy); - void set_wm_hints (int sx, int sy); + void set_wm_hints (); void dealloc_image (); bool alloc_image (int sx, int sy); void resize_window (int sx, int sy); @@ -95,56 +97,68 @@ struct FormatX11 : Format { void report_pointer(int y, int x, int state); void prepare_colormap(); Window FormatX11::search_window_tree (Window xid, Atom key, const char *value, int level=0); - \decl void initialize (...); \decl void frame (); \decl void close (); \decl void call (); \decl void _0_out_size (int sy, int sx); - \decl void _0_draw (); - \decl void _0_autodraw (int autodraw); \decl void _0_setcursor (int shape); \decl void _0_hidecursor (); \decl void _0_set_geometry (int y, int x, int sy, int sx); \decl void _0_fall_thru (int flag); + \decl void _0_transfer (Symbol s); + \decl void _0_title (String s=Qnil); \grin 0 int }; /* ---------------------------------------------------------------- */ +static const char *xfers[3] = {"plain","xshm","xvideo"}; + void FormatX11::show_section(int x, int y, int sx, int sy) { - if (y>dim->get(0)||x>dim->get(1)) return; - if (y+sy>dim->get(0)) sy=dim->get(0)-y; - if (x+sx>dim->get(1)) sx=dim->get(1)-x; + int zy=dim->get(0), zx=dim->get(1); + if (y>zy||x>zx) return; + if (y+sy>zy) sy=zy-y; + if (x+sx>zx) sx=zx-x; + switch (transfer) { + case 0: XPutImage(display,window,imagegc,ximage,x,y,x,y,sx,sy); + XFlush(display); + break; #ifdef HAVE_X11_SHARED_MEMORY - if (use_shm) { - XSync(display,False); + case 1: XSync(display,False); XShmPutImage(display,window,imagegc,ximage,x,y,x,y,sx,sy,False); - /* should completion events be waited for? looks like a bug */ - } else + XFlush(display); + //XPutImage( display,window,imagegc,ximage,x,y,x,y,sx,sy); + // should completion events be waited for? looks like a bug + break; #endif - XPutImage(display,window,imagegc,ximage,x,y,x,y,sx,sy); - XFlush(display); +#ifdef HAVE_X11_XVIDEO + case 2: + break; +#endif + default: RAISE("transfer mode '%s' not available", xfers[transfer]); + } } /* window manager hints, defines the window as non-resizable */ -void FormatX11::set_wm_hints (int sx, int sy) { +void FormatX11::set_wm_hints () { + Ruby title = rb_ivar_get(rself,SI(@title)); if (!is_owner) return; - XWMHints wmhints; - XTextProperty window_name, icon_name; - XSizeHints hints; - // enable recommended, maximum and minimum size - hints.flags=PSize|PMaxSize|PMinSize; - // set those - hints.min_width = hints.max_width = hints.width = sx; - hints.min_height = hints.max_height = hints.height = sy; - - wmhints.input = True; - wmhints.flags = InputHint; - XStringListToTextProperty((char **)&name, 1, &window_name); - XStringListToTextProperty((char **)&name, 1, &icon_name); - XSetWMProperties(display, window, - &window_name, &icon_name, NULL, 0, &hints, &wmhints, NULL); + XWMHints wmh; + char buf[256],*bufp=buf; + if (title==Qnil) { + sprintf(buf,"GridFlow (%d,%d,%d)",dim->get(0),dim->get(1),dim->get(2)); + } else { + sprintf(buf,"%.255s",rb_str_ptr(title)); + } + XTextProperty wtitle; XStringListToTextProperty((char **)&bufp, 1, &wtitle); + XSizeHints sh; + sh.flags=PSize|PMaxSize|PMinSize; + sh.min_width = sh.max_width = sh.width = dim->get(1); + sh.min_height = sh.max_height = sh.height = dim->get(0); + wmh.input = True; + wmh.flags = InputHint; + XSetWMProperties(display,window,&wtitle,&wtitle,0,0,&sh,&wmh,0); } void FormatX11::report_pointer(int y, int x, int state) { @@ -202,30 +216,16 @@ void FormatX11::report_pointer(int y, int x, int state) { return; }break; case ConfigureNotify:break; // as if we cared - case ClientMessage:{ - // tnx to vektor&walken - /* - if (e.xclient.message_type==wmProtocolsAtom - && e.xclient.format==32 - && (Atom)(e.xclient.data.l[0])==wmDeleteAtom) { - gfpost("This window is being closed, so this handler will close too!"); - rb_funcall(rself,SI(close),0); - return; - } - */ - }break; } } IEVAL(rself,"@clock.delay 20"); } \def void frame () { - XGetSubImage(display, window, - 0, 0, dim->get(1), dim->get(0), + XGetSubImage(display, window, 0, 0, dim->get(1), dim->get(0), (unsigned)-1, ZPixmap, ximage, 0, 0); GridOutlet out(this,0,dim,NumberTypeE_find(rb_ivar_get(rself,SI(@cast)))); - int sy=dim->get(0), sx=dim->get(1); - int bs=dim->prod(1); + int sy=dim->get(0), sx=dim->get(1), bs=dim->prod(1); STACK_ARRAY(uint8,b2,bs); for(int y=0; y<sy; y++) { Pt<uint8> b1 = Pt<uint8>(image,ximage->bytes_per_line*dim->get(0)) @@ -238,86 +238,129 @@ void FormatX11::report_pointer(int y, int x, int state) { /* loathe Xlib's error handlers */ static FormatX11 *current_x11; static int FormatX11_error_handler (Display *d, XErrorEvent *xee) { - gfpost("X11 reports Error: display=0x%08x",(int)d); - gfpost("serial=0x%08x error=0x%08x request=0x%08lx minor=0x%08x", + gfpost("XErrorEvent: type=0x%08x display=0x%08x xid=0x%08x", + xee->type, xee->display, xee->resourceid); + gfpost("... serial=0x%08x error=0x%08x request=0x%08lx minor=0x%08x", xee->serial, xee->error_code, xee->request_code, xee->minor_code); - current_x11->use_shm = false; - return 42; /* it seems that the return value is ignored. */ -} - -void FormatX11::dealloc_image () { - if (!ximage) return; - if (use_shm) { - #ifdef HAVE_X11_SHARED_MEMORY - shmdt(ximage->data); - XShmDetach(display,shm_info); - if (shm_info) {delete shm_info; shm_info=0;} - //ximage->data = new char[1]; // bogus - //ximage->data = 0; - //XDestroyImage(ximage); - XFree(ximage); - ximage = 0; - image = Pt<uint8>(); - #endif - } else { - //XDestroyImage(ximage); - XFree(ximage); - ximage = 0; - image = Pt<uint8>(); + if (current_x11->transfer==1) { + gfpost("(note: turning shm off)"); + current_x11->transfer = 0; } + return 42; /* it seems that the return value is ignored. */ } bool FormatX11::alloc_image (int sx, int sy) { - dim = new Dim(sy, sx, 3); + dim = new Dim(sy,sx,3); dealloc_image(); if (sx==0 || sy==0) return false; + current_x11 = this; + switch (transfer) { + case 0: { + ximage = XCreateImage(display,visual,depth,ZPixmap,0,0,sx,sy,8,0); + int size = ximage->bytes_per_line*ximage->height; + if (!ximage) RAISE("can't create image"); + image = ARRAY_NEW(uint8,size); + ximage->data = (int8 *)image; + } break; #ifdef HAVE_X11_SHARED_MEMORY - if (use_shm) { + case 1: { shm_info = new XShmSegmentInfo; ximage = XShmCreateImage(display,visual,depth,ZPixmap,0,shm_info,sx,sy); - if (!ximage) { - gfpost("shm got disabled (1), retrying..."); - return alloc_image(sx,sy);} - shm_info->shmid = shmget(IPC_PRIVATE, - ximage->bytes_per_line*ximage->height, IPC_CREAT|0777); - if(shm_info->shmid < 0) - RAISE("ERROR: shmget failed: %s",strerror(errno)); - ximage->data = shm_info->shmaddr = - (char *)shmat(shm_info->shmid,0,0); - image = Pt<uint8>((uint8 *)ximage->data, - ximage->bytes_per_line*sy); + if (!ximage) {gfpost("shm got disabled, retrying..."); transfer=0;} + XSync(display,0); + if (transfer==0) return alloc_image(sx,sy); + int size = ximage->bytes_per_line*ximage->height; + gfpost("size = %d",size); + shm_info->shmid = shmget(IPC_PRIVATE,size,IPC_CREAT|0777); + if(shm_info->shmid < 0) RAISE("shmget() failed: %s",strerror(errno)); + ximage->data = shm_info->shmaddr = (char *)shmat(shm_info->shmid,0,0); + if ((long)(shm_info->shmaddr) == -1) RAISE("shmat() failed: %s",strerror(errno)); + gfpost("shmaddr=%p",shm_info->shmaddr); + image = Pt<uint8>((uint8 *)ximage->data,size); shm_info->readOnly = False; - current_x11 = this; - //XSetErrorHandler(FormatX11_error_handler); if (!XShmAttach(display, shm_info)) RAISE("ERROR: XShmAttach: big problem"); XSync(display,0); // make sure the server picks it up - //XSetErrorHandler(0); - /* yes, this can be done now. should cause auto-cleanup. */ + // yes, this can be done now. should cause auto-cleanup. shmctl(shm_info->shmid,IPC_RMID,0); - if (!use_shm) { - gfpost("shm got disabled (2), retrying..."); - return alloc_image(sx,sy);} - } else + if (transfer==0) return alloc_image(sx,sy); + } break; +#endif +#ifdef HAVE_X11_XVIDEO + case 2: { + unsigned int ver, rel, req, ev, err, i, j, adaptors, formats; + XvAdaptorInfo *ai; + if (Success != XvQueryExtension(display,&ver,&rel,&req,&ev,&err)) RAISE("XvQueryExtension problem"); + /* find + lock port */ + if (Success != XvQueryAdaptors(display,DefaultRootWindow(display),&adaptors,&ai)) RAISE("XvQueryAdaptors problem"); + 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(display,ai[i].base_id+j,CurrentTime)) RAISE("XvGrabPort problem"); + xv_port = ai[i].base_id + j; + goto breakout; + } + } + } + breakout: + XFree(ai); + if (!xv_port) RAISE("no xv_port"); +/* unsigned int encn; + XvEncodingInfo *enc; + XvQueryEncodings(display,xv_port,&encn,&enc); + for (i=0; i<encn; i++) gfpost("XvEncodingInfo: name='%s' encoding_id=0x%08x",enc[i].name,enc[i].encoding_id);*/ + gfpost("pdp_xvideo: grabbed port %d on adaptor %d",xv_port,i); + size_t size = sx*sy*4; + data = new uint8[size]; + for (i=0; i<size; i++) data[i]=0; + xvi = XvCreateImage(display,xv_port,0x51525762,(char *)data,sx,sy); + last_encoding=-1; + if (!xvi) RAISE("XvCreateImage problem"); + } break; #endif - ximage = XCreateImage(display,visual,depth,ZPixmap,0,0,sx,sy,8,0); - if (!ximage) RAISE("can't create image"); - image = ARRAY_NEW(uint8,ximage->bytes_per_line*sy); - ximage->data = (int8 *)image; + default: RAISE("transfer mode '%s' not available", xfers[transfer]); + } int status = XInitImage(ximage); if (status!=1) gfpost("XInitImage returned: %d", status); return true; +retry: + gfpost("shm got disabled, retrying..."); + return alloc_image(sx,sy); +} + +void FormatX11::dealloc_image () { + if (!ximage) return; + switch (transfer) { + case 0: XFree(ximage); ximage=0; image=Pt<uint8>(); break; +#ifdef HAVE_X11_SHARED_MEMORY + case 1: + shmdt(ximage->data); + XShmDetach(display,shm_info); + if (shm_info) {delete shm_info; shm_info=0;} + XFree(ximage); + ximage = 0; + image = Pt<uint8>(); + break; +#endif +#ifdef HAVE_X11_XVIDEO + case 2: { + if (data) delete[] data; + if (xvi) XFree(xvi); + xvi=0; + data=0; + } + break; +#endif + default: RAISE("transfer mode '%s' not available",xfers[transfer]); + } } void FormatX11::resize_window (int sx, int sy) { if (sy<16) sy=16; if (sy>4096) RAISE("height too big"); if (sx<16) sx=16; if (sx>4096) RAISE("width too big"); alloc_image(sx,sy); - if (name) delete name; - name = new char[64]; - sprintf(name,"GridFlow (%d,%d,3)",sy,sx); if (window) { if (is_owner && !lock_size) { - set_wm_hints(sx,sy); + set_wm_hints(); XResizeWindow(display,window,sx,sy); } } else { @@ -325,23 +368,13 @@ void FormatX11::resize_window (int sx, int sy) { xswa.do_not_propagate_mask = 0; //? xswa.override_redirect = override_redirect; //#!@#$ window = XCreateWindow(display, - parent, pos_x, pos_y, sx, sy, 0, + parent, pos[1], pos[0], sx, sy, 0, CopyFromParent, InputOutput, CopyFromParent, CWOverrideRedirect|CWDontPropagate, &xswa); if(!window) RAISE("can't create window"); - set_wm_hints(sx,sy); - if (is_owner) { - // fall_thru 0 - XSelectInput(display, window, - ExposureMask | StructureNotifyMask | PointerMotionMask | - ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | - KeyPressMask | KeyReleaseMask); - XMapRaised(display, window); - } else { - // fall_thru 1 - XSelectInput(display, window, - ExposureMask | StructureNotifyMask); - } + set_wm_hints(); + _0_fall_thru(0,0,is_owner); + if (is_owner) XMapRaised(display, window); imagegc = XCreateGC(display, window, 0, NULL); if (visual->c_class == PseudoColor) prepare_colormap(); } @@ -380,9 +413,8 @@ GRID_INLET(FormatX11,0) { bit_packing->pack(sx, data, image+y*bypl); } } - if (autodraw==2) show_section(0,oy,sx,y-oy); } GRID_FINISH { - if (autodraw==1) show_section(0,0,in->dim->get(1),in->dim->get(0)); + show_section(0,0,in->dim->get(1),in->dim->get(0)); } GRID_END \def void close () { @@ -398,13 +430,6 @@ GRID_INLET(FormatX11,0) { } \def void _0_out_size (int sy, int sx) { resize_window(sx,sy); } -\def void _0_draw () { show_section(0,0,dim->get(1),dim->get(0)); } - -\def void _0_autodraw (int autodraw) { - if (autodraw<0 || autodraw>2) - RAISE("autodraw=%d is out of range",autodraw); - this->autodraw = autodraw; -} \def void _0_setcursor (int shape) { shape = 2*(shape&63); @@ -448,42 +473,32 @@ void FormatX11::prepare_colormap() { } void FormatX11::open_display(const char *disp_string) { - int screen_num; - Screen *screen; - - // Open an X11 connection display = XOpenDisplay(disp_string); if(!display) RAISE("ERROR: opening X11 display: %s",strerror(errno)); - // btw don't expect too much from Xlib error handling. // Xlib, you are so free of the ravages of intelligence... XSetErrorHandler(FormatX11_error_handler); - - screen = DefaultScreenOfDisplay(display); - screen_num = DefaultScreen(display); + Screen *screen = DefaultScreenOfDisplay(display); + int screen_num = DefaultScreen(display); visual = DefaultVisual(display, screen_num); - white = XWhitePixel(display,screen_num); - black = XBlackPixel(display,screen_num); root_window = DefaultRootWindow(display); depth = DefaultDepthOfScreen(screen); colormap = 0; switch(visual->c_class) { - case TrueColor: case DirectColor: /* without colormap */ - break; - case PseudoColor: /* with colormap */ - if (depth!=8) - RAISE("ERROR: with colormap, only supported depth is 8 (got %d)", - depth); - break; - default: RAISE("ERROR: visual type not supported (got %d)", - visual->c_class); + // without colormap + case TrueColor: case DirectColor: break; + // with colormap + case PseudoColor: if (depth!=8) RAISE("ERROR: with colormap, only supported depth is 8 (got %d)", depth); break; + default: RAISE("ERROR: visual type not supported (got %d)", visual->c_class); } -#ifdef HAVE_X11_SHARED_MEMORY - use_shm = !! XShmQueryExtension(display); +#if defined(HAVE_X11_XVIDEO) + transfer = 2; +#elif defined(HAVE_X11_SHARED_MEMORY) + transfer = !! XShmQueryExtension(display); #else - use_shm = false; + transfer = 0; #endif } @@ -514,55 +529,56 @@ Window FormatX11::search_window_tree (Window xid, Atom key, const char *value, i } \def void _0_set_geometry (int y, int x, int sy, int sx) { - pos_x = x; - pos_y = y; + pos[0]=y; pos[1]=x; XMoveWindow(display,window,x,y); resize_window(sx,sy); XFlush(display); } \def void _0_fall_thru (int flag) { - if (flag) { - gfpost("falling through!"); - XSelectInput(display, window, - ExposureMask | StructureNotifyMask); - } else { - gfpost("NOT falling through!"); - XSelectInput(display, window, - ExposureMask | StructureNotifyMask | - PointerMotionMask | - ButtonPressMask | ButtonReleaseMask | ButtonMotionMask); - } + int mask = ExposureMask | StructureNotifyMask; + if (flag) mask |= ExposureMask|StructureNotifyMask|PointerMotionMask| + ButtonPressMask|ButtonReleaseMask|ButtonMotionMask| + KeyPressMask|KeyReleaseMask; + XSelectInput(display, window, mask); XFlush(display); } +\def void _0_transfer (Symbol s) { + if (s==SYM(plain)) transfer=0; + else if (s==SYM(xshm)) transfer=1; + else if (s==SYM(xvideo)) transfer=2; + else RAISE("unknown transfer mode (possible: plain xshm xvideo)"); +} + +\def void _0_title (String s=Qnil) { + rb_ivar_set(rself,SI(@title),s); + set_wm_hints(); +} + \def void initialize (...) { int sy=240, sx=320; // defaults rb_call_super(argc,argv); + rb_ivar_set(rself,SI(@title),Qnil); argv++, argc--; VALUE domain = argc<1 ? SYM(here) : argv[0]; int i; + char host[256]; if (domain==SYM(here)) { open_display(0); i=1; } else if (domain==SYM(local)) { if (argc<2) RAISE("open x11 local: not enough args"); - char host[256]; - int dispnum = NUM2INT(argv[1]); - sprintf(host,":%d",dispnum); + sprintf(host,":%ld",NUM2LONG(argv[1])); open_display(host); i=2; } else if (domain==SYM(remote)) { if (argc<3) RAISE("open x11 remote: not enough args"); - char host[256]; - strcpy(host,rb_sym_name(argv[1])); - int dispnum = NUM2INT(argv[2]); - sprintf(host+strlen(host),":%d",dispnum); + sprintf(host,"%s:%ld",rb_sym_name(argv[1]),NUM2LONG(argv[2])); open_display(host); i=3; } else if (domain==SYM(display)) { if (argc<2) RAISE("open x11 display: not enough args"); - char host[256]; strcpy(host,rb_sym_name(argv[1])); for (int k=0; host[k]; k++) if (host[k]=='%') host[k]==':'; gfpost("mode `display', DISPLAY=`%s'",host); @@ -574,16 +590,12 @@ Window FormatX11::search_window_tree (Window xid, Atom key, const char *value, i for(;i<argc;i++) { Ruby a=argv[i]; - if (a==SYM(override_redirect)) { - override_redirect = true; - } else if (a==SYM(use_stripes)){ - use_stripes = true; - } else { - break; - } + if (a==SYM(override_redirect)) override_redirect = true; + else if (a==SYM(use_stripes)) use_stripes = true; + else RAISE("argument '%s' not recognized",rb_sym_name(argv[i])); } - pos_x=pos_y=0; + pos[1]=pos[0]=0; parent = root_window; if (i>=argc) { } else { @@ -594,7 +606,7 @@ Window FormatX11::search_window_tree (Window xid, Atom key, const char *value, i } else if (winspec==SYM(embed)) { Ruby title_s = rb_funcall(argv[i+1],SI(to_s),0); char *title = strdup(rb_str_ptr(title_s)); - sy = sx = pos_y = pos_x = 0; + sy = sx = pos[0] = pos[1] = 0; parent = search_window_tree(root_window,XInternAtom(display,"WM_NAME",0),title); free(title); if (parent == 0xDeadBeef) RAISE("Window not found."); @@ -617,7 +629,7 @@ Window FormatX11::search_window_tree (Window xid, Atom key, const char *value, i window = INT(winspec); } is_owner = false; - sy = sx = pos_y = pos_x = 0; + sy = sx = pos[0] = pos[1] = 0; } } @@ -625,8 +637,7 @@ Window FormatX11::search_window_tree (Window xid, Atom key, const char *value, i resize_window(sx,sy); if (is_owner) { - wmProtocolsAtom = XInternAtom(display, "WM_PROTOCOLS", False); - wmDeleteAtom = XInternAtom(display, "WM_DELETE_WINDOW", False); + Atom wmDeleteAtom = XInternAtom(display, "WM_DELETE_WINDOW", False); XSetWMProtocols(display,window,&wmDeleteAtom,1); } @@ -642,14 +653,17 @@ Window FormatX11::search_window_tree (Window xid, Atom key, const char *value, i uint32 masks[3] = { 0x07, 0x38, 0xC0 }; bit_packing = new BitPacking(disp_is_le, bpp/8, 3, masks); } break; + default: { RAISE("huh?"); } } IEVAL(rself,"@clock = Clock.new self; @clock.delay 0"); + show_section(0,0,sx,sy); } \classinfo { - IEVAL(rself,"install '#io:x11',1,1;@mode=6;@comment='X Window System Version 11.5'"); + IEVAL(rself,"install '#io:x11',1,1;@mode=6;@comment='X Window System Version 11.x'"); } \end class FormatX11 void startup_x11 () { \startall } + |