diff options
-rw-r--r-- | Makefile | 6 | ||||
-rw-r--r-- | joystick.cpp | 219 | ||||
-rw-r--r-- | joystick.h | 64 | ||||
-rw-r--r-- | mariokart.cpp | 438 | ||||
-rw-r--r-- | os.h | 2 | ||||
-rw-r--r-- | xorg_grabber.cpp | 163 | ||||
-rw-r--r-- | xorg_grabber.h | 25 |
7 files changed, 482 insertions, 435 deletions
@@ -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 @@ -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 |