# HG changeset patch # User giacomo # Date 1168890872 28800 # Node ID 38fe08dff5cdfbcc6f467e8c2d76c70ac0af16de # Parent 1716423d29fe8d67d43284f075ca61527ff234c8 [svn] - added status icon plugin (written from scratch, with code from gtk 2.10) diff -r 1716423d29fe -r 38fe08dff5cd ChangeLog --- a/ChangeLog Mon Jan 15 08:33:07 2007 -0800 +++ b/ChangeLog Mon Jan 15 11:54:32 2007 -0800 @@ -1,3 +1,12 @@ +2007-01-15 16:33:07 +0000 William Pitcock + revision [948] + - remove blanket http:// grabbing -- probing for mp3 now works by VFS + (even with shoutcast) + + trunk/src/mpg123/mpg123.c | 6 +----- + 1 file changed, 1 insertion(+), 5 deletions(-) + + 2007-01-15 10:48:34 +0000 Kiyoshi Aman revision [946] pause functionality should play if not already playing, now diff -r 1716423d29fe -r 38fe08dff5cd configure.ac --- a/configure.ac Mon Jan 15 08:33:07 2007 -0800 +++ b/configure.ac Mon Jan 15 11:54:32 2007 -0800 @@ -381,6 +381,26 @@ GENERAL_PLUGINS="$GENERAL_PLUGINS evdev-plug" fi +dnl *** Status Icon plugin (for X11 only) + +AC_ARG_ENABLE(statusicon, + [ --disable-statusicon disable X11 Status Icon plugin (default=enabled)], + [enable_statusicon=$enableval], + [enable_statusicon="yes"] +) + +if test "x$enable_statusicon" = "xyes"; then + have_statusicon="yes" + PKG_CHECK_MODULES(GDKX11,[gdk-x11-2.0 >= 2.6.0],,[have_statusicon="no"]) +else + AC_MSG_RESULT([*** X11 Status Icon plugin disabled per user request ***]) + have_statusicon="yes" +fi + +if test "x$have_statusicon" = "xyes"; then + GENERAL_PLUGINS="$GENERAL_PLUGINS statusicon" +fi + dnl *** AdPlug requirement (libbinio) AC_ARG_ENABLE(adplug, @@ -1175,6 +1195,7 @@ echo " -------" echo " Alarm: yes" echo " Song Change: yes" +echo " Status Icon: $have_statusicon" echo " Control via event device (evdev-plug): $have_evdevplug" echo " LIRC: $have_lirc" echo " AudioScrobbler Client: $scrobbler" diff -r 1716423d29fe -r 38fe08dff5cd mk/rules.mk.in --- a/mk/rules.mk.in Mon Jan 15 08:33:07 2007 -0800 +++ b/mk/rules.mk.in Mon Jan 15 11:54:32 2007 -0800 @@ -127,6 +127,8 @@ FLUIDSYNTH_LIBS ?= @FLUIDSYNTH_LIBS@ GCONF_CFLAGS ?= @GCONF_CFLAGS@ GCONF_LIBS ?= @GCONF_LIBS@ +GDKX11_CFLAGS ?= @GDKX11_CFLAGS@ +GDKX11_LIBS ?= @GDKX11_LIBS@ GENCAT ?= @GENCAT@ GENERAL_PLUGINS ?= @GENERAL_PLUGINS@ GENERAL_PLUGIN_DIR ?= @GENERAL_PLUGIN_DIR@ diff -r 1716423d29fe -r 38fe08dff5cd src/statusicon/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/statusicon/Makefile Mon Jan 15 11:54:32 2007 -0800 @@ -0,0 +1,18 @@ +include ../../mk/rules.mk +include ../../mk/init.mk + +OBJECTIVE_LIBS = libstatusicon$(SHARED_SUFFIX) + +noinst_HEADERS = si.h si_ui.h si_audacious.h si_common.h gtktrayicon.h + +LIBDIR = $(plugindir)/$(GENERAL_PLUGIN_DIR) + +LIBADD = $(GTK_LIBS) $(GDKX11_LIBS) +SOURCES = si.c si_ui.c gtktrayicon-x11.c + +OBJECTS = ${SOURCES:.c=.o} + +CFLAGS += $(PICFLAGS) $(GTK_CFLAGS) $(GDKX11_CFLAGS) \ + -I../../intl -I../.. -I.. + +include ../../mk/objective.mk diff -r 1716423d29fe -r 38fe08dff5cd src/statusicon/gtktrayicon-x11.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/statusicon/gtktrayicon-x11.c Mon Jan 15 11:54:32 2007 -0800 @@ -0,0 +1,522 @@ +/* gtktrayicon.c + * Copyright (C) 2002 Anders Carlsson + * + * Adapted by Giacomo Lozito for Audacious Status Icon Plugin + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * This is an implementation of the freedesktop.org "system tray" spec, + * http://www.freedesktop.org/wiki/Standards/systemtray-spec + */ + +#include "si_common.h" +#include +#include +#include + +#include +#include "gtktrayicon.h" + +#include +#include + +#define SYSTEM_TRAY_REQUEST_DOCK 0 +#define SYSTEM_TRAY_BEGIN_MESSAGE 1 +#define SYSTEM_TRAY_CANCEL_MESSAGE 2 + +#define SYSTEM_TRAY_ORIENTATION_HORZ 0 +#define SYSTEM_TRAY_ORIENTATION_VERT 1 + +enum { + PROP_0, + PROP_ORIENTATION +}; + +struct _GtkTrayIconPrivate +{ + guint stamp; + + Atom selection_atom; + Atom manager_atom; + Atom system_tray_opcode_atom; + Atom orientation_atom; + Window manager_window; + + GtkOrientation orientation; +}; + +static void gtk_tray_icon_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); + +static void gtk_tray_icon_realize (GtkWidget *widget); +static void gtk_tray_icon_unrealize (GtkWidget *widget); +static gboolean gtk_tray_icon_delete (GtkWidget *widget, + GdkEventAny *event); +static gboolean gtk_tray_icon_expose (GtkWidget *widget, + GdkEventExpose *event); + +static void gtk_tray_icon_update_manager_window (GtkTrayIcon *icon, + gboolean dock_if_realized); +static void gtk_tray_icon_manager_window_destroyed (GtkTrayIcon *icon); + +G_DEFINE_TYPE (GtkTrayIcon, gtk_tray_icon, GTK_TYPE_PLUG) + +static void +gtk_tray_icon_class_init (GtkTrayIconClass *class) +{ + GObjectClass *gobject_class = (GObjectClass *)class; + GtkWidgetClass *widget_class = (GtkWidgetClass *)class; + + gobject_class->get_property = gtk_tray_icon_get_property; + + widget_class->realize = gtk_tray_icon_realize; + widget_class->unrealize = gtk_tray_icon_unrealize; + widget_class->delete_event = gtk_tray_icon_delete; + widget_class->expose_event = gtk_tray_icon_expose; + + g_object_class_install_property (gobject_class, + PROP_ORIENTATION, + g_param_spec_enum ("orientation", + _("Orientation"), + _("The orientation of the tray"), + GTK_TYPE_ORIENTATION, + GTK_ORIENTATION_HORIZONTAL, + GTK_PARAM_READABLE)); + + g_type_class_add_private (class, sizeof (GtkTrayIconPrivate)); +} + +static void +gtk_tray_icon_init (GtkTrayIcon *icon) +{ + icon->priv = G_TYPE_INSTANCE_GET_PRIVATE (icon, GTK_TYPE_TRAY_ICON, + GtkTrayIconPrivate); + + icon->priv->stamp = 1; + icon->priv->orientation = GTK_ORIENTATION_HORIZONTAL; + + gtk_widget_set_app_paintable (GTK_WIDGET (icon), TRUE); + gtk_widget_set_double_buffered (GTK_WIDGET (icon), FALSE); + gtk_widget_add_events (GTK_WIDGET (icon), GDK_PROPERTY_CHANGE_MASK); +} + +static void +gtk_tray_icon_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GtkTrayIcon *icon = GTK_TRAY_ICON (object); + + switch (prop_id) + { + case PROP_ORIENTATION: + g_value_set_enum (value, icon->priv->orientation); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static gboolean +gtk_tray_icon_expose (GtkWidget *widget, + GdkEventExpose *event) +{ + gdk_window_clear_area (widget->window, event->area.x, event->area.y, + event->area.width, event->area.height); + + if (GTK_WIDGET_CLASS (gtk_tray_icon_parent_class)->expose_event) + return GTK_WIDGET_CLASS (gtk_tray_icon_parent_class)->expose_event (widget, event); + + return FALSE; +} + +static void +gtk_tray_icon_get_orientation_property (GtkTrayIcon *icon) +{ + Display *xdisplay; + Atom type; + int format; + union { + gulong *prop; + guchar *prop_ch; + } prop = { NULL }; + gulong nitems; + gulong bytes_after; + int error, result; + + g_assert (icon->priv->manager_window != None); + + xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon))); + + gdk_error_trap_push (); + type = None; + result = XGetWindowProperty (xdisplay, + icon->priv->manager_window, + icon->priv->orientation_atom, + 0, G_MAXLONG, FALSE, + XA_CARDINAL, + &type, &format, &nitems, + &bytes_after, &(prop.prop_ch)); + error = gdk_error_trap_pop (); + + if (error || result != Success) + return; + + if (type == XA_CARDINAL) + { + GtkOrientation orientation; + + orientation = (prop.prop [0] == SYSTEM_TRAY_ORIENTATION_HORZ) ? + GTK_ORIENTATION_HORIZONTAL : + GTK_ORIENTATION_VERTICAL; + + if (icon->priv->orientation != orientation) + { + icon->priv->orientation = orientation; + + g_object_notify (G_OBJECT (icon), "orientation"); + } + } + + if (prop.prop) + XFree (prop.prop); +} + +static GdkFilterReturn +gtk_tray_icon_manager_filter (GdkXEvent *xevent, + GdkEvent *event, + gpointer user_data) +{ + GtkTrayIcon *icon = user_data; + XEvent *xev = (XEvent *)xevent; + + if (xev->xany.type == ClientMessage && + xev->xclient.message_type == icon->priv->manager_atom && + xev->xclient.data.l[1] == icon->priv->selection_atom) + { + gtk_tray_icon_update_manager_window (icon, TRUE); + } + else if (xev->xany.window == icon->priv->manager_window) + { + if (xev->xany.type == PropertyNotify && + xev->xproperty.atom == icon->priv->orientation_atom) + { + gtk_tray_icon_get_orientation_property (icon); + } + if (xev->xany.type == DestroyNotify) + { + gtk_tray_icon_manager_window_destroyed (icon); + } + } + + return GDK_FILTER_CONTINUE; +} + +static void +gtk_tray_icon_unrealize (GtkWidget *widget) +{ + GtkTrayIcon *icon = GTK_TRAY_ICON (widget); + GdkWindow *root_window; + + if (icon->priv->manager_window != None) + { + GdkWindow *gdkwin; + + gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (widget), + icon->priv->manager_window); + + gdk_window_remove_filter (gdkwin, gtk_tray_icon_manager_filter, icon); + } + + root_window = gdk_screen_get_root_window (gtk_widget_get_screen (widget)); + + gdk_window_remove_filter (root_window, gtk_tray_icon_manager_filter, icon); + + if (GTK_WIDGET_CLASS (gtk_tray_icon_parent_class)->unrealize) + (* GTK_WIDGET_CLASS (gtk_tray_icon_parent_class)->unrealize) (widget); +} + +static void +gtk_tray_icon_send_manager_message (GtkTrayIcon *icon, + long message, + Window window, + long data1, + long data2, + long data3) +{ + XClientMessageEvent ev; + Display *display; + + memset (&ev, 0, sizeof (ev)); + ev.type = ClientMessage; + ev.window = window; + ev.message_type = icon->priv->system_tray_opcode_atom; + ev.format = 32; + ev.data.l[0] = gdk_x11_get_server_time (GTK_WIDGET (icon)->window); + ev.data.l[1] = message; + ev.data.l[2] = data1; + ev.data.l[3] = data2; + ev.data.l[4] = data3; + + display = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon))); + + gdk_error_trap_push (); + XSendEvent (display, + icon->priv->manager_window, False, NoEventMask, (XEvent *)&ev); + XSync (display, False); + gdk_error_trap_pop (); +} + +static void +gtk_tray_icon_send_dock_request (GtkTrayIcon *icon) +{ + gtk_tray_icon_send_manager_message (icon, + SYSTEM_TRAY_REQUEST_DOCK, + icon->priv->manager_window, + gtk_plug_get_id (GTK_PLUG (icon)), + 0, 0); +} + +static void +gtk_tray_icon_update_manager_window (GtkTrayIcon *icon, + gboolean dock_if_realized) +{ + Display *xdisplay; + + if (icon->priv->manager_window != None) + return; + + xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon))); + + XGrabServer (xdisplay); + + icon->priv->manager_window = XGetSelectionOwner (xdisplay, + icon->priv->selection_atom); + + if (icon->priv->manager_window != None) + XSelectInput (xdisplay, + icon->priv->manager_window, StructureNotifyMask|PropertyChangeMask); + + XUngrabServer (xdisplay); + XFlush (xdisplay); + + if (icon->priv->manager_window != None) + { + GdkWindow *gdkwin; + + gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (GTK_WIDGET (icon)), + icon->priv->manager_window); + + gdk_window_add_filter (gdkwin, gtk_tray_icon_manager_filter, icon); + + if (dock_if_realized && GTK_WIDGET_REALIZED (icon)) + gtk_tray_icon_send_dock_request (icon); + + gtk_tray_icon_get_orientation_property (icon); + } +} + +static void +gtk_tray_icon_manager_window_destroyed (GtkTrayIcon *icon) +{ + GdkWindow *gdkwin; + + g_return_if_fail (icon->priv->manager_window != None); + + gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (GTK_WIDGET (icon)), + icon->priv->manager_window); + + gdk_window_remove_filter (gdkwin, gtk_tray_icon_manager_filter, icon); + + icon->priv->manager_window = None; + + gtk_tray_icon_update_manager_window (icon, TRUE); +} + +static gboolean +gtk_tray_icon_delete (GtkWidget *widget, + GdkEventAny *event) +{ + GtkTrayIcon *icon = GTK_TRAY_ICON (widget); + GdkWindow *gdkwin; + + if (icon->priv->manager_window != None) + { + gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (GTK_WIDGET (icon)), + icon->priv->manager_window); + + gdk_window_remove_filter (gdkwin, gtk_tray_icon_manager_filter, icon); + + icon->priv->manager_window = None; + } + + gtk_tray_icon_update_manager_window (icon, TRUE); + + return TRUE; +} + +static void +gtk_tray_icon_realize (GtkWidget *widget) +{ + GtkTrayIcon *icon = GTK_TRAY_ICON (widget); + GdkScreen *screen; + GdkDisplay *display; + Display *xdisplay; + char buffer[256]; + GdkWindow *root_window; + + if (GTK_WIDGET_CLASS (gtk_tray_icon_parent_class)->realize) + GTK_WIDGET_CLASS (gtk_tray_icon_parent_class)->realize (widget); + + screen = gtk_widget_get_screen (widget); + display = gdk_screen_get_display (screen); + xdisplay = gdk_x11_display_get_xdisplay (display); + + /* Now see if there's a manager window around */ + g_snprintf (buffer, sizeof (buffer), + "_NET_SYSTEM_TRAY_S%d", + gdk_screen_get_number (screen)); + + icon->priv->selection_atom = XInternAtom (xdisplay, buffer, False); + + icon->priv->manager_atom = XInternAtom (xdisplay, "MANAGER", False); + + icon->priv->system_tray_opcode_atom = XInternAtom (xdisplay, + "_NET_SYSTEM_TRAY_OPCODE", + False); + + icon->priv->orientation_atom = XInternAtom (xdisplay, + "_NET_SYSTEM_TRAY_ORIENTATION", + False); + + gtk_tray_icon_update_manager_window (icon, FALSE); + gtk_tray_icon_send_dock_request (icon); + + root_window = gdk_screen_get_root_window (screen); + + /* Add a root window filter so that we get changes on MANAGER */ + gdk_window_add_filter (root_window, + gtk_tray_icon_manager_filter, icon); +} + +guint +_gtk_tray_icon_send_message (GtkTrayIcon *icon, + gint timeout, + const gchar *message, + gint len) +{ + guint stamp; + + g_return_val_if_fail (GTK_IS_TRAY_ICON (icon), 0); + g_return_val_if_fail (timeout >= 0, 0); + g_return_val_if_fail (message != NULL, 0); + + if (icon->priv->manager_window == None) + return 0; + + if (len < 0) + len = strlen (message); + + stamp = icon->priv->stamp++; + + /* Get ready to send the message */ + gtk_tray_icon_send_manager_message (icon, SYSTEM_TRAY_BEGIN_MESSAGE, + (Window)gtk_plug_get_id (GTK_PLUG (icon)), + timeout, len, stamp); + + /* Now to send the actual message */ + gdk_error_trap_push (); + while (len > 0) + { + XClientMessageEvent ev; + Display *xdisplay; + + xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon))); + + memset (&ev, 0, sizeof (ev)); + ev.type = ClientMessage; + ev.window = (Window)gtk_plug_get_id (GTK_PLUG (icon)); + ev.format = 8; + ev.message_type = XInternAtom (xdisplay, + "_NET_SYSTEM_TRAY_MESSAGE_DATA", False); + if (len > 20) + { + memcpy (&ev.data, message, 20); + len -= 20; + message += 20; + } + else + { + memcpy (&ev.data, message, len); + len = 0; + } + + XSendEvent (xdisplay, + icon->priv->manager_window, False, + StructureNotifyMask, (XEvent *)&ev); + XSync (xdisplay, False); + } + + gdk_error_trap_pop (); + + return stamp; +} + +void +_gtk_tray_icon_cancel_message (GtkTrayIcon *icon, + guint id) +{ + g_return_if_fail (GTK_IS_TRAY_ICON (icon)); + g_return_if_fail (id > 0); + + gtk_tray_icon_send_manager_message (icon, SYSTEM_TRAY_CANCEL_MESSAGE, + (Window)gtk_plug_get_id (GTK_PLUG (icon)), + id, 0, 0); +} + +GtkTrayIcon * +_gtk_tray_icon_new_for_screen (GdkScreen *screen, + const gchar *name) +{ + g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL); + + return g_object_new (GTK_TYPE_TRAY_ICON, + "screen", screen, + "title", name, + NULL); +} + +GtkTrayIcon* +_gtk_tray_icon_new (const gchar *name) +{ + return g_object_new (GTK_TYPE_TRAY_ICON, + "title", name, + NULL); +} + +GtkOrientation +_gtk_tray_icon_get_orientation (GtkTrayIcon *icon) +{ + g_return_val_if_fail (GTK_IS_TRAY_ICON (icon), GTK_ORIENTATION_HORIZONTAL); + + return icon->priv->orientation; +} diff -r 1716423d29fe -r 38fe08dff5cd src/statusicon/gtktrayicon.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/statusicon/gtktrayicon.h Mon Jan 15 11:54:32 2007 -0800 @@ -0,0 +1,75 @@ +/* gtktrayicon.h + * Copyright (C) 2002 Anders Carlsson + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GTK_TRAY_ICON_H__ +#define __GTK_TRAY_ICON_H__ + +#include + +G_BEGIN_DECLS + +#define GTK_TYPE_TRAY_ICON (gtk_tray_icon_get_type ()) +#define GTK_TRAY_ICON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_TRAY_ICON, GtkTrayIcon)) +#define GTK_TRAY_ICON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_TRAY_ICON, GtkTrayIconClass)) +#define GTK_IS_TRAY_ICON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_TRAY_ICON)) +#define GTK_IS_TRAY_ICON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_TRAY_ICON)) +#define GTK_TRAY_ICON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_TRAY_ICON, GtkTrayIconClass)) + +typedef struct _GtkTrayIcon GtkTrayIcon; +typedef struct _GtkTrayIconPrivate GtkTrayIconPrivate; +typedef struct _GtkTrayIconClass GtkTrayIconClass; + +struct _GtkTrayIcon +{ + GtkPlug parent_instance; + + GtkTrayIconPrivate *priv; +}; + +struct _GtkTrayIconClass +{ + GtkPlugClass parent_class; + + void (*__gtk_reserved1); + void (*__gtk_reserved2); + void (*__gtk_reserved3); + void (*__gtk_reserved4); + void (*__gtk_reserved5); + void (*__gtk_reserved6); +}; + +GType gtk_tray_icon_get_type (void) G_GNUC_CONST; + +GtkTrayIcon *_gtk_tray_icon_new_for_screen (GdkScreen *screen, + const gchar *name); + +GtkTrayIcon *_gtk_tray_icon_new (const gchar *name); + +guint _gtk_tray_icon_send_message (GtkTrayIcon *icon, + gint timeout, + const gchar *message, + gint len); +void _gtk_tray_icon_cancel_message (GtkTrayIcon *icon, + guint id); + +GtkOrientation _gtk_tray_icon_get_orientation (GtkTrayIcon *icon); + +G_END_DECLS + +#endif /* __GTK_TRAY_ICON_H__ */ diff -r 1716423d29fe -r 38fe08dff5cd src/statusicon/si.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/statusicon/si.c Mon Jan 15 11:54:32 2007 -0800 @@ -0,0 +1,103 @@ +/* +* +* Author: Giacomo Lozito , (C) 2005-2007 +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 of the License, or (at your +* option) any later version. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +*/ + +#include "si.h" +#include "si_ui.h" +#include "si_audacious.h" +#include "si_common.h" + + +static gboolean plugin_active = FALSE; + + +/* ***************** */ +/* plug-in functions */ + +GeneralPlugin *get_gplugin_info() +{ + return &si_gp; +} + + +void +si_init ( void ) +{ + g_type_init(); + g_log_set_handler( NULL , G_LOG_LEVEL_WARNING , g_log_default_handler , NULL ); + plugin_active = TRUE; + si_ui_statusicon_show(); + return; +} + + +void +si_cleanup ( void ) +{ + if ( plugin_active == TRUE ) + { + plugin_active = FALSE; + si_ui_statusicon_hide(); + } + return; +} + + +void +si_about ( void ) +{ + si_ui_about_show(); +} + + + +/* ***************** */ +/* audacious actions */ + + +void +si_audacious_toggle_visibility ( void ) +{ + static gboolean eq_prevstatus = FALSE; + static gboolean pl_prevstatus = FALSE; + + /* use the main window visibility status to toggle show/hide */ + if ( xmms_remote_is_main_win( si_gp.xmms_session ) == TRUE ) + { + /* remember the visibility status of equalizer and playlist windows */ + eq_prevstatus = xmms_remote_is_eq_win( si_gp.xmms_session ); + pl_prevstatus = xmms_remote_is_pl_win( si_gp.xmms_session ); + /* now hide all of the player windows */ + xmms_remote_main_win_toggle( si_gp.xmms_session , FALSE ); + if ( eq_prevstatus == TRUE ) + xmms_remote_eq_win_toggle( si_gp.xmms_session , FALSE ); + if ( pl_prevstatus == TRUE ) + xmms_remote_pl_win_toggle( si_gp.xmms_session , FALSE ); + } + else + { + /* show the main player window again */ + xmms_remote_main_win_toggle( si_gp.xmms_session , TRUE ); + /* show the equalizer and playlist window if they were visible before */ + if ( eq_prevstatus == TRUE ) + xmms_remote_eq_win_toggle( si_gp.xmms_session , TRUE ); + if ( pl_prevstatus == TRUE ) + xmms_remote_pl_win_toggle( si_gp.xmms_session , TRUE ); + } +} diff -r 1716423d29fe -r 38fe08dff5cd src/statusicon/si.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/statusicon/si.h Mon Jan 15 11:54:32 2007 -0800 @@ -0,0 +1,44 @@ +/* +* +* Author: Giacomo Lozito , (C) 2005-2007 +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 of the License, or (at your +* option) any later version. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +*/ + +#ifndef _I_SI_H +#define _I_SI_H 1 + +#include "si_common.h" +#include +#include + +void si_init ( void ); +void si_cleanup ( void ); +void si_about ( void ); + +GeneralPlugin si_gp = +{ + NULL, /* handle */ + NULL, /* filename */ + -1, /* session */ + "Status Icon Plugin " SI_VERSION_PLUGIN, /* description */ + si_init, /* init */ + si_about, /* about */ + NULL, /* configure */ + si_cleanup /* cleanup */ +}; + +#endif /* !_I_SI_H */ diff -r 1716423d29fe -r 38fe08dff5cd src/statusicon/si.xpm --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/statusicon/si.xpm Mon Jan 15 11:54:32 2007 -0800 @@ -0,0 +1,117 @@ +/* XPM */ +static char * si_xpm[] = { +"22 22 92 2", +" c None", +". c #000000", +"+ c #0D0D0D", +"@ c #202020", +"# c #080808", +"$ c #444444", +"% c #949494", +"& c #BEBEBE", +"* c #C6C6C6", +"= c #929292", +"- c #434343", +"; c #1F1F1F", +"> c #919191", +", c #D1D1D1", +"' c #D9D9D9", +") c #D0D0D0", +"! c #909090", +"~ c #1E1E1E", +"{ c #A8A8A8", +"] c #A7A7A7", +"^ c #D6D6D6", +"/ c #B0B0B0", +"( c #8E8E8E", +"_ c #6F6F6F", +": c #686868", +"< c #C5C5C5", +"[ c #D8D8D8", +"} c #939393", +"| c #454545", +"1 c #ADADAD", +"2 c #101010", +"3 c #2B2B2B", +"4 c #010101", +"5 c #959595", +"6 c #B9B9B9", +"7 c #414141", +"8 c #424242", +"9 c #040404", +"0 c #4C4C4C", +"a c #D5D5D5", +"b c #979797", +"c c #111111", +"d c #C0C0C0", +"e c #CFCFCF", +"f c #0B0B0B", +"g c #262626", +"h c #242424", +"i c #C8C8C8", +"j c #AAAAAA", +"k c #151515", +"l c #BCBCBC", +"m c #252525", +"n c #383838", +"o c #353535", +"p c #282828", +"q c #C7C7C7", +"r c #131313", +"s c #C1C1C1", +"t c #B8B8B8", +"u c #0F0F0F", +"v c #020202", +"w c #636363", +"x c #565656", +"y c #373737", +"z c #9C9C9C", +"A c #2C2C2C", +"B c #030303", +"C c #C9C9C9", +"D c #9E9E9E", +"E c #D3D3D3", +"F c #A0A0A0", +"G c #505050", +"H c #3B3B3B", +"I c #1C1C1C", +"J c #707070", +"K c #4D4D4D", +"L c #999999", +"M c #C4C4C4", +"N c #A9A9A9", +"O c #D4D4D4", +"P c #9A9A9A", +"Q c #AFAFAF", +"R c #AEAEAE", +"S c #9B9B9B", +"T c #0C0C0C", +"U c #A1A1A1", +"V c #C2C2C2", +"W c #CACACA", +"X c #9F9F9F", +"Y c #4E4E4E", +"Z c #161616", +"` c #292929", +". . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . + @ @ + . . . . . . . . . ", +". . . . . . # $ % & * * & = - # . . . . . . ", +". . . . . ; > , ' ' ' ' ' ' ) ! ~ . . . . . ", +". . . . ; { ' ' ' ' ' ' ' ' ' ' ] ; . . . . ", +". . . # = ' ' ^ / ( _ : > < [ ' ' } # . . . ", +". . . | , ' ' 1 2 . . . . 3 / ' ' , | . . . ", +". . 4 5 ' ' ' 6 7 | 8 9 . . 0 a ' ' b 4 . . ", +". . c d ' ' ' ' e ] _ f . . g < ' ' d 2 . . ", +". . h i ' ' ' j ; . . . . . k l ' ' i m . . ", +". . m i ' ' < g . 4 n o 4 . p q ' ' i m . . ", +". . r s ' ' t u . v w x 4 . y e ' ' s r . . ", +". . 4 z ' ' i A . . B B . . A C ' ' D 4 . . ", +". . . 0 E ' [ F g v h G H I J a ' E K . . . ", +". . . f L ' ' [ M N M [ e d O ' ' P f . . . ", +". . . . m Q ' ' ' ' ' ' ' ' ' ' R h . . . . ", +". . . . . g S E ' ' ' ' ' ' E S m . . . . . ", +". . . . . . T G U V W W V X Y f . . . . . . ", +". . . . . . . . 4 Z ` ` k 4 . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . "}; diff -r 1716423d29fe -r 38fe08dff5cd src/statusicon/si_audacious.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/statusicon/si_audacious.h Mon Jan 15 11:54:32 2007 -0800 @@ -0,0 +1,30 @@ +/* +* +* Author: Giacomo Lozito , (C) 2005-2007 +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 of the License, or (at your +* option) any later version. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +*/ + +#ifndef _I_SI_AUDACIOUS_H +#define _I_SI_AUDACIOUS_H 1 + +#include "si_common.h" + + +void si_audacious_toggle_visibility ( void ); + + +#endif /* !_I_SI_AUDACIOUS_H */ diff -r 1716423d29fe -r 38fe08dff5cd src/statusicon/si_common.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/statusicon/si_common.h Mon Jan 15 11:54:32 2007 -0800 @@ -0,0 +1,35 @@ +/* +* +* Author: Giacomo Lozito , (C) 2005-2007 +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 of the License, or (at your +* option) any later version. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +*/ + +#ifndef _I_SI_COMMON_H +#define _I_SI_COMMON_H 1 + +#ifdef DEBUG +#include +#define DEBUGMSG(...) { fprintf(stderr, "statusicon(%s:%s:%d): ", __FILE__, __FUNCTION__, (int) __LINE__); fprintf(stderr, __VA_ARGS__); } +#else +#define DEBUGMSG(...) +#endif /* DEBUG */ + +#include "../../config.h" + +#define SI_VERSION_PLUGIN "0.1beta" + +#endif /* !_I_ED_COMMON_H */ diff -r 1716423d29fe -r 38fe08dff5cd src/statusicon/si_ui.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/statusicon/si_ui.c Mon Jan 15 11:54:32 2007 -0800 @@ -0,0 +1,148 @@ +/* +* +* Author: Giacomo Lozito , (C) 2005-2007 +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 of the License, or (at your +* option) any later version. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +*/ + +#include "si_ui.h" +#include "si_audacious.h" +#include "si_common.h" +#include "gtktrayicon.h" +#include "si.xpm" +#include +#include +#include + + +static GtkWidget * si_evbox = NULL; + + +static GtkTrayIcon * +si_ui_statusicon_create ( void ) +{ + GtkTrayIcon *si_applet = NULL; + + si_applet = _gtk_tray_icon_new( "audacious" ); + + gtk_widget_show( GTK_WIDGET(si_applet) ); + + return si_applet; +} + + +static GtkWidget * +si_ui_rmenu_create ( GtkWidget * evbox ) +{ + GtkWidget *menu; + GtkWidget *menuitem; + + menu = gtk_menu_new(); + + /* gtk_widget_show_all( GTK_WIDGET(menu) ); */ + return menu; +} + + +static gboolean +si_ui_statusicon_cb_btpress ( GtkWidget * evbox , GdkEventButton * event ) +{ + switch ( event->button ) + { + case 1: + { + si_audacious_toggle_visibility(); + break; + } + +/* + case 3: + { + GtkWidget *si_rmenu = GTK_WIDGET(g_object_get_data( G_OBJECT(evbox) , "rmenu" )); + gtk_menu_popup( GTK_MENU(si_rmenu) , NULL , NULL , + NULL , NULL , event->button , event->time ); + break; + } +*/ + } + + return FALSE; +} + + +void +si_ui_statusicon_show ( void ) +{ + GtkWidget *si_image; + GtkWidget *si_rmenu; + GdkPixbuf *si_pixbuf; + GtkTrayIcon *si_applet; + + si_applet = si_ui_statusicon_create(); + if ( si_applet == NULL ) + { + g_warning( "StatusIcon plugin: unable to create a status icon.\n" ); + return; + } + + si_pixbuf = gdk_pixbuf_new_from_xpm_data( (const char**)si_xpm ); + si_image = gtk_image_new_from_pixbuf( si_pixbuf ); + g_object_unref( si_pixbuf ); + + si_evbox = gtk_event_box_new(); + si_rmenu = si_ui_rmenu_create( si_evbox ); + + g_object_set_data( G_OBJECT(si_evbox) , "rmenu" , si_rmenu ); + g_object_set_data( G_OBJECT(si_evbox) , "applet" , si_applet ); + g_signal_connect( G_OBJECT(si_evbox) , "button-press-event" , + G_CALLBACK(si_ui_statusicon_cb_btpress) , NULL ); + + gtk_container_add( GTK_CONTAINER(si_evbox), si_image ); + gtk_container_add( GTK_CONTAINER(si_applet), si_evbox ); + + gtk_widget_show_all( GTK_WIDGET(si_applet) ); + return; +} + + +void +si_ui_statusicon_hide ( void ) +{ + if ( si_evbox != NULL ) + { + GtkTrayIcon *si_applet = g_object_get_data( G_OBJECT(si_evbox) , "applet" ); + GtkWidget *si_rmenu = g_object_get_data( G_OBJECT(si_evbox) , "rmenu" ); + gtk_widget_destroy( GTK_WIDGET(si_evbox) ); + gtk_widget_destroy( GTK_WIDGET(si_rmenu) ); + gtk_widget_destroy( GTK_WIDGET(si_applet) ); + } + return; +} + + +void +si_ui_about_show ( void ) +{ + GtkWidget *about_dlg = gtk_message_dialog_new( + NULL , 0 , GTK_MESSAGE_INFO , GTK_BUTTONS_CLOSE , + _( "Status Icon Plugin " SI_VERSION_PLUGIN "\n" + "written by Giacomo Lozito < james@develia.org >\n\n" + "This plugin provides a status icon, placed in\n" + "the system tray area of the window manager.\n" ) ); + gtk_dialog_run( GTK_DIALOG(about_dlg) ); + gtk_widget_destroy( about_dlg ); + return; +} diff -r 1716423d29fe -r 38fe08dff5cd src/statusicon/si_ui.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/statusicon/si_ui.h Mon Jan 15 11:54:32 2007 -0800 @@ -0,0 +1,32 @@ +/* +* +* Author: Giacomo Lozito , (C) 2005-2007 +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 of the License, or (at your +* option) any later version. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +*/ + +#ifndef _I_SI_UI_H +#define _I_SI_UI_H 1 + +#include "si_ui.h" + + +void si_ui_statusicon_show( void ); +void si_ui_statusicon_hide( void ); +void si_ui_about_show( void ); + + +#endif /* !_I_SI_UI_H */