/* * vgl-sb-plugin.c -- Status bar plugin for Vagalume * Copyright (C) 2008 Mario Sanchez Prada <msanchez@igalia.com> * * This file is part of Vagalume and is published under the GNU GPLv3 * See the README file for more details. */ #include <glib/gi18n.h> #include <string.h> #include <gtk/gtk.h> #include <dbus/dbus.h> #include <libosso.h> #include <hildon/hildon-banner.h> #include <libhildonwm/hd-wm.h> #include <libhildonwm/hd-wm-application.h> #include <libhildondesktop/statusbar-item.h> #include <libhildondesktop/libhildondesktop.h> #include "vgl-sb-plugin.h" #include "globaldefs.h" #include "dbus.h" /* This is run by hildon-desktop, so we need to redefine the _(String) macro to use the Vagalume domain */ #undef _ #define _(String) dgettext (GETTEXT_PACKAGE, String) #define MAIN_PANEL_WIDTH 300 #define NO_ARTIST_STRING _("No artist") #define NO_TRACK_STRING _("No track") #define NO_ALBUM_STRING _("No album") #define PLAY_ITEM_STRING _("Play") #define STOP_ITEM_STRING _("Stop") #define SKIP_ITEM_STRING _("Skip") #define LOVE_ITEM_STRING _("Love") #define BAN_ITEM_STRING _("Ban") #define SHOW_APP_ITEM_STRING _("Show main window") #define CLOSE_APP_ITEM_STRING _("Close Vagalume") #define VGL_SB_PLUGIN_GET_PRIVATE(object) \ (G_TYPE_INSTANCE_GET_PRIVATE ((object), \ VGL_SB_PLUGIN_TYPE, VglSbPluginPrivate)) typedef struct _VglSbPluginPrivate VglSbPluginPrivate; struct _VglSbPluginPrivate { osso_context_t *osso_context; DBusConnection *dbus_connection; gboolean dbus_filter_added; gboolean is_visible; gboolean now_playing; gboolean running_app; gchar *artist_string; gchar *track_string; gchar *album_string; GtkWidget *button; GtkWidget *icon; GtkWidget *main_panel; GtkWidget *artist_item; GtkWidget *track_item; GtkWidget *album_item; GtkWidget *play_item; GtkWidget *stop_item; GtkWidget *next_item; GtkWidget *love_item; GtkWidget *ban_item; GtkWidget *open_vagalume_item; GtkWidget *close_vagalume_item; gint plugin_btn_handler_id; gint main_panel_handler_id; gint play_item_handler_id; gint stop_item_handler_id; gint next_item_handler_id; gint love_item_handler_id; gint ban_item_handler_id; gint open_vagalume_item_handler_id; gint close_vagalume_item_handler_id; gboolean dispose_has_run; }; HD_DEFINE_PLUGIN (VglSbPlugin, vgl_sb_plugin, STATUSBAR_TYPE_ITEM); /* Initialization/destruction functions */ static void vgl_sb_plugin_class_init (VglSbPluginClass *klass); static void vgl_sb_plugin_init (VglSbPlugin *vsbp); static void vgl_sb_plugin_dispose (GObject *object); /* Dbus stuff */ static gboolean dbus_init (VglSbPlugin *vsbp); static void dbus_cleanup (VglSbPlugin *vsbp); static DBusHandlerResult dbus_req_handler (DBusConnection *connection, DBusMessage *message, gpointer data); static void dbus_send_request (VglSbPlugin *vsbp, const gchar *request); static void dbus_send_request_with_params (VglSbPlugin *vsbp, const char *request, int first_type, ...); static void notify_handler (VglSbPlugin *vsbp, DBusMessage *message); /* Setters */ static void set_visibility (VglSbPlugin *vsbp, gboolean visible); static void set_track_info (VglSbPlugin *vsbp, const gchar *artist, const gchar *track, const gchar *album); /* Panel update functions */ static void main_panel_create (VglSbPlugin *vsbp); static void main_panel_update (VglSbPlugin *vsbp); /* Signals handlers */ static void plugin_btn_toggled (GtkWidget *button, gpointer data); static void main_panel_item_activated (GtkWidget *item, gpointer data); static void main_panel_hidden (GtkWidget *main_panel, gpointer user_data); /* Utility functions */ static gboolean vagalume_running (VglSbPlugin *vsbp); /* Initialization/destruction functions */ static void vgl_sb_plugin_class_init (VglSbPluginClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->dispose = vgl_sb_plugin_dispose; g_type_class_add_private (object_class, sizeof (VglSbPluginPrivate)); bindtextdomain (GETTEXT_PACKAGE, VAGALUME_LOCALE_DIR); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); } static void vgl_sb_plugin_init (VglSbPlugin *vsbp) { VglSbPluginPrivate *priv = VGL_SB_PLUGIN_GET_PRIVATE (vsbp); GdkPixbuf *icon_pixbuf; /* Init private attributes to their default values */ priv->osso_context = NULL; priv->dbus_connection = NULL; priv->dbus_filter_added = FALSE; priv->is_visible = FALSE; priv->now_playing = FALSE; priv->running_app = FALSE; priv->artist_string = NULL; priv->track_string = NULL; priv->album_string = NULL; priv->button = NULL; priv->icon = NULL; priv->main_panel = NULL; priv->artist_item = NULL; priv->track_item = NULL; priv->album_item = NULL; priv->play_item = NULL; priv->stop_item = NULL; priv->next_item = NULL; priv->love_item = NULL; priv->ban_item = NULL; priv->open_vagalume_item = NULL; priv->close_vagalume_item = NULL; priv->dispose_has_run = FALSE; /* Setup libosso */ priv->osso_context = osso_initialize ("vgl_sb_plugin", APP_VERSION, TRUE, NULL); if (!priv->osso_context) { g_debug ("Unable to initialize OSSO context"); return; } /* Setup dbus */ if (!dbus_init (vsbp)) { g_debug ("Unable to initialize D-Bus system"); return; } /* Create status bar plugin button */ icon_pixbuf = gdk_pixbuf_new_from_file (APP_ICON, NULL); priv->button = gtk_toggle_button_new (); priv->icon = gtk_image_new_from_pixbuf (icon_pixbuf); gtk_container_add (GTK_CONTAINER (priv->button), priv->icon); gtk_container_add (GTK_CONTAINER (vsbp), priv->button); /* Connect signals */ priv->plugin_btn_handler_id = g_signal_connect (priv->button, "toggled", G_CALLBACK(plugin_btn_toggled), vsbp); /* Show widgets */ gtk_widget_show_all (priv->button); /* Create main panel */ main_panel_create (vsbp); /* Check if vagalume is running */ if (vagalume_running (vsbp)) { priv->is_visible = TRUE; dbus_send_request (vsbp, APP_DBUS_METHOD_REQUEST_STATUS); } /* Update visibililty */ set_visibility (vsbp, priv->is_visible); } static void vgl_sb_plugin_dispose (GObject *object) { VglSbPlugin *vsbp = VGL_SB_PLUGIN (object); VglSbPluginPrivate *priv = VGL_SB_PLUGIN_GET_PRIVATE (vsbp); /* Ensure dispose is called only once */ if (priv->dispose_has_run) { return; } priv->dispose_has_run = TRUE; /* Dbus cleanup */ dbus_cleanup (vsbp); /* Libosso cleanup */ osso_deinitialize (priv->osso_context); /* Disconnect handlers */ g_signal_handler_disconnect (priv->button, priv->plugin_btn_handler_id); g_signal_handler_disconnect (priv->main_panel, priv->main_panel_handler_id); g_signal_handler_disconnect (priv->play_item, priv->play_item_handler_id); g_signal_handler_disconnect (priv->stop_item, priv->stop_item_handler_id); g_signal_handler_disconnect (priv->next_item, priv->next_item_handler_id); g_signal_handler_disconnect (priv->love_item, priv->love_item_handler_id); g_signal_handler_disconnect (priv->ban_item, priv->ban_item_handler_id); g_signal_handler_disconnect (priv->open_vagalume_item, priv->open_vagalume_item_handler_id); g_signal_handler_disconnect (priv->close_vagalume_item, priv->close_vagalume_item_handler_id); /* Destroy local widgets */ if (priv->main_panel) { gtk_widget_destroy (priv->main_panel); } /* Free private strings */ if (priv->artist_string != NULL) { g_free (priv->artist_string); } if (priv->track_string != NULL) { g_free (priv->track_string); } if (priv->album_string != NULL) { g_free (priv->album_string); } G_OBJECT_CLASS (g_type_class_peek_parent (G_OBJECT_GET_CLASS(object)))->dispose(object); } /* Dbus stuff */ static gboolean dbus_init(VglSbPlugin *vsbp) { VglSbPluginPrivate *priv = VGL_SB_PLUGIN_GET_PRIVATE (vsbp); /* Get the D-Bus connection to the session bus */ priv->dbus_connection = dbus_bus_get (DBUS_BUS_SESSION, NULL); if (!priv->dbus_connection) { g_debug ("Unable to get DBUS connection"); return FALSE; } /* Integrate D-Bus with GMainLoop */ dbus_connection_setup_with_g_main (priv->dbus_connection, NULL); /* Match only signals emitted from Vagalume */ dbus_bus_add_match (priv->dbus_connection, "type='signal',interface='" APP_DBUS_IFACE "'", NULL); dbus_connection_flush (priv->dbus_connection); /* Add a handler for incoming messages */ if (!dbus_connection_add_filter (priv->dbus_connection, dbus_req_handler, vsbp, NULL)) { g_debug ("Unable to add D-Bus filter"); return FALSE; } priv->dbus_filter_added = TRUE; return TRUE; } static void dbus_cleanup (VglSbPlugin *vsbp) { VglSbPluginPrivate *priv = VGL_SB_PLUGIN_GET_PRIVATE (vsbp); /* Remove filter and matching rules */ if (priv->dbus_filter_added) { dbus_connection_remove_filter (priv->dbus_connection, dbus_req_handler, vsbp); dbus_bus_remove_match (priv->dbus_connection, "type='signal',interface='" APP_DBUS_IFACE "'", NULL); } /* Unref the D-bus connection */ if (priv->dbus_connection) { dbus_connection_unref (priv->dbus_connection); } } static DBusHandlerResult dbus_req_handler (DBusConnection *connection, DBusMessage *message, gpointer data) { VglSbPlugin *vsbp = VGL_SB_PLUGIN (data); if (dbus_message_is_signal (message, APP_DBUS_IFACE, APP_DBUS_SIGNAL_NOTIFY)) { /* Received a playback notification signal */ notify_handler (vsbp, message); return DBUS_HANDLER_RESULT_HANDLED; } return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } static void dbus_send_request (VglSbPlugin *vsbp, const gchar *request) { /* Delegate on dbus_send_request_with_params() */ dbus_send_request_with_params (vsbp, request, DBUS_TYPE_INVALID); } static void dbus_send_request_with_params (VglSbPlugin *vsbp, const char *request, int first_type, ...) { VglSbPluginPrivate *priv = VGL_SB_PLUGIN_GET_PRIVATE (vsbp); DBusMessage *dbus_msg = NULL; va_list ap; dbus_msg = dbus_message_new_method_call (APP_DBUS_SERVICE, APP_DBUS_OBJECT, APP_DBUS_IFACE, request); if (first_type != DBUS_TYPE_INVALID) { va_start (ap, first_type); dbus_message_append_args_valist (dbus_msg, first_type, ap); va_end (ap); } dbus_connection_send (priv->dbus_connection, dbus_msg, 0); dbus_connection_flush (priv->dbus_connection); dbus_message_unref (dbus_msg); } static void notify_handler (VglSbPlugin *vsbp, DBusMessage *message) { VglSbPluginPrivate *priv = VGL_SB_PLUGIN_GET_PRIVATE (vsbp); DBusMessageIter iter; gchar *type = NULL; gboolean msg_handled = FALSE; /* Ensure you have appropiate arguments */ if (!dbus_message_iter_init (message, &iter)) { g_debug ("Message has no parameters"); g_return_if_reached (); } /* Check notification type */ if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING) { g_debug ("First parameter is not a string"); g_return_if_reached (); } dbus_message_iter_get_basic (&iter, &type); /* Let's assume that an application is running if a message was received from Vagalume */ priv->running_app = TRUE; if (!strcmp (type, APP_DBUS_SIGNAL_NOTIFY_PLAYING)) { /* Retrieve arguments */ gchar *artist = NULL; gchar *track = NULL; gchar *album = NULL; g_debug ("NOTIFY PLAYING RECEIVED"); /* Artist */ if (dbus_message_iter_next (&iter) && dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_STRING) { dbus_message_iter_get_basic (&iter, &artist); } /* Track title */ if (dbus_message_iter_next (&iter) && dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_STRING) { dbus_message_iter_get_basic (&iter, &track); } /* Album */ if (dbus_message_iter_next (&iter) && dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_STRING) { dbus_message_iter_get_basic (&iter, &album); } /* Update private attributes */ set_track_info (vsbp, artist, track, album); priv->now_playing = TRUE; msg_handled = TRUE; } else if (!strcmp (type, APP_DBUS_SIGNAL_NOTIFY_STOPPED)) { g_debug ("NOTIFY STOPPED RECEIVED"); /* Update private attributes */ set_track_info (vsbp, NULL, NULL, NULL); priv->now_playing = FALSE; msg_handled = TRUE; } else if (!strcmp (type, APP_DBUS_SIGNAL_NOTIFY_STARTED)) { g_debug ("NOTIFY STARTED RECEIVED"); /* Set the plugin invisible */ set_visibility (vsbp, TRUE); dbus_send_request (vsbp, APP_DBUS_METHOD_REQUEST_STATUS); msg_handled = TRUE; } else if (!strcmp (type, APP_DBUS_SIGNAL_NOTIFY_CLOSING)) { g_debug ("NOTIFY CLOSING RECEIVED"); /* Update private attributes */ priv->running_app = FALSE; priv->now_playing = FALSE; /* Set the plugin invisible */ set_visibility (vsbp, FALSE); msg_handled = TRUE; } else { /* Wrong notification */ g_debug ("Wrong notification received: %s", type); msg_handled = FALSE; } /* If the message was handled update the panel */ if (msg_handled) { main_panel_update (vsbp); } } /* Setters */ static void set_visibility (VglSbPlugin *vsbp, gboolean visible) { VglSbPluginPrivate *priv = VGL_SB_PLUGIN_GET_PRIVATE (vsbp); gboolean old_condition; g_object_get (vsbp, "condition", &old_condition, NULL); if (old_condition != visible) g_object_set (vsbp, "condition", visible, NULL); priv->is_visible = visible; g_debug ("Setting visibility to '%s'", (visible ? "visible" : "hidden")); } static void set_field (gchar **field, const gchar *text, const gchar *markup_fmt) { g_return_if_fail (text != NULL); gchar *final_text = NULL; gchar *final_markup_fmt = NULL; if (*field != NULL) { g_free (*field); *field = NULL; } final_text = g_strstrip (g_strdup (text)); if (markup_fmt != NULL) { final_markup_fmt = g_strdup (markup_fmt); } else { final_markup_fmt = g_strdup ("<span>%s</span>"); } *field = g_markup_printf_escaped (final_markup_fmt, final_text); g_free (final_markup_fmt); g_free (final_text); g_debug ("Setting field to '%s'", *field); } static void set_track_info (VglSbPlugin *vsbp, const gchar *artist, const gchar *track, const gchar *album) { g_return_if_fail(VGL_IS_SB_PLUGIN(vsbp)); VglSbPluginPrivate *priv = VGL_SB_PLUGIN_GET_PRIVATE (vsbp); /* Call to set_field (), always with valid data */ set_field (&priv->artist_string, (artist?artist:NO_ARTIST_STRING), "<b>%s</b>"); set_field (&priv->track_string, (track?track:NO_TRACK_STRING), "<i>%s</i>"); if ((album != NULL) && g_str_equal (album, "")) { /* Set album string to NULL if not available yet */ if (priv->album_string != NULL) { g_free (priv->album_string); } priv->album_string = NULL; } else { set_field (&priv->album_string, (album?album:NO_ALBUM_STRING), NULL); } } /* Panel update functions */ static PangoFontDescription * get_small_font (GtkWidget *widget) { static PangoFontDescription *new_font = NULL; if (new_font == NULL) { new_font = pango_font_description_from_string ("Nokia Sans 13.625"); } return new_font; } static void main_panel_create (VglSbPlugin *vsbp) { VglSbPluginPrivate *priv = VGL_SB_PLUGIN_GET_PRIVATE (vsbp); GtkWidget *label; /* Create main_panel and main_panel items */ priv->main_panel = gtk_menu_new (); gtk_widget_set_size_request (priv->main_panel, MAIN_PANEL_WIDTH, -1); /* Insensitive items */ priv->artist_item = gtk_menu_item_new (); label = gtk_label_new (NULL); gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_END); gtk_widget_modify_font (label, get_small_font (label)); gtk_misc_set_alignment (GTK_MISC(label), 0.0, 0.5); gtk_container_add (GTK_CONTAINER (priv->artist_item), label); gtk_widget_set_sensitive (priv->artist_item, FALSE); label->state = GTK_STATE_NORMAL; priv->track_item = gtk_menu_item_new (); label = gtk_label_new (NULL); gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_END); gtk_widget_modify_font (label, get_small_font (label)); gtk_misc_set_alignment (GTK_MISC(label), 0.0, 0.5); gtk_container_add (GTK_CONTAINER (priv->track_item), label); gtk_widget_set_sensitive (priv->track_item, FALSE); label->state = GTK_STATE_NORMAL; priv->album_item = gtk_menu_item_new (); label = gtk_label_new (NULL); gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_END); gtk_widget_modify_font (label, get_small_font (label)); gtk_misc_set_alignment (GTK_MISC(label), 0.0, 0.5); gtk_container_add (GTK_CONTAINER (priv->album_item), label); gtk_widget_set_sensitive (priv->album_item, FALSE); label->state = GTK_STATE_NORMAL; /* Active items */ priv->play_item = gtk_menu_item_new_with_label (PLAY_ITEM_STRING); priv->stop_item = gtk_menu_item_new_with_label (STOP_ITEM_STRING); priv->next_item = gtk_menu_item_new_with_label (SKIP_ITEM_STRING); priv->love_item = gtk_menu_item_new_with_label (LOVE_ITEM_STRING); priv->ban_item = gtk_menu_item_new_with_label (BAN_ITEM_STRING); priv->open_vagalume_item = gtk_menu_item_new_with_label (SHOW_APP_ITEM_STRING); priv->close_vagalume_item = gtk_menu_item_new_with_label (CLOSE_APP_ITEM_STRING); /* Add items to main_panel */ gtk_menu_append (priv->main_panel, priv->artist_item); gtk_menu_append (priv->main_panel, priv->track_item); gtk_menu_append (priv->main_panel, priv->album_item); gtk_menu_append (priv->main_panel, gtk_separator_menu_item_new ()); gtk_menu_append (priv->main_panel, priv->play_item); gtk_menu_append (priv->main_panel, priv->stop_item); gtk_menu_append (priv->main_panel, priv->next_item); gtk_menu_append (priv->main_panel, priv->love_item); gtk_menu_append (priv->main_panel, priv->ban_item); gtk_menu_append (priv->main_panel, gtk_separator_menu_item_new ()); gtk_menu_append (priv->main_panel, priv->open_vagalume_item); gtk_menu_append (priv->main_panel, priv->close_vagalume_item); /* Connect signals */ priv->main_panel_handler_id = g_signal_connect(priv->main_panel, "selection-done", G_CALLBACK(main_panel_hidden), vsbp); priv->play_item_handler_id = g_signal_connect(priv->play_item, "activate", G_CALLBACK (main_panel_item_activated), vsbp); priv->stop_item_handler_id = g_signal_connect(priv->stop_item, "activate", G_CALLBACK (main_panel_item_activated), vsbp); priv->next_item_handler_id = g_signal_connect(priv->next_item, "activate", G_CALLBACK (main_panel_item_activated), vsbp); priv->love_item_handler_id = g_signal_connect(priv->love_item, "activate", G_CALLBACK (main_panel_item_activated), vsbp); priv->ban_item_handler_id = g_signal_connect(priv->ban_item, "activate", G_CALLBACK (main_panel_item_activated), vsbp); priv->open_vagalume_item_handler_id = g_signal_connect(priv->open_vagalume_item, "activate", G_CALLBACK (main_panel_item_activated), vsbp); priv->close_vagalume_item_handler_id = g_signal_connect(priv->close_vagalume_item, "activate", G_CALLBACK (main_panel_item_activated), vsbp); /* Show widgets */ gtk_widget_show_all (priv->main_panel); } static void main_panel_update (VglSbPlugin *vsbp) { VglSbPluginPrivate *priv = VGL_SB_PLUGIN_GET_PRIVATE (vsbp); GtkWidget *label; if (!priv->running_app) { /* Application closed */ priv->is_visible = FALSE; priv->now_playing = FALSE; } /* Adjust sentitiveness for main_panel items and show/hide buttons */ if (priv->now_playing) { gtk_widget_set_sensitive (priv->play_item, FALSE); gtk_widget_set_sensitive (priv->stop_item, TRUE); gtk_widget_set_sensitive (priv->next_item, TRUE); gtk_widget_set_sensitive (priv->love_item, TRUE); gtk_widget_set_sensitive (priv->ban_item, TRUE); gtk_widget_hide (priv->play_item); gtk_widget_show (priv->stop_item); } else { /* Not playing: set default strings */ set_track_info (vsbp, NULL, NULL, NULL); gtk_widget_set_sensitive (priv->play_item, TRUE); gtk_widget_set_sensitive (priv->stop_item, FALSE); gtk_widget_set_sensitive (priv->next_item, FALSE); gtk_widget_set_sensitive (priv->love_item, FALSE); gtk_widget_set_sensitive (priv->ban_item, FALSE); gtk_widget_show (priv->play_item); gtk_widget_hide (priv->stop_item); } gtk_widget_show (priv->open_vagalume_item); gtk_widget_show (priv->close_vagalume_item); /* Detail labels */ label = gtk_bin_get_child (GTK_BIN (priv->artist_item)); gtk_label_set_markup (GTK_LABEL (label), priv->artist_string); label = gtk_bin_get_child (GTK_BIN (priv->track_item)); gtk_label_set_markup (GTK_LABEL (label), priv->track_string); /* Show / hide the album label depending on its availability */ if (priv->album_string != NULL) { label = gtk_bin_get_child (GTK_BIN (priv->album_item)); gtk_label_set_markup (GTK_LABEL (label), priv->album_string); gtk_widget_show (priv->album_item); } else { gtk_widget_hide (priv->album_item); } } /* Signals handlers */ static void main_panel_position_func (GtkMenu *main_panel, gint *x, gint *y, gboolean *push_in, gpointer data) { VglSbPluginPrivate *priv = VGL_SB_PLUGIN_GET_PRIVATE (data); GtkRequisition req; gtk_widget_size_request (GTK_WIDGET (main_panel->toplevel), &req); gdk_window_get_origin (priv->button->window, x, y); *x += (priv->button->allocation.x + priv->button->allocation.width - req.width); *y += (priv->button->allocation.y + priv->button->allocation.height + 10); } static void plugin_btn_toggled (GtkWidget *button, gpointer data) { VglSbPlugin *vsbp = VGL_SB_PLUGIN (data); VglSbPluginPrivate *priv = VGL_SB_PLUGIN_GET_PRIVATE (vsbp); if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button))) return; g_debug ("Plugin button toggled"); gtk_menu_popup (GTK_MENU (priv->main_panel), NULL, NULL, main_panel_position_func, vsbp, 1, gtk_get_current_event_time ()); } static void main_panel_item_activated (GtkWidget *item, gpointer data) { VglSbPlugin *vsbp = VGL_SB_PLUGIN (data); VglSbPluginPrivate *priv = VGL_SB_PLUGIN_GET_PRIVATE (vsbp); const gboolean interactive = TRUE; if (item == priv->play_item) { dbus_send_request (vsbp, APP_DBUS_METHOD_PLAY); g_debug ("DBUS request sent: Play"); } else if (item == priv->stop_item) { dbus_send_request (vsbp, APP_DBUS_METHOD_STOP); g_debug ("DBUS request sent: Stop"); } else if (item == priv->next_item) { dbus_send_request (vsbp, APP_DBUS_METHOD_SKIP); g_debug ("DBUS request sent: Skip"); } else if (item == priv->love_item) { dbus_send_request_with_params (vsbp, APP_DBUS_METHOD_LOVETRACK, DBUS_TYPE_BOOLEAN, &interactive, DBUS_TYPE_INVALID); g_debug ("DBUS request sent: LoveTrack"); } else if (item == priv->ban_item) { dbus_send_request_with_params (vsbp, APP_DBUS_METHOD_BANTRACK, DBUS_TYPE_BOOLEAN, &interactive, DBUS_TYPE_INVALID); g_debug ("DBUS request sent: BanTrack"); } else if (item == priv->open_vagalume_item) { dbus_send_request (vsbp, APP_DBUS_METHOD_SHOWWINDOW); g_debug ("DBUS request sent: Show application"); } else if (item == priv->close_vagalume_item) { dbus_send_request (vsbp, APP_DBUS_METHOD_CLOSEAPP); g_debug ("DBUS request sent: Close application"); } else { g_debug ("Unknown action"); } } static void main_panel_hidden (GtkWidget *main_panel, gpointer data) { VglSbPlugin *vsbp = VGL_SB_PLUGIN (data); VglSbPluginPrivate *priv = VGL_SB_PLUGIN_GET_PRIVATE (vsbp); g_debug ("Main panel hidden"); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->button), FALSE); } /* Utility functions */ static gboolean vagalume_running (VglSbPlugin *vsbp) { HDWM *hdwm; HDWMEntryInfo *info = NULL; GList *apps_list = NULL; GList *l = NULL; gchar *appname = NULL; gboolean app_found = FALSE; hdwm = hd_wm_get_singleton (); hd_wm_update_client_list (hdwm); apps_list = hd_wm_get_applications (hdwm); g_debug ("Searching for application: %s", APP_NAME); for (l = apps_list; l; l = l->next) { info = (HDWMEntryInfo *) l->data; if (appname != NULL) g_free (appname); appname = hd_wm_entry_info_get_app_name (info); g_debug ("Application\n\tApp:'%s', Title:'%s'", hd_wm_entry_info_get_app_name (info), hd_wm_entry_info_get_title (info)); if (appname && !strcmp (APP_NAME, appname)) { app_found = TRUE; break; } } /* Free resources */ g_free (appname); return app_found; }