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