$ git clone http://tcclient.ion.nu/tc_client.git
commit 2b1624b7cb264087519b487b0fd3508becccdc34
Author: Alicia <...>
Date:   Sat Oct 8 01:52:10 2016 +0200

    libcamera: added support for a virtual X11 camera.

diff --git a/ChangeLog b/ChangeLog
index 4bf9b0f..32b2949 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -20,6 +20,7 @@ tc_client-gtk: fixed resampling of incoming audio.
 tc_client-gtk: added GTK+2 compatibility code related to the greenscreen camera color picker.
 tc_client-gtk: added compatibility code for windows' lack of pipe()
 tc_client-gtk: added workaround for libao not handling the "client_name" option on windows.
+libcamera: added support for a virtual X11 camera.
 tc_client-gtk and camviewer: updated to libavcodec's avcodec_{send,receive}_{frame,packet} API.
 camviewer: removed the old, buggy audio code.
 libcamera(v4l2): cache the frame and if there is no data to be read, return the cache instead of blocking.
diff --git a/Makefile b/Makefile
index b1fa0c3..ae86c88 100644
--- a/Makefile
+++ b/Makefile
@@ -72,6 +72,11 @@ ifdef SWSCALE_LIBS
   else
     CONFINFO+=|  v4l2 camera support will not be enabled
   endif
+  ifdef LIBX11_LIBS
+    CONFINFO+=|  Will enable X11 virtual camera support
+    CFLAGS+=-DHAVE_X11 $(LIBX11_CFLAGS)
+    LIBCAMERA_OBJ+=utilities/libcamera/camera_x11.o
+  endif
 endif
 endif
 endif
@@ -107,13 +112,13 @@ modbot: $(MODBOT_OBJ)
  $(CC) $(LDFLAGS) $^ $(LIBS) $(CURL_LIBS) -o $@
 
 camviewer: $(CAMVIEWER_OBJ)
- $(CC) $(LDFLAGS) $^ $(LIBS) $(GTK_LIBS) $(AVCODEC_LIBS) $(AVUTIL_LIBS) $(SWSCALE_LIBS) $(AVRESAMPLE_LIBS) $(SWRESAMPLE_LIBS) $(AO_LIBS) $(LIBV4L2_LIBS) -o $@
+ $(CC) $(LDFLAGS) $^ $(LIBS) $(GTK_LIBS) $(AVCODEC_LIBS) $(AVUTIL_LIBS) $(SWSCALE_LIBS) $(AVRESAMPLE_LIBS) $(SWRESAMPLE_LIBS) $(AO_LIBS) $(LIBV4L2_LIBS) $(LIBX11_LIBS) -o $@
 
 cursedchat: $(CURSEDCHAT_OBJ)
  $(CC) $(LDFLAGS) $^ $(LIBS) $(READLINE_LIBS) $(CURSES_LIBS) -o $@
 
 tc_client-gtk: $(TC_CLIENT_GTK_OBJ) camplaceholder.gif
- $(CC) $(LDFLAGS) $(TC_CLIENT_GTK_OBJ) $(LIBS) $(GTK_LIBS) $(AVCODEC_LIBS) $(AVUTIL_LIBS) $(SWSCALE_LIBS) $(AVRESAMPLE_LIBS) $(SWRESAMPLE_LIBS) $(AO_LIBS) $(LIBV4L2_LIBS) -o $@
+ $(CC) $(LDFLAGS) $(TC_CLIENT_GTK_OBJ) $(LIBS) $(GTK_LIBS) $(AVCODEC_LIBS) $(AVUTIL_LIBS) $(SWSCALE_LIBS) $(AVRESAMPLE_LIBS) $(SWRESAMPLE_LIBS) $(AO_LIBS) $(LIBV4L2_LIBS) $(LIBX11_LIBS) -o $@
 
 camplaceholder.gif: utilities/gtk/gencamplaceholder.sh utilities/gtk/camplaceholder.xcf utilities/gtk/spinnerdot.xcf
  utilities/gtk/gencamplaceholder.sh
@@ -133,7 +138,7 @@ SOURCES+=utilities/cursedchat/cursedchat.c utilities/cursedchat/buffer.c utiliti
 SOURCES+=utilities/gtk/camviewer.c utilities/gtk/userlist.c utilities/gtk/media.c utilities/gtk/compat.c utilities/gtk/config.c utilities/gtk/gui.c utilities/gtk/logging.c utilities/gtk/postproc.c utilities/gtk/inputhistory.c utilities/gtk/userlist.h utilities/gtk/media.h utilities/gtk/compat.h utilities/gtk/config.h utilities/gtk/gui.h utilities/gtk/logging.h utilities/gtk/postproc.h utilities/gtk/inputhistory.h gtkgui.glade
 SOURCES+=utilities/gtk/gencamplaceholder.sh utilities/gtk/camplaceholder.xcf utilities/gtk/spinnerdot.xcf
 SOURCES+=utilities/compat.c utilities/compat.h utilities/list.c utilities/list.h utilities/stringutils.c utilities/stringutils.h utilities/compat_av.c utilities/compat_av.h
-SOURCES+=utilities/libcamera/camera.c utilities/libcamera/camera.h utilities/libcamera/camera_v4l2.c utilities/libcamera/camera_v4l2.h utilities/libcamera/camera_img.c utilities/libcamera/camera_img.h utilities/libcamera/camera_escapi.cpp utilities/libcamera/camera_escapi.h
+SOURCES+=utilities/libcamera/camera.c utilities/libcamera/camera.h utilities/libcamera/camera_v4l2.c utilities/libcamera/camera_v4l2.h utilities/libcamera/camera_img.c utilities/libcamera/camera_img.h utilities/libcamera/camera_escapi.cpp utilities/libcamera/camera_escapi.h utilities/libcamera/camera_x11.c utilities/libcamera/camera_x11.h
 tarball:
  tar -cJf tc_client-$(VERSION).tar.xz --transform='s|^|tc_client-$(VERSION)/|' $(SOURCES)
 
diff --git a/configure b/configure
index 2865aea..8868c34 100755
--- a/configure
+++ b/configure
@@ -252,6 +252,16 @@ else
   echo no
 fi
 
+printf 'Checking for X11... '
+x11libs="`pkg-config --libs x11 2> /dev/null`"
+if [ "x$x11libs" != "x" ]; then
+  echo "LIBX11_LIBS=${x11libs}" >> config.mk
+  echo "LIBX11_CFLAGS=`pkg-config --cflags x11`" >> config.mk
+  echo yes
+else
+  echo no
+fi
+
 # TODO: handle crosscompiling better
 printf 'Checking if endianness macros work... '
 echo '#include <stdio.h>' > endiantest.c
diff --git a/utilities/libcamera/camera.c b/utilities/libcamera/camera.c
index e5b2603..95a638b 100644
--- a/utilities/libcamera/camera.c
+++ b/utilities/libcamera/camera.c
@@ -1,6 +1,6 @@
 /*
     libcamera, a camera access abstraction library
-    Copyright (C) 2015  alicia@ion.nu
+    Copyright (C) 2015-2016  alicia@ion.nu
 
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU Affero General Public License as published by
@@ -18,6 +18,7 @@
 #include "camera.h"
 #include "camera_v4l2.h"
 #include "camera_escapi.h"
+#include "camera_x11.h"
 #include "camera_img.h"
 
 struct CAM_t
@@ -35,6 +36,9 @@ char** cam_list(unsigned int* count)
   #ifdef HAVE_ESCAPI
   list=cam_list_escapi(list, count);
   #endif
+  #ifdef HAVE_X11
+  list=cam_list_x11(list, count);
+  #endif
   list=cam_list_img(list, count);
   return list;
 }
@@ -47,6 +51,9 @@ CAM* cam_open(const char* name)
   #ifdef HAVE_ESCAPI
   if(!strncmp(name, "escapi:", 7)){return cam_open_escapi(name);}
   #endif
+  #ifdef HAVE_X11
+  if(!strcmp(name, "X11")){return cam_open_x11();}
+  #endif
   if(!strcmp(name, "Image")){return cam_open_img();}
   return 0;
 }
@@ -61,6 +68,9 @@ void cam_resolution(CAM* cam, unsigned int* width, unsigned int* height)
     #ifdef HAVE_ESCAPI
     case CAMTYPE_ESCAPI: cam_resolution_escapi(cam, width, height); break;
     #endif
+    #ifdef HAVE_X11
+    case CAMTYPE_X11: cam_resolution_x11(cam, width, height); break;
+    #endif
     case CAMTYPE_IMG: cam_resolution_img(cam, width, height); break;
   }
 }
@@ -75,6 +85,9 @@ void cam_getframe(CAM* cam, void* pixmap)
     #ifdef HAVE_ESCAPI
     case CAMTYPE_ESCAPI: cam_getframe_escapi(cam, pixmap); break;
     #endif
+    #ifdef HAVE_X11
+    case CAMTYPE_X11: cam_getframe_x11(cam, pixmap); break;
+    #endif
     case CAMTYPE_IMG: cam_getframe_img(cam, pixmap); break;
   }
 }
@@ -89,6 +102,9 @@ void cam_close(CAM* cam)
     #ifdef HAVE_ESCAPI
     case CAMTYPE_ESCAPI: cam_close_escapi(cam); break;
     #endif
+    #ifdef HAVE_X11
+    case CAMTYPE_X11: cam_close_x11(cam); break;
+    #endif
     case CAMTYPE_IMG: cam_close_img(cam); break;
   }
 }
diff --git a/utilities/libcamera/camera.h b/utilities/libcamera/camera.h
index 6cf4776..77d17b4 100644
--- a/utilities/libcamera/camera.h
+++ b/utilities/libcamera/camera.h
@@ -1,6 +1,6 @@
 /*
     libcamera, a camera access abstraction library
-    Copyright (C) 2015  alicia@ion.nu
+    Copyright (C) 2015-2016  alicia@ion.nu
 
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU Affero General Public License as published by
@@ -19,7 +19,8 @@
 enum{
   CAMTYPE_V4L2,
   CAMTYPE_ESCAPI,
-  CAMTYPE_IMG
+  CAMTYPE_IMG,
+  CAMTYPE_X11
 };
 struct CAM_t;
 typedef struct CAM_t CAM;
diff --git a/utilities/libcamera/camera_x11.c b/utilities/libcamera/camera_x11.c
new file mode 100644
index 0000000..7ca76a8
--- /dev/null
+++ b/utilities/libcamera/camera_x11.c
@@ -0,0 +1,85 @@
+/*
+    libcamera, a camera access abstraction library
+    Copyright (C) 2016  alicia@ion.nu
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Affero General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    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 Affero General Public License for more details.
+
+    You should have received a copy of the GNU Affero General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#include <stdlib.h>
+#include <string.h>
+#include <X11/Xlib.h>
+#include "camera.h"
+typedef struct CAM_t
+{
+  unsigned int type;
+  Display* display;
+  int screen;
+  Window rootwindow;
+  int width;
+  int height;
+} CAM;
+
+char** cam_list_x11(char** list, unsigned int* count)
+{
+  ++*count;
+  list=realloc(list, sizeof(char*)*(*count));
+  list[(*count)-1]=strdup("X11");
+  return list;
+}
+
+CAM* cam_open_x11(void) // const char* name)
+{
+  Display* display=XOpenDisplay(getenv("DISPLAY"));
+  if(!display){return 0;}
+  CAM* cam=malloc(sizeof(CAM));
+  cam->type=CAMTYPE_X11;
+  cam->display=display;
+  cam->screen=XDefaultScreen(display);
+  cam->width=DisplayWidth(cam->display, cam->screen);
+  cam->height=DisplayHeight(cam->display, cam->screen);
+  cam->rootwindow=RootWindow(cam->display, cam->screen);
+  return cam;
+}
+
+void cam_resolution_x11(CAM* cam, unsigned int* width, unsigned int* height)
+{
+  *width=cam->width;
+  *height=cam->height;
+}
+
+void cam_getframe_x11(CAM* cam, void* pixmap)
+{
+  XImage* img=XGetImage(cam->display, cam->rootwindow, 0, 0, cam->width, cam->height, AllPlanes, ZPixmap);
+  unsigned int bpp=img->bits_per_pixel/8;
+  unsigned int x, y;
+  for(y=0; y<cam->height; ++y)
+  {
+    for(x=0; x<cam->width; ++x)
+    {
+      if(img->blue_mask>img->red_mask)
+      {
+        memcpy(pixmap+(y*cam->width+x)*3, img->data+y*img->bytes_per_line+x*bpp, 3);
+      }else{
+        memcpy(pixmap+(y*cam->width+x)*3+2, img->data+y*img->bytes_per_line+x*bpp, 1);
+        memcpy(pixmap+(y*cam->width+x)*3+1, img->data+y*img->bytes_per_line+x*bpp+1, 1);
+        memcpy(pixmap+(y*cam->width+x)*3, img->data+y*img->bytes_per_line+x*bpp+2, 1);
+      }
+    }
+  }
+  img->f.destroy_image(img);
+}
+
+void cam_close_x11(CAM* cam)
+{
+  XCloseDisplay(cam->display);
+  free(cam);
+}
diff --git a/utilities/libcamera/camera_x11.h b/utilities/libcamera/camera_x11.h
new file mode 100644
index 0000000..6b87c21
--- /dev/null
+++ b/utilities/libcamera/camera_x11.h
@@ -0,0 +1,21 @@
+/*
+    libcamera, a camera access abstraction library
+    Copyright (C) 2016  alicia@ion.nu
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Affero General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    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 Affero General Public License for more details.
+
+    You should have received a copy of the GNU Affero General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+extern char** cam_list_x11(char** list, unsigned int* count);
+extern CAM* cam_open_x11(void);
+extern void cam_resolution_x11(CAM* cam, unsigned int* width, unsigned int* height);
+extern void cam_getframe_x11(CAM* cam, void* pixmap);
+extern void cam_close_x11(CAM* cam);