]> www.fi.muni.cz Git - evince.git/blob - shell/ev-media-player-keys.c
b8489067a6f2a83b7d8361e8ae56c648b4a1af0a
[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         KEY_PRESSED,
36         LAST_SIGNAL
37 };
38
39 struct _EvMediaPlayerKeys
40 {
41         GObject        parent;
42
43         GDBusConnection *connection;
44         guint watch_id;
45         guint subscription_id;
46 };
47
48 struct _EvMediaPlayerKeysClass
49 {
50         GObjectClass parent_class;
51
52         /* Signals */
53         void (* key_pressed) (EvMediaPlayerKeys *keys,
54                               const gchar       *key);
55 };
56
57 static guint signals[LAST_SIGNAL];
58
59 G_DEFINE_TYPE (EvMediaPlayerKeys, ev_media_player_keys, G_TYPE_OBJECT)
60
61 static void ev_media_player_keys_finalize (GObject *object);
62
63 static void
64 ev_media_player_keys_class_init (EvMediaPlayerKeysClass *klass)
65 {
66         GObjectClass *object_class = G_OBJECT_CLASS (klass);
67
68         signals[KEY_PRESSED] =
69                 g_signal_new ("key_pressed",
70                               EV_TYPE_MEDIA_PLAYER_KEYS,
71                               G_SIGNAL_RUN_LAST,
72                               G_STRUCT_OFFSET (EvMediaPlayerKeysClass, key_pressed),
73                               NULL, NULL,
74                               g_cclosure_marshal_VOID__STRING,
75                               G_TYPE_NONE,
76                               1, G_TYPE_STRING);
77         
78         object_class->finalize = ev_media_player_keys_finalize;
79 }
80
81 static void
82 ev_media_player_keys_grab_keys (EvMediaPlayerKeys *keys)
83 {
84         /*
85          * The uint as second argument is time. We give a very low value so that
86          * if a media player is there it gets higher priority on the keys (0 is
87          * a special value having maximum priority).
88          */
89         g_dbus_connection_call (keys->connection,
90                                 SD_NAME,
91                                 SD_OBJECT_PATH,
92                                 SD_INTERFACE,
93                                 "GrabMediaPlayerKeys",
94                                 g_variant_new ("(su)", "Evince", 1),
95                                 G_DBUS_CALL_FLAGS_NO_AUTO_START,
96                                 -1,
97                                 NULL, NULL, NULL);
98 }
99
100 static void
101 ev_media_player_keys_release_keys (EvMediaPlayerKeys *keys)
102 {
103         g_dbus_connection_call (keys->connection,
104                                 SD_NAME,
105                                 SD_OBJECT_PATH,
106                                 SD_INTERFACE,
107                                 "ReleaseMediaPlayerKeys",
108                                 g_variant_new ("(s)", "Evince"),
109                                 G_DBUS_CALL_FLAGS_NO_AUTO_START,
110                                 -1,
111                                 NULL, NULL, NULL);
112 }
113
114 static void
115 media_player_key_pressed_cb (GDBusConnection *connection,
116                              const gchar *sender_name,
117                              const gchar *object_path,
118                              const gchar *interface_name,
119                              const gchar *signal_name,
120                              GVariant *parameters,
121                              gpointer user_data)
122 {
123         const char *application, *key;
124
125         if (g_strcmp0 (sender_name, SD_NAME) != 0)
126                 return;
127         if (g_strcmp0 (signal_name, "MediaPlayerKeyPressed") != 0)
128                 return;
129
130         if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(ss)")))
131                 return;
132
133         g_variant_get (parameters, "(&s&s)", &application, &key);
134
135         if (strcmp ("Evince", application) == 0) {
136                 g_signal_emit (user_data, signals[KEY_PRESSED], 0, key);
137         }
138 }
139
140 static void
141 mediakeys_service_appeared_cb (GDBusConnection *connection,
142                                const char      *name,
143                                const char      *name_owner,
144                                gpointer         user_data)
145 {
146         EvMediaPlayerKeys *keys = EV_MEDIA_PLAYER_KEYS (user_data);
147
148         keys->connection = g_object_ref (connection);
149
150         keys->subscription_id = g_dbus_connection_signal_subscribe (connection,
151                                                                     name_owner,
152                                                                     SD_INTERFACE,
153                                                                     "MediaPlayerKeyPressed",
154                                                                     SD_OBJECT_PATH,
155                                                                     NULL,
156                                                                     media_player_key_pressed_cb,
157                                                                     keys, NULL);
158
159         ev_media_player_keys_grab_keys (keys);
160 }
161
162 static void
163 mediakeys_service_disappeared_cb (GDBusConnection *connection,
164                                  const char      *name,
165                                  gpointer         user_data)
166 {
167         EvMediaPlayerKeys *keys = EV_MEDIA_PLAYER_KEYS (user_data);
168
169         g_assert (keys->connection == connection);
170
171         g_dbus_connection_signal_unsubscribe (connection, keys->subscription_id);
172         keys->subscription_id = 0;
173
174         g_object_unref (keys->connection);
175         keys->connection = NULL;
176 }
177
178 static void
179 ev_media_player_keys_init (EvMediaPlayerKeys *keys)
180 {
181         keys->watch_id = g_bus_watch_name (G_BUS_TYPE_SESSION,
182                                            SD_NAME,
183                                            G_BUS_NAME_WATCHER_FLAGS_NONE,
184                                            mediakeys_service_appeared_cb,
185                                            mediakeys_service_disappeared_cb,
186                                            keys, NULL);
187 }
188
189 void
190 ev_media_player_keys_focused (EvMediaPlayerKeys *keys)
191 {
192         if (keys->connection == NULL)
193                 return;
194         
195         ev_media_player_keys_grab_keys (keys);
196 }
197
198 static void
199 ev_media_player_keys_finalize (GObject *object)
200 {
201         EvMediaPlayerKeys *keys = EV_MEDIA_PLAYER_KEYS (object);
202
203         ev_media_player_keys_release_keys (keys);
204
205         if (keys->subscription_id != 0) {
206                 g_assert (keys->connection != NULL);
207                 g_dbus_connection_signal_unsubscribe (keys->connection, keys->subscription_id);
208                 g_object_unref (keys->connection);
209         }
210
211         g_bus_unwatch_name (keys->watch_id);
212
213         G_OBJECT_CLASS (ev_media_player_keys_parent_class)->finalize (object);
214 }
215
216 EvMediaPlayerKeys *
217 ev_media_player_keys_new (void)
218 {
219         return g_object_new (EV_TYPE_MEDIA_PLAYER_KEYS, NULL);
220 }
221