diff options
6 files changed, 1652 insertions, 0 deletions
diff --git a/gnome-base/gnome-settings-daemon/Manifest b/gnome-base/gnome-settings-daemon/Manifest new file mode 100644 index 0000000..bb17bb1 --- /dev/null +++ b/gnome-base/gnome-settings-daemon/Manifest @@ -0,0 +1,4 @@ +AUX gnome-settings-daemon-2.30.0-gst-vol-control-support.patch 27189 RMD160 77e44583894977b6255fba168d565c5948481401 SHA1 8db1dde75b1866619d6589e989ed27fc45050c50 SHA256 0858e7fdb97086f7f0a284d535d642c23f06fb7d9fc71d9f7477dc856439a158 +AUX gnome-settings-daemon-2.30.0-osd-notifications.patch 27262 RMD160 7821d5b11c058f1a40fe71e4fefd33e8c2633d62 SHA1 2a9f33f69dbfa1d22e29a6e71d6528eb1c889d77 SHA256 2a99de82289ca80281a4c71c5b38b19edf30a9f78a4dd9b355b43e1bf1d8fff2 +DIST gnome-settings-daemon-2.30.0.tar.bz2 1230687 RMD160 b88c58ab6344c78990aa84c999a0c33f00f3a273 SHA1 af65282fd28249a7958115568cc4e410858c4f26 SHA256 cb759f2aa403ad10f7b0a196c523fa0b3842cf4432b26a4b308ed1e5bf67e6aa +EBUILD gnome-settings-daemon-2.30.0-r1.ebuild 2113 RMD160 f7b9155c01318b77f7211d55cc9d4d753c8b92ad SHA1 4611e42ec9bd671dbd04bda0a5ef39d55c089a8b SHA256 6ef84aa58d3e3a90b86e1c33b078bf95d32bc73aea74342417bac5236fd9cda3 diff --git a/gnome-base/gnome-settings-daemon/files/gnome-settings-daemon-2.30.0-gst-vol-control-support.patch b/gnome-base/gnome-settings-daemon/files/gnome-settings-daemon-2.30.0-gst-vol-control-support.patch new file mode 100644 index 0000000..57bb633 --- /dev/null +++ b/gnome-base/gnome-settings-daemon/files/gnome-settings-daemon-2.30.0-gst-vol-control-support.patch @@ -0,0 +1,856 @@ +From 32a79f1b04c352dc9b9c28c4bdd3d772eeff974d Mon Sep 17 00:00:00 2001 +From: Priit Laes <plaes@plaes.org> +Date: Wed, 31 Mar 2010 20:53:05 +0300 +Subject: [PATCH] GStreamer support in the volume applet; powered by the Gentoo GNOME team. + +https://bugzilla.gnome.org/show_bug.cgi?id=571145 +--- + configure.ac | 43 ++ + plugins/media-keys/Makefile.am | 15 +- + plugins/media-keys/cut-n-paste/Makefile.am | 34 ++- + .../cut-n-paste/gvc-gstreamer-acme-vol.c | 402 ++++++++++++++++++++ + .../cut-n-paste/gvc-gstreamer-acme-vol.h | 56 +++ + plugins/media-keys/gsd-media-keys-manager.c | 64 +++- + 6 files changed, 589 insertions(+), 25 deletions(-) + create mode 100644 plugins/media-keys/cut-n-paste/gvc-gstreamer-acme-vol.c + create mode 100644 plugins/media-keys/cut-n-paste/gvc-gstreamer-acme-vol.h + +diff --git a/configure.ac b/configure.ac +index 92f20c8..723a0cf 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -251,6 +251,48 @@ AM_CONDITIONAL(HAVE_PULSE, test "x$have_pulse" = "xtrue") + AC_SUBST(PULSE_CFLAGS) + AC_SUBST(PULSE_LIBS) + ++dnl ============================================== ++dnl GStreamer section ++dnl ============================================== ++GST_MAJORMINOR=auto ++ ++AC_ARG_ENABLE(gstreamer, ++AC_HELP_STRING([--enable-gstreamer],[use gstreamer if available (and optionally specify a version)]), ++[case "${enableval}" in ++ yes) ENABLE_GSTREAMER=yes ;; ++ 0.10) ENABLE_GSTREAMER=yes && GST_MAJORMINOR=0.10 ;; ++ no) ENABLE_GSTREAMER=no ;; ++ *) AC_MSG_ERROR([ ++ *** Bad value ${enableval} for --enable-gstreamer ++ *** Please use one of the following: ++ *** --enable-gstreamer=0.10 ++ ]) ;; ++esac], ++[ENABLE_GSTREAMER=yes]) dnl Default value ++ ++have_gstreamer=no ++if test "x$ENABLE_GSTREAMER" = "xyes"; then ++ GST_REQS=0.10.1.2 ++ PKGS="gstreamer-0.10 >= $GST_REQS gstreamer-plugins-base-0.10 >= $GST_REQS" ++ ++ PKG_CHECK_MODULES(GST, $PKGS, have_gstreamer=yes, ++ AC_MSG_RESULT([no])) ++ ++ if test "x$have_pulse" = "xtrue"; then ++ AC_MSG_ERROR([*** GStreamer & Pulseaudio both are selected ***]) ++ fi ++ ++ if test "x$have_gstreamer" = "xyes"; then ++ GST_LIBS="$GST_LIBS -lgstinterfaces-0.10 -lgstaudio-0.10" ++ AC_DEFINE(HAVE_GSTREAMER,1,[enable gstreamer]) ++ fi ++else ++ AC_MSG_NOTICE([*** GStreamer support disabled ***]) ++fi ++AM_CONDITIONAL(HAVE_GSTREAMER, test "x$have_gstreamer" = "xyes") ++AC_SUBST(GST_LIBS) ++AC_SUBST(GST_CFLAGS) ++ + # --------------------------------------------------------------------------- + # Enable Profiling + # --------------------------------------------------------------------------- +@@ -389,6 +431,7 @@ echo " + dbus-1 system.d dir: ${DBUS_SYS_DIR} + + Libnotify support: ${have_libnotify} ++ GStreamer support: ${have_gstreamer} + PulseAudio support: ${have_pulse} + Profiling support: ${enable_profiling} + " +diff --git a/plugins/media-keys/Makefile.am b/plugins/media-keys/Makefile.am +index f9a71cd..92b19f4 100644 +--- a/plugins/media-keys/Makefile.am ++++ b/plugins/media-keys/Makefile.am +@@ -3,13 +3,8 @@ context = actions + + NULL = + +-SUBDIRS = +-plugin_LTLIBRARIES = +- +-if HAVE_PULSE +-SUBDIRS += cut-n-paste +-plugin_LTLIBRARIES += libmedia-keys.la +-endif ++SUBDIRS = cut-n-paste ++plugin_LTLIBRARIES = libmedia-keys.la + + BUILT_SOURCES = \ + gsd-media-keys-manager-glue.h \ +@@ -100,7 +95,7 @@ libmedia_keys_la_LDFLAGS = \ + + libmedia_keys_la_LIBADD = \ + $(top_builddir)/plugins/common/libcommon.la \ +- $(top_builddir)/plugins/media-keys/cut-n-paste/libgvc.la \ ++ $(top_builddir)/plugins/media-keys/cut-n-paste/libgvc.la \ + $(SETTINGS_PLUGIN_LIBS) \ + $(XF86MISC_LIBS) \ + -lm +@@ -108,9 +103,7 @@ libmedia_keys_la_LIBADD = \ + plugin_in_files = \ + media-keys.gnome-settings-plugin.in + +-if HAVE_PULSE + plugin_DATA = $(plugin_in_files:.gnome-settings-plugin.in=.gnome-settings-plugin) +-endif + + noinst_PROGRAMS = \ + test-media-keys \ +@@ -176,9 +169,7 @@ test_media_keys_LDADD = \ + $(GST_LIBS) \ + -lm + +-if HAVE_PULSE + test_media_keys_LDADD += $(top_builddir)/plugins/media-keys/cut-n-paste/libgvc.la +-endif + + gtkbuilderdir = $(pkgdatadir) + gtkbuilder_DATA = \ +diff --git a/plugins/media-keys/cut-n-paste/Makefile.am b/plugins/media-keys/cut-n-paste/Makefile.am +index bc59a10..6486ac0 100644 +--- a/plugins/media-keys/cut-n-paste/Makefile.am ++++ b/plugins/media-keys/cut-n-paste/Makefile.am +@@ -4,16 +4,24 @@ noinst_LTLIBRARIES = libgvc.la + + INCLUDES = \ + $(WARN_CFLAGS) \ +- $(VOLUME_CONTROL_CFLAGS) \ +- $(PULSE_CFLAGS) \ + $(NULL) + + libgvc_la_LIBADD = \ +- $(VOLUME_CONTROL_LIBS) \ +- $(PULSE_LIBS) \ + $(NULL) + + libgvc_la_SOURCES = \ ++ $(NULL) ++ ++if HAVE_PULSE ++INCLUDES += \ ++ $(VOLUME_CONTROL_CFLAGS) \ ++ $(PULSE_CFLAGS) ++ ++libgvc_la_LIBADD += \ ++ $(VOLUME_CONTROL_LIBS) \ ++ $(PULSE_LIBS) ++ ++libgvc_la_SOURCES += \ + gvc-mixer-stream.h \ + gvc-mixer-stream.c \ + gvc-channel-map.h \ +@@ -31,8 +39,22 @@ libgvc_la_SOURCES = \ + gvc-mixer-event-role.h \ + gvc-mixer-event-role.c \ + gvc-mixer-control.h \ +- gvc-mixer-control.c \ +- $(NULL) ++ gvc-mixer-control.c ++endif ++ ++if HAVE_GSTREAMER ++INCLUDES += \ ++ $(SETTINGS_PLUGIN_CFLAGS) \ ++ $(AM_CFLAGS) \ ++ $(GST_CFLAGS) ++ ++libgvc_la_LIBADD += \ ++ $(GST_LIBS) ++ ++libgvc_la_SOURCES += \ ++ gvc-gstreamer-acme-vol.c \ ++ gvc-gstreamer-acme-vol.h ++endif + + MAINTAINERCLEANFILES = \ + *~ \ +diff --git a/plugins/media-keys/cut-n-paste/gvc-gstreamer-acme-vol.c b/plugins/media-keys/cut-n-paste/gvc-gstreamer-acme-vol.c +new file mode 100644 +index 0000000..8948480 +--- /dev/null ++++ b/plugins/media-keys/cut-n-paste/gvc-gstreamer-acme-vol.c +@@ -0,0 +1,402 @@ ++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ ++ ++/* acme-volume.c ++ ++ Copyright (C) 2002, 2003 Bastien Nocera ++ Copyright (C) 2004 Novell, Inc. ++ Copyright (C) 2009 PERIER Romain <mrpouet@tuxfamily.org> ++ ++ The Gnome Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Library General Public License as ++ published by the Free Software Foundation; either version 2 of the ++ License, or (at your option) any later version. ++ ++ The Gnome 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 ++ Library General Public License for more details. ++ ++ You should have received a copy of the GNU Library General Public ++ License along with the Gnome Library; see the file COPYING.LIB. If not, ++ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, ++ Boston, MA 02111-1307, USA. ++ ++ Author: Bastien Nocera <hadess@hadess.net> ++ Jon Trowbridge <trow@ximian.com> ++*/ ++ ++#include "config.h" ++#include "gvc-gstreamer-acme-vol.h" ++ ++#include <gst/gst.h> ++#include <gst/audio/mixerutils.h> ++#include <gst/interfaces/mixer.h> ++#include <gst/interfaces/propertyprobe.h> ++ ++#include <gconf/gconf-client.h> ++ ++#include <string.h> ++ ++#define TIMEOUT 4 ++ ++#define DEFAULT_MIXER_DEVICE_KEY "/desktop/gnome/sound/default_mixer_device" ++#define DEFAULT_MIXER_TRACKS_KEY "/desktop/gnome/sound/default_mixer_tracks" ++ ++#define ACME_VOLUME_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), ACME_TYPE_VOLUME, AcmeVolumePrivate)) ++ ++struct AcmeVolumePrivate { ++ GstMixer *mixer; ++ GList *mixer_tracks; ++ guint timer_id; ++ gdouble volume; ++ gboolean mute; ++ GConfClient *gconf_client; ++}; ++ ++G_DEFINE_TYPE (AcmeVolume, acme_volume, G_TYPE_OBJECT) ++ ++static gboolean acme_volume_open (AcmeVolume *acme); ++static void acme_volume_close (AcmeVolume *acme); ++static gboolean acme_volume_close_real (AcmeVolume *self); ++ ++static gpointer acme_volume_object = NULL; ++ ++static void ++acme_volume_finalize (GObject *object) ++{ ++ AcmeVolume *self; ++ ++ g_return_if_fail (object != NULL); ++ g_return_if_fail (ACME_IS_VOLUME (object)); ++ ++ self = ACME_VOLUME (object); ++ ++ if (self->_priv->timer_id != 0) ++ g_source_remove (self->_priv->timer_id); ++ acme_volume_close_real (self); ++ ++ if (self->_priv->gconf_client != NULL) { ++ g_object_unref (self->_priv->gconf_client); ++ self->_priv->gconf_client = NULL; ++ } ++ ++ G_OBJECT_CLASS (acme_volume_parent_class)->finalize (object); ++} ++ ++void ++acme_volume_set_mute (AcmeVolume *self, gboolean val) ++{ ++ GList *t; ++ ++ g_return_if_fail(ACME_IS_VOLUME(self)); ++ g_return_if_fail(acme_volume_open(self)); ++ ++ for (t = self->_priv->mixer_tracks; t != NULL; t = t->next) { ++ GstMixerTrack *track = GST_MIXER_TRACK (t->data); ++ gst_mixer_set_mute (self->_priv->mixer, track, val); ++ } ++ self->_priv->mute = val; ++ acme_volume_close (self); ++} ++ ++static void ++update_state (AcmeVolume * self) ++{ ++ gint *volumes, n; ++ gdouble vol = 0; ++ GstMixerTrack *track = GST_MIXER_TRACK (self->_priv->mixer_tracks->data); ++ ++ /* update mixer by getting volume */ ++ volumes = g_new0 (gint, track->num_channels); ++ gst_mixer_get_volume (self->_priv->mixer, track, volumes); ++ for (n = 0; n < track->num_channels; n++) ++ vol += volumes[n]; ++ g_free (volumes); ++ vol /= track->num_channels; ++ vol = 100 * vol / (track->max_volume - track->min_volume); ++ ++ /* update mute flag, and volume if not muted */ ++ if (GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_MUTE)) ++ self->_priv->mute = TRUE; ++ self->_priv->volume = vol; ++} ++ ++gboolean ++acme_volume_get_mute (AcmeVolume *self) ++{ ++ g_return_val_if_fail(acme_volume_open(self), FALSE); ++ ++ update_state (self); ++ acme_volume_close (self); ++ ++ return self->_priv->mute; ++} ++ ++gint ++acme_volume_get_volume (AcmeVolume *self) ++{ ++ ++ g_return_val_if_fail(acme_volume_open(self), 0); ++ ++ update_state (self); ++ ++ acme_volume_close (self); ++ ++ return (gint) (self->_priv->volume + 0.5); ++} ++ ++void ++acme_volume_set_volume (AcmeVolume *self, gint val) ++{ ++ GList *t; ++ ++ g_return_if_fail(acme_volume_open(self)); ++ ++ val = CLAMP (val, 0, 100); ++ ++ for (t = self->_priv->mixer_tracks; t != NULL; t = t->next) { ++ GstMixerTrack *track = GST_MIXER_TRACK (t->data); ++ gint *volumes, n; ++ gdouble scale = (track->max_volume - track->min_volume) / 100.0; ++ gint vol = (gint) (val * scale + track->min_volume + 0.5); ++ ++ volumes = g_new (gint, track->num_channels); ++ for (n = 0; n < track->num_channels; n++) ++ volumes[n] = vol; ++ gst_mixer_set_volume (self->_priv->mixer, track, volumes); ++ g_free (volumes); ++ } ++ ++ /* update state */ ++ self->_priv->volume = val; ++ ++ acme_volume_close (self); ++} ++ ++void ++acme_volume_mute_toggle (AcmeVolume *self) ++{ ++ gboolean muted; ++ ++ g_return_if_fail (self != NULL); ++ g_return_if_fail (ACME_IS_VOLUME(self)); ++ ++ muted = acme_volume_get_mute(self); ++ acme_volume_set_mute(self, !muted); ++} ++ ++gint ++acme_volume_get_threshold (AcmeVolume *self) ++{ ++ GList *t; ++ gint steps = 101; ++ ++ g_return_val_if_fail(acme_volume_open(self), 1); ++ ++ for (t = self->_priv->mixer_tracks; t != NULL; t = t->next) { ++ GstMixerTrack *track = GST_MIXER_TRACK (t->data); ++ gint track_steps = track->max_volume - track->min_volume; ++ if (track_steps > 0 && track_steps < steps) ++ steps = track_steps; ++ } ++ ++ acme_volume_close (self); ++ ++ return 100 / steps + 1; ++} ++ ++static gboolean ++acme_volume_close_real (AcmeVolume *self) ++{ ++ if (self->_priv->mixer != NULL) ++ { ++ gst_element_set_state (GST_ELEMENT (self->_priv->mixer), GST_STATE_NULL); ++ gst_object_unref (GST_OBJECT (self->_priv->mixer)); ++ g_list_foreach (self->_priv->mixer_tracks, (GFunc) g_object_unref, NULL); ++ g_list_free (self->_priv->mixer_tracks); ++ self->_priv->mixer = NULL; ++ self->_priv->mixer_tracks = NULL; ++ } ++ ++ self->_priv->timer_id = 0; ++ return FALSE; ++} ++ ++/* ++ * _acme_set_mixer ++ * @mixer A pointer to mixer element ++ * @data A pointer to user data (AcmeVolume instance to be modified) ++ * @return A gboolean indicating success if Master track was found, failed otherwises. ++ */ ++static gboolean ++_acme_set_mixer(GstMixer *mixer, gpointer user_data) ++{ ++ const GList *tracks; ++ ++ for (tracks = gst_mixer_list_tracks (mixer); tracks != NULL; tracks = tracks->next) { ++ GstMixerTrack *track = GST_MIXER_TRACK (tracks->data); ++ ++ if (GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_MASTER)) { ++ AcmeVolume *self; ++ ++ self = ACME_VOLUME (user_data); ++ ++ self->_priv->mixer = mixer; ++ self->_priv->mixer_tracks = g_list_append (self->_priv->mixer_tracks, g_object_ref (track)); ++ return TRUE; ++ } ++ ++ continue; ++ } ++ ++ return FALSE; ++} ++ ++/* This is a modified version of code from gnome-media's gst-mixer */ ++static gboolean ++acme_volume_open (AcmeVolume *self) ++{ ++ gchar *mixer_device, **factory_and_device = NULL; ++ GList *mixer_list; ++ ++ if (self->_priv->timer_id != 0) { ++ g_source_remove (self->_priv->timer_id); ++ self->_priv->timer_id = 0; ++ return TRUE; ++ } ++ ++ mixer_device = gconf_client_get_string (self->_priv->gconf_client, DEFAULT_MIXER_DEVICE_KEY, NULL); ++ if (mixer_device != NULL) ++ factory_and_device = g_strsplit (mixer_device, ":", 2); ++ ++ if (factory_and_device != NULL && factory_and_device[0] != NULL) { ++ GstElement *element; ++ ++ element = gst_element_factory_make (factory_and_device[0], NULL); ++ ++ if (element != NULL) { ++ if (factory_and_device[1] != NULL && ++ g_object_class_find_property (G_OBJECT_GET_CLASS (element), "device")) ++ g_object_set (G_OBJECT (element), "device", factory_and_device[1], NULL); ++ gst_element_set_state (element, GST_STATE_READY); ++ ++ if (GST_IS_MIXER (element)) ++ self->_priv->mixer = GST_MIXER (element); ++ else { ++ gst_element_set_state (element, GST_STATE_NULL); ++ gst_object_unref (element); ++ } ++ } ++ } ++ ++ g_free (mixer_device); ++ g_strfreev (factory_and_device); ++ ++ if (self->_priv->mixer != NULL) { ++ const GList *m; ++ GSList *tracks, *t; ++ GError *error = NULL; ++ ++ /* Try to use tracks saved in GConf ++ Note: errors need to be treated , for example if the user set a non type list for this key ++ or if the elements type_list are not "matched" */ ++ tracks = gconf_client_get_list (self->_priv->gconf_client, DEFAULT_MIXER_TRACKS_KEY, ++ GCONF_VALUE_STRING, &error); ++ ++ if (error) { ++ g_warning("ERROR: %s\n", error->message); ++ g_error_free(error); ++ } ++ ++ /* We use these tracks ONLY if they are supported on the system with the following mixer */ ++ for (m = gst_mixer_list_tracks (self->_priv->mixer); m != NULL; m = m->next) { ++ GstMixerTrack *track = GST_MIXER_TRACK (m->data); ++ ++ for (t = tracks; t != NULL; t = t->next) ++ if (!strcmp (t->data, track->label)) ++ self->_priv->mixer_tracks = g_list_append (self->_priv->mixer_tracks, g_object_ref (track)); ++ ++ } ++ ++ g_slist_foreach (tracks, (GFunc)g_free, NULL); ++ g_slist_free (tracks); ++ ++ /* If no track stored in GConf is avaiable try to use Master track */ ++ if (self->_priv->mixer_tracks == NULL) { ++ for (m = gst_mixer_list_tracks (self->_priv->mixer); m != NULL; m = m->next) { ++ GstMixerTrack *track = GST_MIXER_TRACK (m->data); ++ ++ if (GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_MASTER)) { ++ self->_priv->mixer_tracks = g_list_append (self->_priv->mixer_tracks, g_object_ref (track)); ++ break; ++ } ++ } ++ } ++ ++ if (self->_priv->mixer_tracks != NULL) ++ return TRUE; ++ else { ++ gst_element_set_state (GST_ELEMENT (self->_priv->mixer), GST_STATE_NULL); ++ gst_object_unref (self->_priv->mixer); ++ } ++ } ++ ++ /* Go through all elements of a certain class and check whether ++ * they implement a mixer. If so, walk through the tracks and look ++ * for first one named "volume". ++ * ++ * We should probably do something intelligent if we don't find an ++ * appropriate mixer/track. But now we do something stupid... ++ * everything just becomes a no-op. ++ */ ++ mixer_list = gst_audio_default_registry_mixer_filter (_acme_set_mixer, ++ TRUE, ++ self); ++ ++ if (mixer_list == NULL) ++ return FALSE; ++ ++ /* do not unref the mixer as we keep the ref for self->priv->mixer */ ++ g_list_free (mixer_list); ++ ++ return TRUE; ++} ++ ++static void ++acme_volume_close (AcmeVolume *self) ++{ ++ self->_priv->timer_id = g_timeout_add_seconds (TIMEOUT, ++ (GSourceFunc) acme_volume_close_real, self); ++} ++ ++static void ++acme_volume_init (AcmeVolume *self) ++{ ++ self->_priv = ACME_VOLUME_GET_PRIVATE (self); ++ self->_priv->gconf_client = gconf_client_get_default (); ++} ++ ++static void ++acme_volume_class_init (AcmeVolumeClass *klass) ++{ ++ G_OBJECT_CLASS (klass)->finalize = acme_volume_finalize; ++ ++ gst_init (NULL, NULL); ++ ++ g_type_class_add_private (klass, sizeof (AcmeVolumePrivate)); ++} ++ ++/* acme_volume_new ++ * @return A singleton instance of type AcmeVolume ++ */ ++AcmeVolume * ++acme_volume_new (void) ++{ ++ if (acme_volume_object == NULL) { ++ acme_volume_object = g_object_new (ACME_TYPE_VOLUME, NULL); ++ return ACME_VOLUME(acme_volume_object); ++ } ++ g_object_ref(acme_volume_object); ++ return ACME_VOLUME(acme_volume_object); ++} ++ +diff --git a/plugins/media-keys/cut-n-paste/gvc-gstreamer-acme-vol.h b/plugins/media-keys/cut-n-paste/gvc-gstreamer-acme-vol.h +new file mode 100644 +index 0000000..c14ebc8 +--- /dev/null ++++ b/plugins/media-keys/cut-n-paste/gvc-gstreamer-acme-vol.h +@@ -0,0 +1,56 @@ ++/* acme-volume.h ++ ++ Copyright (C) 2002, 2003 Bastien Nocera ++ Copyright (C) 2004 Novell, Inc. ++ Copyright (C) 2009 PERIER Romain <mrpouet@tuxfamily.org> ++ ++ The Gnome Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Library General Public License as ++ published by the Free Software Foundation; either version 2 of the ++ License, or (at your option) any later version. ++ ++ The Gnome 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 ++ Library General Public License for more details. ++ ++ You should have received a copy of the GNU Library General Public ++ License along with the Gnome Library; see the file COPYING.LIB. If not, ++ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, ++ Boston, MA 02111-1307, USA. ++ ++ Author: Bastien Nocera <hadess@hadess.net> ++ Jon Trowbridge <trow@ximian.com> ++ */ ++ ++#include <glib-object.h> ++ ++#define ACME_TYPE_VOLUME (acme_volume_get_type ()) ++#define ACME_VOLUME(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), ACME_TYPE_VOLUME, AcmeVolume)) ++#define ACME_VOLUME_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), ACME_TYPE_VOLUME, AcmeVolumeClass)) ++#define ACME_IS_VOLUME(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ACME_TYPE_VOLUME)) ++#define ACME_VOLUME_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), ACME_TYPE_VOLUME, AcmeVolumeClass)) ++ ++typedef struct AcmeVolume AcmeVolume; ++typedef struct AcmeVolumeClass AcmeVolumeClass; ++typedef struct AcmeVolumePrivate AcmeVolumePrivate; ++ ++struct AcmeVolume { ++ GObject parent; ++ AcmeVolumePrivate *_priv; ++}; ++ ++struct AcmeVolumeClass { ++ GObjectClass parent; ++}; ++ ++GType acme_volume_get_type (void); ++AcmeVolume *acme_volume_new (void); ++void acme_volume_set_mute (AcmeVolume *self, gboolean val); ++void acme_volume_mute_toggle (AcmeVolume *self); ++gboolean acme_volume_get_mute (AcmeVolume *self); ++void acme_volume_set_volume (AcmeVolume *self, gint val); ++gint acme_volume_get_volume (AcmeVolume *self); ++gint acme_volume_get_threshold (AcmeVolume *self); ++ ++ +diff --git a/plugins/media-keys/gsd-media-keys-manager.c b/plugins/media-keys/gsd-media-keys-manager.c +index b563f73..64893b5 100644 +--- a/plugins/media-keys/gsd-media-keys-manager.c ++++ b/plugins/media-keys/gsd-media-keys-manager.c +@@ -53,6 +53,8 @@ + #ifdef HAVE_PULSE + #include <canberra-gtk.h> + #include "gvc-mixer-control.h" ++#elif defined(HAVE_GSTREAMER) ++#include "gvc-gstreamer-acme-vol.h" + #endif /* HAVE_PULSE */ + + #define GSD_DBUS_PATH "/org/gnome/SettingsDaemon" +@@ -78,6 +80,8 @@ struct GsdMediaKeysManagerPrivate + /* Volume bits */ + GvcMixerControl *volume; + GvcMixerStream *stream; ++#elif defined(HAVE_GSTREAMER) ++ AcmeVolume *volume; + #endif /* HAVE_PULSE */ + GtkWidget *dialog; + GConfClient *conf_client; +@@ -650,14 +654,16 @@ do_touchpad_action (GsdMediaKeysManager *manager) + gconf_client_set_bool (client, TOUCHPAD_ENABLED_KEY, !state, NULL); + } + +-#ifdef HAVE_PULSE ++#if defined(HAVE_PULSE) || defined(HAVE_GSTREAMER) + static void + update_dialog (GsdMediaKeysManager *manager, + guint vol, + gboolean muted, + gboolean sound_changed) + { ++#ifdef HAVE_PULSE + vol = (int) (100 * (double) vol / PA_VOLUME_NORM); ++#endif + vol = CLAMP (vol, 0, 100); + + dialog_init (manager); +@@ -668,12 +674,14 @@ update_dialog (GsdMediaKeysManager *manager, + GSD_MEDIA_KEYS_WINDOW_ACTION_VOLUME); + dialog_show (manager); + ++#ifdef HAVE_PULSE + if (sound_changed != FALSE && muted == FALSE) + ca_gtk_play_for_widget (manager->priv->dialog, 0, + CA_PROP_EVENT_ID, "audio-volume-change", + CA_PROP_EVENT_DESCRIPTION, "volume changed through key press", + CA_PROP_APPLICATION_ID, "org.gnome.VolumeControl", + NULL); ++#endif + } + + static void +@@ -685,7 +693,11 @@ do_sound_action (GsdMediaKeysManager *manager, + int vol_step; + gboolean sound_changed; + ++#ifdef HAVE_PULSE + if (manager->priv->stream == NULL) ++#else ++ if (manager->priv->volume == NULL) ++#endif + return; + + vol_step = gconf_client_get_int (manager->priv->conf_client, +@@ -695,20 +707,35 @@ do_sound_action (GsdMediaKeysManager *manager, + if (vol_step <= 0 || vol_step > 100) + vol_step = VOLUME_STEP; + ++ sound_changed = FALSE; ++#ifdef HAVE_PULSE + norm_vol_step = PA_VOLUME_NORM * vol_step / 100; + + /* FIXME: this is racy */ + vol = gvc_mixer_stream_get_volume (manager->priv->stream); + muted = gvc_mixer_stream_get_is_muted (manager->priv->stream); +- sound_changed = FALSE; +- ++#else ++ if (vol_step > 0) { ++ gint threshold = acme_volume_get_threshold (manager->priv->volume); ++ if (vol_step < threshold) ++ vol_step = threshold; ++ g_debug ("Using volume step of %d", vol_step); ++ } ++ vol = acme_volume_get_volume (manager->priv->volume); ++ muted = acme_volume_get_mute (manager->priv->volume); ++#endif + switch (type) { + case MUTE_KEY: + muted = !muted; +- gvc_mixer_stream_change_is_muted (manager->priv->stream, muted); + sound_changed = TRUE; ++#ifdef HAVE_PULSE ++ gvc_mixer_stream_change_is_muted (manager->priv->stream, muted); ++#else ++ acme_volume_mute_toggle (manager->priv->volume); ++#endif + break; + case VOLUME_DOWN_KEY: ++#ifdef HAVE_PULSE + if (!muted && (vol <= norm_vol_step)) { + muted = !muted; + vol = 0; +@@ -724,11 +751,17 @@ do_sound_action (GsdMediaKeysManager *manager, + sound_changed = TRUE; + } + } ++#else ++ if (!muted && (vol <= vol_step)) ++ acme_volume_mute_toggle (manager->priv->volume); ++ acme_volume_set_volume (manager->priv->volume, vol - vol_step); ++#endif + break; + case VOLUME_UP_KEY: + if (muted) { + muted = !muted; + if (vol == 0) { ++#ifdef HAVE_PULSE + vol = vol + norm_vol_step; + gvc_mixer_stream_change_is_muted (manager->priv->stream, muted); + if (gvc_mixer_stream_set_volume (manager->priv->stream, vol) != FALSE) { +@@ -739,7 +772,15 @@ do_sound_action (GsdMediaKeysManager *manager, + gvc_mixer_stream_change_is_muted (manager->priv->stream, muted); + sound_changed = TRUE; + } ++#else ++ /* We need to unmute otherwise vol is blocked (and muted) */ ++ acme_volume_set_mute (manager->priv->volume, FALSE); ++ } ++ acme_volume_set_volume (manager->priv->volume, vol + vol_step); ++ ++#endif + } else { ++#ifdef HAVE_PULSE + if (vol < MAX_VOLUME) { + if (vol + norm_vol_step >= MAX_VOLUME) { + vol = MAX_VOLUME; +@@ -751,13 +792,18 @@ do_sound_action (GsdMediaKeysManager *manager, + sound_changed = TRUE; + } + } ++#else ++ acme_volume_set_volume (manager->priv->volume, vol + vol_step); ++#endif /* HAVE_PULSE */ + } + break; + } + + update_dialog (manager, vol, muted, sound_changed); + } ++#endif /* defined(HAVE_PULSE) || defined(HAVE_GSTREAMER) */ + ++#ifdef HAVE_PULSE + static void + update_default_sink (GsdMediaKeysManager *manager) + { +@@ -793,7 +839,6 @@ on_control_default_sink_changed (GvcMixerControl *control, + { + update_default_sink (manager); + } +- + #endif /* HAVE_PULSE */ + + static gint +@@ -919,9 +964,9 @@ do_action (GsdMediaKeysManager *manager, + case MUTE_KEY: + case VOLUME_DOWN_KEY: + case VOLUME_UP_KEY: +-#ifdef HAVE_PULSE ++#if defined(HAVE_PULSE) || defined(HAVE_GSTREAMER) + do_sound_action (manager, type); +-#endif /* HAVE_PULSE */ ++#endif /* HAVE_PULSE || HAVE_GSTREAMER */ + break; + case POWER_KEY: + do_exit_action (manager); +@@ -1122,6 +1167,10 @@ gsd_media_keys_manager_start (GsdMediaKeysManager *manager, + gvc_mixer_control_open (manager->priv->volume); + + gnome_settings_profile_end ("gvc_mixer_control_new"); ++#elif defined(HAVE_GSTREAMER) ++ gnome_settings_profile_start ("acme_volume_new"); ++ manager->priv->volume = acme_volume_new (); ++ gnome_settings_profile_end ("acme_volume_new"); + #endif /* HAVE_PULSE */ + g_idle_add ((GSourceFunc) start_media_keys_idle_cb, manager); + +@@ -1199,6 +1248,7 @@ gsd_media_keys_manager_stop (GsdMediaKeysManager *manager) + g_object_unref (priv->stream); + priv->stream = NULL; + } ++#elif defined(HAVE_GSTREAMER) + + if (priv->volume) { + g_object_unref (priv->volume); +-- +1.7.0.3 + diff --git a/gnome-base/gnome-settings-daemon/files/gnome-settings-daemon-2.30.0-osd-notifications.patch b/gnome-base/gnome-settings-daemon/files/gnome-settings-daemon-2.30.0-osd-notifications.patch new file mode 100644 index 0000000..9b2f131 --- /dev/null +++ b/gnome-base/gnome-settings-daemon/files/gnome-settings-daemon-2.30.0-osd-notifications.patch @@ -0,0 +1,670 @@ + plugins/common/Makefile.am | 9 +- + plugins/common/gsd-osd-notification.c | 296 +++++++++++++++++++++++++++ + plugins/common/gsd-osd-notification.h | 75 +++++++ + plugins/media-keys/gsd-media-keys-manager.c | 106 +++++++--- + 4 files changed, 456 insertions(+), 30 deletions(-) + +diff --git a/plugins/common/Makefile.am b/plugins/common/Makefile.am +index 447d02d..94ad74f 100644 +--- a/plugins/common/Makefile.am ++++ b/plugins/common/Makefile.am +@@ -7,17 +7,22 @@ libcommon_la_SOURCES = \ + gsd-keygrab.c \ + gsd-keygrab.h \ + gsd-osd-window.c \ +- gsd-osd-window.h ++ gsd-osd-window.h \ ++ gsd-osd-notification.c \ ++ gsd-osd-notification.h + + libcommon_la_CPPFLAGS = \ + $(AM_CPPFLAGS) + + libcommon_la_CFLAGS = \ + $(SETTINGS_PLUGIN_CFLAGS) \ ++ $(LIBNOTIFY_CFLAGS) \ + $(AM_CFLAGS) + + libcommon_la_LDFLAGS = \ + $(GSD_PLUGIN_LDFLAGS) $(X11_LIBS) + + libcommon_la_LIBADD = \ +- $(SETTINGS_PLUGIN_LIBS) ++ $(SETTINGS_PLUGIN_LIBS) \ ++ $(LIBNOTIFY_LIBS) ++ +diff --git a/plugins/common/gsd-osd-notification.c b/plugins/common/gsd-osd-notification.c +new file mode 100644 +index 0000000..8ebc5a5 +--- /dev/null ++++ b/plugins/common/gsd-osd-notification.c +@@ -0,0 +1,296 @@ ++/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8; tab-width: 8 -*- */ ++/* ++ * gsd-osd-notification.c ++ * Copyright (C) 2010 Chris Coulson <chrisccoulson@ubuntu.com> ++ * Copyright (C) 2009 Canonical Ltd ++ * ++ * gsd-osd-notification.c 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 3 of the License, or ++ * (at your option) any later version. ++ * ++ * gsd-osd-notification.c 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, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#include <libnotify/notify.h> ++#include "gsd-osd-notification.h" ++ ++struct _GsdOsdNotificationPrivate ++{ ++ NotifyNotification *notification; ++ char **icon_names; ++ char *hint; ++ guint icon_array_size; ++}; ++ ++#define GSD_OSD_NOTIFICATION_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_OSD_NOTIFICATION, GsdOsdNotificationPrivate)) ++ ++enum ++{ ++ PROP_0, ++ PROP_ICON_NAMES, ++ PROP_HINT ++}; ++ ++static NotifyNotification *icon_only_notification = NULL; ++static gulong handler_id; ++ ++#define NOTIFY_CAP_PRIVATE_SYNCHRONOUS "x-canonical-private-synchronous" ++#define NOTIFY_CAP_PRIVATE_ICON_ONLY "x-canonical-private-icon-only" ++#define NOTIFY_HINT_TRUE "true" ++ ++G_DEFINE_TYPE (GsdOsdNotification, gsd_osd_notification, G_TYPE_OBJECT); ++ ++static const char* ++_calculate_icon (GsdOsdNotification *notifier, guint value, gboolean muted) ++{ ++ guint s; ++ ++ s = (notifier->priv->icon_array_size -1) * value / 100 + 1; ++ s = MAX (s, 1); ++ s = MIN (s, notifier->priv->icon_array_size -1); ++ if (value <= 0) ++ s = 0; ++ ++ return muted ? notifier->priv->icon_names[0] : notifier->priv->icon_names[s]; ++} ++ ++void ++gsd_osd_notification_set_icon_array (GsdOsdNotification *notifier, const char **icon_names) ++{ ++ g_return_if_fail (GSD_IS_OSD_NOTIFICATION (notifier)); ++ ++ g_strfreev (notifier->priv->icon_names); ++ notifier->priv->icon_names = g_strdupv ((gchar **) icon_names); ++ ++ notifier->priv->icon_array_size = g_strv_length ((gchar **) icon_names); ++} ++ ++void ++gsd_osd_notification_set_hint (GsdOsdNotification *notifier, const char *hint) ++{ ++ g_return_if_fail (GSD_IS_OSD_NOTIFICATION (notifier)); ++ ++ g_free (notifier->priv->hint); ++ notifier->priv->hint = g_strdup (hint); ++} ++ ++gboolean ++gsd_osd_notification_is_supported (void) ++{ ++ GList *caps; ++ gboolean has_cap; ++ ++ caps = notify_get_server_caps (); ++ has_cap = (g_list_find_custom (caps, NOTIFY_CAP_PRIVATE_SYNCHRONOUS, (GCompareFunc) g_strcmp0) != NULL); ++ g_list_foreach (caps, (GFunc) g_free, NULL); ++ g_list_free (caps); ++ ++ return has_cap; ++} ++ ++static void ++notification_closed_cb (NotifyNotification *notification, ++ gpointer data) ++{ ++ g_signal_handler_disconnect (icon_only_notification, handler_id); ++ g_object_unref (icon_only_notification); ++ icon_only_notification = NULL; ++} ++ ++gboolean ++gsd_osd_notification_show_icon_only (const char *icon, const char *hint) ++{ ++ g_return_val_if_fail (icon != NULL, FALSE); ++ g_return_val_if_fail (hint != NULL, FALSE); ++ ++ if (!gsd_osd_notification_is_supported ()) ++ return FALSE; ++ ++ if (icon_only_notification == NULL) { ++ icon_only_notification = notify_notification_new (" ", "", icon, NULL); ++ notify_notification_set_hint_string (icon_only_notification, NOTIFY_CAP_PRIVATE_SYNCHRONOUS, hint); ++ notify_notification_set_hint_string (icon_only_notification, NOTIFY_CAP_PRIVATE_ICON_ONLY, NOTIFY_HINT_TRUE); ++ handler_id = g_signal_connect (icon_only_notification, "closed", G_CALLBACK (notification_closed_cb), NULL); ++ } else { ++ notify_notification_set_hint_string (icon_only_notification, NOTIFY_CAP_PRIVATE_SYNCHRONOUS, hint); ++ notify_notification_update (icon_only_notification, " ", "", icon); ++ } ++ ++ if (!notify_notification_show (icon_only_notification, NULL)) { ++ g_signal_handler_disconnect (icon_only_notification, handler_id); ++ g_object_unref (icon_only_notification); ++ icon_only_notification = NULL; ++ return FALSE; ++ } ++ ++ return TRUE; ++} ++ ++gboolean ++gsd_osd_notification_show_value (GsdOsdNotification *notifier, gint value, gboolean muted) ++{ ++ const char *icon; ++ ++ g_return_val_if_fail (GSD_IS_OSD_NOTIFICATION (notifier), FALSE); ++ g_return_val_if_fail (notifier->priv->icon_names != NULL, FALSE); ++ g_return_val_if_fail (notifier->priv->hint != NULL, FALSE); ++ ++ if (!gsd_osd_notification_is_supported ()) ++ return FALSE; ++ ++ if (notifier->priv->notification == NULL) { ++ notifier->priv->notification = notify_notification_new (" ", "", NULL, NULL); ++ notify_notification_set_hint_string (notifier->priv->notification, NOTIFY_CAP_PRIVATE_SYNCHRONOUS, notifier->priv->hint); ++} ++ if (notifier->priv->notification != NULL) { ++ value = MIN (value, 101); ++ value = MAX (value, -1); ++ icon = _calculate_icon (notifier, value, muted); ++ notify_notification_set_hint_int32(notifier->priv->notification, "value", (muted && value > 0) ? 0 : value); ++ notify_notification_update (notifier->priv->notification, " ", "", icon); ++ } else { ++ return FALSE; ++ } ++ ++ if (!notify_notification_show (notifier->priv->notification, NULL)) ++ return FALSE; ++ ++ return TRUE; ++} ++ ++gboolean ++gsd_osd_notification_show_overshoot (GsdOsdNotification *notifier, GsdOsdNotifierOvershootType type) ++{ ++ gint value; ++ gboolean muted; ++ ++ g_return_val_if_fail (type == GSD_OSD_NOTIFICATION_UNDERSHOOT || type == GSD_OSD_NOTIFICATION_OVERSHOOT, FALSE); ++ ++ switch (type) ++ { ++ case GSD_OSD_NOTIFICATION_UNDERSHOOT: ++ value = -1; ++ muted = TRUE; ++ break; ++ case GSD_OSD_NOTIFICATION_OVERSHOOT: ++ value = 101; ++ muted = FALSE; ++ break; ++ default: ++ g_assert_not_reached (); ++ break; ++ } ++ ++ return gsd_osd_notification_show_value (notifier, value, muted); ++} ++ ++GsdOsdNotification* ++gsd_osd_notification_new (const char **icon_names, const char *hint) ++{ ++ return (GsdOsdNotification *) g_object_new (GSD_TYPE_OSD_NOTIFICATION, ++ "icon-names", icon_names, ++ "hint", hint, ++ NULL); ++} ++ ++static void ++gsd_osd_notification_init (GsdOsdNotification *object) ++{ ++ object->priv = GSD_OSD_NOTIFICATION_PRIVATE (object); ++ ++ if (!notify_is_initted ()) ++ notify_init (g_get_application_name ()); ++ ++ object->priv->hint = NULL; ++ object->priv->icon_names = NULL; ++ object->priv->notification = NULL; ++} ++ ++static void ++gsd_osd_notification_finalize (GObject *object) ++{ ++ GsdOsdNotification *notifier = GSD_OSD_NOTIFICATION (object); ++ ++ g_strfreev (notifier->priv->icon_names); ++ g_free (notifier->priv->hint); ++ ++ if (notifier->priv->notification) ++ g_object_unref (notifier->priv->notification); ++ ++ G_OBJECT_CLASS (gsd_osd_notification_parent_class)->finalize (object); ++} ++ ++static void ++gsd_osd_notification_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) ++{ ++ g_return_if_fail (GSD_IS_OSD_NOTIFICATION (object)); ++ GsdOsdNotification *notifier = GSD_OSD_NOTIFICATION (object); ++ ++ switch (prop_id) ++ { ++ case PROP_ICON_NAMES: ++ gsd_osd_notification_set_icon_array (notifier, (const char**) g_value_get_boxed (value)); ++ break; ++ case PROP_HINT: ++ gsd_osd_notification_set_hint (notifier, g_value_get_string (value)); ++ break; ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); ++ break; ++ } ++} ++ ++static void ++gsd_osd_notification_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) ++{ ++ g_return_if_fail (GSD_IS_OSD_NOTIFICATION (object)); ++ GsdOsdNotification *notifier = GSD_OSD_NOTIFICATION (object); ++ ++ switch (prop_id) ++ { ++ case PROP_ICON_NAMES: ++ g_value_set_boxed (value, notifier->priv->icon_names); ++ break; ++ case PROP_HINT: ++ g_value_set_string (value, notifier->priv->hint); ++ break; ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); ++ break; ++ } ++} ++ ++static void ++gsd_osd_notification_class_init (GsdOsdNotificationClass *klass) ++{ ++ GObjectClass* object_class = G_OBJECT_CLASS (klass); ++ ++ object_class->finalize = gsd_osd_notification_finalize; ++ object_class->set_property = gsd_osd_notification_set_property; ++ object_class->get_property = gsd_osd_notification_get_property; ++ ++ g_object_class_install_property (object_class, ++ PROP_ICON_NAMES, ++ g_param_spec_boxed ("icon-names", ++ "Icon name array", ++ "An array of icon names for the notification", ++ G_TYPE_STRV, ++ G_PARAM_WRITABLE | G_PARAM_CONSTRUCT)); ++ ++ g_object_class_install_property (object_class, ++ PROP_HINT, ++ g_param_spec_string ("hint", ++ "Notification hint", ++ "Hint for the notification", ++ NULL, ++ G_PARAM_WRITABLE | G_PARAM_CONSTRUCT)); ++ ++ g_type_class_add_private (klass, sizeof (GsdOsdNotificationPrivate)); ++} +diff --git a/plugins/common/gsd-osd-notification.h b/plugins/common/gsd-osd-notification.h +new file mode 100644 +index 0000000..8205639 +--- /dev/null ++++ b/plugins/common/gsd-osd-notification.h +@@ -0,0 +1,75 @@ ++/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8; tab-width: 8 -*- */ ++/* ++ * gsd-osd-notification.c ++ * Copyright (C) 2010 Chris Coulson <chrisccoulson@ubuntu.com> ++ * Copyright (C) 2009 Canonical Ltd ++ * ++ * gsd-osd-notification.c 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 3 of the License, or ++ * (at your option) any later version. ++ * ++ * gsd-osd-notification.c 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, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#ifndef _GSD_OSD_NOTIFICATION_H_ ++#define _GSD_OSD_NOTIFICATION_H_ ++ ++#include <glib-object.h> ++ ++G_BEGIN_DECLS ++ ++#define GSD_TYPE_OSD_NOTIFICATION (gsd_osd_notification_get_type ()) ++#define GSD_OSD_NOTIFICATION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSD_TYPE_OSD_NOTIFICATION, GsdOsdNotification)) ++#define GSD_OSD_NOTIFICATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSD_TYPE_OSD_NOTIFICATION, GsdOsdNotificationClass)) ++#define GSD_IS_OSD_NOTIFICATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSD_TYPE_OSD_NOTIFICATION)) ++#define GSD_IS_OSD_NOTIFICATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSD_TYPE_OSD_NOTIFICATION)) ++#define GSD_OSD_NOTIFICATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSD_TYPE_OSD_NOTIFICATION, GsdOsdNotificationClass)) ++ ++typedef struct _GsdOsdNotificationClass GsdOsdNotificationClass; ++typedef struct _GsdOsdNotification GsdOsdNotification; ++typedef struct _GsdOsdNotificationPrivate GsdOsdNotificationPrivate; ++ ++struct _GsdOsdNotificationClass ++{ ++ GObjectClass parent_class; ++}; ++ ++struct _GsdOsdNotification ++{ ++ GObject parent_instance; ++ ++ GsdOsdNotificationPrivate *priv; ++}; ++ ++typedef enum { ++ GSD_OSD_NOTIFICATION_NO_OVERSHOOT = 0, ++ GSD_OSD_NOTIFICATION_UNDERSHOOT, ++ GSD_OSD_NOTIFICATION_OVERSHOOT, ++} GsdOsdNotifierOvershootType; ++ ++GType gsd_osd_notification_get_type (void) G_GNUC_CONST; ++GsdOsdNotification* gsd_osd_notification_new (const char **icon_names, ++ const char *hint); ++void gsd_osd_notification_set_icon_array (GsdOsdNotification *notifier, ++ const char **icon_names); ++void gsd_osd_notification_set_hint (GsdOsdNotification *notifier, ++ const char *hint); ++gboolean gsd_osd_notification_is_supported (void); ++gboolean gsd_osd_notification_show_value (GsdOsdNotification *notifier, ++ gint value, ++ gboolean muted); ++gboolean gsd_osd_notification_show_overshoot (GsdOsdNotification *notifier, ++ GsdOsdNotifierOvershootType type); ++gboolean gsd_osd_notification_show_icon_only (const char *icon, ++ const char *hint); ++ ++G_END_DECLS ++ ++#endif /* _GSD_OSD_NOTIFICATION_H_ */ +diff --git a/plugins/media-keys/gsd-media-keys-manager.c b/plugins/media-keys/gsd-media-keys-manager.c +index 64893b5..ef977f0 100644 +--- a/plugins/media-keys/gsd-media-keys-manager.c ++++ b/plugins/media-keys/gsd-media-keys-manager.c +@@ -49,6 +49,7 @@ + #include "eggaccelerators.h" + #include "acme.h" + #include "gsd-media-keys-window.h" ++#include "gsd-osd-notification.h" + + #ifdef HAVE_PULSE + #include <canberra-gtk.h> +@@ -86,6 +87,7 @@ struct GsdMediaKeysManagerPrivate + GtkWidget *dialog; + GConfClient *conf_client; + GVolumeMonitor *volume_monitor; ++ GsdOsdNotification *notifier; + + /* Multihead stuff */ + GdkScreen *current_screen; +@@ -112,6 +114,13 @@ G_DEFINE_TYPE (GsdMediaKeysManager, gsd_media_keys_manager, G_TYPE_OBJECT) + + static gpointer manager_object = NULL; + ++static const char *volume_icons[] = { ++ "notification-audio-volume-muted", ++ "notification-audio-volume-low", ++ "notification-audio-volume-medium", ++ "notification-audio-volume-high", ++ NULL ++}; + + static void + init_screens (GsdMediaKeysManager *manager) +@@ -616,12 +625,14 @@ do_eject_action (GsdMediaKeysManager *manager) + } + + /* Show the dialogue */ +- dialog_init (manager); +- gsd_media_keys_window_set_action_custom (GSD_MEDIA_KEYS_WINDOW (manager->priv->dialog), +- "media-eject", +- FALSE); +- dialog_show (manager); +- ++ if (!gsd_osd_notification_show_icon_only ("notification-device-eject", "Eject")) { ++ dialog_init (manager); ++ gsd_media_keys_window_set_action_custom (GSD_MEDIA_KEYS_WINDOW (manager->priv->dialog), ++ "media-eject", ++ FALSE); ++ dialog_show (manager); ++ } ++ + /* Clean up the drive selection and exit if no suitable + * drives are found */ + if (fav_drive != NULL) +@@ -645,12 +656,14 @@ do_touchpad_action (GsdMediaKeysManager *manager) + GConfClient *client = manager->priv->conf_client; + gboolean state = gconf_client_get_bool (client, TOUCHPAD_ENABLED_KEY, NULL); + +- dialog_init (manager); +- gsd_media_keys_window_set_action_custom (GSD_MEDIA_KEYS_WINDOW (manager->priv->dialog), +- (!state) ? "touchpad-enabled" : "touchpad-disabled", +- FALSE); +- dialog_show (manager); +- ++ if (!gsd_osd_notification_show_icon_only ((!state) ? "touchpad-enabled" : "touchpad-disabled", "Touchpad")) { ++ dialog_init (manager); ++ gsd_media_keys_window_set_action_custom (GSD_MEDIA_KEYS_WINDOW (manager->priv->dialog), ++ (!state) ? "touchpad-enabled" : "touchpad-disabled", ++ FALSE); ++ dialog_show (manager); ++ } ++ + gconf_client_set_bool (client, TOUCHPAD_ENABLED_KEY, !state, NULL); + } + +@@ -659,11 +672,20 @@ static void + update_dialog (GsdMediaKeysManager *manager, + guint vol, + gboolean muted, +- gboolean sound_changed) ++ gboolean sound_changed, ++ GsdOsdNotifierOvershootType overshoot) + { ++ GtkWidget *window; + #ifdef HAVE_PULSE + vol = (int) (100 * (double) vol / PA_VOLUME_NORM); + #endif ++ if (overshoot != GSD_OSD_NOTIFICATION_NO_OVERSHOOT) { ++ if (gsd_osd_notification_show_overshoot (manager->priv->notifier, overshoot)) ++ goto done; ++ } else { ++ if (gsd_osd_notification_show_value (manager->priv->notifier, vol, muted)) ++ goto done; ++ } + vol = CLAMP (vol, 0, 100); + + dialog_init (manager); +@@ -673,14 +695,25 @@ update_dialog (GsdMediaKeysManager *manager, + gsd_media_keys_window_set_action (GSD_MEDIA_KEYS_WINDOW (manager->priv->dialog), + GSD_MEDIA_KEYS_WINDOW_ACTION_VOLUME); + dialog_show (manager); +- ++done: + #ifdef HAVE_PULSE +- if (sound_changed != FALSE && muted == FALSE) +- ca_gtk_play_for_widget (manager->priv->dialog, 0, +- CA_PROP_EVENT_ID, "audio-volume-change", +- CA_PROP_EVENT_DESCRIPTION, "volume changed through key press", +- CA_PROP_APPLICATION_ID, "org.gnome.VolumeControl", +- NULL); ++ if (sound_changed != FALSE && muted == FALSE) { ++ if (manager->priv->dialog == NULL) { ++ window = gtk_window_new (GTK_WINDOW_TOPLEVEL); ++ gtk_window_set_screen (GTK_WINDOW (window), manager->priv->current_screen); ++ gtk_widget_realize (window); ++ play_volume_event_sound (window); ++ gtk_widget_destroy (window); ++ } else { ++ ca_gtk_play_for_widget (manager->priv->dialog, 0, ++ CA_PROP_EVENT_ID, "audio-volume-change", ++ CA_PROP_EVENT_DESCRIPTION, "volume changed through key press", ++ CA_PROP_APPLICATION_ID, "org.gnome.VolumeControl", ++ NULL); ++ } ++ } ++#else ++ return; + #endif + } + +@@ -691,6 +724,7 @@ do_sound_action (GsdMediaKeysManager *manager, + gboolean muted; + guint vol, norm_vol_step; + int vol_step; ++ GsdOsdNotifierOvershootType overshoot = GSD_OSD_NOTIFICATION_NO_OVERSHOOT; + gboolean sound_changed; + + #ifdef HAVE_PULSE +@@ -743,17 +777,23 @@ do_sound_action (GsdMediaKeysManager *manager, + if (gvc_mixer_stream_set_volume (manager->priv->stream, vol) != FALSE) { + gvc_mixer_stream_push_volume (manager->priv->stream); + sound_changed = TRUE; ++ } else { ++ overshoot = GSD_OSD_NOTIFICATION_UNDERSHOOT; + } + } else if (!muted) { + vol = vol - norm_vol_step; + if (gvc_mixer_stream_set_volume (manager->priv->stream, vol) != FALSE) { + gvc_mixer_stream_push_volume (manager->priv->stream); + sound_changed = TRUE; ++ } else { ++ overshoot = GSD_OSD_NOTIFICATION_UNDERSHOOT; + } + } + #else +- if (!muted && (vol <= vol_step)) ++ if (!muted && (vol <= vol_step)) { + acme_volume_mute_toggle (manager->priv->volume); ++ overshoot = GSD_OSD_NOTIFICATION_UNDERSHOOT; ++ } + acme_volume_set_volume (manager->priv->volume, vol - vol_step); + #endif + break; +@@ -767,6 +807,8 @@ do_sound_action (GsdMediaKeysManager *manager, + if (gvc_mixer_stream_set_volume (manager->priv->stream, vol) != FALSE) { + gvc_mixer_stream_push_volume (manager->priv->stream); + sound_changed = TRUE; ++ } else { ++ overshoot = GSD_OSD_NOTIFICATION_OVERSHOOT; + } + } else { + gvc_mixer_stream_change_is_muted (manager->priv->stream, muted); +@@ -777,7 +819,6 @@ do_sound_action (GsdMediaKeysManager *manager, + acme_volume_set_mute (manager->priv->volume, FALSE); + } + acme_volume_set_volume (manager->priv->volume, vol + vol_step); +- + #endif + } else { + #ifdef HAVE_PULSE +@@ -794,12 +835,14 @@ do_sound_action (GsdMediaKeysManager *manager, + } + #else + acme_volume_set_volume (manager->priv->volume, vol + vol_step); ++ if (acme_volume_get_volume (manager->priv->volume) == 100) ++ overshoot = GSD_OSD_NOTIFICATION_OVERSHOOT; + #endif /* HAVE_PULSE */ + } + break; + } + +- update_dialog (manager, vol, muted, sound_changed); ++ update_dialog (manager, vol, muted, sound_changed, overshoot); + } + #endif /* defined(HAVE_PULSE) || defined(HAVE_GSTREAMER) */ + +@@ -945,8 +988,11 @@ gsd_media_player_key_pressed (GsdMediaKeysManager *manager, + + static gboolean + do_multimedia_player_action (GsdMediaKeysManager *manager, ++ const char *icon, + const char *key) + { ++ if (icon != NULL) ++ gsd_osd_notification_show_icon_only (icon, key); + return gsd_media_player_key_pressed (manager, key); + } + +@@ -1017,19 +1063,19 @@ do_action (GsdMediaKeysManager *manager, + execute (manager, "gcalctool", FALSE, FALSE); + break; + case PLAY_KEY: +- return do_multimedia_player_action (manager, "Play"); ++ return do_multimedia_player_action (manager, NULL, "Play"); + break; + case PAUSE_KEY: +- return do_multimedia_player_action (manager, "Pause"); ++ return do_multimedia_player_action (manager, NULL, "Pause"); + break; + case STOP_KEY: +- return do_multimedia_player_action (manager, "Stop"); ++ return do_multimedia_player_action (manager, NULL, "Stop"); + break; + case PREVIOUS_KEY: +- return do_multimedia_player_action (manager, "Previous"); ++ return do_multimedia_player_action (manager, NULL, "Previous"); + break; + case NEXT_KEY: +- return do_multimedia_player_action (manager, "Next"); ++ return do_multimedia_player_action (manager, NULL, "Next"); + break; + default: + g_assert_not_reached (); +@@ -1172,6 +1218,7 @@ gsd_media_keys_manager_start (GsdMediaKeysManager *manager, + manager->priv->volume = acme_volume_new (); + gnome_settings_profile_end ("acme_volume_new"); + #endif /* HAVE_PULSE */ ++ manager->priv->notifier = gsd_osd_notification_new (volume_icons, "volume"); + g_idle_add ((GSourceFunc) start_media_keys_idle_cb, manager); + + gnome_settings_profile_end (NULL); +@@ -1268,6 +1315,9 @@ gsd_media_keys_manager_stop (GsdMediaKeysManager *manager) + } + g_list_free (priv->media_players); + priv->media_players = NULL; ++ ++ if (manager->priv->notifier != NULL) ++ g_object_unref (manager->priv->notifier); + } + + static void diff --git a/gnome-base/gnome-settings-daemon/gnome-settings-daemon-2.30.0-r1.ebuild b/gnome-base/gnome-settings-daemon/gnome-settings-daemon-2.30.0-r1.ebuild new file mode 100644 index 0000000..cdd9471 --- /dev/null +++ b/gnome-base/gnome-settings-daemon/gnome-settings-daemon-2.30.0-r1.ebuild @@ -0,0 +1,85 @@ +# Copyright 1999-2010 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: $ + +EAPI="2" + +inherit autotools eutils gnome2 + +DESCRIPTION="Gnome Settings Daemon" +HOMEPAGE="http://www.gnome.org" + +LICENSE="GPL-2" +SLOT="0" +KEYWORDS="~alpha ~amd64 ~arm ~hppa ~ia64 ~ppc ~ppc64 ~sh ~sparc ~x86 ~x86-fbsd ~x86-freebsd ~amd64-linux ~x86-linux ~x86-solaris" +IUSE="debug libnotify pulseaudio" + +RDEPEND=">=dev-libs/dbus-glib-0.74 + >=dev-libs/glib-2.18.0 + >=x11-libs/gtk+-2.16 + >=gnome-base/gconf-2.6.1 + >=gnome-base/libgnomekbd-2.29.5 + >=gnome-base/gnome-desktop-2.29.92 + + x11-libs/libX11 + x11-libs/libXi + x11-libs/libXrandr + x11-libs/libXext + x11-libs/libXxf86misc + >=x11-libs/libxklavier-5.0 + media-libs/fontconfig + + libnotify? ( >=x11-libs/libnotify-0.4.3 ) + pulseaudio? ( + >=media-sound/pulseaudio-0.9.15 + media-libs/libcanberra[gtk] ) + !pulseaudio? ( + >=media-libs/gstreamer-0.10.1.2 + >=media-libs/gst-plugins-base-0.10.1.2 )" +DEPEND="${RDEPEND} + !<gnome-base/gnome-control-center-2.22 + sys-devel/gettext + >=dev-util/intltool-0.40 + >=dev-util/pkgconfig-0.19 + x11-proto/inputproto + x11-proto/xproto" + +# README is empty +DOCS="AUTHORS NEWS ChangeLog MAINTAINERS" + +pkg_setup() { + G2CONF="${G2CONF} + --disable-static + $(use_enable debug) + $(use_with libnotify) + $(use_enable pulseaudio pulse) + $(use_enable !pulseaudio gstreamer)" + + if use pulseaudio; then + elog "Building volume media keys using Pulseaudio" + else + elog "Building volume media keys using GStreamer" + fi +} + +src_prepare() { + gnome2_src_prepare + + # Restore gstreamer volume control support, upstream bug #571145 + epatch "${FILESDIR}/${PN}-2.30.0-gst-vol-control-support.patch" + + # Use OSD notifications (import from ubuntu) + epatch "${FILESDIR}/${PN}-2.30.0-osd-notifications.patch" + + intltoolize --force --copy --automake || die "intltoolize failed" + eautoreconf +} + +pkg_postinst() { + gnome2_pkg_postinst + + if ! use pulseaudio; then + elog "GStreamer volume control support is a feature powered by Gentoo GNOME Team" + elog "PLEASE DO NOT report bugs upstream, report on https://bugs.gentoo.org instead" + fi +} diff --git a/gnome-extra/xchat-indicator/Manifest b/gnome-extra/xchat-indicator/Manifest new file mode 100644 index 0000000..2670f0a --- /dev/null +++ b/gnome-extra/xchat-indicator/Manifest @@ -0,0 +1,2 @@ +DIST xchat-indicator-0.3.2.tar.gz 287084 RMD160 c5861a86f856c2947ac86f0072d239a39dbc2945 SHA1 5da1f32a179cf0f41081149b6555b9c20056d6c1 SHA256 3ae672df9e9d3f67eae3bde2d344927a926d89e427f6e92829809bf5e201521a +EBUILD xchat-indicator-0.3.2.ebuild 869 RMD160 ce83a65839bd0acd9fcdc6ad6b8c5682517673e9 SHA1 bb557dc9edcbd7df8b38dccab4774c780642376e SHA256 c64f3ba517f34e89040f94dab214f2f989052827526deba0c871085a7effe6df diff --git a/gnome-extra/xchat-indicator/xchat-indicator-0.3.2.ebuild b/gnome-extra/xchat-indicator/xchat-indicator-0.3.2.ebuild new file mode 100644 index 0000000..7fc31f9 --- /dev/null +++ b/gnome-extra/xchat-indicator/xchat-indicator-0.3.2.ebuild @@ -0,0 +1,35 @@ +# Copyright 1999-2010 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: $ + +EAPI="2" + +inherit gnome2 + +DESCRIPTION="Plugin to make XChat use the messaging indicator" +HOMEPAGE="https://launchpad.net/xchat-indicator" +SRC_URI="http://launchpad.net/${PN}/trunk/${PV}/+download/${P}.tar.gz" + +LICENSE="GPL-2" +SLOT="0" +KEYWORDS="~amd64" +IUSE="" + +RDEPEND=">=x11-libs/gtk+-2.14.0 + >=dev-libs/libindicate-0.3.0 + net-irc/xchat-gnome" +DEPEND="${COMMON_DEPEND} + dev-util/pkgconfig" + +pkg_setup() { + G2CONF="--disable-dependency-tracking --disable-static" + DOCS="AUTHORS NEWS" +} + +src_prepare() { + gnome2_src_prepare + + # Don't use embedded header, use system header instead. + # xchat-gnome installs its own xchat-gnome/xchat-plugin.h so we've to use it + sed "s:\"\(xchat-plugin.h\)\":<xchat-gnome/\1>:g" -i indicator.c || die "sed failed" +} |