aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas White <taw@bitwiz.org.uk>2013-09-17 22:38:50 +0200
committerThomas White <taw@bitwiz.org.uk>2013-09-17 22:38:50 +0200
commita91aa0a9e947831f618e4c5e608c56742273d8b9 (patch)
tree6954ef762d8653b11c1d917927dbe41601b88ef0
parent4e90a9c416a66e3ab6170e2a557d8966d93fbbd2 (diff)
Inhibit screensaver when slideshow is running
-rw-r--r--AUTHORS6
-rw-r--r--Makefile.am6
-rw-r--r--configure.ac12
-rw-r--r--src/inhibit_screensaver.c256
-rw-r--r--src/inhibit_screensaver.h36
-rw-r--r--src/presentation.c3
-rw-r--r--src/presentation.h2
-rw-r--r--src/slideshow.c8
8 files changed, 324 insertions, 5 deletions
diff --git a/AUTHORS b/AUTHORS
index 53415e1..25a0f4b 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1 +1,5 @@
-Thomas White <taw@bitwiz.org.uk>
+Copyright © 2013 Thomas White <taw@bitwiz.org.uk>
+
+Screensaver inhibition code, from VLC (src/inhibit_screensaver.c):
+ Copyright © 2009-2012 Rémi Denis-Courmont
+ Copyright © 2007-2012 Rafaël Carré
diff --git a/Makefile.am b/Makefile.am
index 859ae33..ae8eedc 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -14,13 +14,15 @@ src_colloquium_SOURCES = src/colloquium.c src/render.c \
src/mainwindow.c src/presentation.c \
src/stylesheet.c src/loadsave.c src/frame.c \
src/slideshow.c src/wrap.c src/storycode.c \
- src/imagestore.c src/notes.c src/pr_clock.c
+ src/imagestore.c src/notes.c src/pr_clock.c \
+ src/inhibit_screensaver.c
INCLUDES = -Iharfatum/src
EXTRA_DIST += src/presentation.h src/render.h src/wrap.h \
src/stylesheet.h src/loadsave.h src/slideshow.h src/storycode.h \
- src/imagestore.h src/notes.h src/pr_clock.h
+ src/imagestore.h src/notes.h src/pr_clock.h \
+ src/inhibit_screensaver.h
src/default_stylesheet.o: src/default_stylesheet.sty
ld -r -b binary -o src/default_stylesheet.o src/default_stylesheet.sty
diff --git a/configure.ac b/configure.ac
index eff1f2a..fc161e2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -55,6 +55,14 @@ PKG_CHECK_MODULES([GDK_pixbuf], [gdk-pixbuf], [],
])
+PKG_CHECK_MODULES([DBUS], [dbus-1 >= 1.0.0],
+[ ],
+[
+ AC_MSG_ERROR([dbus is required.])
+])
+
+
+
gl_IGNORE_UNUSED_LIBRARIES
LIBHARFATUM_CFLAGS="$CFLAGS -D_GNU_SOURCE $Cairo_CFLAGS"
@@ -62,10 +70,10 @@ LIBHARFATUM_LIBS="$LIBS $Cairo_LIBS"
AC_SUBST([LIBHARFATUM_LIBS])
CFLAGS="$CFLAGS $GTK_CFLAGS -D_GNU_SOURCE $libPNG_CFLAGS $Cairo_CFLAGS"
-CFLAGS="$CFLAGS $GDK_pixbuf_CFLAGS $GDK_pixbuf_2_CFLAGS"
+CFLAGS="$CFLAGS $GDK_pixbuf_CFLAGS $GDK_pixbuf_2_CFLAGS $DBUS_CFLAGS"
LIBS="$LIBS -lm -lz $GTK_LIBS $libPNG_LIBS $Cairo_LIBS $GDK_pixbuf_LIBS"
-LIBS="$LIBS $GDK_pixbuf_2_LIBS $LDFLAGS"
+LIBS="$LIBS $GDK_pixbuf_2_LIBS $DBUS_LIBS $LDFLAGS"
AC_CONFIG_FILES(Makefile lib/Makefile)
diff --git a/src/inhibit_screensaver.c b/src/inhibit_screensaver.c
new file mode 100644
index 0000000..007c550
--- /dev/null
+++ b/src/inhibit_screensaver.c
@@ -0,0 +1,256 @@
+/*
+ * inhibit_screensaver.h
+ *
+ * Copyright © 2013 Thomas White <taw@bitwiz.org.uk>
+ * Copyright © 2009-2012 Rémi Denis-Courmont
+ * Copyright © 2007-2012 Rafaël Carré
+ *
+ * This file is part of Colloquium.
+ *
+ * Colloquium is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * >>> This file is based on dbus.c from VLC. The original licence is below. <<<
+ *
+ */
+
+/*****************************************************************************
+ * dbus.c: power management inhibition using D-Bus
+ *****************************************************************************
+ * Copyright © 2009-2012 Rémi Denis-Courmont
+ * Copyright © 2007-2012 Rafaël Carré
+ *
+ * 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.
+ *****************************************************************************/
+
+/*
+ * Based on freedesktop Power Management Specification version 0.2
+ * http://people.freedesktop.org/~hughsient/temp/power-management-spec-0.2.html
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <dbus/dbus.h>
+
+
+enum inhibit_api
+{
+ FDO_SS, /**< KDE >= 4 and GNOME >= 3.6 */
+ FDO_PM, /**< KDE and GNOME <= 2.26 */
+ MATE, /**< >= 1.0 */
+ GNOME, /**< GNOME 2.26..3.4 */
+};
+
+#define MAX_API (GNOME+1)
+
+
+/* Currently, all services have identical service and interface names. */
+static const char dbus_service[][40] =
+{
+ [FDO_SS] = "org.freedesktop.ScreenSaver",
+ [FDO_PM] = "org.freedesktop.PowerManagement.Inhibit",
+ [MATE] = "org.mate.SessionManager",
+ [GNOME] = "org.gnome.SessionManager",
+};
+
+
+static const char dbus_path[][33] =
+{
+ [FDO_SS] = "/ScreenSaver",
+ [FDO_PM] = "/org/freedesktop/PowerManagement",
+ [MATE] = "/org/mate/SessionManager",
+ [GNOME] = "/org/gnome/SessionManager",
+};
+
+
+static const char dbus_method_uninhibit[][10] =
+{
+ [FDO_SS] = "UnInhibit",
+ [FDO_PM] = "UnInhibit",
+ [MATE] = "Uninhibit",
+ [GNOME] = "Uninhibit",
+};
+
+
+struct inhibit_sys
+{
+ DBusConnection *conn;
+ DBusPendingCall *pending;
+ dbus_uint32_t cookie;
+ enum inhibit_api api;
+};
+
+
+void do_inhibit(struct inhibit_sys *sys, int flags)
+{
+ enum inhibit_api type = sys->api;
+
+ /* Receive reply from previous request, possibly hours later ;-) */
+ if ( sys->pending != NULL ) {
+
+ DBusMessage *reply;
+
+ /* NOTE: Unfortunately, the pending reply cannot simply be
+ * cancelled. Otherwise, the cookie would be lost and
+ * inhibition would remain on (until complete disconnection from
+ * the bus). */
+ dbus_pending_call_block(sys->pending);
+ reply = dbus_pending_call_steal_reply(sys->pending);
+ dbus_pending_call_unref(sys->pending);
+ sys->pending = NULL;
+
+ if ( reply != NULL ) {
+ if ( !dbus_message_get_args(reply, NULL,
+ DBUS_TYPE_UINT32,
+ &sys->cookie,
+ DBUS_TYPE_INVALID))
+ {
+ sys->cookie = 0;
+ }
+ dbus_message_unref(reply);
+ }
+ fprintf(stderr, "got cookie %i", (int)sys->cookie);
+
+ }
+
+ /* FIXME: This check is incorrect if flags change from one non-zero value
+ * to another one. But the D-Bus API cannot currently inhibit suspend
+ * independently from the screensaver. */
+ if ( !sys->cookie == !flags ) return; /* nothing to do */
+
+ /* Send request */
+ const char *method = flags ? "Inhibit" : dbus_method_uninhibit[type];
+ dbus_bool_t ret;
+
+ DBusMessage *msg = dbus_message_new_method_call(dbus_service[type],
+ dbus_path[type],
+ dbus_service[type],
+ method);
+ if ( msg == NULL ) return;
+
+ if (flags)
+ {
+ const char *app = PACKAGE;
+ const char *reason = "Presentation in progress";
+
+ assert(sys->cookie == 0);
+
+ switch (type)
+ {
+ case MATE:
+ case GNOME:
+ {
+ dbus_uint32_t xid = 0; // FIXME ?
+ dbus_uint32_t gflags = 0xC;
+
+ ret = dbus_message_append_args(msg, DBUS_TYPE_STRING, &app,
+ DBUS_TYPE_UINT32, &xid,
+ DBUS_TYPE_STRING, &reason,
+ DBUS_TYPE_UINT32, &gflags,
+ DBUS_TYPE_INVALID);
+ break;
+ }
+ default:
+ ret = dbus_message_append_args(msg, DBUS_TYPE_STRING, &app,
+ DBUS_TYPE_STRING, &reason,
+ DBUS_TYPE_INVALID);
+ break;
+ }
+
+ if (!ret
+ || !dbus_connection_send_with_reply(sys->conn, msg, &sys->pending, -1))
+ sys->pending = NULL;
+ }
+ else
+ {
+ assert(sys->cookie != 0);
+ if (!dbus_message_append_args(msg, DBUS_TYPE_UINT32, &sys->cookie,
+ DBUS_TYPE_INVALID)
+ || !dbus_connection_send (sys->conn, msg, NULL))
+ sys->cookie = 0;
+ }
+ dbus_connection_flush(sys->conn);
+ dbus_message_unref(msg);
+}
+
+
+void inhibit_cleanup(struct inhibit_sys *sys)
+{
+ if ( sys->pending != NULL ) {
+ dbus_pending_call_cancel(sys->pending);
+ dbus_pending_call_unref(sys->pending);
+ }
+
+ dbus_connection_close(sys->conn);
+ dbus_connection_unref(sys->conn);
+ free(sys);
+}
+
+
+struct inhibit_sys *inhibit_prepare()
+{
+ struct inhibit_sys *sys;
+ DBusError err;
+ int i;
+
+ sys = malloc(sizeof(struct inhibit_sys));
+ if ( sys == NULL ) {
+ fprintf(stderr, "Failed to allocate inhibit.\n");
+ return NULL;
+ }
+
+ dbus_error_init(&err);
+
+ sys->conn = dbus_bus_get_private(DBUS_BUS_SESSION, &err);
+ if ( sys->conn == NULL ) {
+ fprintf(stderr, "cannot connect to session bus: %s",
+ err.message);
+ dbus_error_free(&err);
+ free(sys);
+ return NULL;
+ }
+
+ sys->pending = NULL;
+ sys->cookie = 0;
+
+ for ( i=0; i<MAX_API; i++ ) {
+ if ( dbus_bus_name_has_owner(sys->conn, dbus_service[i], NULL) )
+ {
+ fprintf(stderr, "found service %s", dbus_service[i]);
+ sys->api = i;
+ return sys;
+ }
+
+ fprintf(stderr, "cannot find service %s", dbus_service[i]);
+ }
+
+ inhibit_cleanup(sys);
+ return NULL;
+}
diff --git a/src/inhibit_screensaver.h b/src/inhibit_screensaver.h
new file mode 100644
index 0000000..0a62adc
--- /dev/null
+++ b/src/inhibit_screensaver.h
@@ -0,0 +1,36 @@
+/*
+ * inhibit_screensaver.h
+ *
+ * Copyright © 2013 Thomas White <taw@bitwiz.org.uk>
+ *
+ * This file is part of Colloquium.
+ *
+ * Colloquium is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef INHIBIT_SCREENSAVER_H
+#define INHIBIT_SCREENSAVER_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+struct inhibit_sys;
+
+extern void do_inhibit(struct inhibit_sys *sys, int flags);
+extern void inhibit_cleanup(struct inhibit_sys *sys);
+extern struct inhibit_sys *inhibit_prepare(void);
+
+#endif /* INHIBIT_SCREENSAVER_H */
diff --git a/src/presentation.c b/src/presentation.c
index 3c4e593..0847e84 100644
--- a/src/presentation.c
+++ b/src/presentation.c
@@ -38,6 +38,7 @@
#include "imagestore.h"
#include "wrap.h"
#include "notes.h"
+#include "inhibit_screensaver.h"
static int num_presentations = 0;
@@ -55,6 +56,8 @@ void free_presentation(struct presentation *p)
(*p->num_presentations)--;
if ( *p->num_presentations == 0 ) final = 1;
+ if ( p->inhibit != NULL ) inhibit_cleanup(p->inhibit);
+
/* FIXME: Loads of stuff leaks here */
free(p->filename);
imagestore_destroy(p->is);
diff --git a/src/presentation.h b/src/presentation.h
index ff065a6..5af844c 100644
--- a/src/presentation.h
+++ b/src/presentation.h
@@ -186,6 +186,8 @@ struct presentation
StyleSheet *ss;
unsigned int num_slides;
struct slide **slides;
+
+ struct inhibit_sys *inhibit;
};
diff --git a/src/slideshow.c b/src/slideshow.c
index 4847077..66e4994 100644
--- a/src/slideshow.c
+++ b/src/slideshow.c
@@ -35,6 +35,7 @@
#include "mainwindow.h"
#include "render.h"
#include "pr_clock.h"
+#include "inhibit_screensaver.h"
/* Force a redraw of the slideshow */
@@ -134,6 +135,7 @@ static gint next_slide_sig(GtkWidget *widget, struct presentation *p)
void end_slideshow(struct presentation *p)
{
+ if ( p->inhibit != NULL ) do_inhibit(p->inhibit, 0);
gtk_widget_destroy(p->ss_drawingarea);
gtk_widget_destroy(p->slideshow);
p->slideshow = NULL;
@@ -223,6 +225,10 @@ void try_start_slideshow(struct presentation *p)
p->ss_blank = 0;
+ if ( p->inhibit == NULL ) {
+ p->inhibit = inhibit_prepare();
+ }
+
n = gtk_window_new(GTK_WINDOW_TOPLEVEL);
p->ss_drawingarea = gtk_drawing_area_new();
@@ -266,6 +272,8 @@ void try_start_slideshow(struct presentation *p)
gtk_window_fullscreen(GTK_WINDOW(n));
gtk_widget_show_all(GTK_WIDGET(n));
+ if ( p->inhibit != NULL ) do_inhibit(p->inhibit, 1);
+
//if ( p->prefs->open_notes ) open_notes(p); FIXME!
p->cur_proj_slide = p->cur_edit_slide;