[vlc-devel] [PATCH] Add dpms module to switch it off while playing
Olivier Brunel
jjk at jjacky.com
Fri Oct 25 19:43:41 CEST 2013
Assumes it was on before/should be on again after. Point is to switch it off
when starting to play, and (back) on when pausing/stopping.
Signed-off-by: Olivier Brunel <jjk at jjacky.com>
---
Hi,
It was suggested to me to send this here, so here we go. A few things I feel I
should say about this:
- As I explained in a blog post[1], the main reason I wrote this is because I
wanted DPMS to be turned back on when pausing a video (and off on resume),
which VLC doesn't do. The inhibit in VLC only works on play/stop and that's
not good enough for me (I'll often pause and go AFK, for a while). This is why
it uses the "interface" capability.
- The right thing to do might have been to call xdg-screensaver suspend/resume,
and instead I'm calling `xset +/-dpms` directly, which means on pause/stop
DPMS will be turned back on, whereas it would have otherwise maybe not been
done because another app had called xdg-screensaver suspend.
It's a known "flaw" because I don't use a session manager myself, so the call
to xdg-screensaver would have been one to xset anyways, plus I have no idea
how to get the window ID from VLC.
- I'm not familiar at all with the VLC codebase, so this was very much inspired
from previous similar modules. (Any horrible bug in there is most likely my
doing though :p)
-jjacky
[1] http://jjacky.com/2013-09-30-automatically-switch-dpms-off-in-vlc-2.1/
modules/misc/Modules.am | 4 +-
modules/misc/dpms.c | 228 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 231 insertions(+), 1 deletion(-)
create mode 100644 modules/misc/dpms.c
diff --git a/modules/misc/Modules.am b/modules/misc/Modules.am
index d2d6a22..2a123da 100644
--- a/modules/misc/Modules.am
+++ b/modules/misc/Modules.am
@@ -5,6 +5,7 @@ SOURCES_fingerprinter = fingerprinter.c \
webservices/acoustid.h \
webservices/json.c \
webservices/json.h
+SOURCES_dpms = dpms.c
SOURCES_xml = xml/libxml.c
@@ -55,7 +56,8 @@ libstats_plugin_la_LIBADD = $(AM_LIBADD)
libvlc_LTLIBRARIES += \
libaudioscrobbler_plugin.la \
liblogger_plugin.la \
- libstats_plugin.la
+ libstats_plugin.la \
+ libdpms_plugin.la
if ENABLE_SOUT
libvlc_LTLIBRARIES += \
diff --git a/modules/misc/dpms.c b/modules/misc/dpms.c
new file mode 100644
index 0000000..12b3b1d
--- /dev/null
+++ b/modules/misc/dpms.c
@@ -0,0 +1,228 @@
+/**
+ * dpms.c Copyright (C) 2013 Olivier Brunel GPL 3+
+ * based on inhibit.c Copyright © 2007 Rafaël Carré GPL 2+
+ * based on xdg.c Copyright (C) 2008 Rémi Denis-Courmont LGPL 2.1+
+ * */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_common.h>
+#include <vlc_plugin.h>
+#include <vlc_input.h>
+#include <vlc_interface.h>
+#include <vlc_playlist.h>
+#include <assert.h>
+#include <signal.h>
+#include <spawn.h>
+#include <sys/wait.h>
+
+static int Activate (vlc_object_t *p_this);
+static void Deactivate (vlc_object_t *p_this);
+
+static void Inhibit (intf_thread_t *p_intf, bool suspend);
+
+static int StateChange (vlc_object_t *p_input, const char *var,
+ vlc_value_t prev, vlc_value_t value, void *data);
+static int ItemChange (vlc_object_t *p_playlist, const char *var,
+ vlc_value_t prev, vlc_value_t value, void *data);
+static void *Thread (void *data);
+
+struct intf_sys_t
+{
+ playlist_t *p_playlist;
+ vlc_thread_t thread;
+ vlc_cond_t update;
+ vlc_cond_t inactive;
+ vlc_mutex_t lock;
+ posix_spawnattr_t attr;
+ bool suspend;
+ bool suspended;
+ bool has_callback;
+};
+
+vlc_module_begin ()
+ set_shortname (N_("dpms"))
+ set_description (N_("Switch DPMS off while playing"))
+ set_capability ("interface", 10)
+ set_callbacks (Activate, Deactivate)
+vlc_module_end ()
+
+/*****************************************************************************
+ * Activate: initialize and create stuff
+ *****************************************************************************/
+static int Activate (vlc_object_t *p_this)
+{
+ intf_thread_t *p_intf = (intf_thread_t *) p_this;
+ intf_sys_t *p_sys;
+
+ p_sys = p_intf->p_sys = (intf_sys_t *) calloc (1, sizeof (intf_sys_t));
+ if (!p_sys)
+ return VLC_ENOMEM;
+
+ vlc_mutex_init (&p_sys->lock);
+ vlc_cond_init (&p_sys->update);
+ vlc_cond_init (&p_sys->inactive);
+ posix_spawnattr_init (&p_sys->attr);
+ /* Reset signal handlers to default and clear mask in the child process */
+ {
+ sigset_t set;
+
+ sigemptyset (&set);
+ posix_spawnattr_setsigmask (&p_sys->attr, &set);
+ sigaddset (&set, SIGPIPE);
+ posix_spawnattr_setsigdefault (&p_sys->attr, &set);
+ posix_spawnattr_setflags (&p_sys->attr, POSIX_SPAWN_SETSIGDEF
+ | POSIX_SPAWN_SETSIGMASK);
+ }
+
+ if (vlc_clone (&p_sys->thread, Thread, p_intf, VLC_THREAD_PRIORITY_LOW))
+ {
+ vlc_cond_destroy (&p_sys->inactive);
+ vlc_cond_destroy (&p_sys->update);
+ vlc_mutex_destroy (&p_sys->lock);
+ free (p_sys);
+ return VLC_ENOMEM;
+ }
+ p_sys->p_playlist = pl_Get (p_intf);
+ var_AddCallback (p_sys->p_playlist, "activity", ItemChange, p_intf);
+ return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * Deactivate: uninitialize and cleanup
+ *****************************************************************************/
+static void Deactivate (vlc_object_t *p_this)
+{
+ intf_thread_t *p_intf = (intf_thread_t*)p_this;
+ intf_sys_t *p_sys = p_intf->p_sys;
+ input_thread_t *p_input;
+
+ var_DelCallback (p_sys->p_playlist, "activity", ItemChange, p_intf);
+
+ p_input = playlist_CurrentInput (p_sys->p_playlist);
+ if (p_input)
+ {
+ if (p_sys->has_callback)
+ var_DelCallback (p_input, "intf-event", StateChange, p_intf);
+ vlc_object_release (p_input);
+ }
+
+ Inhibit (p_intf, false);
+
+ /* Make sure xset is gone for good */
+ vlc_mutex_lock (&p_sys->lock);
+ while (p_sys->suspended)
+ vlc_cond_wait (&p_sys->inactive, &p_sys->lock);
+ vlc_mutex_unlock (&p_sys->lock);
+
+ vlc_cancel (p_sys->thread);
+ vlc_join (p_sys->thread, NULL);
+ posix_spawnattr_destroy (&p_sys->attr);
+ vlc_cond_destroy (&p_sys->inactive);
+ vlc_cond_destroy (&p_sys->update);
+ vlc_mutex_destroy (&p_sys->lock);
+
+ free (p_sys);
+}
+
+static void Inhibit (intf_thread_t *p_intf, bool suspend)
+{
+ intf_sys_t *p_sys = p_intf->p_sys;
+
+ /* in case xset take a little while to start up (e.g. 1 second), avoid
+ * waiting for it unless we really need to (clean up). */
+ vlc_mutex_lock (&p_sys->lock);
+ p_sys->suspend = suspend;
+ vlc_cond_signal (&p_sys->update);
+ vlc_mutex_unlock (&p_sys->lock);
+}
+
+static int StateChange (vlc_object_t *p_input, const char *var,
+ vlc_value_t prev, vlc_value_t value, void *data)
+{
+ intf_thread_t *p_intf = data;
+ int state;
+
+ if (value.i_int != INPUT_EVENT_STATE)
+ return VLC_SUCCESS;
+
+ state = var_GetInteger (p_input, "state");
+
+ if ((state == PLAYING_S) == p_intf->p_sys->suspended)
+ return VLC_SUCCESS;
+
+ Inhibit (p_intf, state == PLAYING_S);
+
+ (void)var; (void)prev;
+ return VLC_SUCCESS;
+}
+
+static int ItemChange (vlc_object_t *p_playlist, const char *var,
+ vlc_value_t prev, vlc_value_t value, void *data)
+{
+ intf_thread_t *p_intf = data;
+ intf_sys_t *p_sys = p_intf->p_sys;
+ input_thread_t *p_input;
+
+ p_input = playlist_CurrentInput (p_sys->p_playlist);
+ if (!p_input || p_input->b_dead)
+ return VLC_SUCCESS;
+
+ Inhibit (p_intf, true);
+ var_AddCallback (p_input, "intf-event", StateChange, p_intf);
+ p_sys->has_callback = true;
+ vlc_object_release (p_input);
+
+ (void)var; (void)prev; (void)value; (void)p_playlist;
+ return VLC_SUCCESS;
+}
+
+
+extern char **environ;
+
+VLC_NORETURN
+static void *Thread (void *data)
+{
+ intf_thread_t *p_intf = data;
+ intf_sys_t *p_sys = p_intf->p_sys;
+
+ vlc_mutex_lock (&p_sys->lock);
+ mutex_cleanup_push (&p_sys->lock);
+ for (;;)
+ {
+ while (p_sys->suspended == p_sys->suspend)
+ vlc_cond_wait (&p_sys->update, &p_sys->lock);
+
+ int canc = vlc_savecancel ();
+ char *argv[3] = {
+ (char *) "xset",
+ (char *) ((p_sys->suspend) ? "-dpms" : "+dpms"),
+ NULL,
+ };
+ pid_t pid;
+
+ vlc_mutex_unlock (&p_sys->lock);
+ if (!posix_spawnp (&pid, argv[0], NULL, &p_sys->attr,
+ argv, environ))
+ {
+ int status;
+
+ /* Wait for command to complete */
+ while (waitpid (pid, &status, 0) == -1);
+ }
+ else
+ /* We don't handle the error, but busy looping would be worse :( */
+ msg_Warn (p_intf, "Failed to start xset");
+
+ vlc_mutex_lock (&p_sys->lock);
+ p_sys->suspended = p_sys->suspend;
+ if (!p_sys->suspended)
+ vlc_cond_signal (&p_sys->inactive);
+ vlc_restorecancel (canc);
+ }
+
+ vlc_cleanup_pop ();
+ assert (0);
+}
--
1.8.4
More information about the vlc-devel
mailing list