]> git.sesse.net Git - vlc/blob - modules/video_output/keythread.c
21039f23d18491db1df5379917f6e8c2de0bd852
[vlc] / modules / video_output / keythread.c
1 /*****************************************************************************
2  * keythread.c: Asynchronous threads to emit key events
3  *****************************************************************************
4  * Copyright (C) 2010 RĂ©mi Denis-Courmont
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation; either version 2.1 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19  *****************************************************************************/
20
21 #ifdef HAVE_CONFIG_H
22 # include "config.h"
23 #endif
24
25 #include <stdlib.h>
26
27 #include <vlc_common.h>
28 #include <assert.h>
29
30 #include "keythread.h"
31
32 struct key_thread
33 {
34     vlc_object_t *libvlc;
35     int          value;
36     vlc_mutex_t  lock;
37     vlc_cond_t   wait;
38     vlc_thread_t thread;
39 };
40
41 static void *KeyThread (void *data)
42 {
43     key_thread_t *keys = data;
44
45     mutex_cleanup_push (&keys->lock);
46     for (;;)
47     {
48         int value;
49
50         vlc_mutex_lock (&keys->lock);
51         /* Note: Key strokes may be lost. A chained list should be used. */
52         while (!(value = keys->value))
53             vlc_cond_wait (&keys->wait, &keys->lock);
54         keys->value = 0;
55         vlc_mutex_unlock (&keys->lock);
56
57         int canc = vlc_savecancel ();
58         var_SetInteger (keys->libvlc, "key-pressed", value);
59         vlc_restorecancel (canc);
60     }
61
62     vlc_cleanup_pop ();
63     assert (0);
64 }
65
66
67 #undef vlc_CreateKeyThread
68 /**
69  * Create an asynchronous key event thread.
70  *
71  * Normally, key events are received by the interface thread (e.g. Qt4), or
72  * the window provider (e.g. XCB). However, some legacy video output plugins
73  * do not use window providers, neither do they run their own event threads.
74  * Instead, those lame video outputs insist on receiving key events from their
75  * Manage() function.
76  *
77  * Some key event handlers are quite slow so they should not be triggered from
78  * the video output thread. Worse yet, some handlers (such as snapshot) would
79  * deadlock if triggered from the video output thread.
80  */
81 key_thread_t *vlc_CreateKeyThread (vlc_object_t *obj)
82 {
83     key_thread_t *keys = malloc (sizeof (*keys));
84     if (unlikely(keys == NULL))
85         return NULL;
86
87     keys->libvlc = VLC_OBJECT(obj->p_libvlc);
88     keys->value = 0;
89     vlc_mutex_init (&keys->lock);
90     vlc_cond_init (&keys->wait);
91     if (vlc_clone (&keys->thread, KeyThread, keys, VLC_THREAD_PRIORITY_LOW))
92     {
93         vlc_cond_destroy (&keys->wait);
94         vlc_mutex_destroy (&keys->lock);
95         free (keys);
96         return NULL;
97     }
98     return keys;
99 }
100
101 void vlc_DestroyKeyThread (key_thread_t *keys)
102 {
103     if (keys == NULL)
104         return;
105
106     vlc_cancel (keys->thread);
107     vlc_join(keys->thread, NULL);
108     vlc_cond_destroy(&keys->wait);
109     vlc_mutex_destroy(&keys->lock);
110     free (keys);
111 }
112
113 void vlc_EmitKey (key_thread_t *keys, int value)
114 {
115     if (keys == NULL)
116         return;
117
118     vlc_mutex_lock(&keys->lock);
119     keys->value = value;
120     vlc_cond_signal(&keys->wait);
121     vlc_mutex_unlock(&keys->lock);
122 }