]> www.fi.muni.cz Git - evince.git/blob - shell/ev-media-player-keys.c
[dualscreen] fix crash on ctrl+w and fix control window closing
[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  * Copyright © 2010 Christian Persch
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA.
20  *
21  */
22
23 #include "config.h"
24
25 #include "ev-media-player-keys.h"
26
27 #include <string.h>
28 #include <glib.h>
29 #include <gio/gio.h>
30
31 #define SD_NAME        "org.gnome.SettingsDaemon"
32 #define SD_OBJECT_PATH "/org/gnome/SettingsDaemon/MediaKeys"
33 #define SD_INTERFACE   "org.gnome.SettingsDaemon.MediaKeys"
34
35 enum {
36         KEY_PRESSED,
37         LAST_SIGNAL
38 };
39
40 struct _EvMediaPlayerKeys
41 {
42         GObject        parent;
43
44         GDBusProxy *proxy;
45         gboolean    has_name_owner;
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         object_class->finalize = ev_media_player_keys_finalize;
69
70         signals[KEY_PRESSED] =
71                 g_signal_new ("key_pressed",
72                               EV_TYPE_MEDIA_PLAYER_KEYS,
73                               G_SIGNAL_RUN_LAST,
74                               G_STRUCT_OFFSET (EvMediaPlayerKeysClass, key_pressed),
75                               NULL, NULL,
76                               g_cclosure_marshal_VOID__STRING,
77                               G_TYPE_NONE,
78                               1, G_TYPE_STRING);
79 }
80
81 static void
82 ev_media_player_keys_update_has_name_owner (EvMediaPlayerKeys *keys)
83 {
84         gchar *name_owner;
85
86         if (!keys->proxy) {
87                 keys->has_name_owner = FALSE;
88                 return;
89         }
90
91         name_owner = g_dbus_proxy_get_name_owner (keys->proxy);
92         keys->has_name_owner = (name_owner != NULL);
93         g_free (name_owner);
94 }
95
96 static void
97 ev_media_player_keys_grab_keys (EvMediaPlayerKeys *keys)
98 {
99         if (!keys->has_name_owner)
100                 return;
101
102         /*
103          * The uint as second argument is time. We give a very low value so that
104          * if a media player is there it gets higher priority on the keys (0 is
105          * a special value having maximum priority).
106          */
107         g_dbus_proxy_call (keys->proxy,
108                            "GrabMediaPlayerKeys",
109                            g_variant_new ("(su)", "Evince", 1),
110                            G_DBUS_CALL_FLAGS_NO_AUTO_START,
111                            -1,
112                            NULL, NULL, NULL);
113 }
114
115 static void
116 ev_media_player_keys_release_keys (EvMediaPlayerKeys *keys)
117 {
118         if (!keys->has_name_owner)
119                 return;
120
121         g_dbus_proxy_call (keys->proxy,
122                            "ReleaseMediaPlayerKeys",
123                            g_variant_new ("(s)", "Evince"),
124                            G_DBUS_CALL_FLAGS_NO_AUTO_START,
125                            -1,
126                            NULL, NULL, NULL);
127 }
128
129 static void
130 media_player_key_pressed_cb (GDBusProxy *proxy,
131                              gchar      *sender_name,
132                              gchar      *signal_name,
133                              GVariant   *parameters,
134                              gpointer    user_data)
135 {
136         const char *application, *key;
137
138         if (g_strcmp0 (sender_name, SD_NAME) != 0)
139                 return;
140
141         if (g_strcmp0 (signal_name, "MediaPlayerKeyPressed") != 0)
142                 return;
143
144         if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(ss)")))
145                 return;
146
147         g_variant_get (parameters, "(&s&s)", &application, &key);
148
149         if (strcmp ("Evince", application) == 0) {
150                 g_signal_emit (user_data, signals[KEY_PRESSED], 0, key);
151         }
152 }
153
154 static void
155 mediakeys_name_owner_changed (GObject    *object,
156                               GParamSpec *pspec,
157                               gpointer    user_data)
158 {
159         EvMediaPlayerKeys *keys = EV_MEDIA_PLAYER_KEYS (user_data);
160
161         ev_media_player_keys_update_has_name_owner (keys);
162 }
163
164 static void
165 mediakeys_service_appeared_cb (GObject      *source_object,
166                                GAsyncResult *res,
167                                gpointer      user_data)
168 {
169         EvMediaPlayerKeys *keys = EV_MEDIA_PLAYER_KEYS (user_data);
170         GDBusProxy *proxy;
171
172         proxy = g_dbus_proxy_new_for_bus_finish (res, NULL);
173
174         if (proxy == NULL) {
175                 return;
176         }
177
178         g_signal_connect (proxy, "g-signal",
179                           G_CALLBACK (media_player_key_pressed_cb),
180                           keys);
181         g_signal_connect (proxy, "notify::g-name-owner",
182                           G_CALLBACK (mediakeys_name_owner_changed),
183                           keys);
184
185         keys->proxy = proxy;
186         ev_media_player_keys_update_has_name_owner (keys);
187         ev_media_player_keys_grab_keys (keys);
188 }
189
190 static void
191 ev_media_player_keys_init (EvMediaPlayerKeys *keys)
192 {
193         g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
194                                   G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
195                                   NULL,
196                                   SD_NAME,
197                                   SD_OBJECT_PATH,
198                                   SD_INTERFACE,
199                                   NULL,
200                                   mediakeys_service_appeared_cb,
201                                   keys);
202 }
203
204 void
205 ev_media_player_keys_focused (EvMediaPlayerKeys *keys)
206 {
207         if (keys->proxy == NULL)
208                 return;
209         
210         ev_media_player_keys_grab_keys (keys);
211 }
212
213 static void
214 ev_media_player_keys_finalize (GObject *object)
215 {
216         EvMediaPlayerKeys *keys = EV_MEDIA_PLAYER_KEYS (object);
217
218         if (keys->proxy != NULL) {
219                 ev_media_player_keys_release_keys (keys);
220                 g_object_unref (keys->proxy);
221                 keys->proxy = NULL;
222                 keys->has_name_owner = FALSE;
223         }
224
225         G_OBJECT_CLASS (ev_media_player_keys_parent_class)->finalize (object);
226 }
227
228 EvMediaPlayerKeys *
229 ev_media_player_keys_new (void)
230 {
231         return g_object_new (EV_TYPE_MEDIA_PLAYER_KEYS, NULL);
232 }
233