diff options
author | phintuka <phintuka> | 2011-01-23 19:42:08 +0000 |
---|---|---|
committer | phintuka <phintuka> | 2011-01-23 19:42:08 +0000 |
commit | 7f9ae5ee0222e54abb2c7a98cedaed927f563f91 (patch) | |
tree | 8bfde405b01b819eb58aedad091a80a7f91a8d6c | |
parent | b20599cb1602fdd10d769f8d047e70469ec14293 (diff) | |
download | xineliboutput-7f9ae5ee0222e54abb2c7a98cedaed927f563f91.tar.gz xineliboutput-7f9ae5ee0222e54abb2c7a98cedaed927f563f91.tar.bz2 |
Moved keyboard handling to xine_frontend_kbd.c
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | xine_frontend_kbd.c | 328 | ||||
-rw-r--r-- | xine_frontend_kbd.h | 19 | ||||
-rw-r--r-- | xine_frontend_main.c | 296 |
4 files changed, 351 insertions, 296 deletions
@@ -4,7 +4,7 @@ # See the main source file 'xineliboutput.c' for copyright information and # how to reach the author. # -# $Id: Makefile,v 1.105 2010-12-15 14:43:36 phintuka Exp $ +# $Id: Makefile,v 1.106 2011-01-23 19:42:08 phintuka Exp $ # # The official name of this plugin. @@ -219,7 +219,7 @@ OBJS_MPG = black_720x576.o nosignal_720x576.o vdrlogo_720x576.o OBJS_FE_SO = xine_frontend.o logdefs.o \ xine/post.o xine/vo_hook.o xine/vo_osdscaler.o xine/vo_osdreorder.o xine/vo_lastpts.o \ tools/rle.o -OBJS_FE = $(OBJS_FE_SO) tools/vdrdiscovery.o xine_frontend_main.o xine_frontend_lirc.o +OBJS_FE = $(OBJS_FE_SO) tools/vdrdiscovery.o xine_frontend_main.o xine_frontend_lirc.o xine_frontend_kbd.o OBJS_SXFE_SO = xine_sxfe_frontend.o $(OBJS_FE_SO) OBJS_SXFE = xine_sxfe_frontend.o $(OBJS_FE) diff --git a/xine_frontend_kbd.c b/xine_frontend_kbd.c new file mode 100644 index 00000000..c750d08f --- /dev/null +++ b/xine_frontend_kbd.c @@ -0,0 +1,328 @@ +/* + * xine_frontend_kbd.c: Forward (local) console key presses to VDR (server) + * + * See the main source file 'xineliboutput.c' for copyright information and + * how to reach the author. + * + * $Id: xine_frontend_kbd.c,v 1.1 2011-01-23 19:42:08 phintuka Exp $ + * + */ + +#include "features.h" + +#include <inttypes.h> +#include <poll.h> +#include <pthread.h> +#include <stdlib.h> +#include <stdint.h> +#include <stdio.h> +#include <string.h> +#include <termios.h> +#include <unistd.h> + + +#define LOG_MODULENAME "[console] " +#include "logdefs.h" + +#include "xine_frontend.h" +#include "xine_frontend_kbd.h" + +/* + * stdin (keyboard/slave mode) reading + */ + +/* static data */ +static pthread_t kbd_thread; +static struct termios tm, saved_tm; + +/* xine_frontend_main.c: */ +extern int gui_hotkeys; + + +/* + * read_key() + * + * Try to read single char from stdin. + * + * Returns: >=0 char readed + * -1 nothing to read + * -2 fatal error + */ +#define READ_KEY_ERROR -2 +#define READ_KEY_EAGAIN -1 +static int read_key(void) +{ + unsigned char ch; + int err; + struct pollfd pfd; + pfd.fd = STDIN_FILENO; + pfd.events = POLLIN; + + errno = 0; + pthread_testcancel(); + + if (1 == (err = poll(&pfd, 1, 50))) { + pthread_testcancel(); + + if (1 == (err = read(STDIN_FILENO, &ch, 1))) + return (int)ch; + + if (err < 0) + LOGERR("read_key: read(stdin) failed"); + else + LOGERR("read_key: read(stdin) failed: no stdin"); + return READ_KEY_ERROR; + + } else if (err < 0 && errno != EINTR) { + LOGERR("read_key: poll(stdin) failed"); + return READ_KEY_ERROR; + } + + pthread_testcancel(); + + return READ_KEY_EAGAIN; +} + +/* + * read_key_seq() + * + * Read a key sequence from stdin. + * Key sequence is either normal key or escape sequence. + * + * Returns the key or escape sequence as uint64_t. + * + * Originally copied from vdr: + * remote.c: General Remote Control handling + * Copyright (C) 2000, 2003, 2006, 2008 Klaus Schmidinger + */ +#define READ_KEY_SEQ_ERROR 0xffffffff +static uint64_t read_key_seq(void) +{ + /* from vdr, remote.c */ + uint64_t k = 0; + int key1; + + if ((key1 = read_key()) >= 0) { + k = key1; + if (key1 == 0x1B) { + /* Start of escape sequence */ + if ((key1 = read_key()) >= 0) { + k <<= 8; + k |= key1 & 0xFF; + switch (key1) { + case 0x4F: /* 3-byte sequence */ + if ((key1 = read_key()) >= 0) { + k <<= 8; + k |= key1 & 0xFF; + } + break; + case 0x5B: /* 3- or more-byte sequence */ + if ((key1 = read_key()) >= 0) { + k <<= 8; + k |= key1 & 0xFF; + switch (key1) { + case 0x31 ... 0x3F: /* more-byte sequence */ + case 0x5B: /* strange, may apparently occur */ + do { + if ((key1 = read_key()) < 0) + break; /* Sequence ends here */ + k <<= 8; + k |= key1 & 0xFF; + } while (key1 != 0x7E); + break; + default:; + } + } + break; + default:; + } + } + } + } + + if (key1 == READ_KEY_ERROR) + return READ_KEY_SEQ_ERROR; + + return k; +} + +/* + * kbd_receiver_thread() + * + * Read key(sequence)s from stdin and pass those to frontend. + */ + +static void kbd_receiver_thread_cleanup(void *arg) +{ + int status; + tcsetattr(STDIN_FILENO, TCSANOW, &saved_tm); + status = system("setterm -cursor on"); + LOGMSG("Keyboard thread terminated"); +} + +static void *kbd_receiver_thread(void *fe_gen) +{ + frontend_t *fe = (frontend_t*)fe_gen; + uint64_t code = 0; + char str[64]; + int status; + + status = system("setterm -cursor off"); + status = system("setterm -blank off"); + + /* Set stdin to deliver keypresses without buffering whole lines */ + tcgetattr(STDIN_FILENO, &saved_tm); + if (tcgetattr(STDIN_FILENO, &tm) == 0) { + tm.c_iflag = 0; + tm.c_lflag &= ~(ICANON | ECHO); + tm.c_cc[VMIN] = 0; + tm.c_cc[VTIME] = 0; + tcsetattr(STDIN_FILENO, TCSANOW, &tm); + } + + pthread_cleanup_push(kbd_receiver_thread_cleanup, NULL); + + do { + alarm(0); + errno = 0; + code = read_key_seq(); + alarm(3); /* watchdog */ + if (code == 0) + continue; + if (code == READ_KEY_SEQ_ERROR) + break; + if (code == 27) { + fe->send_event(fe, "QUIT"); + break; + } + + if (gui_hotkeys) { + if (code == 'f' || code == 'F') { + fe->send_event(fe, "TOGGLE_FULLSCREEN"); + continue; + } + if (code == 'p' || code == 'P') { + fe->send_event(fe, "POWER_OFF"); + continue; + } + if (code == 'd' || code == 'D') { + fe->send_event(fe, "TOGGLE_DEINTERLACE"); + continue; + } + } + + snprintf(str, sizeof(str), "%016" PRIX64, code); + fe->send_input_event(fe, "KBD", str, 0, 0); + + } while (fe->xine_is_finished(fe, 0) != FE_XINE_EXIT); + + alarm(0); + + LOGDBG("Keyboard thread terminating"); + + pthread_cleanup_pop(1); + + pthread_exit(NULL); + return NULL; /* never reached */ +} + +/* + * slave_receiver_thread() + * + * Read slave mode commands from stdin + * Interpret and execute valid commands + */ + +static void slave_receiver_thread_cleanup(void *arg) +{ + /* restore terminal settings */ + tcsetattr(STDIN_FILENO, TCSANOW, &saved_tm); + LOGDBG("Slave mode receiver terminated"); +} + +static void *slave_receiver_thread(void *fe_gen) +{ + frontend_t *fe = (frontend_t*)fe_gen; + char str[128], *pt; + + tcgetattr(STDIN_FILENO, &saved_tm); + + pthread_cleanup_push(slave_receiver_thread_cleanup, NULL); + + do { + errno = 0; + str[0] = 0; + + pthread_testcancel(); + if (!fgets(str, sizeof(str), stdin)) + break; + pthread_testcancel(); + + if (NULL != (pt = strchr(str, '\r'))) + *pt = 0; + if (NULL != (pt = strchr(str, '\n'))) + *pt = 0; + + if (!strncasecmp(str, "QUIT", 4)) { + fe->send_event(fe, "QUIT"); + break; + } + if (!strncasecmp(str, "FULLSCREEN", 10)) { + if (strpbrk(str + 10, "01")) + fe->send_event(fe, str); + else + fe->send_event(fe, "TOGGLE_FULLSCREEN"); + continue; + } + if (!strncasecmp(str, "DEINTERLACE ", 12)) { + fe->send_event(fe, str); + continue; + } + if (!strncasecmp(str, "HITK ", 5)) { + fe->send_input_event(fe, NULL, str+5, 0, 0); + continue; + } + + LOGMSG("Unknown slave mode command: %s", str); + + } while (fe->xine_is_finished(fe, 0) != FE_XINE_EXIT); + + LOGDBG("Slave mode receiver terminating"); + + pthread_cleanup_pop(1); + + pthread_exit(NULL); + return NULL; /* never reached */ +} + +/* + * kbd_start() + * + * Start keyboard/slave mode reader thread + */ +void kbd_start(frontend_t *fe, int slave_mode) +{ + int err; + if ((err = pthread_create (&kbd_thread, + NULL, + slave_mode ? slave_receiver_thread : kbd_receiver_thread, + (void*)fe)) != 0) { + fprintf(stderr, "Can't create new thread for keyboard (%s)\n", + strerror(err)); + } +} + +/* + * kbd_stop() + * + * Stop keyboard/slave mode reader thread + */ +void kbd_stop(void) +{ + void *p; + + pthread_cancel(kbd_thread); + pthread_join(kbd_thread, &p); +} + + diff --git a/xine_frontend_kbd.h b/xine_frontend_kbd.h new file mode 100644 index 00000000..af22ad42 --- /dev/null +++ b/xine_frontend_kbd.h @@ -0,0 +1,19 @@ +/* + * xine_frontend_kbd.h: + * + * See the main source file 'xineliboutput.c' for copyright information and + * how to reach the author. + * + * $Id: xine_frontend_kbd.h,v 1.1 2011-01-23 19:42:08 phintuka Exp $ + * + */ + +#ifndef XINE_FRONTEND_KBD_H +#define XINE_FRONTEND_KBD_H + +struct frontend_s; + +void kbd_start(frontend_t *fe, int slave_mode); +void kbd_stop(void); + +#endif /* XINE_FRONTEND_KBD_H */ diff --git a/xine_frontend_main.c b/xine_frontend_main.c index 6d1dede7..48cc0e38 100644 --- a/xine_frontend_main.c +++ b/xine_frontend_main.c @@ -4,7 +4,7 @@ * See the main source file 'xineliboutput.c' for copyright information and * how to reach the author. * - * $Id: xine_frontend_main.c,v 1.93 2011-01-17 12:54:22 phintuka Exp $ + * $Id: xine_frontend_main.c,v 1.94 2011-01-23 19:42:08 phintuka Exp $ * */ @@ -14,10 +14,6 @@ #include <inttypes.h> #include <stdlib.h> #include <string.h> -#include <poll.h> -#include <errno.h> -#include <termios.h> -#include <pthread.h> #include <unistd.h> #include <syslog.h> #include <getopt.h> @@ -32,6 +28,7 @@ #include "xine_frontend.h" #include "tools/vdrdiscovery.h" #include "xine_frontend_lirc.h" +#include "xine_frontend_kbd.h" /* static data */ @@ -42,295 +39,6 @@ volatile int last_signal = 0; int gui_hotkeys = 0; /* - * stdin (keyboard/slave mode) reading - */ - -/* static data */ -pthread_t kbd_thread; -struct termios tm, saved_tm; - -/* - * read_key() - * - * Try to read single char from stdin. - * - * Returns: >=0 char readed - * -1 nothing to read - * -2 fatal error - */ -#define READ_KEY_ERROR -2 -#define READ_KEY_EAGAIN -1 -static int read_key(void) -{ - unsigned char ch; - int err; - struct pollfd pfd; - pfd.fd = STDIN_FILENO; - pfd.events = POLLIN; - - errno = 0; - pthread_testcancel(); - - if (1 == (err = poll(&pfd, 1, 50))) { - pthread_testcancel(); - - if (1 == (err = read(STDIN_FILENO, &ch, 1))) - return (int)ch; - - if (err < 0) - LOGERR("read_key: read(stdin) failed"); - else - LOGERR("read_key: read(stdin) failed: no stdin"); - return READ_KEY_ERROR; - - } else if (err < 0 && errno != EINTR) { - LOGERR("read_key: poll(stdin) failed"); - return READ_KEY_ERROR; - } - - pthread_testcancel(); - return READ_KEY_EAGAIN; -} - -/* - * read_key_seq() - * - * Read a key sequence from stdin. - * Key sequence is either normal key or escape sequence. - * - * Returns the key or escape sequence as uint64_t. - */ -#define READ_KEY_SEQ_ERROR 0xffffffff -static uint64_t read_key_seq(void) -{ - /* from vdr, remote.c */ - uint64_t k = 0; - int key1; - - if ((key1 = read_key()) >= 0) { - k = key1; - if (key1 == 0x1B) { - /* Start of escape sequence */ - if ((key1 = read_key()) >= 0) { - k <<= 8; - k |= key1 & 0xFF; - switch (key1) { - case 0x4F: /* 3-byte sequence */ - if ((key1 = read_key()) >= 0) { - k <<= 8; - k |= key1 & 0xFF; - } - break; - case 0x5B: /* 3- or more-byte sequence */ - if ((key1 = read_key()) >= 0) { - k <<= 8; - k |= key1 & 0xFF; - switch (key1) { - case 0x31 ... 0x3F: /* more-byte sequence */ - case 0x5B: /* strange, may apparently occur */ - do { - if ((key1 = read_key()) < 0) - break; /* Sequence ends here */ - k <<= 8; - k |= key1 & 0xFF; - } while (key1 != 0x7E); - break; - default:; - } - } - break; - default:; - } - } - } - } - - if (key1 == READ_KEY_ERROR) - return READ_KEY_SEQ_ERROR; - - return k; -} - -/* - * kbd_receiver_thread() - * - * Read key(sequence)s from stdin and pass those to frontend. - */ - -static void kbd_receiver_thread_cleanup(void *arg) -{ - int status; - tcsetattr(STDIN_FILENO, TCSANOW, &saved_tm); - status = system("setterm -cursor on"); - LOGMSG("Keyboard thread terminated"); -} - -static void *kbd_receiver_thread(void *fe_gen) -{ - frontend_t *fe = (frontend_t*)fe_gen; - uint64_t code = 0; - char str[64]; - int status; - - status = system("setterm -cursor off"); - status = system("setterm -blank off"); - - /* Set stdin to deliver keypresses without buffering whole lines */ - tcgetattr(STDIN_FILENO, &saved_tm); - if (tcgetattr(STDIN_FILENO, &tm) == 0) { - tm.c_iflag = 0; - tm.c_lflag &= ~(ICANON | ECHO); - tm.c_cc[VMIN] = 0; - tm.c_cc[VTIME] = 0; - tcsetattr(STDIN_FILENO, TCSANOW, &tm); - } - - pthread_cleanup_push(kbd_receiver_thread_cleanup, NULL); - - do { - alarm(0); - errno = 0; - code = read_key_seq(); - alarm(3); /* watchdog */ - if (code == 0) - continue; - if (code == READ_KEY_SEQ_ERROR) - break; - if (code == 27) { - fe->send_event(fe, "QUIT"); - break; - } - - if (gui_hotkeys) { - if (code == 'f' || code == 'F') { - fe->send_event(fe, "TOGGLE_FULLSCREEN"); - continue; - } - if (code == 'p' || code == 'P') { - fe->send_event(fe, "POWER_OFF"); - continue; - } - if (code == 'd' || code == 'D') { - fe->send_event(fe, "TOGGLE_DEINTERLACE"); - continue; - } - } - - snprintf(str, sizeof(str), "%016" PRIX64, code); - fe->send_input_event(fe, "KBD", str, 0, 0); - - } while (fe->xine_is_finished(fe, 0) != FE_XINE_EXIT); - - alarm(0); - - LOGDBG("Keyboard thread terminating"); - - pthread_cleanup_pop(1); - - pthread_exit(NULL); - return NULL; /* never reached */ -} - -/* - * slave_receiver_thread() - * - * Read slave mode commands from stdin - * Interpret and execute valid commands - */ - -static void slave_receiver_thread_cleanup(void *arg) -{ - /* restore terminal settings */ - tcsetattr(STDIN_FILENO, TCSANOW, &saved_tm); - LOGDBG("Slave mode receiver terminated"); -} - -static void *slave_receiver_thread(void *fe_gen) -{ - frontend_t *fe = (frontend_t*)fe_gen; - char str[128], *pt; - - tcgetattr(STDIN_FILENO, &saved_tm); - - pthread_cleanup_push(slave_receiver_thread_cleanup, NULL); - - do { - errno = 0; - str[0] = 0; - - pthread_testcancel(); - if (!fgets(str, sizeof(str), stdin)) - break; - pthread_testcancel(); - - if (NULL != (pt = strchr(str, '\r'))) - *pt = 0; - if (NULL != (pt = strchr(str, '\n'))) - *pt = 0; - - if (!strncasecmp(str, "QUIT", 4)) { - fe->send_event(fe, "QUIT"); - break; - } - if (!strncasecmp(str, "FULLSCREEN", 10)) { - if (strpbrk(str + 10, "01")) - fe->send_event(fe, str); - else - fe->send_event(fe, "TOGGLE_FULLSCREEN"); - continue; - } - if (!strncasecmp(str, "DEINTERLACE ", 12)) { - fe->send_event(fe, str); - continue; - } - if (!strncasecmp(str, "HITK ", 5)) { - fe->send_input_event(fe, NULL, str+5, 0, 0); - continue; - } - - LOGMSG("Unknown slave mode command: %s", str); - - } while (fe->xine_is_finished(fe, 0) != FE_XINE_EXIT); - - LOGDBG("Slave mode receiver terminating"); - - pthread_cleanup_pop(1); - - pthread_exit(NULL); - return NULL; /* never reached */ -} - -/* - * kbd_start() - * - * Start keyboard/slave mode reader thread - */ -static void kbd_start(frontend_t *fe, int slave_mode) -{ - int err; - if ((err = pthread_create (&kbd_thread, - NULL, - slave_mode ? slave_receiver_thread : kbd_receiver_thread, - (void*)fe)) != 0) { - fprintf(stderr, "Can't create new thread for keyboard (%s)\n", - strerror(err)); - } -} - -/* - * kbd_stop() - * - * Stop keyboard/slave mode reader thread - */ -static void kbd_stop(void) -{ - void *p; - - pthread_cancel(kbd_thread); - pthread_join(kbd_thread, &p); -} - -/* * SignalHandler() */ static void SignalHandler(int signum) |