⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sdl_gsevents.c

📁 MPEG-4编解码的实现(包括MPEG4视音频编解码)
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
	SDL - Simple DirectMedia Layer
	Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002  Sam Lantinga

	This library is free software; you can redistribute it and/or
	modify it under the terms of the GNU Library General Public
	License as published by the Free Software Foundation; either
	version 2 of the License, or (at your option) any later version.

	This library 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
	Library General Public License for more details.

	You should have received a copy of the GNU Library General Public
	License along with this library; if not, write to the Free
	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

	Sam Lantinga
	slouken@libsdl.org
*/

#ifdef SAVE_RCSID
static char rcsid =
 "@(#) $Id: SDL_gsevents.c,v 1.3 2002/04/22 21:38:05 wmay Exp $";
#endif

/* Handle the event stream, converting console events into SDL events */

#include <sys/types.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <limits.h>

/* For parsing /proc */
#include <dirent.h>
#include <ctype.h>

#include <linux/vt.h>
#include <linux/kd.h>
#include <linux/keyboard.h>

#include "SDL.h"
#include "SDL_mutex.h"
#include "SDL_sysevents.h"
#include "SDL_sysvideo.h"
#include "SDL_events_c.h"
#include "SDL_gsvideo.h"
#include "SDL_gsevents_c.h"
#include "SDL_gskeys.h"

#ifndef GPM_NODE_FIFO
#define GPM_NODE_FIFO	"/dev/gpmdata"
#endif

/* The translation tables from a console scancode to a SDL keysym */
#define NUM_VGAKEYMAPS	(1<<KG_CAPSSHIFT)
static Uint16 vga_keymap[NUM_VGAKEYMAPS][NR_KEYS];
static SDLKey keymap[128];
static Uint16 keymap_temp[128]; /* only used at startup */
static SDL_keysym *TranslateKey(int scancode, SDL_keysym *keysym);

/* Ugh, we have to duplicate the kernel's keysym mapping code...
   Oh, it's not so bad. :-)

   FIXME: Add keyboard LED handling code
 */
static void GS_vgainitkeymaps(int fd)
{
	struct kbentry entry;
	int map, i;

	/* Don't do anything if we are passed a closed keyboard */
	if ( fd < 0 ) {
		return;
	}

	/* Load all the keysym mappings */
	for ( map=0; map<NUM_VGAKEYMAPS; ++map ) {
		memset(vga_keymap[map], 0, NR_KEYS*sizeof(Uint16));
		for ( i=0; i<NR_KEYS; ++i ) {
			entry.kb_table = map;
			entry.kb_index = i;
			if ( ioctl(fd, KDGKBENT, &entry) == 0 ) {
				/* fill keytemp. This replaces SDL_fbkeys.h */
				if ( (map == 0) && (i<128) ) {
					keymap_temp[i] = entry.kb_value;
				}
				/* The "Enter" key is a special case */
				if ( entry.kb_value == K_ENTER ) {
					entry.kb_value = K(KT_ASCII,13);
				}
				/* Handle numpad specially as well */
				if ( KTYP(entry.kb_value) == KT_PAD ) {
					switch ( entry.kb_value ) {
					case K_P0:
					case K_P1:
					case K_P2:
					case K_P3:
					case K_P4:
					case K_P5:
					case K_P6:
					case K_P7:
					case K_P8:
					case K_P9:
						vga_keymap[map][i]=entry.kb_value;
						vga_keymap[map][i]+= '0';
						break;
										case K_PPLUS:
						vga_keymap[map][i]=K(KT_ASCII,'+');
						break;
										case K_PMINUS:
						vga_keymap[map][i]=K(KT_ASCII,'-');
						break;
										case K_PSTAR:
						vga_keymap[map][i]=K(KT_ASCII,'*');
						break;
										case K_PSLASH:
						vga_keymap[map][i]=K(KT_ASCII,'/');
						break;
										case K_PENTER:
						vga_keymap[map][i]=K(KT_ASCII,'\r');
						break;
										case K_PCOMMA:
						vga_keymap[map][i]=K(KT_ASCII,',');
						break;
										case K_PDOT:
						vga_keymap[map][i]=K(KT_ASCII,'.');
						break;
					default:
						break;
					}
				}
				/* Do the normal key translation */
				if ( (KTYP(entry.kb_value) == KT_LATIN) ||
					 (KTYP(entry.kb_value) == KT_ASCII) ||
					 (KTYP(entry.kb_value) == KT_LETTER) ) {
					vga_keymap[map][i] = entry.kb_value;
				}
			}
		}
	}
}

int GS_InGraphicsMode(_THIS)
{
	return((keyboard_fd >= 0) && (saved_kbd_mode >= 0));
}

int GS_EnterGraphicsMode(_THIS)
{
	struct termios keyboard_termios;

	/* Set medium-raw keyboard mode */
	if ( (keyboard_fd >= 0) && !GS_InGraphicsMode(this) ) {

		/* Switch to the correct virtual terminal */
		if ( current_vt > 0 ) {
			struct vt_stat vtstate;

			if ( ioctl(keyboard_fd, VT_GETSTATE, &vtstate) == 0 ) {
				saved_vt = vtstate.v_active;
			}
			if ( ioctl(keyboard_fd, VT_ACTIVATE, current_vt) == 0 ) {
				ioctl(keyboard_fd, VT_WAITACTIVE, current_vt);
			}
		}

		/* Set the terminal input mode */
		if ( tcgetattr(keyboard_fd, &saved_kbd_termios) < 0 ) {
			SDL_SetError("Unable to get terminal attributes");
			if ( keyboard_fd > 0 ) {
				close(keyboard_fd);
			}
			keyboard_fd = -1;
			return(-1);
		}
		if ( ioctl(keyboard_fd, KDGKBMODE, &saved_kbd_mode) < 0 ) {
			SDL_SetError("Unable to get current keyboard mode");
			if ( keyboard_fd > 0 ) {
				close(keyboard_fd);
			}
			keyboard_fd = -1;
			return(-1);
		}
		keyboard_termios = saved_kbd_termios;
		keyboard_termios.c_lflag &= ~(ICANON | ECHO | ISIG);
		keyboard_termios.c_iflag &= ~(ISTRIP | IGNCR | ICRNL | INLCR | IXOFF | IXON);
		keyboard_termios.c_cc[VMIN] = 0;
		keyboard_termios.c_cc[VTIME] = 0;
		if (tcsetattr(keyboard_fd, TCSAFLUSH, &keyboard_termios) < 0) {
			GS_CloseKeyboard(this);
			SDL_SetError("Unable to set terminal attributes");
			return(-1);
		}
		/* This will fail if we aren't root or this isn't our tty */
		if ( ioctl(keyboard_fd, KDSKBMODE, K_MEDIUMRAW) < 0 ) {
			GS_CloseKeyboard(this);
			SDL_SetError("Unable to set keyboard in raw mode");
			return(-1);
		}
		if ( ioctl(keyboard_fd, KDSETMODE, KD_GRAPHICS) < 0 ) {
			GS_CloseKeyboard(this);
			SDL_SetError("Unable to set keyboard in graphics mode");
			return(-1);
		}
	}
	return(keyboard_fd);
}

void GS_LeaveGraphicsMode(_THIS)
{
	if ( GS_InGraphicsMode(this) ) {
		ioctl(keyboard_fd, KDSETMODE, KD_TEXT);
		ioctl(keyboard_fd, KDSKBMODE, saved_kbd_mode);
		tcsetattr(keyboard_fd, TCSAFLUSH, &saved_kbd_termios);
		saved_kbd_mode = -1;

		/* Head back over to the original virtual terminal */
		if ( saved_vt > 0 ) {
			ioctl(keyboard_fd, VT_ACTIVATE, saved_vt);
		}
	}
}

void GS_CloseKeyboard(_THIS)
{
	if ( keyboard_fd >= 0 ) {
		GS_LeaveGraphicsMode(this);
		if ( keyboard_fd > 0 ) {
			close(keyboard_fd);
		}
	}
	keyboard_fd = -1;
}

int GS_OpenKeyboard(_THIS)
{
	/* Open only if not already opened */
 	if ( keyboard_fd < 0 ) {
		char *tty0[] = { "/dev/tty0", "/dev/vc/0", NULL };
		char *vcs[] = { "/dev/vc/%d", "/dev/tty%d", NULL };
		int i, tty0_fd;

		/* Try to query for a free virtual terminal */
		tty0_fd = -1;
		for ( i=0; tty0[i] && (tty0_fd < 0); ++i ) {
			tty0_fd = open(tty0[i], O_WRONLY, 0);
		}
		if ( tty0_fd < 0 ) {
			tty0_fd = dup(0); /* Maybe stdin is a VT? */
		}
		ioctl(tty0_fd, VT_OPENQRY, &current_vt);
		close(tty0_fd);
		if ( (geteuid() == 0) && (current_vt > 0) ) {
			for ( i=0; vcs[i] && (keyboard_fd < 0); ++i ) {
				char vtpath[12];

				sprintf(vtpath, vcs[i], current_vt);
				keyboard_fd = open(vtpath, O_RDWR, 0);
#ifdef DEBUG_KEYBOARD
				fprintf(stderr, "vtpath = %s, fd = %d\n",
					vtpath, keyboard_fd);
#endif /* DEBUG_KEYBOARD */

				/* This needs to be our controlling tty
				   so that the kernel ioctl() calls work
				*/
				if ( keyboard_fd >= 0 ) {
					tty0_fd = open("/dev/tty", O_RDWR, 0);
					if ( tty0_fd >= 0 ) {
						ioctl(tty0_fd, TIOCNOTTY, 0);
						close(tty0_fd);
					}
				}
			}
		}
 		if ( keyboard_fd < 0 ) {
			/* Last resort, maybe our tty is a usable VT */
			current_vt = 0;
			keyboard_fd = open("/dev/tty", O_RDWR);
 		}
#ifdef DEBUG_KEYBOARD
		fprintf(stderr, "Current VT: %d\n", current_vt);
#endif
 		saved_kbd_mode = -1;

		/* Make sure that our input is a console terminal */
		{ int dummy;
		  if ( ioctl(keyboard_fd, KDGKBMODE, &dummy) < 0 ) {
			close(keyboard_fd);
			keyboard_fd = -1;
			SDL_SetError("Unable to open a console terminal");
		  }
		}

		/* Set up keymap */
		GS_vgainitkeymaps(keyboard_fd);
 	}
 	return(keyboard_fd);
}

static enum {
	MOUSE_NONE = -1,
	MOUSE_GPM,	/* Note: GPM uses the MSC protocol */
	MOUSE_PS2,
	MOUSE_IMPS2,
	MOUSE_MS,
	MOUSE_BM,
	NUM_MOUSE_DRVS
} mouse_drv = MOUSE_NONE;

void GS_CloseMouse(_THIS)
{
	if ( mouse_fd > 0 ) {
		close(mouse_fd);
	}
	mouse_fd = -1;
}

/* Returns processes listed in /proc with the desired name */
static int find_pid(DIR *proc, const char *wanted_name)
{
	struct dirent *entry;
	int pid;

	/* First scan proc for the gpm process */
	pid = 0;
	while ( (pid == 0) && ((entry=readdir(proc)) != NULL) ) {
		if ( isdigit(entry->d_name[0]) ) {
			FILE *status;
			char path[PATH_MAX];
			char name[PATH_MAX];

			sprintf(path, "/proc/%s/status", entry->d_name);
			status=fopen(path, "r");
			if ( status ) {
				name[0] = '\0';
				fscanf(status, "Name: %s", name);
				if ( strcmp(name, wanted_name) == 0 ) {
					pid = atoi(entry->d_name);
				}
				fclose(status);
			}
		}
	}
	return pid;
}

/* Returns true if /dev/gpmdata is being written to by gpm */
static int gpm_available(void)
{
	int available;
	DIR *proc;
	int pid;
	int cmdline, len, arglen;
	char path[PATH_MAX];
	char args[PATH_MAX], *arg;

	/* Don't bother looking if the fifo isn't there */
	if ( access(GPM_NODE_FIFO, F_OK) < 0 ) {
		return(0);
	}

	available = 0;
	proc = opendir("/proc");
	if ( proc ) {
		while ( (pid=find_pid(proc, "gpm")) > 0 ) {
			sprintf(path, "/proc/%d/cmdline", pid);
			cmdline = open(path, O_RDONLY, 0);
			if ( cmdline >= 0 ) {
				len = read(cmdline, args, sizeof(args));
				arg = args;
				while ( len > 0 ) {
					if ( strcmp(arg, "-R") == 0 ) {
						available = 1;
					}
					arglen = strlen(arg)+1;
					len -= arglen;
					arg += arglen;
				}
				close(cmdline);
			}
		}
		closedir(proc);
	}
	return available;
}


/* rcg06112001 Set up IMPS/2 mode, if possible. This gives
 *  us access to the mousewheel, etc. Returns zero if
 *  writes to device failed, but you still need to query the
 *  device to see which mode it's actually in.
 */
static int set_imps2_mode(int fd)
{
	/* If you wanted to control the mouse mode (and we do :)  ) ...
		Set IMPS/2 protocol:
			{0xf3,200,0xf3,100,0xf3,80}
		Reset mouse device:
			{0xFF}
	*/
	Uint8 set_imps2[] = {0xf3, 200, 0xf3, 100, 0xf3, 80};
	Uint8 reset = 0xff;
	fd_set fdset;
	struct timeval tv;
	int retval = 0;

	if ( write(fd, &set_imps2, sizeof(set_imps2)) == sizeof(set_imps2) ) {
		if (write(fd, &reset, sizeof (reset)) == sizeof (reset) ) {
			retval = 1;
		}
	}

	/* Get rid of any chatter from the above */
	FD_ZERO(&fdset);
	FD_SET(fd, &fdset);
	tv.tv_sec = 0;
	tv.tv_usec = 0;
	while ( select(fd+1, &fdset, 0, 0, &tv) > 0 ) {
		char temp[32];
		read(fd, temp, sizeof(temp));
	}

	return retval;
}


/* Returns true if the mouse uses the IMPS/2 protocol */
static int detect_imps2(int fd)
{
	int imps2;

	imps2 = 0;

	if ( getenv("SDL_MOUSEDEV_IMPS2") ) {
		imps2 = 1;
	}
	if ( ! imps2 ) {
		Uint8 query_ps2 = 0xF2;
		fd_set fdset;
		struct timeval tv;

		/* Get rid of any mouse motion noise */
		FD_ZERO(&fdset);
		FD_SET(fd, &fdset);
		tv.tv_sec = 0;
		tv.tv_usec = 0;
		while ( select(fd+1, &fdset, 0, 0, &tv) > 0 ) {
			char temp[32];
			read(fd, temp, sizeof(temp));
		}

   		/* Query for the type of mouse protocol */
   		if ( write(fd, &query_ps2, sizeof (query_ps2)) == sizeof (query_ps2)) {
   			Uint8 ch = 0;

			/* Get the mouse protocol response */
			do {
				FD_ZERO(&fdset);
				FD_SET(fd, &fdset);
				tv.tv_sec = 1;
				tv.tv_usec = 0;
				if ( select(fd+1, &fdset, 0, 0, &tv) < 1 ) {
					break;
				}
			} while ( (read(fd, &ch, sizeof (ch)) == sizeof (ch)) &&
			          ((ch == 0xFA) || (ch == 0xAA)) );

			/* Experimental values (Logitech wheelmouse) */
#ifdef DEBUG_MOUSE
fprintf(stderr, "Last mouse mode: 0x%x\n", ch);
#endif
			if ( ch == 3 ) {
				imps2 = 1;
			}
		}
	}
	return imps2;
}

int GS_OpenMouse(_THIS)
{
	int i;
	const char *mousedev;
	const char *mousedrv;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -