win32: Inhibit: Call SetThreadExecutionState from a dedicated thread
[vlc.git] / modules / video_output / win32 / inhibit.c
blobaae006daaa600cb24c1f1a0f92886fbdce48d980
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_sem_t sem;
35 vlc_mutex_t mutex;
36 vlc_cond_t cond;
37 vlc_thread_t thread;
38 bool signaled;
39 unsigned int mask;
42 static void Inhibit (vlc_inhibit_t *ih, unsigned mask)
44 vlc_inhibit_sys_t *sys = ih->p_sys;
45 vlc_mutex_lock(&sys->mutex);
46 sys->mask = mask;
47 sys->signaled = true;
48 vlc_mutex_unlock(&sys->mutex);
49 vlc_cond_signal(&sys->cond);
52 static void* Run(void* obj)
54 vlc_inhibit_t *ih = (vlc_inhibit_t*)obj;
55 vlc_inhibit_sys_t *sys = ih->p_sys;
56 EXECUTION_STATE prev_state = ES_CONTINUOUS;
58 vlc_sem_post(&sys->sem);
59 while (true)
61 unsigned int mask;
63 vlc_mutex_lock(&sys->mutex);
64 mutex_cleanup_push(&sys->mutex);
65 while (!sys->signaled)
66 vlc_cond_wait(&sys->cond, &sys->mutex);
67 mask = sys->mask;
68 sys->signaled = false;
69 vlc_mutex_unlock(&sys->mutex);
70 vlc_cleanup_pop();
72 bool suspend = (mask & VLC_INHIBIT_DISPLAY) != 0;
73 if (suspend)
74 /* Prevent monitor from powering off */
75 prev_state = SetThreadExecutionState( ES_DISPLAY_REQUIRED |
76 ES_SYSTEM_REQUIRED |
77 ES_CONTINUOUS );
78 else
79 SetThreadExecutionState( prev_state );
81 vlc_assert_unreachable();
84 static void CloseInhibit (vlc_object_t *obj)
86 vlc_inhibit_t *ih = (vlc_inhibit_t*)obj;
87 vlc_inhibit_sys_t* sys = ih->p_sys;
88 vlc_cancel(sys->thread);
89 vlc_join(sys->thread, NULL);
90 vlc_cond_destroy(&sys->cond);
91 vlc_mutex_destroy(&sys->mutex);
92 vlc_sem_destroy(&sys->sem);
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_sem_init(&sys->sem, 0);
104 vlc_mutex_init(&sys->mutex);
105 vlc_cond_init(&sys->cond);
106 sys->signaled = false;
108 /* SetThreadExecutionState always needs to be called from the same thread */
109 if (vlc_clone(&sys->thread, Run, ih, VLC_THREAD_PRIORITY_LOW))
111 vlc_cond_destroy(&sys->cond);
112 vlc_mutex_destroy(&sys->mutex);
113 vlc_sem_destroy(&sys->sem);
114 return VLC_EGENERIC;
117 vlc_sem_wait(&sys->sem);
119 ih->inhibit = Inhibit;
120 return VLC_SUCCESS;
123 vlc_module_begin ()
124 set_shortname (N_("Windows screensaver"))
125 set_description (N_("Windows screen saver inhibition"))
126 set_category (CAT_ADVANCED)
127 set_subcategory (SUBCAT_ADVANCED_MISC)
128 set_capability ("inhibit", 10)
129 set_callbacks (OpenInhibit, CloseInhibit)
130 vlc_module_end ()