From 78f8fce7f286fd0c71774e2567404ed51f24fef3 Mon Sep 17 00:00:00 2001 From: Vito Caputo Date: Fri, 26 May 2017 21:51:04 -0700 Subject: *: initial commit of stripped schism stuff Forking schism tracker's IT playback stuff into a little playback library for embedding in demos. --- src/sys/x11/xkb.c | 129 +++++++++++++++++++++++++++++++++ src/sys/x11/xscreensaver.c | 175 +++++++++++++++++++++++++++++++++++++++++++++ src/sys/x11/xv.c | 139 +++++++++++++++++++++++++++++++++++ 3 files changed, 443 insertions(+) create mode 100644 src/sys/x11/xkb.c create mode 100644 src/sys/x11/xscreensaver.c create mode 100644 src/sys/x11/xv.c (limited to 'src/sys/x11') diff --git a/src/sys/x11/xkb.c b/src/sys/x11/xkb.c new file mode 100644 index 0000000..ee0114b --- /dev/null +++ b/src/sys/x11/xkb.c @@ -0,0 +1,129 @@ +/* + * Schism Tracker - a cross-platform Impulse Tracker clone + * copyright (c) 2003-2005 Storlek + * copyright (c) 2005-2008 Mrs. Brisby + * copyright (c) 2009 Storlek & Mrs. Brisby + * copyright (c) 2010-2012 Storlek + * URL: http://schismtracker.org/ + * + * 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. + * + * 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 "headers.h" + +#include "sdlmain.h" +#include "it.h" +#include "osdefs.h" + +#include +#include +#include +#include +#include + +#ifdef USE_XKB +# include +#endif + +static int virgin = 1; +static unsigned int delay, rate; + +#ifdef USE_XKB +static XkbDescPtr us_kb_map; +#endif + +static void _key_info_setup(void) +{ + Display *dpy; + SDL_SysWMinfo info; + + if (!virgin) return; + virgin = 0; + + memset(&info, 0, sizeof(info)); + SDL_VERSION(&info.version); + if (SDL_GetWMInfo(&info)) { + if (info.info.x11.lock_func) + info.info.x11.lock_func(); + dpy = info.info.x11.display; + } else { + dpy = NULL; + } + if (!dpy) { + dpy = XOpenDisplay(NULL); + if (!dpy) return; + memset(&info, 0, sizeof(info)); + } + +#ifdef USE_XKB + /* Dear X11, + You suck. + Sincerely, Storlek */ + char blank[] = ""; + char symbols[] = "+us(basic)"; + XkbComponentNamesRec rec = { + .symbols = symbols, + .keymap = blank, + .keycodes = blank, + .types = blank, + .compat = blank, + .geometry = blank, + }; + us_kb_map = XkbGetKeyboardByName(dpy, XkbUseCoreKbd, &rec, + XkbGBN_AllComponentsMask, XkbGBN_AllComponentsMask, False); + if (!us_kb_map) + log_appendf(3, "Warning: XKB support missing or broken; keyjamming might not work right"); + + if (XkbGetAutoRepeatRate(dpy, XkbUseCoreKbd, &delay, &rate)) { + if (info.info.x11.unlock_func) + info.info.x11.unlock_func(); + return; + } +#else + log_appendf(3, "Warning: XKB support not compiled in; keyjamming might not work right"); +#endif + + /* eh... */ + delay = 125; + rate = 30; + + if (info.info.x11.unlock_func) + info.info.x11.unlock_func(); +} + +unsigned int key_repeat_rate(void) +{ + _key_info_setup(); + return rate; +} + +unsigned int key_repeat_delay(void) +{ + _key_info_setup(); + return delay; +} + +#ifdef USE_XKB +int key_scancode_lookup(int k, int def) +{ + static unsigned int d; + KeySym sym; + + if (us_kb_map != NULL && + XkbTranslateKeyCode(us_kb_map, k, 0, &d, &sym)) { + return sym; + } + return def; +} +#endif diff --git a/src/sys/x11/xscreensaver.c b/src/sys/x11/xscreensaver.c new file mode 100644 index 0000000..5f1f4ce --- /dev/null +++ b/src/sys/x11/xscreensaver.c @@ -0,0 +1,175 @@ +/* + * Schism Tracker - a cross-platform Impulse Tracker clone + * copyright (c) 2003-2005 Storlek + * copyright (c) 2005-2008 Mrs. Brisby + * copyright (c) 2009 Storlek & Mrs. Brisby + * copyright (c) 2010-2012 Storlek + * URL: http://schismtracker.org/ + * + * 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. + * + * 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 + */ + +/* I wanted to just lift this code out of xscreensaver-command, + but that wasn't really convenient. xscreensaver really should've + had this (or something like it) as a simple library call like: + xscreensaver_synthetic_user_active(display); + or something like that. spawning a subprocess is really expensive on + some systems, and might have subtle interactions with SDL or the player. + + -mrsb +*/ + +#define NEED_TIME +#include "headers.h" + +#include "sdlmain.h" +#include "osdefs.h" + +#include +#include +#include +#include +#include + + +static XErrorHandler old_handler = NULL; +static int BadWindow_ehandler(Display *dpy, XErrorEvent *error) +{ + if (error->error_code == BadWindow) { + return 0; + } else { + if (old_handler) return (*old_handler)(dpy,error); + /* shrug */ + return 1; + } +} + +void x11_screensaver_deactivate(void) +{ + static Atom XA_SCREENSAVER_VERSION; + static Atom XA_DEACTIVATE; + static Atom XA_SCREENSAVER; + static int setup = 0; + static int useit = 0; + static SDL_SysWMinfo info; + + Window root, tmp, parent, *kids; + unsigned int nkids, i; + + static time_t lastpoll = 0; + Window win; + time_t now; + + Display *dpy = NULL; + XEvent ev; + + if (!setup) { + setup = 1; + SDL_GetWMInfo(&info); + dpy = info.info.x11.display; + if (!dpy) { + dpy = XOpenDisplay(NULL); + if (!dpy) return; + memset(&info, 0, sizeof(info)); + info.info.x11.display = dpy; + } + + useit = 1; + if (info.info.x11.lock_func) info.info.x11.lock_func(); + XA_SCREENSAVER = XInternAtom(dpy, "SCREENSAVER", False); + XA_SCREENSAVER_VERSION = XInternAtom(dpy, + "_SCREENSAVER_VERSION", False); + XA_DEACTIVATE = XInternAtom(dpy, "DEACTIVATE", False); + if (info.info.x11.unlock_func) info.info.x11.unlock_func(); + } + + if (!useit) return; + + time(&now); + if (!(lastpoll - now)) { + return; + } + lastpoll = now; + + if (info.info.x11.lock_func) + info.info.x11.lock_func(); + dpy = info.info.x11.display; + if (!dpy) { + useit = 0; + if (info.info.x11.unlock_func) + info.info.x11.unlock_func(); + return; + } + + root = RootWindowOfScreen(DefaultScreenOfDisplay(dpy)); + if (!XQueryTree(dpy, root, &tmp, &parent, &kids, &nkids)) { + useit = 0; + if (info.info.x11.unlock_func) + info.info.x11.unlock_func(); + return; + } + if (root != tmp || parent || !(kids && nkids)) { + useit = 0; + if (info.info.x11.unlock_func) + info.info.x11.unlock_func(); + return; + } + + win = 0; + for (i = 0; i < nkids; i++) { + Atom type; + int format; + unsigned long nitems, bytesafter; + unsigned char *v = NULL; + + XSync(dpy, False); + old_handler = XSetErrorHandler(BadWindow_ehandler); + if (XGetWindowProperty(dpy, kids[i], + XA_SCREENSAVER_VERSION, 0, 200, + False, XA_STRING, &type, &format, + &nitems, &bytesafter, + (unsigned char **)&v) == Success) { + XSetErrorHandler(old_handler); + if (v) XFree(v); /* don't care */ + if (type != None) { + win = kids[i]; + break; + } + } + XSetErrorHandler(old_handler); + } + XFree(kids); + if (!win) { + useit = 0; + if (info.info.x11.unlock_func) + info.info.x11.unlock_func(); + return; + } + + ev.xany.type = ClientMessage; + ev.xclient.display = dpy; + ev.xclient.window = win; + ev.xclient.message_type = XA_SCREENSAVER; + ev.xclient.format = 32; + memset(&ev.xclient.data, 0, sizeof(ev.xclient.data)); + ev.xclient.data.l[0] = XA_DEACTIVATE; + ev.xclient.data.l[1] = 0; + ev.xclient.data.l[2] = 0; + (void)XSendEvent(dpy, win, False, 0L, &ev); + XSync(dpy, 0); + if (info.info.x11.unlock_func) + info.info.x11.unlock_func(); +} + diff --git a/src/sys/x11/xv.c b/src/sys/x11/xv.c new file mode 100644 index 0000000..1a275e8 --- /dev/null +++ b/src/sys/x11/xv.c @@ -0,0 +1,139 @@ +/* + * Schism Tracker - a cross-platform Impulse Tracker clone + * copyright (c) 2003-2005 Storlek + * copyright (c) 2005-2008 Mrs. Brisby + * copyright (c) 2009 Storlek & Mrs. Brisby + * copyright (c) 2010-2012 Storlek + * URL: http://schismtracker.org/ + * + * 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. + * + * 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 "headers.h" + +#include +#include +#include + +#ifndef HAVE_X11_EXTENSIONS_XVLIB_H +# error what +#endif + +#include "sdlmain.h" +#include "video.h" +#include "osdefs.h" + +unsigned int xv_yuvlayout(void) +{ + unsigned int ver, rev, eventB, reqB, errorB; + XvImageFormatValues *formats; + XvAdaptorInfo *ainfo; + XvEncodingInfo *encodings; + SDL_SysWMinfo info; + Display *dpy; + unsigned int nencode, nadaptors; + unsigned int fmt = VIDEO_YUV_NONE; + int numImages; + int screen, nscreens, img; + unsigned int adaptor, enc; + unsigned int w, h; + unsigned int best; + + memset(&info, 0, sizeof(info)); + SDL_VERSION(&info.version); + if (SDL_GetWMInfo(&info)) { + dpy = info.info.x11.display; + } else { + dpy = NULL; + printf("sdl_getwminfo?\n"); + } + + if (!dpy) { +#if 0 + /* this never closes the display, thus causing a memleak + (and we can't reasonably call XCloseDisplay ourselves) */ + dpy = XOpenDisplay(NULL); + if (!dpy) + return VIDEO_YUV_NONE; +#else + return VIDEO_YUV_NONE; +#endif + } + + + ver = rev = reqB = eventB = errorB = 0; + if (XvQueryExtension(dpy, &ver, &rev, &reqB, &eventB, &errorB) != Success) { + /* no XV support */ + return VIDEO_YUV_NONE; + } + + nscreens = ScreenCount(dpy); + w = h = 0; + for (screen = 0; screen < nscreens; screen++) { + XvQueryAdaptors(dpy, RootWindow(dpy, screen), &nadaptors, &ainfo); + for (adaptor = 0; adaptor < nadaptors; adaptor++) { + XvQueryEncodings(dpy, ainfo[adaptor].base_id, &nencode, &encodings); + best = nencode; // impossible value + for (enc = 0; enc < nencode; enc++) { + if (strcmp(encodings[enc].name, "XV_IMAGE") != 0) + continue; + if (encodings[enc].width > w || encodings[enc].height > h) { + w = encodings[enc].width; + h = encodings[enc].height; + best = enc; + } + } + XvFreeEncodingInfo(encodings); + + if (best == nencode || w < 640 || h < 400) + continue; + + formats = XvListImageFormats(dpy, ainfo[adaptor].base_id, &numImages); + for (img = 0; img < numImages; img++) { + if (formats[img].type == XvRGB) continue; + if (w < 1280 || h < 400) { + /* not enough xv memory for packed */ + switch (formats[img].id) { + case VIDEO_YUV_YV12: + fmt = VIDEO_YUV_YV12_TV; + break; + case VIDEO_YUV_IYUV: + fmt = VIDEO_YUV_IYUV_TV; + break; + } + continue; + } + switch (formats[img].id) { + case VIDEO_YUV_UYVY: + case VIDEO_YUV_YUY2: + case VIDEO_YUV_YVYU: + /* a packed format, and we have enough memory... */ + fmt = formats[img].id; + XFree(formats); + XvFreeAdaptorInfo(ainfo); + return fmt; + + case VIDEO_YUV_YV12: + case VIDEO_YUV_IYUV: + fmt = formats[img].id; + break; + } + } + XFree(formats); + } + XvFreeAdaptorInfo(ainfo); + } + return fmt; +} + -- cgit v1.2.3