aboutsummaryrefslogtreecommitdiff
path: root/externals/gridflow/format
diff options
context:
space:
mode:
Diffstat (limited to 'externals/gridflow/format')
-rw-r--r--externals/gridflow/format/aalib.c2
-rw-r--r--externals/gridflow/format/dc1394.c2
-rw-r--r--externals/gridflow/format/jpeg.c12
-rw-r--r--externals/gridflow/format/main.rb33
-rw-r--r--externals/gridflow/format/mpeg3.c4
-rw-r--r--externals/gridflow/format/opengl.c181
-rw-r--r--externals/gridflow/format/png.c2
-rw-r--r--externals/gridflow/format/quartz.m2
-rw-r--r--externals/gridflow/format/quicktimeapple.c2
-rw-r--r--externals/gridflow/format/quicktimehw.c19
-rw-r--r--externals/gridflow/format/sdl.c2
-rw-r--r--externals/gridflow/format/videodev.c2
-rw-r--r--externals/gridflow/format/x11.c418
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
}
+