1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * Copyright (C) 2007 Bastien Nocera <hadess@hadess.net>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA.
18  *
19  * The Totem project hereby grant permission for non-gpl compatible GStreamer
20  * plugins to be used and distributed together with GStreamer and Totem. This
21  * permission are above and beyond the permissions granted by the GPL license
22  * Totem is covered by.
23  *
24  * See license_change file for details.
25  *
26  */
27 
28 #include "config.h"
29 
30 #include <glib.h>
31 #include <glib-object.h>
32 #include <glib/gi18n-lib.h>
33 #include <libpeas/peas-extension-base.h>
34 #include <libpeas/peas-object-module.h>
35 #include <libpeas/peas-activatable.h>
36 #include <string.h>
37 
38 #include "totem-plugin.h"
39 #include "totem.h"
40 #include "backend/bacon-video-widget.h"
41 
42 #define TOTEM_TYPE_SCREENSAVER_PLUGIN		(totem_screensaver_plugin_get_type ())
43 #define TOTEM_SCREENSAVER_PLUGIN(o)		(G_TYPE_CHECK_INSTANCE_CAST ((o), TOTEM_TYPE_SCREENSAVER_PLUGIN, TotemScreensaverPlugin))
44 #define TOTEM_SCREENSAVER_PLUGIN_CLASS(k)	(G_TYPE_CHECK_CLASS_CAST((k), TOTEM_TYPE_SCREENSAVER_PLUGIN, TotemScreensaverPluginClass))
45 #define TOTEM_IS_SCREENSAVER_PLUGIN(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), TOTEM_TYPE_SCREENSAVER_PLUGIN))
46 #define TOTEM_IS_SCREENSAVER_PLUGIN_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), TOTEM_TYPE_SCREENSAVER_PLUGIN))
47 #define TOTEM_SCREENSAVER_PLUGIN_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), TOTEM_TYPE_SCREENSAVER_PLUGIN, TotemScreensaverPluginClass))
48 
49 typedef struct {
50 	TotemObject *totem;
51 	BaconVideoWidget *bvw;
52 
53 	GDBusProxy    *screensaver;
54 	GCancellable  *cancellable;
55 
56 	gboolean       inhibit_available;
57 	guint          handler_id_playing;
58 	guint          inhibit_cookie;
59 	guint          uninhibit_timeout;
60 } TotemScreensaverPluginPrivate;
61 
TOTEM_PLUGIN_REGISTER(TOTEM_TYPE_SCREENSAVER_PLUGIN,TotemScreensaverPlugin,totem_screensaver_plugin)62 TOTEM_PLUGIN_REGISTER(TOTEM_TYPE_SCREENSAVER_PLUGIN,
63 		      TotemScreensaverPlugin,
64 		      totem_screensaver_plugin)
65 
66 static void
67 totem_screensaver_update_from_state (TotemObject *totem,
68 				     TotemScreensaverPlugin *pi)
69 {
70 	if (totem_object_is_playing (totem) != FALSE) {
71 		if (pi->priv->inhibit_cookie == 0 &&
72 		    pi->priv->inhibit_available) {
73 			GtkWindow *window;
74 
75 			window = totem_object_get_main_window (totem);
76 			pi->priv->inhibit_cookie = gtk_application_inhibit (GTK_APPLICATION (totem),
77 										window,
78 										GTK_APPLICATION_INHIBIT_IDLE,
79 										_("Playing a movie"));
80 			if (pi->priv->inhibit_cookie == 0)
81 				pi->priv->inhibit_available = FALSE;
82 			g_object_unref (window);
83 		}
84 	} else {
85 		if (pi->priv->inhibit_cookie != 0) {
86 			gtk_application_uninhibit (GTK_APPLICATION (pi->priv->totem), pi->priv->inhibit_cookie);
87 			pi->priv->inhibit_cookie = 0;
88 		}
89 	}
90 }
91 
92 static gboolean
uninhibit_timeout_cb(TotemScreensaverPlugin * pi)93 uninhibit_timeout_cb (TotemScreensaverPlugin *pi)
94 {
95 	totem_screensaver_update_from_state (pi->priv->totem, pi);
96 	pi->priv->uninhibit_timeout = 0;
97 	return G_SOURCE_REMOVE;
98 }
99 
100 static void
property_notify_cb(TotemObject * totem,GParamSpec * spec,TotemScreensaverPlugin * pi)101 property_notify_cb (TotemObject *totem,
102 		    GParamSpec *spec,
103 		    TotemScreensaverPlugin *pi)
104 {
105 	if (pi->priv->uninhibit_timeout != 0) {
106 		g_source_remove (pi->priv->uninhibit_timeout);
107 		pi->priv->uninhibit_timeout = 0;
108 	}
109 
110 	if (totem_object_is_playing (totem) == FALSE) {
111 		pi->priv->uninhibit_timeout = g_timeout_add_seconds (5, (GSourceFunc) uninhibit_timeout_cb, pi);
112 		g_source_set_name_by_id (pi->priv->uninhibit_timeout, "[totem] uninhibit_timeout_cb");
113 		return;
114 	}
115 
116 	totem_screensaver_update_from_state (totem, pi);
117 }
118 
119 static void
screensaver_signal_cb(GDBusProxy * proxy,const gchar * sender_name,const gchar * signal_name,GVariant * parameters,gpointer user_data)120 screensaver_signal_cb (GDBusProxy  *proxy,
121 		       const gchar *sender_name,
122 		       const gchar *signal_name,
123 		       GVariant    *parameters,
124 		       gpointer     user_data)
125 {
126 	TotemScreensaverPlugin *pi = user_data;
127 
128 	if (g_strcmp0 (signal_name, "ActiveChanged") == 0) {
129 		gboolean active;
130 
131 		g_variant_get (parameters, "(b)", &active);
132 		if (active)
133 			totem_object_pause (pi->priv->totem);
134 	}
135 }
136 
137 static void
screensaver_proxy_ready_cb(GObject * source_object,GAsyncResult * res,gpointer user_data)138 screensaver_proxy_ready_cb (GObject      *source_object,
139 			    GAsyncResult *res,
140 			    gpointer      user_data)
141 {
142 	TotemScreensaverPlugin *pi;
143 	GDBusProxy *proxy;
144 	GError *error = NULL;
145 
146 	proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
147 	if (!proxy) {
148 		if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
149 			g_warning ("Failed to acquire screensaver proxy: %s", error->message);
150 		g_error_free (error);
151 		return;
152 	}
153 
154 	pi = TOTEM_SCREENSAVER_PLUGIN (user_data);
155 	pi->priv->screensaver = proxy;
156 	g_signal_connect (G_OBJECT (proxy), "g-signal",
157 			  G_CALLBACK (screensaver_signal_cb), pi);
158 }
159 
160 static void
impl_activate(PeasActivatable * plugin)161 impl_activate (PeasActivatable *plugin)
162 {
163 	TotemScreensaverPlugin *pi = TOTEM_SCREENSAVER_PLUGIN (plugin);
164 	TotemObject *totem;
165 
166 	pi->priv->inhibit_available = TRUE;
167 
168 	totem = g_object_get_data (G_OBJECT (plugin), "object");
169 	pi->priv->bvw = BACON_VIDEO_WIDGET (totem_object_get_video_widget (totem));
170 
171 	pi->priv->handler_id_playing = g_signal_connect (G_OBJECT (totem),
172 						   "notify::playing",
173 						   G_CALLBACK (property_notify_cb),
174 						   pi);
175 
176 	pi->priv->totem = g_object_ref (totem);
177 
178 	pi->priv->cancellable = g_cancellable_new ();
179 	g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
180 				  G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
181 				  NULL,
182 				  "org.gnome.ScreenSaver",
183 				  "/org/gnome/ScreenSaver",
184 				  "org.gnome.ScreenSaver",
185 				  pi->priv->cancellable,
186 				  screensaver_proxy_ready_cb,
187 				  pi);
188 
189 	/* Force setting the current status */
190 	totem_screensaver_update_from_state (totem, pi);
191 }
192 
193 static void
impl_deactivate(PeasActivatable * plugin)194 impl_deactivate	(PeasActivatable *plugin)
195 {
196 	TotemScreensaverPlugin *pi = TOTEM_SCREENSAVER_PLUGIN (plugin);
197 
198 	if (pi->priv->cancellable) {
199 		g_cancellable_cancel (pi->priv->cancellable);
200 		g_clear_object (&pi->priv->cancellable);
201 	}
202 	g_clear_object (&pi->priv->screensaver);
203 
204 	if (pi->priv->handler_id_playing != 0) {
205 		TotemObject *totem;
206 		totem = g_object_get_data (G_OBJECT (plugin), "object");
207 		g_signal_handler_disconnect (G_OBJECT (totem), pi->priv->handler_id_playing);
208 		pi->priv->handler_id_playing = 0;
209 	}
210 
211 	if (pi->priv->uninhibit_timeout != 0) {
212 		g_source_remove (pi->priv->uninhibit_timeout);
213 		pi->priv->uninhibit_timeout = 0;
214 	}
215 
216 	if (pi->priv->inhibit_cookie != 0) {
217 		gtk_application_uninhibit (GTK_APPLICATION (pi->priv->totem), pi->priv->inhibit_cookie);
218 		pi->priv->inhibit_cookie = 0;
219 	}
220 
221 	g_object_unref (pi->priv->totem);
222 	g_object_unref (pi->priv->bvw);
223 }
224 
225