1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2008 RĂ©mi Denis-Courmont
6 * This program is free software; you can redistribute it and/or modify it
7 * 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.
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 Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19 *****************************************************************************/
25 #include <vlc_common.h>
26 #include <vlc_plugin.h>
27 #include <vlc_inhibit.h>
33 static int Open (vlc_object_t *);
34 static void Close (vlc_object_t *);
37 set_shortname (N_("XDG-screensaver") )
38 set_description (N_("XDG screen saver inhibition") )
39 set_capability ("inhibit", 10 )
40 set_callbacks (Open, Close)
41 set_category (CAT_ADVANCED)
42 set_subcategory (SUBCAT_ADVANCED_MISC)
45 struct vlc_inhibit_sys
48 vlc_cond_t update, inactive;
50 posix_spawnattr_t attr;
51 bool suspend, suspended;
54 static void Inhibit (vlc_inhibit_t *ih, bool suspend);
55 static void *Thread (void *);
57 static int Open (vlc_object_t *obj)
59 vlc_inhibit_t *ih = (vlc_inhibit_t *)obj;
60 vlc_inhibit_sys_t *p_sys = malloc (sizeof (*p_sys));
65 ih->inhibit = Inhibit;
67 vlc_mutex_init (&p_sys->lock);
68 vlc_cond_init (&p_sys->update);
69 vlc_cond_init (&p_sys->inactive);
70 posix_spawnattr_init (&p_sys->attr);
71 /* Reset signal handlers to default and clear mask in the child process */
76 posix_spawnattr_setsigmask (&p_sys->attr, &set);
77 sigaddset (&set, SIGPIPE);
78 posix_spawnattr_setsigdefault (&p_sys->attr, &set);
79 posix_spawnattr_setflags (&p_sys->attr, POSIX_SPAWN_SETSIGDEF
80 | POSIX_SPAWN_SETSIGMASK);
82 p_sys->suspend = false;
83 p_sys->suspended = false;
85 if (vlc_clone (&p_sys->thread, Thread, ih, VLC_THREAD_PRIORITY_LOW))
87 vlc_cond_destroy (&p_sys->inactive);
88 vlc_cond_destroy (&p_sys->update);
89 vlc_mutex_destroy (&p_sys->lock);
96 static void Close (vlc_object_t *obj)
98 vlc_inhibit_t *ih = (vlc_inhibit_t *)obj;
99 vlc_inhibit_sys_t *p_sys = ih->p_sys;
101 /* Make sure xdg-screensaver is gone for good */
102 vlc_mutex_lock (&p_sys->lock);
103 while (p_sys->suspended)
104 vlc_cond_wait (&p_sys->inactive, &p_sys->lock);
105 vlc_mutex_unlock (&p_sys->lock);
107 vlc_cancel (p_sys->thread);
108 vlc_join (p_sys->thread, NULL);
109 posix_spawnattr_destroy (&p_sys->attr);
110 vlc_cond_destroy (&p_sys->inactive);
111 vlc_cond_destroy (&p_sys->update);
112 vlc_mutex_destroy (&p_sys->lock);
116 static void Inhibit (vlc_inhibit_t *ih, bool suspend)
118 vlc_inhibit_sys_t *p_sys = ih->p_sys;
120 /* xdg-screensaver can take quite a while to start up (e.g. 1 second).
121 * So we avoid _waiting_ for it unless we really need to (clean up). */
122 vlc_mutex_lock (&p_sys->lock);
123 p_sys->suspend = suspend;
124 vlc_cond_signal (&p_sys->update);
125 vlc_mutex_unlock (&p_sys->lock);
128 extern char **environ;
131 static void *Thread (void *data)
133 vlc_inhibit_t *ih = data;
134 vlc_inhibit_sys_t *p_sys = ih->p_sys;
137 snprintf (id, sizeof (id), "0x%08"PRIx32, ih->window_id);
139 vlc_mutex_lock (&p_sys->lock);
140 mutex_cleanup_push (&p_sys->lock);
142 { /* TODO: detach the thread, so we don't need one at all time */
143 while (p_sys->suspended == p_sys->suspend)
144 vlc_cond_wait (&p_sys->update, &p_sys->lock);
146 int canc = vlc_savecancel ();
148 (char *)"xdg-screensaver",
149 (char *)(p_sys->suspend ? "suspend" : "resume"),
155 vlc_mutex_unlock (&p_sys->lock);
156 if (!posix_spawnp (&pid, "xdg-screensaver", NULL, &p_sys->attr,
161 msg_Dbg (ih, "started xdg-screensaver (PID = %d)", (int)pid);
162 /* Wait for command to complete */
163 while (waitpid (pid, &status, 0) == -1);
165 else/* We don't handle the error, but busy looping would be worse :( */
166 msg_Warn (ih, "could not start xdg-screensaver");
168 vlc_mutex_lock (&p_sys->lock);
169 p_sys->suspended = p_sys->suspend;
170 if (!p_sys->suspended)
171 vlc_cond_signal (&p_sys->inactive);
172 vlc_restorecancel (canc);