summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile6
-rw-r--r--joystick.cpp219
-rw-r--r--joystick.h64
-rw-r--r--mariokart.cpp438
-rw-r--r--os.h2
-rw-r--r--xorg_grabber.cpp163
-rw-r--r--xorg_grabber.h25
7 files changed, 482 insertions, 435 deletions
diff --git a/Makefile b/Makefile
index e7a632c..f8ad6c4 100644
--- a/Makefile
+++ b/Makefile
@@ -9,14 +9,16 @@ clean:
.cpp.o:
g++ `pkg-config --cflags opencv` -g -c $<
+joystick.o: joystick.cpp os.h
+ g++ `pkg-config --cflags opencv` -g -c $<
detect_road_borders: detect_road_borders.cpp
- g++ `pkg-config --libs --cflags opencv` -g $^ -o $@
+ g++ `pkg-config --libs --cflags opencv` -g $> -o $@
test_detect: detect_road_borders
./detect_road_borders test.mpg
-mariokart: mariokart.o road_thresholder.o horizon_steerer.o naive_steerer.o steer_accumulator.o util.o
+mariokart: mariokart.o os.h joystick.o xorg_grabber.o road_thresholder.o horizon_steerer.o naive_steerer.o steer_accumulator.o util.o
g++ `pkg-config --libs --cflags opencv` -lxcb -lpthread -g $> -o $@
diff --git a/joystick.cpp b/joystick.cpp
new file mode 100644
index 0000000..92c2d5e
--- /dev/null
+++ b/joystick.cpp
@@ -0,0 +1,219 @@
+#include "joystick.h"
+#include "os.h"
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <string>
+#include <iostream>
+#include <fcntl.h>
+
+#ifdef LINUX
+#include <linux/input.h>
+#include <linux/uinput.h>
+#endif
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/uio.h>
+
+using namespace std;
+
+#define THROTTLE_CNT_MAX 10
+
+#ifdef FREEBSD
+static char* pack(const BUTTONS* buttons, char* buf)
+{
+ buf[0]= (buttons->A_BUTTON ? 1 : 0) +
+ (buttons->B_BUTTON ? 2 : 0) +
+ (buttons->L_TRIG ? 4 : 0) +
+ (buttons->R_TRIG ? 8 : 0) +
+ (buttons->Z_TRIG ? 16 : 0) +
+ (buttons->START_BUTTON ? 32 : 0) +
+ 128;
+
+ buf[1]= (buttons->R_DPAD ? 1 : 0) +
+ (buttons->L_DPAD ? 2 : 0) +
+ (buttons->U_DPAD ? 4 : 0) +
+ (buttons->D_DPAD ? 8 : 0) +
+ ((buttons->X_AXIS & 128) ? 16 : 0) +
+ ((buttons->Y_AXIS & 128) ? 32 : 0);
+
+ buf[2]= (buttons->R_CBUTTON ? 1 : 0) +
+ (buttons->L_CBUTTON ? 2 : 0) +
+ (buttons->U_CBUTTON ? 4 : 0) +
+ (buttons->D_CBUTTON ? 8 : 0);
+
+ buf[3]= (buttons->X_AXIS & 127);
+
+ buf[4]= (buttons->Y_AXIS & 127);
+
+ return buf;
+}
+#endif
+
+
+
+#ifdef FREEBSD
+Joystick::Joystick()
+{
+ if ((fifo_fd=open("/var/tmp/mupen64plus_ctl", O_WRONLY )) == -1) {throw string(strerror(errno));}
+ cout << "opened" << endl;
+ if (fcntl(fifo_fd, F_SETFL, O_NONBLOCK) == -1) throw string("failed to set nonblocking io");
+
+ reset();
+}
+
+void Joystick::press_a(bool state)
+{
+ buttons.A_BUTTON=state;
+ send_data();
+}
+
+void Joystick::send_data()
+{
+ char buf[5];
+ pack(&buttons, buf);
+ write(fifo_fd, buf, 5);
+}
+
+
+
+void Joystick::steer(float dir, float dead_zone)
+{
+ if (dir<-1.0) dir=-1.0;
+ if (dir>1.0) dir=1.0;
+
+ if (fabs(dir)<dead_zone) dir=0.0;
+
+ buttons.X_AXIS = (signed) (127.0*dir);
+ send_data();
+}
+
+void Joystick::reset()
+{
+ memset(&buttons, sizeof(buttons), 0);
+ buttons.Z_TRIG=0;
+ buttons.R_TRIG=0;
+ buttons.L_TRIG=0;
+ buttons.A_BUTTON=0;
+ buttons.B_BUTTON=0;
+ send_data();
+}
+
+Joystick::~Joystick()
+{
+ close(fifo_fd);
+}
+#endif // FREEBSD
+#ifdef LINUX
+Joystick::Joystick()
+{
+ fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
+ if(fd < 0) {
+ cerr << "open uinput failed. do you have privilegies to access it? (try chown flo:root /dev/uinput)" << endl;
+ exit(EXIT_FAILURE);
+ }
+
+ int ret;
+
+ ret=ioctl(fd, UI_SET_EVBIT, EV_KEY);
+ ret=ioctl(fd, UI_SET_EVBIT, EV_SYN);
+ ret=ioctl(fd, UI_SET_KEYBIT , BTN_A);
+ ioctl(fd, UI_SET_EVBIT, EV_ABS);
+ ioctl(fd, UI_SET_ABSBIT, ABS_X);
+ ioctl(fd, UI_SET_ABSBIT, ABS_Y);
+
+ struct uinput_user_dev meh;
+ memset(&meh,0,sizeof(meh));
+
+ strcpy(meh.name, "flotest");
+ meh.id.bustype=BUS_USB;
+ meh.id.vendor=0xdead;
+ meh.id.product=0xbeef;
+ meh.id.version=1;
+ meh.absmin[ABS_X]=0;
+ meh.absmax[ABS_X]=10000;
+ meh.absmin[ABS_Y]=0;
+ meh.absmax[ABS_Y]=10000;
+
+
+ ret=write(fd, &meh, sizeof(meh));
+
+ ioctl(fd,UI_DEV_CREATE);
+
+ reset();
+}
+
+Joystick::~Joystick()
+{
+ ioctl(fd, UI_DEV_DESTROY);
+ close(fd);
+}
+
+void Joystick::steer(float dir, float dead_zone)
+{
+ if (dir<-1.0) dir=-1.0;
+ if (dir>1.0) dir=1.0;
+
+ if (fabs(dir)<dead_zone) dir=0.0;
+
+ struct input_event ev;
+ ev.type=EV_ABS;
+ ev.code=ABS_X;
+ ev.value=5000+dir*5000;
+ write(fd, &ev, sizeof(ev));
+}
+
+
+void Joystick::press_a(bool a)
+{
+ struct input_event ev;
+ ev.type=EV_KEY;
+ ev.code=BTN_A;
+ ev.value = a ? 1 : 0;
+ write(fd, &ev, sizeof(ev));
+}
+
+void Joystick::reset()
+{
+ struct input_event ev;
+ ev.type=EV_ABS;
+ ev.code=ABS_Y;
+ ev.value=5001;
+ write(fd, &ev, sizeof(ev));
+ ev.value=5000;
+ write(fd, &ev, sizeof(ev));
+
+ cout << "Y zeroed" << endl;
+
+ steer(0.1);
+ steer(0);
+ cout << "X zeroed" << endl;
+
+ press_a(true);
+ press_a(false);
+ cout << "A zeroed" << endl;
+}
+
+#endif // LINUX
+
+
+void Joystick::throttle(float t)
+{
+ if (t<0.0) t=0.0;
+ if (t>1.0) t=1.0;
+
+ throt=t;
+}
+
+void Joystick::process()
+{
+ throttle_cnt++;
+ if (throttle_cnt>=THROTTLE_CNT_MAX) throttle_cnt=0;
+
+ press_a((throttle_cnt < throt*THROTTLE_CNT_MAX));
+}
+
diff --git a/joystick.h b/joystick.h
new file mode 100644
index 0000000..2c55a2e
--- /dev/null
+++ b/joystick.h
@@ -0,0 +1,64 @@
+#ifndef __JOYSTICK_H__
+#define __JOYSTICK_H__
+
+#include "os.h"
+
+#ifdef FREEBSD
+typedef union {
+ unsigned int Value;
+ struct {
+ unsigned R_DPAD : 1;
+ unsigned L_DPAD : 1;
+ unsigned D_DPAD : 1;
+ unsigned U_DPAD : 1;
+ unsigned START_BUTTON : 1;
+ unsigned Z_TRIG : 1;
+ unsigned B_BUTTON : 1;
+ unsigned A_BUTTON : 1;
+
+ unsigned R_CBUTTON : 1;
+ unsigned L_CBUTTON : 1;
+ unsigned D_CBUTTON : 1;
+ unsigned U_CBUTTON : 1;
+ unsigned R_TRIG : 1;
+ unsigned L_TRIG : 1;
+ unsigned Reserved1 : 1;
+ unsigned Reserved2 : 1;
+
+ signed X_AXIS : 8;
+ signed Y_AXIS : 8;
+ };
+} BUTTONS;
+
+#endif // FREEBSD
+
+
+class Joystick
+{
+ public:
+ Joystick();
+ ~Joystick();
+ void steer(float dir, float dead_zone=0.0);
+ void throttle(float t);
+ void press_a(bool);
+
+
+ void process();
+ void reset();
+
+ private:
+#ifdef FREEBSD
+ BUTTONS buttons;
+ void send_data();
+ int fifo_fd;
+#endif
+#ifdef LINUX
+ int fd;
+#endif
+
+ float throt;
+ int throttle_cnt;
+
+};
+
+#endif // __JOYSTICK_H__
diff --git a/mariokart.cpp b/mariokart.cpp
index dc6eaa9..ff5fbaa 100644
--- a/mariokart.cpp
+++ b/mariokart.cpp
@@ -20,8 +20,8 @@
*/
-#define FREEBSD
-//#define LINUX
+#include "os.h"
+
#include <vector>
#include <unistd.h>
@@ -32,15 +32,6 @@
#include <semaphore.h>
#include <fcntl.h>
-#ifdef LINUX
-#include <linux/input.h>
-#include <linux/uinput.h>
-#endif
-
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/uio.h>
#include "util.h"
#include "steer_interface.h"
@@ -48,9 +39,11 @@
#include "road_thresholder_iface.h"
#include "road_thresholder.h"
+#include "xorg_grabber.h"
+#include "joystick.h"
+
#include <iostream>
#include <list>
-#include <xcb/xcb.h>
#include <assert.h>
#include <opencv2/opencv.hpp>
@@ -58,433 +51,12 @@
using namespace std;
using namespace cv;
-class XorgGrabber
-{
- public:
- XorgGrabber(const char* win_title);
- ~XorgGrabber();
- void read(Mat& mat);
-
- private:
- xcb_connection_t* conn;
- xcb_window_t grabbed_win;
- int grab_width, grab_height;
- xcb_screen_t* grab_screen;
- xcb_get_image_reply_t* img;
-
-};
-
-XorgGrabber::XorgGrabber(const char* win_title)
-{
- conn=xcb_connect(NULL,NULL);
-
- bool found_win=false;
- grab_screen=NULL;
- img=NULL;
-
- /* Find configured screen */
- const xcb_setup_t* setup = xcb_get_setup(conn);
- for (xcb_screen_iterator_t i = xcb_setup_roots_iterator(setup);
- i.rem > 0; xcb_screen_next (&i))
- {
- xcb_screen_t* scr = i.data;
- xcb_query_tree_reply_t* reply = xcb_query_tree_reply( conn, xcb_query_tree(conn, scr->root), NULL);
- if (reply)
- {
- int len = xcb_query_tree_children_length(reply);
- xcb_window_t* children = xcb_query_tree_children(reply);
- xcb_get_window_attributes_cookie_t* cookies = new xcb_get_window_attributes_cookie_t[len];
- for (int i=0; i<len; ++i)
- cookies[i]=xcb_get_window_attributes(conn, children[i]);
-
- for (int i=0; i<len; ++i)
- {
- xcb_get_window_attributes_reply_t* attr =
- xcb_get_window_attributes_reply (conn, cookies[i], NULL);
-
-
- xcb_get_property_reply_t* title_reply = xcb_get_property_reply(conn,
- xcb_get_property(conn, false, children[i], XCB_ATOM_WM_NAME, XCB_GET_PROPERTY_TYPE_ANY, 0, 128),
- NULL );
-
- if (!attr->override_redirect && attr->map_state == XCB_MAP_STATE_VIEWABLE)
- {
- char* title=(char*)(title_reply+1);
- cout << title << endl;
- if (strstr(title, win_title))
- {
- xcb_get_geometry_reply_t* geo;
- geo = xcb_get_geometry_reply (conn, xcb_get_geometry (conn, children[i]), NULL);
- if (geo)
- {
- grab_width=geo->width;
- grab_height=geo->height;
-
- free(geo);
-
- grabbed_win=children[i];
- found_win=true;
-
- grab_screen=scr;
- }
- else
- {
- cerr << "geo==NULL!" << endl;
- }
- }
- }
-
- free(title_reply);
- free(attr);
- }
-
- free(reply);
- delete[] cookies;
- }
- else
- {
- cout << "xcb_get_setup failed" << endl;
- }
- }
-
- if (found_win)
- {
- xcb_get_image_reply_t* img = xcb_get_image_reply (conn,
- xcb_get_image (conn, XCB_IMAGE_FORMAT_Z_PIXMAP, grabbed_win,
- 0, 0, grab_width, grab_height, ~0), NULL);
-
-
-
- xcb_depth_iterator_t depth_iterator = xcb_screen_allowed_depths_iterator(grab_screen);
-
- int ndepths=xcb_screen_allowed_depths_length(grab_screen);
-
- for (int i=0; i<ndepths; ++i)
- {
- if (depth_iterator.data->depth == img->depth)
- {
- xcb_visualtype_t* visuals = xcb_depth_visuals(depth_iterator.data);
- int nvisuals = xcb_depth_visuals_length(depth_iterator.data);
-
- for (int j=0;j<nvisuals;j++)
- {
- if (visuals[j].visual_id==img->visual)
- {
- assert(visuals[j]._class==XCB_VISUAL_CLASS_TRUE_COLOR || visuals[j]._class==XCB_VISUAL_CLASS_DIRECT_COLOR);
- cout << (int)visuals[j]._class << "," << XCB_VISUAL_CLASS_TRUE_COLOR << endl;
- cout << visuals[j].red_mask << endl;
- cout << visuals[j].green_mask << endl;
- cout << visuals[j].blue_mask << endl;
- break;
- }
- }
-
- break;
- }
-
- xcb_depth_next(&depth_iterator);
- }
-
-
-
- int nformats = xcb_setup_pixmap_formats_length(setup);
- xcb_format_t* formats = xcb_setup_pixmap_formats(setup);
- for (int i=0;i<nformats;i++)
- {
- if (formats[i].depth==img->depth)
- {
- cout << (int)formats[i].bits_per_pixel << endl;
- cout << (int)formats[i].scanline_pad << endl;
- break;
- }
- }
-
- cout << grab_width << "x" << grab_height << endl;
-
- free(img);
-
- }
- else
- {
- throw string("FATAL: did not find window, exiting.");
- }
-
-
-}
-
-XorgGrabber::~XorgGrabber()
-{
- if (img) free(img);
- xcb_disconnect(conn);
-}
-
-void XorgGrabber::read(Mat& mat)
-{
- if (img) free(img);
-
-
- // mat gets invalid when the next read() is called!
- img = xcb_get_image_reply (conn,
- xcb_get_image (conn, XCB_IMAGE_FORMAT_Z_PIXMAP, grabbed_win,
- 0, 0, grab_width, grab_height, ~0), NULL);
-
- mat = Mat(grab_height, grab_width, CV_8UC4, xcb_get_image_data(img));
- mat.addref();
-}
-
-
-
-
-#define THROTTLE_CNT_MAX 10
-
-
-#ifdef FREEBSD
-typedef union {
- unsigned int Value;
- struct {
- unsigned R_DPAD : 1;
- unsigned L_DPAD : 1;
- unsigned D_DPAD : 1;
- unsigned U_DPAD : 1;
- unsigned START_BUTTON : 1;
- unsigned Z_TRIG : 1;
- unsigned B_BUTTON : 1;
- unsigned A_BUTTON : 1;
-
- unsigned R_CBUTTON : 1;
- unsigned L_CBUTTON : 1;
- unsigned D_CBUTTON : 1;
- unsigned U_CBUTTON : 1;
- unsigned R_TRIG : 1;
- unsigned L_TRIG : 1;
- unsigned Reserved1 : 1;
- unsigned Reserved2 : 1;
-
- signed X_AXIS : 8;
- signed Y_AXIS : 8;
- };
-} BUTTONS;
-
-
-char* pack(const BUTTONS* buttons, char* buf)
-{
- buf[0]= (buttons->A_BUTTON ? 1 : 0) +
- (buttons->B_BUTTON ? 2 : 0) +
- (buttons->L_TRIG ? 4 : 0) +
- (buttons->R_TRIG ? 8 : 0) +
- (buttons->Z_TRIG ? 16 : 0) +
- (buttons->START_BUTTON ? 32 : 0) +
- 128;
-
- buf[1]= (buttons->R_DPAD ? 1 : 0) +
- (buttons->L_DPAD ? 2 : 0) +
- (buttons->U_DPAD ? 4 : 0) +
- (buttons->D_DPAD ? 8 : 0) +
- ((buttons->X_AXIS & 128) ? 16 : 0) +
- ((buttons->Y_AXIS & 128) ? 32 : 0);
-
- buf[2]= (buttons->R_CBUTTON ? 1 : 0) +
- (buttons->L_CBUTTON ? 2 : 0) +
- (buttons->U_CBUTTON ? 4 : 0) +
- (buttons->D_CBUTTON ? 8 : 0);
-
- buf[3]= (buttons->X_AXIS & 127);
-
- buf[4]= (buttons->Y_AXIS & 127);
-
- return buf;
-}
-#endif
-
-class Joystick
-{
- public:
- Joystick();
- ~Joystick();
- void steer(float dir, float dead_zone=0.0);
- void throttle(float t);
- void press_a(bool);
-
-
- void process();
- void reset();
-
- private:
-#ifdef FREEBSD
- BUTTONS buttons;
- void send_data();
- int fifo_fd;
-#endif
-#ifdef LINUX
- int fd;
-#endif
-
- float throt;
- int throttle_cnt;
-
-};
-
-#ifdef FREEBSD
-Joystick::Joystick()
-{
- if ((fifo_fd=open("/var/tmp/mupen64plus_ctl", O_WRONLY )) == -1) {throw string(strerror(errno));}
- cout << "opened" << endl;
- if (fcntl(fifo_fd, F_SETFL, O_NONBLOCK) == -1) throw string("failed to set nonblocking io");
-
- reset();
-}
-
-void Joystick::press_a(bool state)
-{
- buttons.A_BUTTON=state;
- send_data();
-}
-
-void Joystick::send_data()
-{
- char buf[5];
- pack(&buttons, buf);
- write(fifo_fd, buf, 5);
-}
-
-
-
-void Joystick::steer(float dir, float dead_zone)
-{
- if (dir<-1.0) dir=-1.0;
- if (dir>1.0) dir=1.0;
-
- if (fabs(dir)<dead_zone) dir=0.0;
-
- buttons.X_AXIS = (signed) (127.0*dir);
- send_data();
-}
-
-void Joystick::reset()
-{
- memset(&buttons, sizeof(buttons), 0);
- buttons.Z_TRIG=0;
- buttons.R_TRIG=0;
- buttons.L_TRIG=0;
- buttons.A_BUTTON=0;
- buttons.B_BUTTON=0;
- send_data();
-}
-
-Joystick::~Joystick()
-{
- close(fifo_fd);
-}
-#endif
-#ifdef LINUX
-Joystick::Joystick()
-{
- fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
- if(fd < 0) {
- cerr << "open uinput failed. do you have privilegies to access it? (try chown flo:root /dev/uinput)" << endl;
- exit(EXIT_FAILURE);
- }
-
- int ret;
-
- ret=ioctl(fd, UI_SET_EVBIT, EV_KEY);
- ret=ioctl(fd, UI_SET_EVBIT, EV_SYN);
- ret=ioctl(fd, UI_SET_KEYBIT , BTN_A);
- ioctl(fd, UI_SET_EVBIT, EV_ABS);
- ioctl(fd, UI_SET_ABSBIT, ABS_X);
- ioctl(fd, UI_SET_ABSBIT, ABS_Y);
-
- struct uinput_user_dev meh;
- memset(&meh,0,sizeof(meh));
-
- strcpy(meh.name, "flotest");
- meh.id.bustype=BUS_USB;
- meh.id.vendor=0xdead;
- meh.id.product=0xbeef;
- meh.id.version=1;
- meh.absmin[ABS_X]=0;
- meh.absmax[ABS_X]=10000;
- meh.absmin[ABS_Y]=0;
- meh.absmax[ABS_Y]=10000;
-
-
- ret=write(fd, &meh, sizeof(meh));
-
- ioctl(fd,UI_DEV_CREATE);
-
- reset();
-}
-
-Joystick::~Joystick()
-{
- ioctl(fd, UI_DEV_DESTROY);
- close(fd);
-}
-void Joystick::steer(float dir, float dead_zone)
-{
- if (dir<-1.0) dir=-1.0;
- if (dir>1.0) dir=1.0;
-
- if (fabs(dir)<dead_zone) dir=0.0;
-
- struct input_event ev;
- ev.type=EV_ABS;
- ev.code=ABS_X;
- ev.value=5000+dir*5000;
- write(fd, &ev, sizeof(ev));
-}
-void Joystick::press_a(bool a)
-{
- struct input_event ev;
- ev.type=EV_KEY;
- ev.code=BTN_A;
- ev.value = a ? 1 : 0;
- write(fd, &ev, sizeof(ev));
-}
-void Joystick::reset()
-{
- struct input_event ev;
- ev.type=EV_ABS;
- ev.code=ABS_Y;
- ev.value=5001;
- write(fd, &ev, sizeof(ev));
- ev.value=5000;
- write(fd, &ev, sizeof(ev));
-
- cout << "Y zeroed" << endl;
-
- steer(0.1);
- steer(0);
- cout << "X zeroed" << endl;
-
- press_a(true);
- press_a(false);
- cout << "A zeroed" << endl;
-}
-
-#endif
-void Joystick::throttle(float t)
-{
- if (t<0.0) t=0.0;
- if (t>1.0) t=1.0;
-
- throt=t;
-}
-
-void Joystick::process()
-{
- throttle_cnt++;
- if (throttle_cnt>=THROTTLE_CNT_MAX) throttle_cnt=0;
-
- press_a((throttle_cnt < throt*THROTTLE_CNT_MAX));
-}
-
#define HIST_SMOOTH 7
diff --git a/os.h b/os.h
new file mode 100644
index 0000000..c7433e2
--- /dev/null
+++ b/os.h
@@ -0,0 +1,2 @@
+#define FREEBSD
+//#define LINUX
diff --git a/xorg_grabber.cpp b/xorg_grabber.cpp
new file mode 100644
index 0000000..386cab6
--- /dev/null
+++ b/xorg_grabber.cpp
@@ -0,0 +1,163 @@
+#include "xorg_grabber.h"
+
+#include <iostream>
+using namespace std;
+
+XorgGrabber::XorgGrabber(const char* win_title)
+{
+ conn=xcb_connect(NULL,NULL);
+
+ bool found_win=false;
+ grab_screen=NULL;
+ img=NULL;
+
+ /* Find configured screen */
+ const xcb_setup_t* setup = xcb_get_setup(conn);
+ for (xcb_screen_iterator_t i = xcb_setup_roots_iterator(setup);
+ i.rem > 0; xcb_screen_next (&i))
+ {
+ xcb_screen_t* scr = i.data;
+ xcb_query_tree_reply_t* reply = xcb_query_tree_reply( conn, xcb_query_tree(conn, scr->root), NULL);
+ if (reply)
+ {
+ int len = xcb_query_tree_children_length(reply);
+ xcb_window_t* children = xcb_query_tree_children(reply);
+ xcb_get_window_attributes_cookie_t* cookies = new xcb_get_window_attributes_cookie_t[len];
+ for (int i=0; i<len; ++i)
+ cookies[i]=xcb_get_window_attributes(conn, children[i]);
+
+ for (int i=0; i<len; ++i)
+ {
+ xcb_get_window_attributes_reply_t* attr =
+ xcb_get_window_attributes_reply (conn, cookies[i], NULL);
+
+
+ xcb_get_property_reply_t* title_reply = xcb_get_property_reply(conn,
+ xcb_get_property(conn, false, children[i], XCB_ATOM_WM_NAME, XCB_GET_PROPERTY_TYPE_ANY, 0, 128),
+ NULL );
+
+ if (!attr->override_redirect && attr->map_state == XCB_MAP_STATE_VIEWABLE)
+ {
+ char* title=(char*)(title_reply+1);
+ cout << title << endl;
+ if (strstr(title, win_title))
+ {
+ xcb_get_geometry_reply_t* geo;
+ geo = xcb_get_geometry_reply (conn, xcb_get_geometry (conn, children[i]), NULL);
+ if (geo)
+ {
+ grab_width=geo->width;
+ grab_height=geo->height;
+
+ free(geo);
+
+ grabbed_win=children[i];
+ found_win=true;
+
+ grab_screen=scr;
+ }
+ else
+ {
+ cerr << "geo==NULL!" << endl;
+ }
+ }
+ }
+
+ free(title_reply);
+ free(attr);
+ }
+
+ free(reply);
+ delete[] cookies;
+ }
+ else
+ {
+ cout << "xcb_get_setup failed" << endl;
+ }
+ }
+
+ if (found_win)
+ {
+ xcb_get_image_reply_t* img = xcb_get_image_reply (conn,
+ xcb_get_image (conn, XCB_IMAGE_FORMAT_Z_PIXMAP, grabbed_win,
+ 0, 0, grab_width, grab_height, ~0), NULL);
+
+
+
+ xcb_depth_iterator_t depth_iterator = xcb_screen_allowed_depths_iterator(grab_screen);
+
+ int ndepths=xcb_screen_allowed_depths_length(grab_screen);
+
+ for (int i=0; i<ndepths; ++i)
+ {
+ if (depth_iterator.data->depth == img->depth)
+ {
+ xcb_visualtype_t* visuals = xcb_depth_visuals(depth_iterator.data);
+ int nvisuals = xcb_depth_visuals_length(depth_iterator.data);
+
+ for (int j=0;j<nvisuals;j++)
+ {
+ if (visuals[j].visual_id==img->visual)
+ {
+ assert(visuals[j]._class==XCB_VISUAL_CLASS_TRUE_COLOR || visuals[j]._class==XCB_VISUAL_CLASS_DIRECT_COLOR);
+ cout << (int)visuals[j]._class << "," << XCB_VISUAL_CLASS_TRUE_COLOR << endl;
+ cout << visuals[j].red_mask << endl;
+ cout << visuals[j].green_mask << endl;
+ cout << visuals[j].blue_mask << endl;
+ break;
+ }
+ }
+
+ break;
+ }
+
+ xcb_depth_next(&depth_iterator);
+ }
+
+
+
+ int nformats = xcb_setup_pixmap_formats_length(setup);
+ xcb_format_t* formats = xcb_setup_pixmap_formats(setup);
+ for (int i=0;i<nformats;i++)
+ {
+ if (formats[i].depth==img->depth)
+ {
+ cout << (int)formats[i].bits_per_pixel << endl;
+ cout << (int)formats[i].scanline_pad << endl;
+ break;
+ }
+ }
+
+ cout << grab_width << "x" << grab_height << endl;
+
+ free(img);
+
+ }
+ else
+ {
+ throw string("FATAL: did not find window, exiting.");
+ }
+
+
+}
+
+XorgGrabber::~XorgGrabber()
+{
+ if (img) free(img);
+ xcb_disconnect(conn);
+}
+
+void XorgGrabber::read(Mat& mat)
+{
+ if (img) free(img);
+
+
+ // mat gets invalid when the next read() is called!
+ img = xcb_get_image_reply (conn,
+ xcb_get_image (conn, XCB_IMAGE_FORMAT_Z_PIXMAP, grabbed_win,
+ 0, 0, grab_width, grab_height, ~0), NULL);
+
+ mat = Mat(grab_height, grab_width, CV_8UC4, xcb_get_image_data(img));
+ mat.addref();
+}
+
diff --git a/xorg_grabber.h b/xorg_grabber.h
new file mode 100644
index 0000000..54bbb8f
--- /dev/null
+++ b/xorg_grabber.h
@@ -0,0 +1,25 @@
+#ifndef __XORG_GRABBER_H__
+#define __XORG_GRABBER_H__
+
+#include <xcb/xcb.h>
+#include <opencv2/opencv.hpp>
+
+using namespace cv;
+
+class XorgGrabber
+{
+ public:
+ XorgGrabber(const char* win_title);
+ ~XorgGrabber();
+ void read(Mat& mat);
+
+ private:
+ xcb_connection_t* conn;
+ xcb_window_t grabbed_win;
+ int grab_width, grab_height;
+ xcb_screen_t* grab_screen;
+ xcb_get_image_reply_t* img;
+
+};
+
+#endif