diff options
author | Marcin Kurczewski <mkurczew@gmail.com> | 2015-04-19 09:39:58 +0200 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2015-04-19 21:18:15 +0200 |
commit | 34d5b73fbbae87db10e4503a363753ea60ba0b24 (patch) | |
tree | c0f1152cb06ee85b76549aae0eda2a26c574dc0f /video/out/drm_common.c | |
parent | bd5d047c893cda0b533f9457a6fb2bfbd60de13e (diff) | |
download | mpv-34d5b73fbbae87db10e4503a363753ea60ba0b24.tar.bz2 mpv-34d5b73fbbae87db10e4503a363753ea60ba0b24.tar.xz |
vo_drm: extract vt_switcher to drm_common
Diffstat (limited to 'video/out/drm_common.c')
-rw-r--r-- | video/out/drm_common.c | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/video/out/drm_common.c b/video/out/drm_common.c new file mode 100644 index 0000000000..cbb0f0182a --- /dev/null +++ b/video/out/drm_common.c @@ -0,0 +1,151 @@ +/* + * This file is part of mpv. + * + * by rr- <rr-@sakuya.pl> + * + * mpv 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. + * + * mpv 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 mpv. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <errno.h> +#include <signal.h> +#include <sys/ioctl.h> +#include <sys/poll.h> +#include <sys/vt.h> +#include <unistd.h> + +#include "drm_common.h" + +#include "common/common.h" +#include "common/msg.h" +#include "osdep/io.h" + +#define EVT_RELEASE 1 +#define EVT_ACQUIRE 2 +#define EVT_INTERRUPT 255 +#define HANDLER_ACQUIRE 0 +#define HANDLER_RELEASE 1 + +static int vt_switcher_pipe[2]; + +static void vt_switcher_sighandler(int sig) +{ + unsigned char event = sig == SIGUSR1 ? EVT_RELEASE : EVT_ACQUIRE; + write(vt_switcher_pipe[1], &event, sizeof(event)); +} + +int vt_switcher_init(struct vt_switcher *s, struct mp_log *log) +{ + s->log = log; + s->tty_fd = -1; + vt_switcher_pipe[0] = -1; + vt_switcher_pipe[1] = -1; + + if (mp_make_cloexec_pipe(vt_switcher_pipe)) { + MP_ERR(s, "Creating pipe failed: %s", mp_strerror(errno)); + return -1; + } + + s->tty_fd = open("/dev/tty", O_RDWR | O_CLOEXEC); + if (s->tty_fd < 0) { + MP_ERR(s, "Can't open TTY for VT control: %s", mp_strerror(errno)); + return -1; + } + + struct sigaction act; + act.sa_handler = vt_switcher_sighandler; + act.sa_flags = SA_RESTART; + sigemptyset(&act.sa_mask); + sigaction(SIGUSR1, &act, 0); + sigaction(SIGUSR2, &act, 0); + + struct vt_mode vt_mode; + if (ioctl(s->tty_fd, VT_GETMODE, &vt_mode) < 0) { + MP_ERR(s, "VT_GETMODE failed: %s", mp_strerror(errno)); + return -1; + } + + vt_mode.mode = VT_PROCESS; + vt_mode.relsig = SIGUSR1; + vt_mode.acqsig = SIGUSR2; + if (ioctl(s->tty_fd, VT_SETMODE, &vt_mode) < 0) { + MP_ERR(s, "VT_SETMODE failed: %s", mp_strerror(errno)); + return -1; + } + + return 0; +} + +void vt_switcher_acquire(struct vt_switcher *s, + void (*handler)(void*), void *user_data) +{ + s->handlers[HANDLER_ACQUIRE] = handler; + s->handler_data[HANDLER_ACQUIRE] = user_data; +} + +void vt_switcher_release(struct vt_switcher *s, + void (*handler)(void*), void *user_data) +{ + s->handlers[HANDLER_RELEASE] = handler; + s->handler_data[HANDLER_RELEASE] = user_data; +} + +void vt_switcher_interrupt_poll(struct vt_switcher *s) +{ + unsigned char event = EVT_INTERRUPT; + write(vt_switcher_pipe[1], &event, sizeof(event)); +} + +void vt_switcher_destroy(struct vt_switcher *s) +{ + close(s->tty_fd); + close(vt_switcher_pipe[0]); + close(vt_switcher_pipe[1]); +} + +void vt_switcher_poll(struct vt_switcher *s, int timeout_ms) +{ + struct pollfd fds[1] = { + { .events = POLLIN, .fd = vt_switcher_pipe[0] }, + }; + poll(fds, 1, timeout_ms); + if (!fds[0].revents) { + return; + } + + unsigned char event; + if (read(fds[0].fd, &event, sizeof(event)) != sizeof(event)) { + return; + } + + switch (event) { + case EVT_RELEASE: + s->handlers[HANDLER_RELEASE](s->handler_data[HANDLER_RELEASE]); + + if (ioctl(s->tty_fd, VT_RELDISP, 1) < 0) { + MP_ERR(s, "Failed to release virtual terminal\n"); + } + break; + + case EVT_ACQUIRE: + s->handlers[HANDLER_ACQUIRE](s->handler_data[HANDLER_ACQUIRE]); + + if (ioctl(s->tty_fd, VT_RELDISP, VT_ACKACQ) < 0) { + MP_ERR(s, "Failed to acquire virtual terminal\n"); + } + break; + + case EVT_INTERRUPT: + break; + } +} |