hythmbox-2.98/plugins/mmkeys/rb-mmkeys-plugin.c

No issues found

Incomplete coverage

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
Failure running clang-analyzer ('no-output-found')
Message
Unable to locate XML output from invoke-clang-analyzer
  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 }