]> www.fi.muni.cz Git - evince.git/blob - shell/ev-media-player-keys.c
11a36487d0d6b202db8b9f6e3b402856bfa11687
[evince.git] / shell / ev-media-player-keys.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /* 
3  * Copyright (C) 2007 Jan Arne Petersen <jap@gnome.org>
4  * Copyright (C) 2008 Bastien Nocera <hadess@hadess.net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA.
19  *
20  */
21
22 #include "config.h"
23
24 #include "ev-media-player-keys.h"
25
26 #include <string.h>
27 #include <glib.h>
28 #include <gio/gio.h>
29
30 #define SD_NAME        "org.gnome.SettingsDaemon"
31 #define SD_OBJECT_PATH "/org/gnome/SettingsDaemon/MediaKeys"
32 #define SD_INTERFACE   "org.gnome.SettingsDaemon.MediaKeys"
33
34 enum {
35         PROP_0,
36         PROP_CONNECTION
37 };
38
39 enum {
40         KEY_PRESSED,
41         LAST_SIGNAL
42 };
43
44 struct _EvMediaPlayerKeys
45 {
46         GObject        parent;
47
48         GDBusConnection *connection;
49         guint watch_id;
50         guint subscription_id;
51 };
52
53 struct _EvMediaPlayerKeysClass
54 {
55         GObjectClass parent_class;
56
57         /* Signals */
58         void (* key_pressed) (EvMediaPlayerKeys *keys,
59                               const gchar       *key);
60 };
61
62 static guint signals[LAST_SIGNAL];
63
64 G_DEFINE_TYPE (EvMediaPlayerKeys, ev_media_player_keys, G_TYPE_OBJECT)
65
66 static void ev_media_player_keys_set_property (GObject      *object,
67                                                guint         prop_id,
68                                                const GValue *value,
69                                                GParamSpec   *pspec);
70 static void ev_media_player_keys_constructed (GObject *object);
71 static void ev_media_player_keys_finalize (GObject *object);
72
73 static void
74 ev_media_player_keys_class_init (EvMediaPlayerKeysClass *klass)
75 {
76         GObjectClass *object_class = G_OBJECT_CLASS (klass);
77
78         object_class->set_property = ev_media_player_keys_set_property;
79         object_class->constructed = ev_media_player_keys_constructed;
80         object_class->finalize = ev_media_player_keys_finalize;
81
82         signals[KEY_PRESSED] =
83                 g_signal_new ("key_pressed",
84                               EV_TYPE_MEDIA_PLAYER_KEYS,
85                               G_SIGNAL_RUN_LAST,
86                               G_STRUCT_OFFSET (EvMediaPlayerKeysClass, key_pressed),
87                               NULL, NULL,
88                               g_cclosure_marshal_VOID__STRING,
89                               G_TYPE_NONE,
90                               1, G_TYPE_STRING);
91
92         g_object_class_install_property (object_class,
93                                          PROP_CONNECTION,
94                                          g_param_spec_object ("connection", NULL, NULL,
95                                                               G_TYPE_DBUS_CONNECTION,
96                                                               G_PARAM_WRITABLE |
97                                                               G_PARAM_CONSTRUCT_ONLY |
98                                                               G_PARAM_STATIC_STRINGS));
99 }
100
101 static void
102 ev_media_player_keys_grab_keys (EvMediaPlayerKeys *keys)
103 {
104         /*
105          * The uint as second argument is time. We give a very low value so that
106          * if a media player is there it gets higher priority on the keys (0 is
107          * a special value having maximum priority).
108          */
109         g_dbus_connection_call (keys->connection,
110                                 SD_NAME,
111                                 SD_OBJECT_PATH,
112                                 SD_INTERFACE,
113                                 "GrabMediaPlayerKeys",
114                                 g_variant_new ("(su)", "Evince", 1),
115                                 G_DBUS_CALL_FLAGS_NO_AUTO_START,
116                                 -1,
117                                 NULL, NULL, NULL);
118 }
119
120 static void
121 ev_media_player_keys_release_keys (EvMediaPlayerKeys *keys)
122 {
123         g_dbus_connection_call (keys->connection,
124                                 SD_NAME,
125                                 SD_OBJECT_PATH,
126                                 SD_INTERFACE,
127                                 "ReleaseMediaPlayerKeys",
128                                 g_variant_new ("(s)", "Evince"),
129                                 G_DBUS_CALL_FLAGS_NO_AUTO_START,
130                                 -1,
131                                 NULL, NULL, NULL);
132 }
133
134 static void
135 media_player_key_pressed_cb (GDBusConnection *connection,
136                              const gchar *sender_name,
137                              const gchar *object_path,
138                              const gchar *interface_name,
139                              const gchar *signal_name,
140                              GVariant *parameters,
141                              gpointer user_data)
142 {
143         const char *application, *key;
144
145         if (g_strcmp0 (sender_name, SD_NAME) != 0)
146                 return;
147         if (g_strcmp0 (signal_name, "MediaPlayerKeyPressed") != 0)
148                 return;
149
150         if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(ss)")))
151                 return;
152
153         g_variant_get (parameters, "(&s&s)", &application, &key);
154
155         if (strcmp ("Evince", application) == 0) {
156                 g_signal_emit (user_data, signals[KEY_PRESSED], 0, key);
157         }
158 }
159
160 static void
161 mediakeys_service_appeared_cb (GDBusConnection *connection,
162                                const char      *name,
163                                const char      *name_owner,
164                                gpointer         user_data)
165 {
166         EvMediaPlayerKeys *keys = EV_MEDIA_PLAYER_KEYS (user_data);
167
168         g_assert (connection == keys->connection);
169
170         keys->subscription_id = g_dbus_connection_signal_subscribe (keys->connection,
171                                                                     name_owner,
172                                                                     SD_INTERFACE,
173                                                                     "MediaPlayerKeyPressed",
174                                                                     SD_OBJECT_PATH,
175                                                                     NULL,
176                                                                     media_player_key_pressed_cb,
177                                                                     keys, NULL);
178
179         ev_media_player_keys_grab_keys (keys);
180 }
181
182 static void
183 mediakeys_service_disappeared_cb (GDBusConnection *connection,
184                                  const char      *name,
185                                  gpointer         user_data)
186 {
187         EvMediaPlayerKeys *keys = EV_MEDIA_PLAYER_KEYS (user_data);
188
189         g_assert (connection == keys->connection);
190
191         if (keys->subscription_id != 0) {
192                 g_dbus_connection_signal_unsubscribe (connection, keys->subscription_id);
193                 keys->subscription_id = 0;
194         }
195 }
196
197 static void
198 ev_media_player_keys_init (EvMediaPlayerKeys *keys)
199 {
200 }
201
202 static void
203 ev_media_player_keys_constructed (GObject *object)
204 {
205         EvMediaPlayerKeys *keys = EV_MEDIA_PLAYER_KEYS (object);
206
207         keys->watch_id = g_bus_watch_name_on_connection (keys->connection,
208                                                          SD_NAME,
209                                                          G_BUS_NAME_WATCHER_FLAGS_NONE,
210                                                          mediakeys_service_appeared_cb,
211                                                          mediakeys_service_disappeared_cb,
212                                                          keys, NULL);
213 }
214
215 void
216 ev_media_player_keys_focused (EvMediaPlayerKeys *keys)
217 {
218         if (keys->connection == NULL)
219                 return;
220         
221         ev_media_player_keys_grab_keys (keys);
222 }
223
224 static void
225 ev_media_player_keys_finalize (GObject *object)
226 {
227         EvMediaPlayerKeys *keys = EV_MEDIA_PLAYER_KEYS (object);
228
229         ev_media_player_keys_release_keys (keys);
230
231         g_bus_unwatch_name (keys->watch_id);
232
233         if (keys->subscription_id != 0) {
234                 g_dbus_connection_signal_unsubscribe (keys->connection, keys->subscription_id);
235         }
236
237         if (keys->connection != NULL) {
238                 g_object_unref (keys->connection);
239         }
240
241         G_OBJECT_CLASS (ev_media_player_keys_parent_class)->finalize (object);
242 }
243
244 static void
245 ev_media_player_keys_set_property (GObject      *object,
246                                    guint         prop_id,
247                                    const GValue *value,
248                                    GParamSpec   *pspec)
249 {
250         EvMediaPlayerKeys *keys = EV_MEDIA_PLAYER_KEYS (object);
251
252         switch (prop_id) {
253         case PROP_CONNECTION:
254                 keys->connection = g_value_dup_object (value);
255                 break;
256         default:
257                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
258                 break;
259         }
260 }
261
262 EvMediaPlayerKeys *
263 ev_media_player_keys_new (GDBusConnection *connection)
264 {
265         return g_object_new (EV_TYPE_MEDIA_PLAYER_KEYS,
266                              "connection", connection,
267                              NULL);
268 }
269