No issues found
Tool | Failure ID | Location | Function | Message | Data |
---|---|---|---|---|---|
clang-analyzer | no-output-found | rb-mmkeys-plugin.c | Message(text='Unable to locate XML output from invoke-clang-analyzer') | None |
1 /*
2 * rb-mmkeys-plugin.c
3 *
4 * Copyright (C) 2002, 2003 Jorn Baayen <jorn@nl.linux.org>
5 * Copyright (C) 2002,2003 Colin Walters <walters@debian.org>
6 * Copyright (C) 2007 James Livingston <doclivingston@gmail.com>
7 * Copyright (C) 2007 Jonathan Matthew <jonathan@d14n.org>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2, or (at your option)
12 * any later version.
13 *
14 * The Rhythmbox authors hereby grant permission for non-GPL compatible
15 * GStreamer plugins to be used and distributed together with GStreamer
16 * and Rhythmbox. This permission is above and beyond the permissions granted
17 * by the GPL license by which Rhythmbox is covered. If you modify this code
18 * you may extend this exception to your version of the code, but you are not
19 * obligated to do so. If you do not wish to do so, delete this exception
20 * statement from your version.
21 *
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
30 */
31
32 #ifdef HAVE_CONFIG_H
33 #include <config.h>
34 #endif
35
36 #include <string.h> /* For strlen */
37 #include <glib/gi18n-lib.h>
38 #include <gmodule.h>
39 #include <gtk/gtk.h>
40 #include <gio/gio.h>
41 #include <glib.h>
42
43 #include "rb-plugin-macros.h"
44 #include "rb-util.h"
45 #include "rb-debug.h"
46 #include "rb-shell.h"
47 #include "rb-shell-player.h"
48 #include "rb-marshal.h"
49
50 #ifdef HAVE_MMKEYS
51 #include <X11/Xlib.h>
52 #include <X11/XF86keysym.h>
53 #include <gdk/gdkx.h>
54 #endif /* HAVE_MMKEYS */
55
56 #define RB_TYPE_MMKEYS_PLUGIN (rb_mmkeys_plugin_get_type ())
57 #define RB_MMKEYS_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), RB_TYPE_MMKEYS_PLUGIN, RBMMKeysPlugin))
58 #define RB_MMKEYS_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), RB_TYPE_MMKEYS_PLUGIN, RBMMKeysPluginClass))
59 #define RB_IS_MMKEYS_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), RB_TYPE_MMKEYS_PLUGIN))
60 #define RB_IS_MMKEYS_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), RB_TYPE_MMKEYS_PLUGIN))
61 #define RB_MMKEYS_PLUGIN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), RB_TYPE_MMKEYS_PLUGIN, RBMMKeysPluginClass))
62
63 typedef struct
64 {
65 PeasExtensionBase parent;
66
67 enum {
68 NONE = 0,
69 SETTINGS_DAEMON,
70 X_KEY_GRAB
71 } grab_type;
72 RBShell *shell;
73 RBShellPlayer *shell_player;
74 GDBusProxy *proxy;
75 } RBMMKeysPlugin;
76
77 typedef struct
78 {
79 PeasExtensionBaseClass parent_class;
80 } RBMMKeysPluginClass;
81
82 RB_DEFINE_PLUGIN(RB_TYPE_MMKEYS_PLUGIN, RBMMKeysPlugin, rb_mmkeys_plugin,)
83
84 G_MODULE_EXPORT void peas_register_types (PeasObjectModule *module);
85
86 static void
87 rb_mmkeys_plugin_init (RBMMKeysPlugin *plugin)
88 {
89 rb_debug ("RBMMKeysPlugin initialising");
90 }
91
92 static void
93 media_player_key_pressed (GDBusProxy *proxy,
94 const char *sender,
95 const char *signal,
96 GVariant *parameters,
97 RBMMKeysPlugin *plugin)
98 {
99 char *key;
100 char *application;
101
102 if (g_strcmp0 (signal, "MediaPlayerKeyPressed") != 0) {
103 rb_debug ("got unexpected signal '%s' from media player keys", signal);
104 return;
105 }
106
107 g_variant_get (parameters, "(ss)", &application, &key);
108
109 rb_debug ("got media key '%s' for application '%s'",
110 key, application);
111
112 if (strcmp (application, "Rhythmbox")) {
113 rb_debug ("got media player key signal for unexpected application '%s'", application);
114 return;
115 }
116
117 if (strcmp (key, "Play") == 0) {
118 rb_shell_player_playpause (plugin->shell_player, FALSE, NULL);
119 } else if (strcmp (key, "Pause") == 0) {
120 rb_shell_player_pause (plugin->shell_player, NULL);
121 } else if (strcmp (key, "Stop") == 0) {
122 rb_shell_player_stop (plugin->shell_player);
123 } else if (strcmp (key, "Previous") == 0) {
124 rb_shell_player_do_previous (plugin->shell_player, NULL);
125 } else if (strcmp (key, "Next") == 0) {
126 rb_shell_player_do_next (plugin->shell_player, NULL);
127 } else if (strcmp (key, "Repeat") == 0) {
128 gboolean shuffle, repeat;
129
130 if (rb_shell_player_get_playback_state (plugin->shell_player, &shuffle, &repeat)) {
131 rb_shell_player_set_playback_state (plugin->shell_player, shuffle, !repeat);
132 }
133 } else if (strcmp (key, "Shuffle") == 0) {
134 gboolean shuffle, repeat;
135
136 if (rb_shell_player_get_playback_state (plugin->shell_player, &shuffle, &repeat)) {
137 rb_shell_player_set_playback_state (plugin->shell_player, !shuffle, repeat);
138 }
139 } else if (strcmp (key, "FastForward") == 0) {
140 rb_shell_player_seek (plugin->shell_player, FFWD_OFFSET, NULL);
141 } else if (strcmp (key, "Rewind") == 0) {
142 rb_shell_player_seek (plugin->shell_player, -RWD_OFFSET, NULL);
143 }
144
145 g_free (key);
146 g_free (application);
147 }
148
149 static void
150 grab_call_complete (GObject *proxy, GAsyncResult *res, RBMMKeysPlugin *plugin)
151 {
152 GError *error = NULL;
153 GVariant *result;
154
155 result = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, &error);
156 if (error != NULL) {
157 g_warning ("Unable to grab media player keys: %s", error->message);
158 g_clear_error (&error);
159 } else {
160 g_variant_unref (result);
161 }
162 }
163
164 static gboolean
165 window_focus_cb (GtkWidget *window,
166 GdkEventFocus *event,
167 RBMMKeysPlugin *plugin)
168 {
169 rb_debug ("window got focus, re-grabbing media keys");
170
171 g_dbus_proxy_call (plugin->proxy,
172 "GrabMediaPlayerKeys",
173 g_variant_new ("(su)", "Rhythmbox", 0),
174 G_DBUS_CALL_FLAGS_NONE,
175 -1,
176 NULL,
177 (GAsyncReadyCallback) grab_call_complete,
178 plugin);
179 return FALSE;
180 }
181
182 #ifdef HAVE_MMKEYS
183
184 static void
185 grab_mmkey (int key_code,
186 GdkWindow *root)
187 {
188 Display *display;
189 gdk_error_trap_push ();
190
191 display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
192 XGrabKey (display, key_code,
193 0,
194 GDK_WINDOW_XID (root), True,
195 GrabModeAsync, GrabModeAsync);
196 XGrabKey (display, key_code,
197 Mod2Mask,
198 GDK_WINDOW_XID (root), True,
199 GrabModeAsync, GrabModeAsync);
200 XGrabKey (display, key_code,
201 Mod5Mask,
202 GDK_WINDOW_XID (root), True,
203 GrabModeAsync, GrabModeAsync);
204 XGrabKey (display, key_code,
205 LockMask,
206 GDK_WINDOW_XID (root), True,
207 GrabModeAsync, GrabModeAsync);
208 XGrabKey (display, key_code,
209 Mod2Mask | Mod5Mask,
210 GDK_WINDOW_XID (root), True,
211 GrabModeAsync, GrabModeAsync);
212 XGrabKey (display, key_code,
213 Mod2Mask | LockMask,
214 GDK_WINDOW_XID (root), True,
215 GrabModeAsync, GrabModeAsync);
216 XGrabKey (display, key_code,
217 Mod5Mask | LockMask,
218 GDK_WINDOW_XID (root), True,
219 GrabModeAsync, GrabModeAsync);
220 XGrabKey (display, key_code,
221 Mod2Mask | Mod5Mask | LockMask,
222 GDK_WINDOW_XID (root), True,
223 GrabModeAsync, GrabModeAsync);
224
225 gdk_flush ();
226 if (gdk_error_trap_pop ()) {
227 rb_debug ("Error grabbing key");
228 }
229 }
230
231 static void
232 ungrab_mmkey (int key_code,
233 GdkWindow *root)
234 {
235 Display *display;
236 gdk_error_trap_push ();
237
238 display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
239 XUngrabKey (display, key_code, 0, GDK_WINDOW_XID (root));
240 XUngrabKey (display, key_code, Mod2Mask, GDK_WINDOW_XID (root));
241 XUngrabKey (display, key_code, Mod5Mask, GDK_WINDOW_XID (root));
242 XUngrabKey (display, key_code, LockMask, GDK_WINDOW_XID (root));
243 XUngrabKey (display, key_code, Mod2Mask | Mod5Mask, GDK_WINDOW_XID (root));
244 XUngrabKey (display, key_code, Mod2Mask | LockMask, GDK_WINDOW_XID (root));
245 XUngrabKey (display, key_code, Mod5Mask | LockMask, GDK_WINDOW_XID (root));
246 XUngrabKey (display, key_code, Mod2Mask | Mod5Mask | LockMask, GDK_WINDOW_XID (root));
247
248 gdk_flush ();
249 if (gdk_error_trap_pop ()) {
250 rb_debug ("Error grabbing key");
251 }
252 }
253
254
255 static GdkFilterReturn
256 filter_mmkeys (GdkXEvent *xevent,
257 GdkEvent *event,
258 gpointer data)
259 {
260 XEvent *xev;
261 XKeyEvent *key;
262 Display *display;
263 RBShellPlayer *player;
264 xev = (XEvent *) xevent;
265 if (xev->type != KeyPress) {
266 return GDK_FILTER_CONTINUE;
267 }
268
269 key = (XKeyEvent *) xevent;
270
271 player = (RBShellPlayer *)data;
272 display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
273
274 if (XKeysymToKeycode (display, XF86XK_AudioPlay) == key->keycode) {
275 rb_shell_player_playpause (player, FALSE, NULL);
276 return GDK_FILTER_REMOVE;
277 } else if (XKeysymToKeycode (display, XF86XK_AudioPause) == key->keycode) {
278 rb_shell_player_pause (player, NULL);
279 return GDK_FILTER_REMOVE;
280 } else if (XKeysymToKeycode (display, XF86XK_AudioStop) == key->keycode) {
281 rb_shell_player_stop (player);
282 return GDK_FILTER_REMOVE;
283 } else if (XKeysymToKeycode (display, XF86XK_AudioPrev) == key->keycode) {
284 rb_shell_player_do_previous (player, NULL);
285 return GDK_FILTER_REMOVE;
286 } else if (XKeysymToKeycode (display, XF86XK_AudioNext) == key->keycode) {
287 rb_shell_player_do_next (player, NULL);
288 return GDK_FILTER_REMOVE;
289 } else {
290 return GDK_FILTER_CONTINUE;
291 }
292 }
293
294 static void
295 mmkeys_grab (RBMMKeysPlugin *plugin, gboolean grab)
296 {
297 gint keycodes[] = {0, 0, 0, 0, 0};
298 GdkDisplay *display;
299 GdkScreen *screen;
300 GdkWindow *root;
301 guint i, j;
302
303 display = gdk_display_get_default ();
304 keycodes[0] = XKeysymToKeycode (GDK_DISPLAY_XDISPLAY (display), XF86XK_AudioPlay);
305 keycodes[1] = XKeysymToKeycode (GDK_DISPLAY_XDISPLAY (display), XF86XK_AudioStop);
306 keycodes[2] = XKeysymToKeycode (GDK_DISPLAY_XDISPLAY (display), XF86XK_AudioPrev);
307 keycodes[3] = XKeysymToKeycode (GDK_DISPLAY_XDISPLAY (display), XF86XK_AudioNext);
308 keycodes[4] = XKeysymToKeycode (GDK_DISPLAY_XDISPLAY (display), XF86XK_AudioPause);
309
310 for (i = 0; i < gdk_display_get_n_screens (display); i++) {
311 screen = gdk_display_get_screen (display, i);
312
313 if (screen != NULL) {
314 root = gdk_screen_get_root_window (screen);
315
316 for (j = 0; j < G_N_ELEMENTS (keycodes) ; j++) {
317 if (keycodes[j] != 0) {
318 if (grab)
319 grab_mmkey (keycodes[j], root);
320 else
321 ungrab_mmkey (keycodes[j], root);
322 }
323 }
324
325 if (grab)
326 gdk_window_add_filter (root, filter_mmkeys,
327 (gpointer) plugin->shell_player);
328 else
329 gdk_window_remove_filter (root, filter_mmkeys,
330 (gpointer) plugin->shell_player);
331 }
332 }
333 }
334
335 #endif
336
337 static void
338 first_call_complete (GObject *proxy, GAsyncResult *res, RBMMKeysPlugin *plugin)
339 {
340 GVariant *result;
341 GError *error = NULL;
342 GtkWindow *window;
343
344 result = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, &error);
345 if (error != NULL) {
346 g_warning ("Unable to grab media player keys: %s", error->message);
347 g_clear_error (&error);
348 #ifdef HAVE_MMKEYS
349 mmkeys_grab (plugin, TRUE);
350 plugin->grab_type = X_KEY_GRAB;
351 #endif
352 return;
353 }
354
355 rb_debug ("grabbed media player keys");
356
357 g_signal_connect_object (plugin->proxy, "g-signal", G_CALLBACK (media_player_key_pressed), plugin, 0);
358
359 /* re-grab keys when the main window gains focus */
360 g_object_get (plugin->shell, "window", &window, NULL);
361 g_signal_connect_object (window, "focus-in-event",
362 G_CALLBACK (window_focus_cb),
363 plugin, 0);
364 g_object_unref (window);
365
366 g_variant_unref (result);
367 }
368
369 static void
370 impl_activate (PeasActivatable *pplugin)
371 {
372 GDBusConnection *bus;
373 RBMMKeysPlugin *plugin;
374 GError *error = NULL;
375
376 rb_debug ("activating media player keys plugin");
377
378 plugin = RB_MMKEYS_PLUGIN (pplugin);
379 g_object_get (plugin, "object", &plugin->shell, NULL);
380 g_object_get (plugin->shell, "shell-player", &plugin->shell_player, NULL);
381
382 bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
383 if (plugin->grab_type == NONE && bus != NULL) {
384 GError *error = NULL;
385
386 plugin->proxy = g_dbus_proxy_new_sync (bus,
387 G_DBUS_PROXY_FLAGS_NONE,
388 NULL,
389 "org.gnome.SettingsDaemon",
390 "/org/gnome/SettingsDaemon/MediaKeys",
391 "org.gnome.SettingsDaemon.MediaKeys",
392 NULL,
393 &error);
394 if (error != NULL) {
395 g_warning ("Unable to grab media player keys: %s", error->message);
396 g_clear_error (&error);
397 } else {
398 g_dbus_proxy_call (plugin->proxy,
399 "GrabMediaPlayerKeys",
400 g_variant_new ("(su)", "Rhythmbox", 0),
401 G_DBUS_CALL_FLAGS_NONE,
402 -1,
403 NULL,
404 (GAsyncReadyCallback) first_call_complete,
405 plugin);
406 plugin->grab_type = SETTINGS_DAEMON;
407 }
408 } else {
409 g_warning ("couldn't get dbus session bus: %s", error->message);
410 g_clear_error (&error);
411 }
412
413 #ifdef HAVE_MMKEYS
414 if (plugin->grab_type == NONE) {
415 rb_debug ("attempting old-style key grabs");
416 mmkeys_grab (plugin, TRUE);
417 plugin->grab_type = X_KEY_GRAB;
418 }
419 #endif
420 }
421
422 static void
423 final_call_complete (GObject *proxy, GAsyncResult *res, gpointer nothing)
424 {
425 GError *error = NULL;
426 GVariant *result;
427
428 result = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, &error);
429 if (error != NULL) {
430 g_warning ("Unable to release media player keys: %s", error->message);
431 g_clear_error (&error);
432 } else {
433 g_variant_unref (result);
434 }
435 }
436
437 static void
438 impl_deactivate (PeasActivatable *pplugin)
439 {
440 RBMMKeysPlugin *plugin;
441
442 plugin = RB_MMKEYS_PLUGIN (pplugin);
443 if (plugin->shell_player != NULL) {
444 g_object_unref (plugin->shell_player);
445 plugin->shell_player = NULL;
446 }
447 if (plugin->shell != NULL) {
448 g_object_unref (plugin->shell);
449 plugin->shell = NULL;
450 }
451
452 if (plugin->proxy != NULL) {
453 if (plugin->grab_type == SETTINGS_DAEMON) {
454 g_dbus_proxy_call (plugin->proxy,
455 "ReleaseMediaPlayerKeys",
456 g_variant_new ("(s)", "Rhythmbox"),
457 G_DBUS_CALL_FLAGS_NONE,
458 -1,
459 NULL,
460 (GAsyncReadyCallback) final_call_complete,
461 NULL);
462 plugin->grab_type = NONE;
463 }
464
465 g_object_unref (plugin->proxy);
466 plugin->proxy = NULL;
467 }
468
469 #ifdef HAVE_MMKEYS
470 if (plugin->grab_type == X_KEY_GRAB) {
471 rb_debug ("undoing old-style key grabs");
472 mmkeys_grab (plugin, FALSE);
473 plugin->grab_type = NONE;
474 }
475 #endif
476 }
477
478 G_MODULE_EXPORT void
479 peas_register_types (PeasObjectModule *module)
480 {
481 rb_mmkeys_plugin_register_type (G_TYPE_MODULE (module));
482 peas_object_module_register_extension_type (module,
483 PEAS_TYPE_ACTIVATABLE,
484 RB_TYPE_MMKEYS_PLUGIN);
485 }