1 /*************************************************************************/
2 /* Copyright (C) 2007 Jan Arne Petersen <jap@gnome.org>                  */
3 /* Copyright (C) 2012-2013 Pavel Vasin                                   */
4 /* This program is free software: you can redistribute it and/or modify  */
5 /* it under the terms of the GNU General Public License as published by  */
6 /* the Free Software Foundation, either version 3 of the License, or     */
7 /* (at your option) any later version.                                   */
8 /*                                                                       */
9 /* This program is distributed in the hope that it will be useful,       */
10 /* but WITHOUT ANY WARRANTY; without even the implied warranty of        */
11 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         */
12 /* GNU General Public License for more details.                          */
13 /*                                                                       */
14 /* You should have received a copy of the GNU General Public License     */
15 /* along with this program.  If not, see <http://www.gnu.org/licenses/>. */
16 /*************************************************************************/
17 
18 #ifdef HAVE_CONFIG_H
19 #include <config.h>
20 #endif
21 
22 #include <glib.h>
23 #include <glib-object.h>
24 #include <gmodule.h>
25 #include <gtk/gtk.h>
26 
27 #include <libpeas/peas.h>
28 #include <libpeas-gtk/peas-gtk.h>
29 
30 #include "pragha-gnome-media-keys-plugin.h"
31 
32 #include "src/pragha.h"
33 #include "src/pragha-playback.h"
34 
35 #define PLAYER_NAME "Pragha"
36 
37 #include "plugins/pragha-plugin-macros.h"
38 
PRAGHA_PLUGIN_REGISTER(PRAGHA_TYPE_GNOME_MEDIA_KEYS_PLUGIN,PraghaGnomeMediaKeysPlugin,pragha_gnome_media_keys_plugin)39 PRAGHA_PLUGIN_REGISTER (PRAGHA_TYPE_GNOME_MEDIA_KEYS_PLUGIN,
40                         PraghaGnomeMediaKeysPlugin,
41                         pragha_gnome_media_keys_plugin)
42 
43 static void
44 on_media_player_key_pressed (PraghaGnomeMediaKeysPlugin *plugin,
45                              const gchar                *key)
46 {
47 	PraghaBackend *backend;
48 	PraghaPreferences *preferences;
49 
50 	PraghaApplication *pragha = plugin->priv->pragha;
51 
52 	backend = pragha_application_get_backend (pragha);
53 	preferences = pragha_application_get_preferences (pragha);
54 
55 	if (pragha_backend_emitted_error (backend))
56 		return;
57 
58 	if (g_strcmp0("Play", key) == 0)
59 		pragha_playback_play_pause_resume(pragha);
60 	else if (g_strcmp0("Pause", key) == 0)
61 		pragha_backend_pause (backend);
62 	else if (g_strcmp0("Stop", key) == 0)
63 		pragha_playback_stop(pragha);
64 	else if (g_strcmp0("Previous", key) == 0)
65 		pragha_playback_prev_track(pragha);
66 	else if (g_strcmp0("Next", key) == 0)
67 		pragha_playback_next_track(pragha);
68 	else if (g_strcmp0("Repeat", key) == 0) {
69 		gboolean repeat = pragha_preferences_get_repeat (preferences);
70 		pragha_preferences_set_repeat (preferences, !repeat);
71 	}
72 	else if (g_strcmp0("Shuffle", key) == 0) {
73 		gboolean shuffle = pragha_preferences_get_shuffle (preferences);
74 		pragha_preferences_set_shuffle (preferences, !shuffle);
75 	}
76 
77 	//XXX missed buttons: "Rewind" and "FastForward"
78 }
79 
80 static void
grab_media_player_keys_cb(GDBusProxy * proxy,GAsyncResult * res,PraghaGnomeMediaKeysPlugin * plugin)81 grab_media_player_keys_cb (GDBusProxy                 *proxy,
82                            GAsyncResult               *res,
83                            PraghaGnomeMediaKeysPlugin *plugin)
84 {
85     GVariant *variant;
86     GError *error = NULL;
87 
88     variant = g_dbus_proxy_call_finish(proxy, res, &error);
89 
90     if (variant == NULL)
91     {
92         if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
93             g_warning("Failed to call \"GrabMediaPlayerKeys\": %s", error->message);
94         g_error_free(error);
95         return;
96     }
97 
98     g_variant_unref(variant);
99 }
100 
101 static void
grab_media_player_keys(PraghaGnomeMediaKeysPlugin * plugin)102 grab_media_player_keys (PraghaGnomeMediaKeysPlugin *plugin)
103 {
104 	if (plugin->priv->proxy == NULL)
105 		return;
106 
107 	g_dbus_proxy_call (plugin->priv->proxy,
108 	                   "GrabMediaPlayerKeys",
109 	                   g_variant_new("(su)", PLAYER_NAME, 0),
110 	                   G_DBUS_CALL_FLAGS_NONE,
111 	                   -1, NULL,
112 	                   (GAsyncReadyCallback) grab_media_player_keys_cb,
113 	                   plugin);
114 }
115 
116 static gboolean
on_window_focus_in_event(GtkWidget * window,GdkEventFocus * event,PraghaGnomeMediaKeysPlugin * plugin)117 on_window_focus_in_event (GtkWidget                  *window,
118                           GdkEventFocus              *event,
119                           PraghaGnomeMediaKeysPlugin *plugin)
120 {
121 	grab_media_player_keys (plugin);
122 
123 	return FALSE;
124 }
125 
126 static void
key_pressed(GDBusProxy * proxy,gchar * sender_name,gchar * signal_name,GVariant * parameters,PraghaGnomeMediaKeysPlugin * plugin)127 key_pressed (GDBusProxy                 *proxy,
128              gchar                      *sender_name,
129              gchar                      *signal_name,
130              GVariant                   *parameters,
131              PraghaGnomeMediaKeysPlugin *plugin)
132 {
133 	char *app, *cmd;
134 
135 	if (g_strcmp0(signal_name, "MediaPlayerKeyPressed") != 0)
136 		return;
137 
138 	g_variant_get(parameters, "(ss)", &app, &cmd);
139 
140 	if (g_strcmp0(app, PLAYER_NAME) == 0)
141 		on_media_player_key_pressed (plugin, cmd);
142 
143 	g_free(app);
144 	g_free(cmd);
145 }
146 
147 static void
got_proxy_cb(GObject * source_object,GAsyncResult * res,PraghaGnomeMediaKeysPlugin * plugin)148 got_proxy_cb (GObject                    *source_object,
149               GAsyncResult               *res,
150               PraghaGnomeMediaKeysPlugin *plugin)
151 {
152 	GError *error = NULL;
153 
154 	plugin->priv->proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
155 
156 	if (plugin->priv->proxy == NULL) {
157 		if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
158 			g_warning("Failed to contact settings daemon: %s", error->message);
159 		g_error_free(error);
160 		return;
161 	}
162 
163 	grab_media_player_keys (plugin);
164 
165 	g_signal_connect (G_OBJECT(plugin->priv->proxy), "g-signal",
166 	                  G_CALLBACK(key_pressed), plugin);
167 }
168 
169 static void
name_appeared_cb(GDBusConnection * connection,const gchar * name,const gchar * name_owner,PraghaGnomeMediaKeysPlugin * plugin)170 name_appeared_cb (GDBusConnection            *connection,
171                   const gchar                *name,
172                   const gchar                *name_owner,
173                   PraghaGnomeMediaKeysPlugin *plugin)
174 {
175 	g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
176 	                          G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
177 	                          G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
178 	                          NULL,
179 	                          "org.gnome.SettingsDaemon",
180 	                          "/org/gnome/SettingsDaemon/MediaKeys",
181 	                          "org.gnome.SettingsDaemon.MediaKeys",
182 	                          NULL,
183 	                          (GAsyncReadyCallback) got_proxy_cb,
184 	                          plugin);
185 }
186 
187 static void
name_vanished_cb(GDBusConnection * connection,const gchar * name,PraghaGnomeMediaKeysPlugin * plugin)188 name_vanished_cb (GDBusConnection            *connection,
189                   const gchar                *name,
190                   PraghaGnomeMediaKeysPlugin *plugin)
191 {
192 	if (plugin->priv->proxy != NULL) {
193 		g_object_unref(plugin->priv->proxy);
194 		plugin->priv->proxy = NULL;
195 	}
196 }
197 
198 static void
pragha_plugin_activate(PeasActivatable * activatable)199 pragha_plugin_activate (PeasActivatable *activatable)
200 {
201 	GtkWidget *window;
202 	PraghaGnomeMediaKeysPlugin *plugin = PRAGHA_GNOME_MEDIA_KEYS_PLUGIN (activatable);
203 
204 	CDEBUG(DBG_PLUGIN, "Gnome-Media-Keys plugin %s", G_STRFUNC);
205 
206 	PraghaGnomeMediaKeysPluginPrivate *priv = plugin->priv;
207 	priv->pragha = g_object_get_data (G_OBJECT (plugin), "object");
208 
209 	plugin->priv->watch_id =
210 		g_bus_watch_name (G_BUS_TYPE_SESSION,
211 		                  "org.gnome.SettingsDaemon",
212 		                  G_BUS_NAME_WATCHER_FLAGS_NONE,
213 		                  (GBusNameAppearedCallback) name_appeared_cb,
214 		                  (GBusNameVanishedCallback) name_vanished_cb,
215 		                  plugin,
216 		                  NULL);
217 
218 	window = pragha_application_get_window (plugin->priv->pragha);
219 
220 	plugin->priv->handler_id =
221 		g_signal_connect (G_OBJECT(window), "focus-in-event",
222 		                  G_CALLBACK(on_window_focus_in_event), plugin);
223 }
224 
225 static void
pragha_plugin_deactivate(PeasActivatable * activatable)226 pragha_plugin_deactivate (PeasActivatable *activatable)
227 {
228 	GtkWidget *window;
229 	PraghaGnomeMediaKeysPlugin *plugin = PRAGHA_GNOME_MEDIA_KEYS_PLUGIN (activatable);
230 
231 	CDEBUG(DBG_PLUGIN, "Gnome-Media-Keys plugin %s", G_STRFUNC);
232 
233 	g_bus_unwatch_name (plugin->priv->watch_id);
234 
235 	window = pragha_application_get_window (plugin->priv->pragha);
236 
237 	if (plugin->priv->handler_id != 0)
238 		g_signal_handler_disconnect (G_OBJECT(window), plugin->priv->handler_id);
239 
240 	if (plugin->priv->proxy != NULL)
241 		g_object_unref(plugin->priv->proxy);
242 }
243