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>
32 static int Open (vlc_object_t *);
33 static void Close (vlc_object_t *);
36 set_shortname (N_("XDG-screensaver") )
37 set_description (N_("XDG screen saver inhibition") )
38 set_capability ("inhibit", 10 )
39 set_callbacks (Open, Close)
40 set_category (CAT_ADVANCED)
41 set_subcategory (SUBCAT_ADVANCED_MISC)
44 struct vlc_inhibit_sys
47 vlc_cond_t update, inactive;
49 posix_spawnattr_t attr;
50 bool suspend, suspended;
53 static void Inhibit (vlc_inhibit_t *ih, bool suspend);
54 static void *Thread (void *);
56 static int Open (vlc_object_t *obj)
58 vlc_inhibit_t *ih = (vlc_inhibit_t *)obj;
59 vlc_inhibit_sys_t *p_sys = malloc (sizeof (*p_sys));
64 ih->inhibit = Inhibit;
66 vlc_mutex_init (&p_sys->lock);
67 vlc_cond_init (&p_sys->update);
68 vlc_cond_init (&p_sys->inactive);
69 posix_spawnattr_init (&p_sys->attr);
70 /* Reset signal handlers to default and clear mask in the child process */
75 posix_spawnattr_setsigmask (&p_sys->attr, &set);
76 sigaddset (&set, SIGPIPE);
77 posix_spawnattr_setsigdefault (&p_sys->attr, &set);
78 posix_spawnattr_setflags (&p_sys->attr, POSIX_SPAWN_SETSIGDEF
79 | POSIX_SPAWN_SETSIGMASK);
81 p_sys->suspend = false;
82 p_sys->suspended = false;
84 if (vlc_clone (&p_sys->thread, Thread, ih, VLC_THREAD_PRIORITY_LOW))
86 vlc_cond_destroy (&p_sys->inactive);
87 vlc_cond_destroy (&p_sys->update);
88 vlc_mutex_destroy (&p_sys->lock);
95 static void Close (vlc_object_t *obj)
97 vlc_inhibit_t *ih = (vlc_inhibit_t *)obj;
98 vlc_inhibit_sys_t *p_sys = ih->p_sys;
100 /* Make sure xdg-screensaver is gone for good */
101 vlc_mutex_lock (&p_sys->lock);
102 while (p_sys->suspended)
103 vlc_cond_wait (&p_sys->inactive, &p_sys->lock);
104 vlc_mutex_unlock (&p_sys->lock);
106 vlc_cancel (p_sys->thread);
107 vlc_join (p_sys->thread, NULL);
108 posix_spawnattr_destroy (&p_sys->attr);
109 vlc_cond_destroy (&p_sys->inactive);
110 vlc_cond_destroy (&p_sys->update);
111 vlc_mutex_destroy (&p_sys->lock);
115 static void Inhibit (vlc_inhibit_t *ih, bool suspend)
117 vlc_inhibit_sys_t *p_sys = ih->p_sys;
119 /* xdg-screensaver can take quite a while to start up (e.g. 1 second).
120 * So we avoid _waiting_ for it unless we really need to (clean up). */
121 vlc_mutex_lock (&p_sys->lock);
122 p_sys->suspend = suspend;
123 vlc_cond_signal (&p_sys->update);
124 vlc_mutex_unlock (&p_sys->lock);
127 extern char **environ;
130 static void *Thread (void *data)
132 vlc_inhibit_t *ih = data;
133 vlc_inhibit_sys_t *p_sys = ih->p_sys;
136 snprintf (id, sizeof (id), "0x%08"PRIx32, ih->window_id);
138 vlc_mutex_lock (&p_sys->lock);
139 mutex_cleanup_push (&p_sys->lock);
141 { /* TODO: detach the thread, so we don't need one at all time */
142 while (p_sys->suspended == p_sys->suspend)
143 vlc_cond_wait (&p_sys->update, &p_sys->lock);
145 int canc = vlc_savecancel ();
147 (char *)"xdg-screensaver",
148 (char *)(p_sys->suspend ? "suspend" : "resume"),
154 vlc_mutex_unlock (&p_sys->lock);
155 if (!posix_spawnp (&pid, "xdg-screensaver", NULL, &p_sys->attr,
160 msg_Dbg (ih, "started xdg-screensaver (PID = %d)", (int)pid);
161 /* Wait for command to complete */
162 while (waitpid (pid, &status, 0) == -1);
164 else/* We don't handle the error, but busy looping would be worse :( */
165 msg_Warn (ih, "could not start xdg-screensaver");
167 vlc_mutex_lock (&p_sys->lock);
168 p_sys->suspended = p_sys->suspend;
169 if (!p_sys->suspended)
170 vlc_cond_signal (&p_sys->inactive);
171 vlc_restorecancel (canc);