win32/inhibit: signal while holding the lock
[vlc.git] / modules / video_output / win32 / inhibit.c
blob566b311189f3bee8e3295a56bf2cd3d8af5a25c9
1 /*****************************************************************************
2 * inhibit.c: Windows video output common code
3 *****************************************************************************
4 * Copyright (C) 2018 VLC authors and VideoLAN
6 * Authors: Steve Lhomme <robux4@ycbcr.xyz>
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation; either version 2.1 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
23 #ifdef HAVE_CONFIG_H
24 # include "config.h"
25 #endif
27 #include <vlc_common.h>
28 #include <vlc_inhibit.h>
29 #include <vlc_plugin.h>
30 #include <assert.h>
32 struct vlc_inhibit_sys
34 vlc_mutex_t mutex;
35 vlc_cond_t cond;
36 vlc_thread_t thread;
37 unsigned int mask;
40 static void Inhibit (vlc_inhibit_t *ih, unsigned mask)
42 vlc_inhibit_sys_t *sys = ih->p_sys;
43 vlc_mutex_lock(&sys->mutex);
44 sys->mask = mask;
45 vlc_cond_signal(&sys->cond);
46 vlc_mutex_unlock(&sys->mutex);
49 static void RestoreStateOnCancel( void* p_opaque )
51 VLC_UNUSED(p_opaque);
52 SetThreadExecutionState( ES_CONTINUOUS );
55 static void* Run(void* obj)
57 vlc_inhibit_t *ih = (vlc_inhibit_t*)obj;
58 vlc_inhibit_sys_t *sys = ih->p_sys;
59 EXECUTION_STATE prev_state = ES_CONTINUOUS;
61 for (unsigned int mask = 0;;)
63 vlc_mutex_lock(&sys->mutex);
64 mutex_cleanup_push(&sys->mutex);
65 vlc_cleanup_push(RestoreStateOnCancel, ih);
66 while (mask == sys->mask)
67 vlc_cond_wait(&sys->cond, &sys->mutex);
68 mask = sys->mask;
69 vlc_mutex_unlock(&sys->mutex);
70 vlc_cleanup_pop();
71 vlc_cleanup_pop();
73 bool suspend = (mask & VLC_INHIBIT_DISPLAY) != 0;
74 if (suspend)
75 /* Prevent monitor from powering off */
76 prev_state = SetThreadExecutionState( ES_DISPLAY_REQUIRED |
77 ES_SYSTEM_REQUIRED |
78 ES_CONTINUOUS );
79 else
80 SetThreadExecutionState( prev_state );
82 vlc_assert_unreachable();
85 static void CloseInhibit (vlc_object_t *obj)
87 vlc_inhibit_t *ih = (vlc_inhibit_t*)obj;
88 vlc_inhibit_sys_t* sys = ih->p_sys;
89 vlc_cancel(sys->thread);
90 vlc_join(sys->thread, NULL);
91 vlc_cond_destroy(&sys->cond);
92 vlc_mutex_destroy(&sys->mutex);
95 static int OpenInhibit (vlc_object_t *obj)
97 vlc_inhibit_t *ih = (vlc_inhibit_t *)obj;
98 vlc_inhibit_sys_t *sys = ih->p_sys =
99 vlc_obj_malloc(obj, sizeof(vlc_inhibit_sys_t));
100 if (unlikely(ih->p_sys == NULL))
101 return VLC_ENOMEM;
103 vlc_mutex_init(&sys->mutex);
104 vlc_cond_init(&sys->cond);
105 sys->mask = 0;
107 /* SetThreadExecutionState always needs to be called from the same thread */
108 if (vlc_clone(&sys->thread, Run, ih, VLC_THREAD_PRIORITY_LOW))
110 vlc_cond_destroy(&sys->cond);
111 vlc_mutex_destroy(&sys->mutex);
112 return VLC_EGENERIC;
115 ih->inhibit = Inhibit;
116 return VLC_SUCCESS;
119 vlc_module_begin ()
120 set_shortname (N_("Windows screensaver"))
121 set_description (N_("Windows screen saver inhibition"))
122 set_category (CAT_ADVANCED)
123 set_subcategory (SUBCAT_ADVANCED_MISC)
124 set_capability ("inhibit", 10)
125 set_callbacks (OpenInhibit, CloseInhibit)
126 vlc_module_end ()