From cb72d26f0825b31fd10af18a03763b41067cfe37 Mon Sep 17 00:00:00 2001 From: =?utf8?q?R=C3=A9mi=20Denis-Courmont?= Date: Sun, 30 May 2010 14:33:35 +0300 Subject: [PATCH] Helpers to emit asynchronous key press events (refs #3661) We have the same bug in several outputs (SDL, AA, CACA), so lets make the solution generic. --- modules/video_output/keythread.c | 122 +++++++++++++++++++++++++++++++ modules/video_output/keythread.h | 26 +++++++ 2 files changed, 148 insertions(+) create mode 100644 modules/video_output/keythread.c create mode 100644 modules/video_output/keythread.h diff --git a/modules/video_output/keythread.c b/modules/video_output/keythread.c new file mode 100644 index 0000000000..21039f23d1 --- /dev/null +++ b/modules/video_output/keythread.c @@ -0,0 +1,122 @@ +/***************************************************************************** + * keythread.c: Asynchronous threads to emit key events + ***************************************************************************** + * Copyright (C) 2010 Rémi Denis-Courmont + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + *****************************************************************************/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include +#include + +#include "keythread.h" + +struct key_thread +{ + vlc_object_t *libvlc; + int value; + vlc_mutex_t lock; + vlc_cond_t wait; + vlc_thread_t thread; +}; + +static void *KeyThread (void *data) +{ + key_thread_t *keys = data; + + mutex_cleanup_push (&keys->lock); + for (;;) + { + int value; + + vlc_mutex_lock (&keys->lock); + /* Note: Key strokes may be lost. A chained list should be used. */ + while (!(value = keys->value)) + vlc_cond_wait (&keys->wait, &keys->lock); + keys->value = 0; + vlc_mutex_unlock (&keys->lock); + + int canc = vlc_savecancel (); + var_SetInteger (keys->libvlc, "key-pressed", value); + vlc_restorecancel (canc); + } + + vlc_cleanup_pop (); + assert (0); +} + + +#undef vlc_CreateKeyThread +/** + * Create an asynchronous key event thread. + * + * Normally, key events are received by the interface thread (e.g. Qt4), or + * the window provider (e.g. XCB). However, some legacy video output plugins + * do not use window providers, neither do they run their own event threads. + * Instead, those lame video outputs insist on receiving key events from their + * Manage() function. + * + * Some key event handlers are quite slow so they should not be triggered from + * the video output thread. Worse yet, some handlers (such as snapshot) would + * deadlock if triggered from the video output thread. + */ +key_thread_t *vlc_CreateKeyThread (vlc_object_t *obj) +{ + key_thread_t *keys = malloc (sizeof (*keys)); + if (unlikely(keys == NULL)) + return NULL; + + keys->libvlc = VLC_OBJECT(obj->p_libvlc); + keys->value = 0; + vlc_mutex_init (&keys->lock); + vlc_cond_init (&keys->wait); + if (vlc_clone (&keys->thread, KeyThread, keys, VLC_THREAD_PRIORITY_LOW)) + { + vlc_cond_destroy (&keys->wait); + vlc_mutex_destroy (&keys->lock); + free (keys); + return NULL; + } + return keys; +} + +void vlc_DestroyKeyThread (key_thread_t *keys) +{ + if (keys == NULL) + return; + + vlc_cancel (keys->thread); + vlc_join(keys->thread, NULL); + vlc_cond_destroy(&keys->wait); + vlc_mutex_destroy(&keys->lock); + free (keys); +} + +void vlc_EmitKey (key_thread_t *keys, int value) +{ + if (keys == NULL) + return; + + vlc_mutex_lock(&keys->lock); + keys->value = value; + vlc_cond_signal(&keys->wait); + vlc_mutex_unlock(&keys->lock); +} diff --git a/modules/video_output/keythread.h b/modules/video_output/keythread.h new file mode 100644 index 0000000000..eeb36755b4 --- /dev/null +++ b/modules/video_output/keythread.h @@ -0,0 +1,26 @@ +/***************************************************************************** + * keythread.h: + ***************************************************************************** + * Copyright (C) 2010 Rémi Denis-Courmont + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + *****************************************************************************/ + +typedef struct key_thread key_thread_t; + +key_thread_t *vlc_CreateKeyThread (vlc_object_t *obj); +#define vlc_CreateKeyThread(o) vlc_CreateKeyThread(VLC_OBJECT(o)) +void vlc_DestroyKeyThread (key_thread_t *keys); +void vlc_EmitKey (key_thread_t *keys, int value); -- 2.39.2