1 /*************************************************************************/ 2 /* Copyright (C) 2007-2009 sujith <m.sujith@gmail.com> */ 3 /* Copyright (C) 2009-2014 matias <mati86dl@gmail.com> */ 4 /* */ 5 /* This program is free software: you can redistribute it and/or modify */ 6 /* it under the terms of the GNU General Public License as published by */ 7 /* the Free Software Foundation, either version 3 of the License, or */ 8 /* (at your option) any later version. */ 9 /* */ 10 /* This program is distributed in the hope that it will be useful, */ 11 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ 12 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ 13 /* GNU General Public License for more details. */ 14 /* */ 15 /* You should have received a copy of the GNU General Public License */ 16 /* along with this program. If not, see <http://www.gnu.org/licenses/>. */ 17 /*************************************************************************/ getFrameIndexReference(const MachineFunction & MF,int FI,Register & FrameReg) const18 19 #ifdef HAVE_CONFIG_H 20 #include <config.h> 21 #endif 22 23 #if defined(GETTEXT_PACKAGE) 24 #include <glib/gi18n-lib.h> 25 #else 26 #include <glib/gi18n.h> 27 #endif 28 29 #include <glib.h> 30 #include <glib-object.h> 31 #include <gmodule.h> 32 #include <gtk/gtk.h> 33 34 #include <libpeas/peas.h> 35 #include <libpeas-gtk/peas-gtk.h> 36 37 #include <libnotify/notify.h> 38 39 #include "plugins/pragha-plugin-macros.h" 40 41 #include "src/pragha.h" 42 #include "src/pragha-hig.h" 43 #include "src/pragha-playback.h" 44 #include "src/pragha-utils.h" 45 #include "src/pragha-preferences-dialog.h" 46 47 #define PRAGHA_TYPE_NOTIFY_PLUGIN (pragha_notify_plugin_get_type ()) 48 #define PRAGHA_NOTIFY_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), PRAGHA_TYPE_NOTIFY_PLUGIN, PraghaNotifyPlugin)) 49 #define PRAGHA_NOTIFY_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), PRAGHA_TYPE_NOTIFY_PLUGIN, PraghaNotifyPlugin)) 50 #define PRAGHA_IS_NOTIFY_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), PRAGHA_TYPE_NOTIFY_PLUGIN)) 51 #define PRAGHA_IS_NOTIFY_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), PRAGHA_TYPE_NOTIFY_PLUGIN)) 52 #define PRAGHA_NOTIFY_PLUGIN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), PRAGHA_TYPE_NOTIFY_PLUGIN, PraghaNotifyPluginClass)) 53 54 typedef struct { 55 PraghaApplication *pragha; 56 GtkWidget *setting_widget; 57 58 NotifyNotification *notify; 59 60 GtkWidget *album_art_in_osd_w; 61 GtkWidget *actions_in_osd_w; 62 gboolean album_art_in_osd; 63 gboolean actions_in_osd; 64 } PraghaNotifyPluginPrivate; 65 66 PRAGHA_PLUGIN_REGISTER (PRAGHA_TYPE_NOTIFY_PLUGIN, 67 PraghaNotifyPlugin, 68 pragha_notify_plugin) 69 70 static gboolean 71 can_support_actions (void) 72 { 73 static gboolean supported; 74 static gboolean have_checked = FALSE; 75 76 if( !have_checked ){ 77 GList * c; 78 GList * caps = notify_get_server_caps( ); 79 80 have_checked = TRUE; 81 82 for( c=caps; c && !supported; c=c->next ) 83 supported = !strcmp( "actions", (char*)c->data ); 84 85 g_list_free_full( caps, g_free ); 86 } 87 88 return supported; 89 } 90 91 static void 92 notify_closed_cb (NotifyNotification *osd, 93 PraghaNotifyPlugin *plugin) 94 { 95 g_object_unref (G_OBJECT(osd)); 96 97 if (plugin->priv->notify == osd) { 98 plugin->priv->notify = NULL; 99 } 100 } 101 102 static void 103 notify_Prev_Callback (NotifyNotification *osd, 104 const char *action, 105 PraghaNotifyPlugin *plugin) 106 { 107 PraghaBackend *backend; 108 109 g_assert (action != NULL); 110 111 PraghaApplication *pragha = plugin->priv->pragha; 112 113 backend = pragha_application_get_backend (pragha); 114 if (pragha_backend_emitted_error (backend) == FALSE) 115 pragha_playback_prev_track(pragha); 116 } 117 118 static void 119 notify_Next_Callback (NotifyNotification *osd, 120 const char *action, 121 PraghaNotifyPlugin *plugin) 122 { 123 PraghaBackend *backend; 124 125 g_assert (action != NULL); 126 127 PraghaApplication *pragha = plugin->priv->pragha; 128 129 backend = pragha_application_get_backend (pragha); 130 if (pragha_backend_emitted_error (backend) == FALSE) 131 pragha_playback_next_track(pragha); 132 } 133 134 void 135 pragha_notify_plugin_show_new_track (PraghaPlaylist *playlist, 136 PraghaMusicobject *mobj, 137 PraghaNotifyPlugin *plugin) 138 { 139 PraghaNotifyPluginPrivate *priv = NULL; 140 PraghaToolbar *toolbar; 141 gchar *summary, *body, *slength; 142 GError *error = NULL; 143 144 priv = plugin->priv; 145 146 if (NULL == mobj) 147 return; 148 149 if (gtk_window_is_active(GTK_WINDOW (pragha_application_get_window(priv->pragha)))) 150 return; 151 152 const gchar *file = pragha_musicobject_get_file (mobj); 153 const gchar *title = pragha_musicobject_get_title (mobj); 154 const gchar *artist = pragha_musicobject_get_artist (mobj); 155 const gchar *album = pragha_musicobject_get_album (mobj); 156 gint length = pragha_musicobject_get_length (mobj); 157 158 if(string_is_not_empty(title)) 159 summary = g_strdup(title); 160 else 161 summary = g_path_get_basename(file); 162 163 slength = convert_length_str(length); 164 165 body = g_markup_printf_escaped(_("by <b>%s</b> in <b>%s</b> <b>(%s)</b>"), 166 string_is_not_empty(artist) ? artist : _("Unknown Artist"), 167 string_is_not_empty(album) ? album : _("Unknown Album"), 168 slength); 169 170 /* Create notification instance */ 171 172 if (priv->notify == NULL) { 173 priv->notify = notify_notification_new(summary, body, NULL); 174 175 if (can_support_actions() && priv->actions_in_osd) { 176 notify_notification_add_action( 177 priv->notify, "media-skip-backward", _("Previous track"), 178 NOTIFY_ACTION_CALLBACK(notify_Prev_Callback), plugin, 179 NULL); 180 notify_notification_add_action( 181 priv->notify, "media-skip-forward", _("Next track"), 182 NOTIFY_ACTION_CALLBACK(notify_Next_Callback), plugin, 183 NULL); 184 } 185 notify_notification_set_hint (priv->notify, "transient", g_variant_new_boolean (TRUE)); 186 g_signal_connect (priv->notify, "closed", G_CALLBACK (notify_closed_cb), plugin); 187 } 188 else { 189 notify_notification_update (priv->notify, summary, body, NULL); 190 191 if (!priv->actions_in_osd) 192 notify_notification_clear_actions (priv->notify); 193 } 194 195 /* Add album art if set */ 196 if (priv->album_art_in_osd) { 197 toolbar = pragha_application_get_toolbar (priv->pragha); 198 notify_notification_set_image_from_pixbuf (priv->notify, 199 pragha_album_art_get_pixbuf (pragha_toolbar_get_album_art(toolbar))); 200 } 201 202 /* Show OSD */ 203 if (!notify_notification_show (priv->notify, &error)) { 204 g_warning("Unable to show OSD notification: %s", error->message); 205 g_error_free (error); 206 } 207 208 /* Cleanup */ 209 210 g_free(summary); 211 g_free(body); 212 g_free(slength); 213 } 214 215 static void 216 pragha_notify_preferences_dialog_response (GtkDialog *dialog, 217 gint response_id, 218 PraghaNotifyPlugin *plugin) 219 { 220 PraghaPreferences *preferences; 221 gchar *plugin_group = NULL; 222 223 PraghaNotifyPluginPrivate *priv = plugin->priv; 224 225 switch(response_id) { 226 case GTK_RESPONSE_CANCEL: 227 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(priv->album_art_in_osd_w), 228 priv->album_art_in_osd); 229 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(priv->actions_in_osd_w), 230 priv->actions_in_osd); 231 break; 232 case GTK_RESPONSE_OK: 233 priv->album_art_in_osd = 234 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(priv->album_art_in_osd_w)); 235 priv->actions_in_osd = 236 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(priv->actions_in_osd_w)); 237 238 preferences = pragha_preferences_get (); 239 plugin_group = pragha_preferences_get_plugin_group_name(preferences, "notify"); 240 241 pragha_preferences_set_boolean (preferences, 242 plugin_group, "album_art_in_osd", 243 priv->album_art_in_osd); 244 pragha_preferences_set_boolean (preferences, 245 plugin_group, "actions_in_osd", 246 priv->actions_in_osd); 247 248 g_object_unref (preferences); 249 g_free (plugin_group); 250 break; 251 default: 252 break; 253 } 254 } 255 256 static void 257 pragha_notify_plugin_append_setting (PraghaNotifyPlugin *plugin) 258 { 259 PreferencesDialog *dialog; 260 GtkWidget *table, *albumart_in_osd, *actions_in_osd; 261 guint row = 0; 262 263 PraghaNotifyPluginPrivate *priv = plugin->priv; 264 265 table = pragha_hig_workarea_table_new (); 266 267 pragha_hig_workarea_table_add_section_title(table, &row, _("Notifications")); 268 269 albumart_in_osd = gtk_check_button_new_with_label(_("Show Album art in notifications")); 270 pragha_hig_workarea_table_add_wide_control(table, &row, albumart_in_osd); 271 272 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(albumart_in_osd), priv->album_art_in_osd); 273 274 actions_in_osd = gtk_check_button_new_with_label(_("Add actions to change track in notifications")); 275 pragha_hig_workarea_table_add_wide_control(table, &row, actions_in_osd); 276 277 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(actions_in_osd), priv->actions_in_osd); 278 279 if (!can_support_actions()) 280 gtk_widget_set_sensitive (actions_in_osd, FALSE); 281 282 priv->setting_widget = table; 283 priv->album_art_in_osd_w = albumart_in_osd; 284 priv->actions_in_osd_w = actions_in_osd; 285 286 dialog = pragha_application_get_preferences_dialog (priv->pragha); 287 pragha_preferences_append_desktop_setting (dialog, table, FALSE); 288 289 /* Configure handler and settings */ 290 pragha_preferences_dialog_connect_handler (dialog, 291 G_CALLBACK(pragha_notify_preferences_dialog_response), 292 plugin); 293 } 294 295 static void 296 pragha_notify_plugin_remove_setting (PraghaNotifyPlugin *plugin) 297 { 298 PreferencesDialog *dialog; 299 PraghaNotifyPluginPrivate *priv = plugin->priv; 300 301 dialog = pragha_application_get_preferences_dialog (priv->pragha); 302 303 pragha_preferences_dialog_disconnect_handler (dialog, 304 G_CALLBACK(pragha_notify_preferences_dialog_response), 305 plugin); 306 pragha_preferences_remove_desktop_setting (dialog, priv->setting_widget); 307 } 308 309 static void 310 pragha_plugin_activate (PeasActivatable *activatable) 311 { 312 PraghaPreferences *preferences; 313 PraghaPlaylist *playlist; 314 gchar *plugin_group = NULL; 315 316 PraghaNotifyPlugin *plugin = PRAGHA_NOTIFY_PLUGIN (activatable); 317 PraghaNotifyPluginPrivate *priv = plugin->priv; 318 319 CDEBUG(DBG_PLUGIN, "Notify plugin %s", G_STRFUNC); 320 321 priv->pragha = g_object_get_data (G_OBJECT (plugin), "object"); 322 323 notify_init (PACKAGE_NAME); 324 325 preferences = pragha_application_get_preferences (priv->pragha); 326 plugin_group = pragha_preferences_get_plugin_group_name (preferences, "notify"); 327 if (pragha_preferences_has_group (preferences, plugin_group)) { 328 priv->actions_in_osd = 329 pragha_preferences_get_boolean (preferences, 330 plugin_group, 331 "actions_in_osd"); 332 priv->album_art_in_osd = 333 pragha_preferences_get_boolean (preferences, 334 plugin_group, 335 "album_art_in_osd"); 336 } 337 else { 338 priv->actions_in_osd = TRUE; 339 priv->album_art_in_osd = TRUE; 340 } 341 342 /* Fix for nofify-osd users */ 343 if (!can_support_actions()) 344 priv->actions_in_osd = FALSE; 345 346 playlist = pragha_application_get_playlist (priv->pragha); 347 g_signal_connect (playlist, "playlist-set-track", 348 G_CALLBACK(pragha_notify_plugin_show_new_track), plugin); 349 350 pragha_notify_plugin_append_setting (plugin); 351 352 g_free (plugin_group); 353 } 354 355 static void 356 pragha_plugin_deactivate (PeasActivatable *activatable) 357 { 358 PraghaPlaylist *playlist; 359 360 PraghaNotifyPlugin *plugin = PRAGHA_NOTIFY_PLUGIN (activatable); 361 PraghaNotifyPluginPrivate *priv = plugin->priv; 362 363 CDEBUG(DBG_PLUGIN, "Notify plugin %s", G_STRFUNC); 364 365 notify_uninit (); 366 367 playlist = pragha_application_get_playlist (priv->pragha); 368 g_signal_handlers_disconnect_by_func (playlist, 369 pragha_notify_plugin_show_new_track, 370 plugin); 371 372 pragha_notify_plugin_remove_setting (plugin); 373 374 priv->pragha= NULL; 375 } 376