summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Jung <flo@windfisch.org>2014-09-06 18:39:33 +0200
committerFlorian Jung <flo@windfisch.org>2014-09-06 18:39:33 +0200
commitb9dcd4d5e8c910fad32f8884a4c83872d77807b8 (patch)
tree58c6616c85c8a34bb0c7d55b204cb3c8ef075b38
parented8b271804c563a6f0959bc13ca56f20c820bcfb (diff)
got it working on gentoo
-rw-r--r--mariokart.cpp13
-rw-r--r--xorg_grabber.cpp273
2 files changed, 275 insertions, 11 deletions
diff --git a/mariokart.cpp b/mariokart.cpp
index eb20bff..d0903b2 100644
--- a/mariokart.cpp
+++ b/mariokart.cpp
@@ -191,7 +191,7 @@ void* thread1_func(void*)
int main(int argc, char* argv[])
{
-try {
+//try {
if (sem_init(&thread1_go, 0, 0)) throw string("sem_init failed");
@@ -208,7 +208,8 @@ try {
cout << "joystick initalized, now starting mupen." << endl;
#endif
- if (fork()==0) { system("mupen64plus --nogui --noask ~/MarioKart64.rom"); exit(0); }
+// for mupen 1.x if (fork()==0) { system("mupen64plus --nogui --noask ~/MarioKart64.rom"); exit(0); }
+ if (fork()==0) { system("mupen64plus --windowed --resolution 640x480 ~/konsolenspiele/N64/MarioKart64.rom"); exit(0); }
#ifdef FREEBSD
sleep(2);
@@ -255,7 +256,7 @@ try {
joystick.reset();
#ifdef LINUX
- XorgGrabber capture("glN64");
+ XorgGrabber capture("Mupen64Plus");
#endif
#ifdef FREEBSD
XorgGrabber capture("Mupen64Plus OpenGL Video");
@@ -453,15 +454,15 @@ joystick.reset();
joystick.process();
}
-} //try
-catch(string meh)
+//} //try
+/*catch(string meh)
{
cout << "error: "<<meh<< endl;
}
catch(...)
{
cout << "error!" << endl;
-}
+}*/
sem_destroy(&thread1_go);
sem_destroy(&thread1_done);
diff --git a/xorg_grabber.cpp b/xorg_grabber.cpp
index 71b529f..26a4ca0 100644
--- a/xorg_grabber.cpp
+++ b/xorg_grabber.cpp
@@ -19,13 +19,245 @@
*/
#include "xorg_grabber.h"
-
+#include "xcb/xcb_icccm.h"
#include <iostream>
using namespace std;
+
+// below code was used and slightly adapted from xwininfo
+// the following license applies.
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+/*
+
+Copyright 1993, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+*/
+
+/*
+ * Window_With_Name: routine to locate a window with a given name on a display.
+ * If no window with the given name is found, 0 is returned.
+ * If more than one window has the given name, the first
+ * one found will be returned. Only top and its subwindows
+ * are looked at. Normally, top should be the RootWindow.
+ */
+
+struct wininfo_cookies {
+ xcb_get_property_cookie_t get_net_wm_name;
+ xcb_get_property_cookie_t get_wm_name;
+ xcb_query_tree_cookie_t query_tree;
+};
+
+#define False 0
+
+int names_match(const char* haystack, int hslen, const char* needle, int nlen)
+{
+ char temph[1024];
+ char tempn[1024];
+
+ strncpy(temph, haystack, 1023);
+ temph[1023]=0;
+ if (hslen < 1024-1)
+ temph[hslen+1]=0;
+
+ strncpy(tempn, needle, 1023);
+ tempn[1023]=0;
+ if (nlen < 1024-1)
+ tempn[nlen+1]=0;
+
+ if (strstr(temph, tempn))
+ return 1;
+ else
+ return 0;
+}
+#define BUFSIZ 42
+
+#ifndef USE_XCB_ICCCM
+# define xcb_icccm_get_wm_name(Dpy, Win) \
+ xcb_get_property (Dpy, False, Win, XCB_ATOM_WM_NAME, \
+ XCB_GET_PROPERTY_TYPE_ANY, 0, BUFSIZ)
+#endif
+
+static xcb_atom_t atom_net_wm_name, atom_utf8_string;
+
+# define xcb_get_net_wm_name(Dpy, Win) \
+ xcb_get_property (Dpy, False, Win, atom_net_wm_name, \
+ atom_utf8_string, 0, BUFSIZ)
+
+
+static xcb_window_t
+recursive_Window_With_Name (xcb_connection_t *dpy, xcb_window_t window, struct wininfo_cookies *cookies, const char *name, size_t namelen)
+{
+ xcb_window_t *children;
+ unsigned int nchildren;
+ int i;
+ xcb_window_t w = 0;
+ xcb_generic_error_t *err;
+ xcb_query_tree_reply_t *tree;
+ struct wininfo_cookies *child_cookies;
+ xcb_get_property_reply_t *prop;
+
+ if (cookies->get_net_wm_name.sequence) {
+ prop = xcb_get_property_reply (dpy, cookies->get_net_wm_name, &err);
+
+ if (prop) {
+ if (prop->type == atom_utf8_string) {
+ const char *prop_name = (const char*) xcb_get_property_value (prop);
+ int prop_name_len = xcb_get_property_value_length (prop);
+
+ /* can't use strcmp, since prop.name is not null terminated */
+ if (names_match(prop_name, prop_name_len, name, namelen))
+ w = window;
+ }
+ free (prop);
+ } else if (err) {
+ if (err->response_type == 0)
+ throw string("error");
+ return 0;
+ }
+ }
+
+ if (w) {
+ xcb_discard_reply (dpy, cookies->get_wm_name.sequence);
+ } else {
+ prop = xcb_get_property_reply (dpy, cookies->get_wm_name, &err);
+
+ if (prop) {
+ if (prop->type == XCB_ATOM_STRING) {
+ const char *prop_name = (const char*) xcb_get_property_value (prop);
+ int prop_name_len = xcb_get_property_value_length (prop);
+
+ /* can't use strcmp, since prop.name is not null terminated */
+ if (names_match(prop_name, prop_name_len, name, namelen))
+ w = window;
+ }
+ free (prop);
+ }
+ else if (err) {
+ if (err->response_type == 0)
+ throw string("error");
+ return 0;
+ }
+ }
+
+ if (w)
+ {
+ xcb_discard_reply (dpy, cookies->query_tree.sequence);
+ return w;
+ }
+
+ tree = xcb_query_tree_reply (dpy, cookies->query_tree, &err);
+ if (!tree) {
+ if (err->response_type == 0)
+ throw string("error");
+ return 0;
+ }
+
+ nchildren = xcb_query_tree_children_length (tree);
+ children = xcb_query_tree_children (tree);
+ child_cookies = (struct wininfo_cookies*) calloc(nchildren, sizeof(struct wininfo_cookies));
+
+ if (child_cookies == NULL)
+ throw string("Failed to allocate memory in recursive_Window_With_Name");
+
+ for (i = 0; i < nchildren; i++) {
+ if (atom_net_wm_name && atom_utf8_string)
+ child_cookies[i].get_net_wm_name =
+ xcb_get_net_wm_name (dpy, children[i]);
+ child_cookies[i].get_wm_name = xcb_icccm_get_wm_name (dpy, children[i]);
+ child_cookies[i].query_tree = xcb_query_tree (dpy, children[i]);
+ }
+ xcb_flush (dpy);
+
+ for (i = 0; i < nchildren; i++) {
+ w = recursive_Window_With_Name (dpy, children[i],
+ &child_cookies[i], name, namelen);
+ if (w)
+ break;
+ }
+
+ if (w)
+ {
+ /* clean up remaining replies */
+ for (/* keep previous i */; i < nchildren; i++) {
+ if (child_cookies[i].get_net_wm_name.sequence)
+ xcb_discard_reply (dpy,
+ child_cookies[i].get_net_wm_name.sequence);
+ xcb_discard_reply (dpy, child_cookies[i].get_wm_name.sequence);
+ xcb_discard_reply (dpy, child_cookies[i].query_tree.sequence);
+ }
+ }
+
+ free (child_cookies);
+ free (tree); /* includes storage for children[] */
+ return (w);
+}
+
+xcb_window_t Window_With_Name (xcb_connection_t *dpy, xcb_window_t top, const char *name)
+{
+ struct wininfo_cookies cookies;
+
+ atom_net_wm_name = 0; // Get_Atom (dpy, "_NET_WM_NAME");
+ atom_utf8_string = 0; // Get_Atom (dpy, "UTF8_STRING");
+
+ if (atom_net_wm_name && atom_utf8_string)
+ cookies.get_net_wm_name = xcb_get_net_wm_name (dpy, top);
+ cookies.get_wm_name = xcb_icccm_get_wm_name (dpy, top);
+ cookies.query_tree = xcb_query_tree (dpy, top);
+ xcb_flush (dpy);
+ return recursive_Window_With_Name(dpy, top, &cookies, name, strlen(name));
+}
+
+// END xwininfo stolen code
+
+
XorgGrabber::XorgGrabber(const char* win_title)
{
conn=xcb_connect(NULL,NULL);
+
+ cerr << "Connected to X server" << endl;
bool found_win=false;
grab_screen=NULL;
@@ -36,11 +268,37 @@ XorgGrabber::XorgGrabber(const char* win_title)
for (xcb_screen_iterator_t i = xcb_setup_roots_iterator(setup);
i.rem > 0; xcb_screen_next (&i))
{
+ cerr << "let's check that screen" << endl;
xcb_screen_t* scr = i.data;
+
+ grabbed_win = Window_With_Name(conn, scr->root, win_title);
+ cout << "GOTCHA" << endl;
+ xcb_get_geometry_reply_t* geo;
+ geo = xcb_get_geometry_reply (conn, xcb_get_geometry (conn, grabbed_win), NULL);
+ if (geo)
+ {
+ grab_width=geo->width;
+ grab_height=geo->height;
+
+ free(geo);
+
+ found_win=true;
+
+ grab_screen=scr;
+ }
+ else
+ {
+ cerr << "geo==NULL!" << endl;
+ }
+
+#if 0
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);
+
+ cout << "screen has "<<len<<" windows"<<endl;
+
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)
@@ -56,12 +314,16 @@ XorgGrabber::XorgGrabber(const char* win_title)
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 << "Considering window with title "<< title << "override_redirect="<<int(attr->override_redirect)<<" map_state="<<int(attr->map_state) <<" ==?"<<XCB_MAP_STATE_VIEWABLE<<endl;
+ //if (!attr->override_redirect && attr->map_state == XCB_MAP_STATE_VIEWABLE)
+ if (attr->map_state == XCB_MAP_STATE_VIEWABLE)
+ //if (!attr->override_redirect)
{
- char* title=(char*)(title_reply+1);
- cout << title << endl;
+ cout << "Checking window with title "<< title << endl;
if (strstr(title, win_title))
{
+ cout << "GOTCHA" << endl;
xcb_get_geometry_reply_t* geo;
geo = xcb_get_geometry_reply (conn, xcb_get_geometry (conn, children[i]), NULL);
if (geo)
@@ -86,7 +348,6 @@ XorgGrabber::XorgGrabber(const char* win_title)
free(title_reply);
free(attr);
}
-
free(reply);
delete[] cookies;
}
@@ -94,6 +355,7 @@ XorgGrabber::XorgGrabber(const char* win_title)
{
cout << "xcb_get_setup failed" << endl;
}
+ #endif
}
if (found_win)
@@ -101,6 +363,7 @@ XorgGrabber::XorgGrabber(const char* win_title)
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);
+ cout << img << endl;