wl-idle-inhibit: add Wayland idle inhibitor
authorRémi Denis-Courmont <remi@remlab.net>
Sat, 19 May 2018 16:57:53 +0000 (19:57 +0300)
committerRémi Denis-Courmont <remi@remlab.net>
Sun, 20 May 2018 17:49:12 +0000 (20:49 +0300)
include/vlc_inhibit.h
modules/MODULES_LIST
modules/misc/Makefile.am
modules/misc/inhibit/wl-idle-inhibit.c [new file with mode: 0644]
po/POTFILES.in

index 73fb0b3..00abfab 100644 (file)
@@ -29,6 +29,8 @@
 typedef struct vlc_inhibit vlc_inhibit_t;
 typedef struct vlc_inhibit_sys vlc_inhibit_sys_t;
 
+struct vout_window_t;
+
 enum vlc_inhibit_flags
 {
     VLC_INHIBIT_NONE=0 /*< No inhibition */,
@@ -46,6 +48,11 @@ struct vlc_inhibit
     void (*inhibit) (vlc_inhibit_t *, unsigned flags);
 };
 
+static inline struct vout_window_t *vlc_inhibit_GetWindow(vlc_inhibit_t *ih)
+{
+    return (struct vout_window_t *)(ih->obj.parent);
+}
+
 static inline void vlc_inhibit_Set (vlc_inhibit_t *ih, unsigned flags)
 {
     ih->inhibit (ih, flags);
index 0cc5546..04ac47d 100644 (file)
@@ -462,6 +462,7 @@ $Id$
  * wingdi: WIN 32 / WIN CE GDI video output
  * winhibit: Win32 screensaver inhibition
  * winstore: Windows Store App audio output
+ * wl_idle_inhibit: Wayland idle inhibitor
  * wl_screenshooter: Wayland screen capture input
  * wl_shell: Wayland shell surface window provider
  * wl_shm: Wayland shared memory video output
index b5a8db5..90e72a0 100644 (file)
@@ -58,6 +58,27 @@ if HAVE_DBUS
 misc_LTLIBRARIES += libdbus_screensaver_plugin.la
 endif
 
+libwl_idle_inhibit_plugin_la_SOURCES = misc/inhibit/wl-idle-inhibit.c
+nodist_libwl_idle_inhibit_plugin_la_SOURCES = \
+       misc/inhibit/idle-inhibit-client-protocol.h \
+       misc/inhibit/idle-inhibit-protocol.c
+libwl_idle_inhibit_plugin_la_CFLAGS = $(WAYLAND_CLIENT_CFLAGS)
+libwl_idle_inhibit_plugin_la_LIBADD = $(WAYLAND_CLIENT_LIBS)
+if HAVE_WAYLAND
+misc_LTLIBRARIES += libwl_idle_inhibit_plugin.la
+BUILT_SOURCES += $(nodist_libwl_idle_inhibit_plugin_la_SOURCES)
+endif
+
+misc/inhibit/idle-inhibit-client-protocol.h: \
+               $(WAYLAND_PROTOCOLS)/unstable/idle-inhibit/idle-inhibit-unstable-v1.xml \
+               misc/Makefile.am
+       $(AM_V_GEN)$(WAYLAND_SCANNER) client-header $< $@
+
+misc/inhibit/idle-inhibit-protocol.c: \
+               $(WAYLAND_PROTOCOLS)/unstable/idle-inhibit/idle-inhibit-unstable-v1.xml \
+               misc/Makefile.am
+       $(AM_V_GEN)$(WAYLAND_SCANNER) private-code $< $@
+
 libaddonsvorepository_plugin_la_SOURCES = \
        misc/addons/vorepository.c misc/addons/xmlreading.h
 libaddonsfsstorage_plugin_la_SOURCES = \
diff --git a/modules/misc/inhibit/wl-idle-inhibit.c b/modules/misc/inhibit/wl-idle-inhibit.c
new file mode 100644 (file)
index 0000000..269c8bf
--- /dev/null
@@ -0,0 +1,152 @@
+/**
+ * @file idle-inhibit.c
+ * @brief Wayland idle inhibitor module for VLC media player
+ */
+/*****************************************************************************
+ * Copyright © 2018 Rémi Denis-Courmont
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <wayland-client.h>
+#include "misc/inhibit/idle-inhibit-client-protocol.h"
+
+#include <vlc_common.h>
+#include <vlc_plugin.h>
+#include <vlc_vout_window.h>
+#include <vlc_inhibit.h>
+
+struct vlc_inhibit_sys
+{
+    struct wl_event_queue *eventq;
+    struct zwp_idle_inhibit_manager_v1 *manager;
+    struct zwp_idle_inhibitor_v1 *inhibitor;
+};
+
+static void Inhibit (vlc_inhibit_t *ih, unsigned mask)
+{
+    vout_window_t *wnd = vlc_inhibit_GetWindow(ih);
+    vlc_inhibit_sys_t *sys = ih->p_sys;
+    bool suspend = (mask & VLC_INHIBIT_DISPLAY) != 0;
+
+    if (sys->inhibitor != NULL) {
+        zwp_idle_inhibitor_v1_destroy(sys->inhibitor);
+        sys->inhibitor = NULL;
+    }
+
+    if (suspend)
+        sys->inhibitor = zwp_idle_inhibit_manager_v1_create_inhibitor(
+            sys->manager, wnd->handle.wl);
+
+}
+
+static void registry_global_cb(void *data, struct wl_registry *registry,
+                               uint32_t name, const char *iface, uint32_t vers)
+{
+    vlc_inhibit_t *ih = data;
+    vlc_inhibit_sys_t *sys = ih->p_sys;
+
+    if (!strcmp(iface, "zwp_idle_inhibit_manager_v1"))
+        sys->manager = wl_registry_bind(registry, name,
+                                    &zwp_idle_inhibit_manager_v1_interface, 1);
+    (void) vers;
+}
+
+static void registry_global_remove_cb(void *data, struct wl_registry *registry,
+                                      uint32_t name)
+{
+    (void) data; (void) registry; (void) name;
+}
+
+static const struct wl_registry_listener registry_cbs =
+{
+    registry_global_cb,
+    registry_global_remove_cb,
+};
+
+static int Open(vlc_object_t *obj)
+{
+    vlc_inhibit_t *ih = (vlc_inhibit_t *)obj;
+    vout_window_t *wnd = vlc_inhibit_GetWindow(ih);
+
+    if (wnd->type != VOUT_WINDOW_TYPE_WAYLAND)
+        return VLC_EGENERIC;
+
+    vlc_inhibit_sys_t *sys = vlc_obj_malloc(obj, sizeof (*sys));
+    if (unlikely(sys == NULL))
+        return VLC_ENOMEM;
+
+    sys->manager = NULL;
+    sys->inhibitor = NULL;
+    ih->p_sys = sys;
+
+    struct wl_display *display = wnd->display.wl;
+
+    sys->eventq = wl_display_create_queue(display);
+    if (sys->eventq == NULL)
+        return VLC_ENOMEM;
+
+    struct wl_registry *registry = wl_display_get_registry(display);
+    if (registry == NULL)
+        goto error;
+
+    wl_registry_add_listener(registry, &registry_cbs, ih);
+    wl_proxy_set_queue((struct wl_proxy *)registry, sys->eventq);
+    wl_display_roundtrip_queue(display, sys->eventq);
+    wl_registry_destroy(registry);
+
+    if (sys->manager == NULL)
+        goto error;
+
+    ih->inhibit = Inhibit;
+    return VLC_SUCCESS;
+
+error:
+    if (sys->eventq != NULL)
+        wl_event_queue_destroy(sys->eventq);
+    return VLC_EGENERIC;
+}
+
+static void Close(vlc_object_t *obj)
+{
+    vlc_inhibit_t *ih = (vlc_inhibit_t *)obj;
+    vlc_inhibit_sys_t *sys = ih->p_sys;
+    vout_window_t *wnd = vlc_inhibit_GetWindow(ih);
+
+    if (sys->inhibitor != NULL)
+        zwp_idle_inhibitor_v1_destroy(sys->inhibitor);
+
+    zwp_idle_inhibit_manager_v1_destroy(sys->manager);
+    wl_display_flush(wnd->display.wl);
+    wl_event_queue_destroy(sys->eventq);
+}
+
+vlc_module_begin()
+    set_shortname(N_("WL idle"))
+    set_description(N_("Wayland idle inhibitor"))
+    set_category(CAT_ADVANCED)
+    set_subcategory(SUBCAT_ADVANCED_MISC)
+    set_capability("inhibit", 30)
+    set_callbacks(Open, Close)
+vlc_module_end()
index f0bda33..a2dbb43 100644 (file)
@@ -990,6 +990,7 @@ modules/misc/audioscrobbler.c
 modules/misc/fingerprinter.c
 modules/misc/gnutls.c
 modules/misc/inhibit/dbus.c
+modules/misc/inhibit/wl-idle-inhibit.c
 modules/misc/inhibit/xdg.c
 modules/misc/logger.c
 modules/misc/playlist/export.c