diff options
author | Nirbheek Chauhan <nirbheek@gentoo.org> | 2009-04-08 14:53:00 +0530 |
---|---|---|
committer | Nirbheek Chauhan <nirbheek@gentoo.org> | 2009-04-08 15:36:28 +0530 |
commit | 4515789c73f8581142924c66fe034e5a4ef3f137 (patch) | |
tree | e0677ee1f2d2ae15b0e93b4c275dbd8ed9c123f6 /gnome-base/gnome-settings-daemon/files | |
parent | net-libs/libnice: Tests no longer fail (diff) | |
download | gnome-4515789c73f8581142924c66fe034e5a4ef3f137.tar.gz gnome-4515789c73f8581142924c66fe034e5a4ef3f137.tar.bz2 gnome-4515789c73f8581142924c66fe034e5a4ef3f137.zip |
gnome-base/gnome-settings-daemon: Bump to 2.26.0
* And update patch for vol control (by mrpouet)
* yay for mrpouet! :)
modified: Manifest
deleted: files/gnome-settings-daemon-2.25.92-readd-AcmeVolume-support.patch
new file: files/gnome-settings-daemon-2.26.0-readd-gst-vol-control-support.patch
renamed: gnome-settings-daemon-2.25.92.ebuild -> gnome-settings-daemon-2.26.0.ebuild
Diffstat (limited to 'gnome-base/gnome-settings-daemon/files')
2 files changed, 915 insertions, 2053 deletions
diff --git a/gnome-base/gnome-settings-daemon/files/gnome-settings-daemon-2.25.92-readd-AcmeVolume-support.patch b/gnome-base/gnome-settings-daemon/files/gnome-settings-daemon-2.25.92-readd-AcmeVolume-support.patch deleted file mode 100644 index 9e9d2872..00000000 --- a/gnome-base/gnome-settings-daemon/files/gnome-settings-daemon-2.25.92-readd-AcmeVolume-support.patch +++ /dev/null @@ -1,2053 +0,0 @@ -From 26040f5f39c0a088d73c358927cf8fbae0d8ec66 Mon Sep 17 00:00:00 2001 -From: Nirbheek Chauhan <nirbheek.chauhan@gmail.com> -Date: Tue, 10 Feb 2009 11:03:36 +0530 -Subject: [PATCH] Re-add AcmeVolume support - ---- - configure.ac | 101 +++++ - plugins/media-keys/Makefile.am | 30 +- - plugins/media-keys/actions/Makefile.am | 78 ++++ - plugins/media-keys/actions/acme-volume-alsa.c | 326 +++++++++++++++ - plugins/media-keys/actions/acme-volume-alsa.h | 47 +++ - plugins/media-keys/actions/acme-volume-dummy.c | 82 ++++ - plugins/media-keys/actions/acme-volume-dummy.h | 44 ++ - plugins/media-keys/actions/acme-volume-gstreamer.c | 432 ++++++++++++++++++++ - plugins/media-keys/actions/acme-volume-gstreamer.h | 48 +++ - plugins/media-keys/actions/acme-volume-oss.c | 215 ++++++++++ - plugins/media-keys/actions/acme-volume-oss.h | 47 +++ - plugins/media-keys/actions/acme-volume.c | 125 ++++++ - plugins/media-keys/actions/acme-volume.h | 63 +++ - plugins/media-keys/gsd-media-keys-manager.c | 89 ++++- - 14 files changed, 1709 insertions(+), 18 deletions(-) - create mode 100644 plugins/media-keys/actions/Makefile.am - create mode 100644 plugins/media-keys/actions/acme-volume-alsa.c - create mode 100644 plugins/media-keys/actions/acme-volume-alsa.h - create mode 100644 plugins/media-keys/actions/acme-volume-dummy.c - create mode 100644 plugins/media-keys/actions/acme-volume-dummy.h - create mode 100644 plugins/media-keys/actions/acme-volume-gstreamer.c - create mode 100644 plugins/media-keys/actions/acme-volume-gstreamer.h - create mode 100644 plugins/media-keys/actions/acme-volume-oss.c - create mode 100644 plugins/media-keys/actions/acme-volume-oss.h - create mode 100644 plugins/media-keys/actions/acme-volume.c - create mode 100644 plugins/media-keys/actions/acme-volume.h - -diff --git a/configure.ac b/configure.ac -index aa55fc1..f4748ff 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -253,11 +253,108 @@ if test x$WANT_PULSE = xyes ; then - AC_DEFINE(HAVE_PULSE, 1, [Define if PULSE sound server should be used])], - [have_pulse=false]) - fi -+ - 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_gstreamer" = "xyes"; then -+ GST_LIBS="$GST_LIBS -lgstinterfaces-0.10 -lgstaudio-0.10" -+ 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) -+ -+dnl ============================================== -+dnl OSS section -+dnl ============================================== -+ -+have_oss=no -+if test "x$have_gstreamer" != "xyes" -a "x$have_pulse" != "xtrue"; then -+ AC_TRY_COMPILE([ -+ #ifdef __NetBSD__ -+ #include <sys/param.h> -+ #include <sys/sysctl.h> -+ #include <soundcard.h> -+ #else -+ #include <sys/soundcard.h> -+ #endif -+ ],[ -+ int arg = SNDCTL_DSP_SETFRAGMENT; -+ ],[ -+ have_oss=yes -+ ]) -+ AC_MSG_CHECKING(for OSS audio support) -+ AC_MSG_RESULT($have_oss) -+fi -+ -+AM_CONDITIONAL(HAVE_OSS, test x"$have_oss" = "xyes") -+ -+dnl ============================================== -+dnl ALSA section -+dnl ============================================== -+ -+have_alsa=no -+if test "x$have_gstreamer" != "xyes"; then -+ AC_ARG_ENABLE(alsa, -+ AC_HELP_STRING([--disable-alsa], -+ [turn off ALSA audio support]), -+ [case "${enableval}" in -+ yes) WANT_ALSA=yes ;; -+ no) WANT_ALSA=no ;; -+ *) AC_MSG_ERROR(bad value ${enableval} for --disable-alsa) ;; -+ esac], -+ [WANT_ALSA=yes]) dnl Default value -+ -+ if test x$WANT_ALSA = xyes ; then -+ PKG_CHECK_MODULES(ALSA, alsa >= 0.9.0, -+ have_alsa=yes, -+ AC_MSG_RESULT([disabled])) -+ fi -+ -+ AC_SUBST(ALSA_LIBS) -+ AC_SUBST(ALSA_CFLAGS) -+fi -+ -+AM_CONDITIONAL(HAVE_ALSA, test x"$have_alsa" = "xyes") -+ -+if test x"$have_pulse" = "xtrue"; then -+ if test x"$have_gstreamer" = "xyes" -o x"$have_alsa" = "xyes" -o x"$have_oss" = "xyes"; then -+ AC_MSG_ERROR(Pulseaudio cannot be enabled with alsa or oss or gstreamer) -+ fi -+fi -+ - # --------------------------------------------------------------------------- - # Enable Profiling - # --------------------------------------------------------------------------- -@@ -355,6 +452,7 @@ plugins/housekeeping/Makefile - plugins/keybindings/Makefile - plugins/keyboard/Makefile - plugins/media-keys/Makefile -+plugins/media-keys/actions/Makefile - plugins/media-keys/cut-n-paste/Makefile - plugins/mouse/Makefile - plugins/screensaver/Makefile -@@ -397,6 +495,9 @@ echo " - dbus-1 system.d dir: ${DBUS_SYS_DIR} - - Libnotify support: ${have_libnotify} -+ OSS support: ${have_oss} -+ ALSA support: ${have_alsa} -+ 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 78f3b2b..d31bc82 100644 ---- a/plugins/media-keys/Makefile.am -+++ b/plugins/media-keys/Makefile.am -@@ -1,11 +1,12 @@ - NULL = - - SUBDIRS = --plugin_LTLIBRARIES = -+plugin_LTLIBRARIES = libmedia-keys.la - - if HAVE_PULSE - SUBDIRS += cut-n-paste --plugin_LTLIBRARIES += libmedia-keys.la -+else -+SUBDIRS += actions - endif - - BUILT_SOURCES = \ -@@ -39,7 +40,6 @@ libmedia_keys_la_SOURCES = \ - libmedia_keys_la_CPPFLAGS = \ - -I$(top_srcdir)/gnome-settings-daemon \ - -I$(top_srcdir)/plugins/common \ -- -I$(top_srcdir)/plugins/media-keys/cut-n-paste \ - -DPIXMAPDIR=\""$(pkgdatadir)"\" \ - -DGLADEDIR=\""$(pkgdatadir)"\" \ - -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \ -@@ -53,10 +53,10 @@ libmedia_keys_la_LDFLAGS = \ - $(GSD_PLUGIN_LDFLAGS) - - libmedia_keys_la_LIBADD = \ -- $(top_builddir)/plugins/common/libcommon.la \ -- $(top_builddir)/plugins/media-keys/cut-n-paste/libgvc.la \ -- $(SETTINGS_PLUGIN_LIBS) \ -- $(XF86MISC_LIBS) -+ $(top_builddir)/plugins/common/libcommon.la \ -+ $(SETTINGS_PLUGIN_LIBS) \ -+ $(XF86MISC_LIBS) \ -+ $(GST_LIBS) - - plugin_in_files = \ - media-keys.gnome-settings-plugin.in -@@ -76,7 +76,6 @@ test_media_window_SOURCES = \ - - test_media_window_CPPFLAGS = \ - -I$(top_srcdir)/gnome-settings-daemon \ -- -I$(top_srcdir)/plugins/media-keys/cut-n-paste \ - -DPIXMAPDIR=\""$(pkgdatadir)"\" \ - -DGLADEDIR=\""$(pkgdatadir)"\" \ - -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \ -@@ -104,7 +103,6 @@ test_media_keys_SOURCES = \ - test_media_keys_CPPFLAGS = \ - -I$(top_srcdir)/gnome-settings-daemon \ - -I$(top_srcdir)/plugins/common \ -- -I$(top_srcdir)/plugins/media-keys/cut-n-paste \ - -DPIXMAPDIR=\""$(pkgdatadir)"\" \ - -DGLADEDIR=\""$(pkgdatadir)"\" \ - -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \ -@@ -123,7 +121,17 @@ test_media_keys_LDADD = \ - $(GST_LIBS) - - if HAVE_PULSE -+libmedia_keys_la_CPPFLAGS += -I$(top_builddir)/plugins/media-keys/cut-n-paste -+libmedia_keys_la_LIBADD += $(top_builddir)/plugins/media-keys/cut-n-paste/libgvc.la -+test_media_window_CPPFLAGS += -I$(top_builddir)/plugins/media-keys/cut-n-paste -+test_media_keys_CPPFLAGS += -I$(top_builddir)/plugins/media-keys/cut-n-paste - test_media_keys_LDADD += $(top_builddir)/plugins/media-keys/cut-n-paste/libgvc.la -+else -+libmedia_keys_la_CPPFLAGS += -I$(top_builddir)/plugins/media-keys/actions -+libmedia_keys_la_LIBADD += $(top_builddir)/plugins/media-keys/actions/libacme.la -+test_media_window_CPPFLAGS += -I$(top_builddir)/plugins/media-keys/actions -+test_media_keys_CPPFLAGS += -I$(top_builddir)/plugins/media-keys/actions -+test_media_keys_LDADD += $(top_builddir)/plugins/media-keys/actions/libacme.la - endif - - gladedir = $(pkgdatadir) -@@ -136,7 +144,11 @@ pixmaps_DATA = \ - acme-eject.png \ - $(NULL) - -+if HAVE_PULSE - DIST_SUBDIRS = cut-n-paste -+else -+DIST_SUBDIRS = actions -+endif - - EXTRA_DIST = \ - gsd-media-keys-manager.xml \ -diff --git a/plugins/media-keys/actions/Makefile.am b/plugins/media-keys/actions/Makefile.am -new file mode 100644 -index 0000000..73c5c9e ---- /dev/null -+++ b/plugins/media-keys/actions/Makefile.am -@@ -0,0 +1,78 @@ -+NULL = -+ -+noinst_LTLIBRARIES = libacme.la -+ -+libacme_la_SOURCES = \ -+ ../acme.h \ -+ acme-volume.c \ -+ acme-volume.h \ -+ acme-volume-dummy.c \ -+ acme-volume-dummy.h \ -+ $(NULL) -+ -+libacme_la_CPPFLAGS = \ -+ -I$(top_srcdir)/gnome-settings-daemon \ -+ -I$(top_srcdir)/plugins/common \ -+ -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \ -+ $(AM_CPPFLAGS) -+ -+libacme_la_CFLAGS = \ -+ $(SETTINGS_PLUGIN_CFLAGS) \ -+ $(GST_CFLAGS) \ -+ $(AM_CFLAGS) -+ -+libacme_la_LIBADD = \ -+ $(NULL) -+ -+if HAVE_GSTREAMER -+libacme_la_SOURCES += \ -+ acme-volume-gstreamer.c \ -+ acme-volume-gstreamer.h \ -+ $(NULL) -+ -+libacme_la_CPPFLAGS += -DHAVE_GSTREAMER -+ -+libacme_la_LIBADD += $(GST_LIBS) -+ -+else # HAVE_GSTREAMER -+ -+if HAVE_ALSA -+libacme_la_SOURCES += \ -+ acme-volume-alsa.c \ -+ acme-volume-alsa.h \ -+ $(NULL) -+ -+libacme_la_CPPFLAGS += -DHAVE_ALSA -+ -+libacme_la_LIBADD += $(ALSA_LIBS) -+ -+else # HAVE_ALSA -+ -+if HAVE_OSS -+libacme_la_SOURCES += \ -+ acme-volume-oss.c \ -+ acme-volume-oss.h \ -+ $(NULL) -+ -+libacme_la_CPPFLAGS += -DHAVE_OSS -+ -+libacme_la_SOURCES += $(OSS_SOURCES) -+ -+endif # HAVE_OSS -+endif # HAVE_ALSA -+endif # HAVE_GSTREAMER -+ -+gladedir = $(pkgdatadir) -+glade_DATA = \ -+ ../acme.glade \ -+ $(NULL) -+ -+pixmapsdir = $(pkgdatadir) -+pixmaps_DATA = \ -+ ../acme-eject.png \ -+ $(NULL) -+ -+EXTRA_DIST = \ -+ $(glade_DATA) \ -+ $(pixmaps_DATA) \ -+ $(NULL) -diff --git a/plugins/media-keys/actions/acme-volume-alsa.c b/plugins/media-keys/actions/acme-volume-alsa.c -new file mode 100644 -index 0000000..314820c ---- /dev/null -+++ b/plugins/media-keys/actions/acme-volume-alsa.c -@@ -0,0 +1,326 @@ -+/* acme-volume-alsa.c -+ -+ Copyright (C) 2002, 2003 Bastien Nocera -+ -+ 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> -+ */ -+ -+#include "config.h" -+#include "acme-volume-alsa.h" -+ -+#include <alsa/asoundlib.h> -+ -+#ifndef DEFAULT_CARD -+#define DEFAULT_CARD "default" -+#endif -+ -+#undef LOG -+#ifdef LOG -+#define D(x...) g_message (x) -+#else -+#define D(x...) -+#endif -+ -+#define ROUND(x) ((x - (int)x > 0.5) ? x+1 : x) -+ -+struct AcmeVolumeAlsaPrivate -+{ -+ long pmin, pmax; -+ gboolean has_mute, has_master; -+ snd_mixer_t *handle; -+ snd_mixer_elem_t *elem; -+ int saved_volume; -+ guint timer_id; -+}; -+ -+static int acme_volume_alsa_get_volume (AcmeVolume *self); -+static void acme_volume_alsa_set_volume (AcmeVolume *self, int val); -+static gboolean acme_volume_alsa_open (AcmeVolumeAlsa *self); -+static void acme_volume_alsa_close (AcmeVolumeAlsa *self); -+static gboolean acme_volume_alsa_close_real (AcmeVolumeAlsa *self); -+ -+G_DEFINE_TYPE (AcmeVolumeAlsa, acme_volume_alsa, ACME_TYPE_VOLUME) -+ -+static void -+acme_volume_alsa_finalize (GObject *object) -+{ -+ AcmeVolumeAlsa *self; -+ -+ self = ACME_VOLUME_ALSA (object); -+ -+ if (self->_priv) -+ { -+ if (self->_priv->timer_id != 0) -+ { -+ g_source_remove (self->_priv->timer_id); -+ self->_priv->timer_id = 0; -+ } -+ -+ acme_volume_alsa_close_real (self); -+ g_free (self->_priv); -+ self->_priv = NULL; -+ } -+ -+ G_OBJECT_CLASS (acme_volume_alsa_parent_class)->finalize (object); -+} -+ -+static void -+acme_volume_alsa_set_mute (AcmeVolume *vol, gboolean val) -+{ -+ AcmeVolumeAlsa *self = (AcmeVolumeAlsa *) vol; -+ -+ if (acme_volume_alsa_open (self) == FALSE) -+ return; -+ -+ /* If we have a hardware mute */ -+ if (self->_priv->has_mute) -+ { -+ snd_mixer_selem_set_playback_switch_all -+ (self->_priv->elem, !val); -+ acme_volume_alsa_close (self); -+ return; -+ } -+ -+ acme_volume_alsa_close (self); -+ -+ /* If we don't */ -+ if (val == TRUE) -+ { -+ self->_priv->saved_volume = acme_volume_alsa_get_volume (vol); -+ acme_volume_alsa_set_volume (vol, 0); -+ } else { -+ if (self->_priv->saved_volume != -1) -+ acme_volume_alsa_set_volume (vol, -+ self->_priv->saved_volume); -+ } -+} -+ -+static gboolean -+acme_volume_alsa_get_mute (AcmeVolume *vol) -+{ -+ AcmeVolumeAlsa *self = (AcmeVolumeAlsa *) vol; -+ int ival; -+ -+ if (acme_volume_alsa_open (self) == FALSE) -+ return FALSE; -+ -+ if (self->_priv->has_mute) -+ { -+ snd_mixer_selem_get_playback_switch(self->_priv->elem, -+ SND_MIXER_SCHN_FRONT_LEFT, &ival); -+ -+ acme_volume_alsa_close (self); -+ -+ return !ival; -+ } else { -+ acme_volume_alsa_close (self); -+ -+ return (acme_volume_alsa_get_volume (vol) == 0); -+ } -+} -+ -+static int -+acme_volume_alsa_get_volume (AcmeVolume *vol) -+{ -+ AcmeVolumeAlsa *self = (AcmeVolumeAlsa *) vol; -+ long lval, rval; -+ int tmp; -+ float alsa_vol; -+ -+ if (acme_volume_alsa_open (self) == FALSE) -+ return 0; -+ -+ snd_mixer_selem_get_playback_volume(self->_priv->elem, -+ SND_MIXER_SCHN_FRONT_LEFT, &lval); -+ snd_mixer_selem_get_playback_volume(self->_priv->elem, -+ SND_MIXER_SCHN_FRONT_RIGHT, &rval); -+ -+ acme_volume_alsa_close (self); -+ -+ alsa_vol = (lval + rval) / 2; -+ alsa_vol = alsa_vol * 100 / (self->_priv->pmax - self->_priv->pmin); -+ tmp = ROUND (alsa_vol); -+ -+ return tmp; -+} -+ -+static void -+acme_volume_alsa_set_volume (AcmeVolume *vol, int val) -+{ -+ AcmeVolumeAlsa *self = (AcmeVolumeAlsa *) vol; -+ float volume; -+ int tmp; -+ -+ if (acme_volume_alsa_open (self) == FALSE) -+ return; -+ -+ volume = (float) val / 100 * (self->_priv->pmax - self->_priv->pmin); -+ volume = CLAMP (volume, self->_priv->pmin, self->_priv->pmax); -+ tmp = ROUND (volume); -+ -+ snd_mixer_selem_set_playback_volume_all (self->_priv->elem, tmp); -+ -+ acme_volume_alsa_close (self); -+} -+ -+static int -+acme_volume_alsa_get_threshold (AcmeVolume *vol) -+{ -+ AcmeVolumeAlsa *self = (AcmeVolumeAlsa *) vol; -+ int steps; -+ -+ if (acme_volume_alsa_open (self) == FALSE) -+ return 1; -+ -+ acme_volume_alsa_close (self); -+ -+ steps = self->_priv->pmax - self->_priv->pmin; -+ return (steps > 0) ? 100 / steps + 1 : 1; -+} -+ -+static gboolean -+acme_volume_alsa_close_real (AcmeVolumeAlsa *self) -+{ -+ if (self->_priv == NULL) -+ return FALSE; -+ -+ if (self->_priv->handle != NULL) -+ { -+ snd_mixer_detach (self->_priv->handle, DEFAULT_CARD); -+ snd_mixer_free (self->_priv->handle); -+ self->_priv->handle = NULL; -+ self->_priv->elem = NULL; -+ } -+ -+ self->_priv->timer_id = 0; -+ -+ return FALSE; -+} -+ -+static gboolean -+acme_volume_alsa_open (AcmeVolumeAlsa *self) -+{ -+ snd_mixer_selem_id_t *sid; -+ snd_mixer_t *handle; -+ snd_mixer_elem_t *elem; -+ -+ if (self->_priv->timer_id != 0) -+ { -+ g_source_remove (self->_priv->timer_id); -+ self->_priv->timer_id = 0; -+ return TRUE; -+ } -+ -+ /* open the mixer */ -+ if (snd_mixer_open (&handle, 0) < 0) -+ { -+ D("snd_mixer_open"); -+ return FALSE; -+ } -+ /* attach the handle to the default card */ -+ if (snd_mixer_attach (handle, DEFAULT_CARD) <0) -+ { -+ D("snd_mixer_attach"); -+ goto bail; -+ } -+ /* ? */ -+ if (snd_mixer_selem_register (handle, NULL, NULL) < 0) -+ { -+ D("snd_mixer_selem_register"); -+ goto bail; -+ } -+ if (snd_mixer_load (handle) < 0) -+ { -+ D("snd_mixer_load"); -+ goto bail; -+ } -+ -+ snd_mixer_selem_id_alloca (&sid); -+ snd_mixer_selem_id_set_name (sid, "Master"); -+ elem = snd_mixer_find_selem (handle, sid); -+ if (!elem) -+ { -+ snd_mixer_selem_id_alloca (&sid); -+ snd_mixer_selem_id_set_name (sid, "PCM"); -+ elem = snd_mixer_find_selem (handle, sid); -+ if (!elem) -+ { -+ D("snd_mixer_find_selem"); -+ goto bail; -+ } -+ } -+ -+ if (!snd_mixer_selem_has_playback_volume (elem)) -+ { -+ D("snd_mixer_selem_has_playback_volume"); -+ goto bail; -+ } -+ -+ snd_mixer_selem_get_playback_volume_range (elem, -+ &(self->_priv->pmin), -+ &(self->_priv->pmax)); -+ -+ self->_priv->has_mute = snd_mixer_selem_has_playback_switch (elem); -+ self->_priv->handle = handle; -+ self->_priv->elem = elem; -+ -+ return TRUE; -+ -+bail: -+ acme_volume_alsa_close_real (self); -+ return FALSE; -+} -+ -+static void -+acme_volume_alsa_close (AcmeVolumeAlsa *self) -+{ -+ self->_priv->timer_id = g_timeout_add (4000, -+ (GSourceFunc) acme_volume_alsa_close_real, self); -+} -+ -+static void -+acme_volume_alsa_init (AcmeVolumeAlsa *self) -+{ -+ self->_priv = g_new0 (AcmeVolumeAlsaPrivate, 1); -+ -+ if (acme_volume_alsa_open (self) == FALSE) -+ { -+ g_free (self->_priv); -+ self->_priv = NULL; -+ return; -+ } -+ -+ if (self->_priv->handle != NULL) { -+ acme_volume_alsa_close_real (self); -+ return; -+ } -+} -+ -+static void -+acme_volume_alsa_class_init (AcmeVolumeAlsaClass *klass) -+{ -+ AcmeVolumeClass *volume_class = ACME_VOLUME_CLASS (klass); -+ G_OBJECT_CLASS (klass)->finalize = acme_volume_alsa_finalize; -+ -+ volume_class->set_volume = acme_volume_alsa_set_volume; -+ volume_class->get_volume = acme_volume_alsa_get_volume; -+ volume_class->set_mute = acme_volume_alsa_set_mute; -+ volume_class->get_mute = acme_volume_alsa_get_mute; -+ volume_class->get_threshold = acme_volume_alsa_get_threshold; -+} -+ -diff --git a/plugins/media-keys/actions/acme-volume-alsa.h b/plugins/media-keys/actions/acme-volume-alsa.h -new file mode 100644 -index 0000000..83746ff ---- /dev/null -+++ b/plugins/media-keys/actions/acme-volume-alsa.h -@@ -0,0 +1,47 @@ -+/* acme-volume-alsa.h -+ -+ Copyright (C) 2002, 2003 Bastien Nocera -+ -+ 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> -+ */ -+ -+#include <glib.h> -+#include <glib-object.h> -+#include "acme-volume.h" -+ -+#define ACME_TYPE_VOLUME_ALSA (acme_volume_get_type ()) -+#define ACME_VOLUME_ALSA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), ACME_TYPE_VOLUME_ALSA, AcmeVolumeAlsa)) -+#define ACME_VOLUME_ALSA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), ACME_TYPE_VOLUME_ALSA, AcmeVolumeAlsaClass)) -+#define ACME_IS_VOLUME_ALSA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ACME_TYPE_VOLUME_ALSA)) -+#define ACME_VOLUME_ALSA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), ACME_TYPE_VOLUME_ALSA, AcmeVolumeAlsaClass)) -+ -+typedef struct AcmeVolumeAlsa AcmeVolumeAlsa; -+typedef struct AcmeVolumeAlsaClass AcmeVolumeAlsaClass; -+typedef struct AcmeVolumeAlsaPrivate AcmeVolumeAlsaPrivate; -+ -+struct AcmeVolumeAlsa { -+ AcmeVolume parent; -+ AcmeVolumeAlsaPrivate *_priv; -+}; -+ -+struct AcmeVolumeAlsaClass { -+ AcmeVolumeClass parent; -+}; -+ -+GType acme_volume_alsa_get_type (void); -+ -diff --git a/plugins/media-keys/actions/acme-volume-dummy.c b/plugins/media-keys/actions/acme-volume-dummy.c -new file mode 100644 -index 0000000..054b9e7 ---- /dev/null -+++ b/plugins/media-keys/actions/acme-volume-dummy.c -@@ -0,0 +1,82 @@ -+/* acme-volume-dummy.c -+ -+ Copyright (C) 2002, 2003 Bastien Nocera -+ -+ 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> -+ */ -+ -+#include "config.h" -+#include "acme-volume-dummy.h" -+ -+G_DEFINE_TYPE (AcmeVolumeDummy, acme_volume_dummy, ACME_TYPE_VOLUME) -+ -+static void -+acme_volume_dummy_finalize (GObject *object) -+{ -+ g_return_if_fail (object != NULL); -+ g_return_if_fail (ACME_IS_VOLUME_DUMMY (object)); -+ -+ G_OBJECT_CLASS (acme_volume_dummy_parent_class)->finalize (object); -+} -+ -+static void -+acme_volume_dummy_set_mute (AcmeVolume *vol, gboolean val) -+{ -+} -+ -+static gboolean -+acme_volume_dummy_get_mute (AcmeVolume *vol) -+{ -+ return FALSE; -+} -+ -+static int -+acme_volume_dummy_get_volume (AcmeVolume *vol) -+{ -+ return 0; -+} -+ -+static void -+acme_volume_dummy_set_volume (AcmeVolume *vol, int val) -+{ -+} -+ -+/* minimum step size (in percent) required to actually affect volume */ -+static int -+acme_volume_dummy_get_threshold (AcmeVolume *vol) -+{ -+ return 1; -+} -+ -+static void -+acme_volume_dummy_init (AcmeVolumeDummy *vol) -+{ -+} -+ -+static void -+acme_volume_dummy_class_init (AcmeVolumeDummyClass *klass) -+{ -+ AcmeVolumeClass *volume_class = ACME_VOLUME_CLASS (klass); -+ G_OBJECT_CLASS (klass)->finalize = acme_volume_dummy_finalize; -+ -+ volume_class->set_volume = acme_volume_dummy_set_volume; -+ volume_class->get_volume = acme_volume_dummy_get_volume; -+ volume_class->set_mute = acme_volume_dummy_set_mute; -+ volume_class->get_mute = acme_volume_dummy_get_mute; -+ volume_class->get_threshold = acme_volume_dummy_get_threshold; -+} -diff --git a/plugins/media-keys/actions/acme-volume-dummy.h b/plugins/media-keys/actions/acme-volume-dummy.h -new file mode 100644 -index 0000000..b66ac14 ---- /dev/null -+++ b/plugins/media-keys/actions/acme-volume-dummy.h -@@ -0,0 +1,44 @@ -+/* acme-volume-dummy.h -+ -+ Copyright (C) 2002, 2003 Bastien Nocera -+ -+ 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> -+ */ -+ -+#include <glib.h> -+#include <glib-object.h> -+#include "acme-volume.h" -+ -+#define ACME_TYPE_VOLUME_DUMMY (acme_volume_dummy_get_type ()) -+#define ACME_VOLUME_DUMMY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), ACME_TYPE_VOLUME_DUMMY, AcmeVolumeDummy)) -+#define ACME_VOLUME_DUMMY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), ACME_TYPE_VOLUME_DUMMY, AcmeVolumeDummyClass)) -+#define ACME_IS_VOLUME_DUMMY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ACME_TYPE_VOLUME_DUMMY)) -+#define ACME_VOLUME_DUMMY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), ACME_TYPE_VOLUME_DUMMY, AcmeVolumeDummyClass)) -+ -+typedef struct AcmeVolumeDummy AcmeVolumeDummy; -+typedef struct AcmeVolumeDummyClass AcmeVolumeDummyClass; -+ -+struct AcmeVolumeDummy { -+ AcmeVolume parent; -+}; -+ -+struct AcmeVolumeDummyClass { -+ AcmeVolumeClass parent; -+}; -+ -+GType acme_volume_dummy_get_type (void); -diff --git a/plugins/media-keys/actions/acme-volume-gstreamer.c b/plugins/media-keys/actions/acme-volume-gstreamer.c -new file mode 100644 -index 0000000..6990447 ---- /dev/null -+++ b/plugins/media-keys/actions/acme-volume-gstreamer.c -@@ -0,0 +1,432 @@ -+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -+ -+/* acme-volume-gstreamer.c -+ -+ Copyright (C) 2002, 2003 Bastien Nocera -+ Copyright (C) 2004 Novell, Inc. -+ -+ 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 "acme-volume-gstreamer.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_GSTREAMER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), ACME_TYPE_VOLUME_GSTREAMER, AcmeVolumeGStreamerPrivate)) -+ -+struct AcmeVolumeGStreamerPrivate -+{ -+ GstMixer *mixer; -+ GList *mixer_tracks; -+ guint timer_id; -+ gdouble volume; -+ gboolean mute; -+ GConfClient *gconf_client; -+}; -+ -+G_DEFINE_TYPE (AcmeVolumeGStreamer, acme_volume_gstreamer, ACME_TYPE_VOLUME) -+ -+static int acme_volume_gstreamer_get_volume (AcmeVolume *self); -+static void acme_volume_gstreamer_set_volume (AcmeVolume *self, int val); -+static gboolean acme_volume_gstreamer_open (AcmeVolumeGStreamer *self); -+static void acme_volume_gstreamer_close (AcmeVolumeGStreamer *self); -+static gboolean acme_volume_gstreamer_close_real (AcmeVolumeGStreamer *self); -+ -+static void -+acme_volume_gstreamer_finalize (GObject *object) -+{ -+ AcmeVolumeGStreamer *self; -+ -+ g_return_if_fail (object != NULL); -+ g_return_if_fail (ACME_IS_VOLUME_GSTREAMER (object)); -+ -+ self = ACME_VOLUME_GSTREAMER (object); -+ -+ if (self->_priv->timer_id != 0) -+ { -+ g_source_remove (self->_priv->timer_id); -+ self->_priv->timer_id = 0; -+ } -+ acme_volume_gstreamer_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_gstreamer_parent_class)->finalize (object); -+} -+ -+static void -+acme_volume_gstreamer_set_mute (AcmeVolume *vol, gboolean val) -+{ -+ AcmeVolumeGStreamer *self = (AcmeVolumeGStreamer *) vol; -+ GList *t; -+ -+ if (acme_volume_gstreamer_open (self) == FALSE) -+ return; -+ -+ 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); -+ } -+ -+ if (val) -+ { -+ self->_priv->mute = TRUE; -+ } else { -+ self->_priv->mute = FALSE; -+ -+ 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) (self->_priv->volume * 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); -+ } -+ } -+ -+ acme_volume_gstreamer_close (self); -+} -+ -+static void -+update_state (AcmeVolumeGStreamer * 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; -+ else -+ self->_priv->volume = vol; -+} -+ -+static gboolean -+acme_volume_gstreamer_get_mute (AcmeVolume *vol) -+{ -+ AcmeVolumeGStreamer *self = (AcmeVolumeGStreamer *) vol; -+ -+ if (acme_volume_gstreamer_open (self) == FALSE) -+ return FALSE; -+ -+ update_state (self); -+ acme_volume_gstreamer_close (self); -+ -+ return self->_priv->mute; -+} -+ -+static int -+acme_volume_gstreamer_get_volume (AcmeVolume *vol) -+{ -+ AcmeVolumeGStreamer *self = (AcmeVolumeGStreamer *) vol; -+ -+ if (acme_volume_gstreamer_open (self) == FALSE) -+ return 0; -+ -+ update_state (self); -+ -+ acme_volume_gstreamer_close (self); -+ -+ return (gint) (self->_priv->volume + 0.5); -+} -+ -+static void -+acme_volume_gstreamer_set_volume (AcmeVolume *vol, int val) -+{ -+ AcmeVolumeGStreamer *self = (AcmeVolumeGStreamer *) vol; -+ GList *t; -+ -+ if (acme_volume_gstreamer_open (self) == FALSE) -+ return; -+ -+ 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_gstreamer_close (self); -+} -+ -+static int -+acme_volume_gstreamer_get_threshold (AcmeVolume *vol) -+{ -+ AcmeVolumeGStreamer *self = (AcmeVolumeGStreamer *) vol; -+ GList *t; -+ int steps = 101; -+ -+ if (acme_volume_gstreamer_open (self) == FALSE) -+ return 1; -+ -+ for (t = self->_priv->mixer_tracks; t != NULL; t = t->next) -+ { -+ GstMixerTrack *track = GST_MIXER_TRACK (t->data); -+ int track_steps = track->max_volume - track->min_volume; -+ if (track_steps > 0 && track_steps < steps) -+ steps = track_steps; -+ } -+ -+ acme_volume_gstreamer_close (self); -+ -+ return 100 / steps + 1; -+} -+ -+static gboolean -+acme_volume_gstreamer_close_real (AcmeVolumeGStreamer *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 -+ * Arguments: mixer - pointer to mixer element -+ * data - pointer to user data (AcmeVolumeGStreamer to be modified) -+ * Returns: gboolean indicating success -+ */ -+static gboolean -+_acme_set_mixer(GstMixer *mixer, gpointer user_data) -+{ -+ const GList *tracks; -+ -+ tracks = gst_mixer_list_tracks (mixer); -+ -+ while (tracks != NULL) { -+ GstMixerTrack *track = GST_MIXER_TRACK (tracks->data); -+ -+ if (GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_MASTER)) { -+ AcmeVolumeGStreamer *self; -+ -+ self = ACME_VOLUME_GSTREAMER (user_data); -+ -+ self->_priv->mixer = mixer; -+ self->_priv->mixer_tracks = g_list_append (self->_priv->mixer_tracks, g_object_ref (track)); -+ return TRUE; -+ } -+ -+ tracks = tracks->next; -+ } -+ -+ return FALSE; -+} -+ -+/* This is a modified version of code from gnome-media's gst-mixer */ -+static gboolean -+acme_volume_gstreamer_open (AcmeVolumeGStreamer *vol) -+{ -+ AcmeVolumeGStreamer *self = (AcmeVolumeGStreamer *) vol; -+ 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; -+ -+ /* Try to use tracks saved in GConf */ -+ tracks = gconf_client_get_list (self->_priv->gconf_client, DEFAULT_MIXER_TRACKS_KEY, GCONF_VALUE_STRING, NULL); -+ -+ 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 != NULL) -+ { -+ 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_gstreamer_close (AcmeVolumeGStreamer *self) -+{ -+ self->_priv->timer_id = g_timeout_add_seconds (TIMEOUT, -+ (GSourceFunc) acme_volume_gstreamer_close_real, self); -+} -+ -+static void -+acme_volume_gstreamer_init (AcmeVolumeGStreamer *self) -+{ -+ self->_priv = ACME_VOLUME_GSTREAMER_GET_PRIVATE (self); -+ self->_priv->gconf_client = gconf_client_get_default (); -+} -+ -+static void -+acme_volume_gstreamer_class_init (AcmeVolumeGStreamerClass *klass) -+{ -+ AcmeVolumeClass *volume_class = ACME_VOLUME_CLASS (klass); -+ G_OBJECT_CLASS (klass)->finalize = acme_volume_gstreamer_finalize; -+ -+ gst_init (NULL, NULL); -+ -+ volume_class->set_volume = acme_volume_gstreamer_set_volume; -+ volume_class->get_volume = acme_volume_gstreamer_get_volume; -+ volume_class->set_mute = acme_volume_gstreamer_set_mute; -+ volume_class->get_mute = acme_volume_gstreamer_get_mute; -+ volume_class->get_threshold = acme_volume_gstreamer_get_threshold; -+ -+ g_type_class_add_private (klass, sizeof (AcmeVolumeGStreamerPrivate)); -+} -diff --git a/plugins/media-keys/actions/acme-volume-gstreamer.h b/plugins/media-keys/actions/acme-volume-gstreamer.h -new file mode 100644 -index 0000000..f260688 ---- /dev/null -+++ b/plugins/media-keys/actions/acme-volume-gstreamer.h -@@ -0,0 +1,48 @@ -+/* acme-volume-gstreamer.h -+ -+ Copyright (C) 2002, 2003 Bastien Nocera -+ Copyright (C) 2004 Novell, Inc. -+ -+ 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.h> -+#include <glib-object.h> -+#include "acme-volume.h" -+ -+#define ACME_TYPE_VOLUME_GSTREAMER (acme_volume_gstreamer_get_type ()) -+#define ACME_VOLUME_GSTREAMER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), ACME_TYPE_VOLUME_GSTREAMER, AcmeVolumeGStreamer)) -+#define ACME_VOLUME_GSTREAMER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), ACME_TYPE_VOLUME_GSTREAMER, AcmeVolumeGStreamerClass)) -+#define ACME_IS_VOLUME_GSTREAMER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ACME_TYPE_VOLUME_GSTREAMER)) -+#define ACME_VOLUME_GSTREAMER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), ACME_TYPE_VOLUME_GSTREAMER, AcmeVolumeGStreamerClass)) -+ -+typedef struct AcmeVolumeGStreamer AcmeVolumeGStreamer; -+typedef struct AcmeVolumeGStreamerClass AcmeVolumeGStreamerClass; -+typedef struct AcmeVolumeGStreamerPrivate AcmeVolumeGStreamerPrivate; -+ -+struct AcmeVolumeGStreamer { -+ AcmeVolume parent; -+ AcmeVolumeGStreamerPrivate *_priv; -+}; -+ -+struct AcmeVolumeGStreamerClass { -+ AcmeVolumeClass parent; -+}; -+ -+GType acme_volume_gstreamer_get_type (void); -diff --git a/plugins/media-keys/actions/acme-volume-oss.c b/plugins/media-keys/actions/acme-volume-oss.c -new file mode 100644 -index 0000000..26685ab ---- /dev/null -+++ b/plugins/media-keys/actions/acme-volume-oss.c -@@ -0,0 +1,215 @@ -+/* acme-volume-oss.c -+ -+ Copyright (C) 2002, 2003 Bastien Nocera -+ -+ 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> -+ */ -+ -+#include "config.h" -+#include "acme-volume-oss.h" -+ -+#include <fcntl.h> -+#include <unistd.h> -+#include <sys/ioctl.h> -+ -+#ifdef __NetBSD__ -+#include <sys/param.h> -+#include <sys/sysctl.h> -+#include <soundcard.h> -+#else -+#include <sys/soundcard.h> -+#endif /* __NetBSD__ */ -+ -+struct AcmeVolumeOssPrivate -+{ -+ gboolean use_pcm; -+ gboolean mixerpb; -+ int volume; -+ int saved_volume; -+ gboolean pcm_avail; -+ gboolean mute; -+}; -+ -+static int acme_volume_oss_get_volume (AcmeVolume *self); -+static void acme_volume_oss_set_volume (AcmeVolume *self, int val); -+static gboolean acme_volume_oss_mixer_check (AcmeVolumeOss *self, int fd); -+ -+G_DEFINE_TYPE (AcmeVolumeOss, acme_volume_oss, ACME_TYPE_VOLUME) -+ -+static void -+acme_volume_oss_finalize (GObject *object) -+{ -+ AcmeVolumeOss *self; -+ -+ g_return_if_fail (object != NULL); -+ g_return_if_fail (ACME_IS_VOLUME_OSS (object)); -+ -+ self = ACME_VOLUME_OSS (object); -+ -+ g_return_if_fail (self->_priv != NULL); -+ g_free (self->_priv); -+ -+ G_OBJECT_CLASS (acme_volume_oss_parent_class)->finalize (object); -+} -+ -+static int -+acme_volume_oss_vol_check (int volume) -+{ -+ return CLAMP (volume, 0, 100); -+} -+ -+static void -+acme_volume_oss_set_mute (AcmeVolume *vol, gboolean val) -+{ -+ AcmeVolumeOss *self = (AcmeVolumeOss *) vol; -+ -+ if (self->_priv->mute == FALSE) -+ { -+ self->_priv->saved_volume = -+ acme_volume_oss_get_volume (vol); -+ acme_volume_oss_set_volume (vol, 0); -+ self->_priv->mute = TRUE; -+ } else { -+ acme_volume_oss_set_volume (vol, self->_priv->saved_volume); -+ self->_priv->mute = FALSE; -+ } -+} -+ -+static gboolean -+acme_volume_oss_get_mute (AcmeVolume *vol) -+{ -+ AcmeVolumeOss *self = (AcmeVolumeOss *) vol; -+ -+ /* somebody else might have changed the volume */ -+ if ((self->_priv->mute == TRUE) && (self->_priv->volume != 0)) -+ { -+ self->_priv->mute = FALSE; -+ } -+ -+ return self->_priv->mute; -+} -+ -+static int -+acme_volume_oss_get_volume (AcmeVolume *vol) -+{ -+ gint volume, r, l, fd; -+ AcmeVolumeOss *self = (AcmeVolumeOss *) vol; -+ -+ fd = open ("/dev/mixer", O_RDONLY); -+ if (acme_volume_oss_mixer_check(self, fd) == FALSE) -+ { -+ volume = 0; -+ } else { -+ if (self->_priv->use_pcm && self->_priv->pcm_avail) -+ ioctl (fd, MIXER_READ (SOUND_MIXER_PCM), &volume); -+ else -+ ioctl (fd, MIXER_READ (SOUND_MIXER_VOLUME), &volume); -+ close (fd); -+ -+ r = (volume & 0xff); -+ l = (volume & 0xff00) >> 8; -+ volume = (r + l) / 2; -+ volume = acme_volume_oss_vol_check (volume); -+ } -+ -+ return volume; -+} -+ -+static void -+acme_volume_oss_set_volume (AcmeVolume *vol, int val) -+{ -+ int fd, tvol, volume; -+ AcmeVolumeOss *self = (AcmeVolumeOss *) vol; -+ -+ volume = acme_volume_oss_vol_check (val); -+ -+ fd = open ("/dev/mixer", O_RDONLY); -+ if (acme_volume_oss_mixer_check (self, fd) == FALSE) -+ { -+ return; -+ } else { -+ tvol = (volume << 8) + volume; -+ if (self->_priv->use_pcm && self->_priv->pcm_avail) -+ ioctl (fd, MIXER_WRITE (SOUND_MIXER_PCM), &tvol); -+ else -+ ioctl (fd, MIXER_WRITE (SOUND_MIXER_VOLUME), &tvol); -+ close (fd); -+ self->_priv->volume = volume; -+ } -+} -+ -+static int -+acme_volume_oss_get_threshold (AcmeVolume *vol) -+{ -+ return 1; -+} -+ -+static void -+acme_volume_oss_init (AcmeVolumeOss *self) -+{ -+ int fd; -+ -+ self->_priv = g_new0 (AcmeVolumeOssPrivate, 1); -+ -+ fd = open ("/dev/mixer", O_RDONLY); -+ if (acme_volume_oss_mixer_check(self, fd) == FALSE) -+ { -+ self->_priv->pcm_avail = FALSE; -+ } else { -+ int mask = 0; -+ -+ ioctl (fd, SOUND_MIXER_READ_DEVMASK, &mask); -+ if (mask & ( 1 << SOUND_MIXER_PCM)) -+ self->_priv->pcm_avail = TRUE; -+ else -+ self->_priv->pcm_avail = FALSE; -+ if (!(mask & ( 1 << SOUND_MIXER_VOLUME))) -+ self->_priv->use_pcm = TRUE; -+ -+ close (fd); -+ } -+} -+ -+static void -+acme_volume_oss_class_init (AcmeVolumeOssClass *klass) -+{ -+ AcmeVolumeClass *volume_class = ACME_VOLUME_CLASS (klass); -+ G_OBJECT_CLASS (klass)->finalize = acme_volume_oss_finalize; -+ -+ volume_class->set_volume = acme_volume_oss_set_volume; -+ volume_class->get_volume = acme_volume_oss_get_volume; -+ volume_class->set_mute = acme_volume_oss_set_mute; -+ volume_class->get_mute = acme_volume_oss_get_mute; -+ volume_class->get_threshold = acme_volume_oss_get_threshold; -+} -+ -+static gboolean -+acme_volume_oss_mixer_check (AcmeVolumeOss *self, int fd) -+{ -+ gboolean retval; -+ -+ if (fd <0) { -+ if (self->_priv->mixerpb == FALSE) { -+ self->_priv->mixerpb = TRUE; -+ //FIXME -+ //volume_oss_fd_problem(self); -+ } -+ } -+ retval = (!self->_priv->mixerpb); -+ return retval; -+} -diff --git a/plugins/media-keys/actions/acme-volume-oss.h b/plugins/media-keys/actions/acme-volume-oss.h -new file mode 100644 -index 0000000..b8805af ---- /dev/null -+++ b/plugins/media-keys/actions/acme-volume-oss.h -@@ -0,0 +1,47 @@ -+/* acme-volume-oss.h -+ -+ Copyright (C) 2002, 2003 Bastien Nocera -+ -+ 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> -+ */ -+ -+#include <glib.h> -+#include <glib-object.h> -+#include "acme-volume.h" -+ -+#define ACME_TYPE_VOLUME_OSS (acme_volume_get_type ()) -+#define ACME_VOLUME_OSS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), ACME_TYPE_VOLUME_OSS, AcmeVolumeOss)) -+#define ACME_VOLUME_OSS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), ACME_TYPE_VOLUME_OSS, AcmeVolumeOssClass)) -+#define ACME_IS_VOLUME_OSS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ACME_TYPE_VOLUME_OSS)) -+#define ACME_VOLUME_OSS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), ACME_TYPE_VOLUME_OSS, AcmeVolumeOssClass)) -+ -+typedef struct AcmeVolumeOss AcmeVolumeOss; -+typedef struct AcmeVolumeOssClass AcmeVolumeOssClass; -+typedef struct AcmeVolumeOssPrivate AcmeVolumeOssPrivate; -+ -+struct AcmeVolumeOss { -+ AcmeVolume parent; -+ AcmeVolumeOssPrivate *_priv; -+}; -+ -+struct AcmeVolumeOssClass { -+ AcmeVolumeClass parent; -+}; -+ -+GType acme_volume_oss_get_type (void); -+ -diff --git a/plugins/media-keys/actions/acme-volume.c b/plugins/media-keys/actions/acme-volume.c -new file mode 100644 -index 0000000..b912749 ---- /dev/null -+++ b/plugins/media-keys/actions/acme-volume.c -@@ -0,0 +1,125 @@ -+/* acme-volume.c -+ -+ Copyright (C) 2002, 2003 Bastien Nocera -+ -+ 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> -+ */ -+ -+#include "config.h" -+#include "acme-volume.h" -+#ifdef HAVE_OSS -+#include "acme-volume-oss.h" -+#endif -+#ifdef HAVE_ALSA -+#include "acme-volume-alsa.h" -+#endif -+#ifdef HAVE_GSTREAMER -+#include "acme-volume-gstreamer.h" -+#endif -+ -+G_DEFINE_TYPE (AcmeVolume, acme_volume, G_TYPE_OBJECT) -+ -+static void -+acme_volume_class_init (AcmeVolumeClass *klass) -+{ -+} -+ -+static void -+acme_volume_init (AcmeVolume *vol) -+{ -+} -+ -+int -+acme_volume_get_volume (AcmeVolume *self) -+{ -+ g_return_val_if_fail (self != NULL, 0); -+ g_return_val_if_fail (ACME_IS_VOLUME (self), 0); -+ -+ return ACME_VOLUME_GET_CLASS (self)->get_volume (self); -+} -+ -+void -+acme_volume_set_volume (AcmeVolume *self, int val) -+{ -+ g_return_if_fail (self != NULL); -+ g_return_if_fail (ACME_IS_VOLUME (self)); -+ -+ ACME_VOLUME_GET_CLASS (self)->set_volume (self, val); -+} -+ -+gboolean -+acme_volume_get_mute (AcmeVolume *self) -+{ -+ g_return_val_if_fail (self != NULL, FALSE); -+ g_return_val_if_fail (ACME_IS_VOLUME (self), FALSE); -+ -+ return ACME_VOLUME_GET_CLASS (self)->get_mute (self); -+} -+ -+void -+acme_volume_set_mute (AcmeVolume *self, gboolean val) -+{ -+ g_return_if_fail (self != NULL); -+ g_return_if_fail (ACME_IS_VOLUME (self)); -+ -+ ACME_VOLUME_GET_CLASS (self)->set_mute (self, val); -+} -+ -+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_CLASS (self)->get_mute (self); -+ ACME_VOLUME_GET_CLASS (self)->set_mute (self, !muted); -+} -+ -+int -+acme_volume_get_threshold (AcmeVolume *self) -+{ -+ g_return_val_if_fail (self != NULL, 0); -+ g_return_val_if_fail (ACME_IS_VOLUME (self), 0); -+ -+ return ACME_VOLUME_GET_CLASS (self)->get_threshold (self); -+} -+ -+AcmeVolume *acme_volume_new (void) -+{ -+ AcmeVolume *vol; -+ -+#ifdef HAVE_GSTREAMER -+ vol = ACME_VOLUME (g_object_new (acme_volume_gstreamer_get_type (), NULL)); -+ return vol; -+#endif -+#ifdef HAVE_ALSA -+ vol = ACME_VOLUME (g_object_new (acme_volume_alsa_get_type (), NULL)); -+ if (vol != NULL && ACME_VOLUME_ALSA (vol)->_priv != NULL) -+ return vol; -+ if (ACME_VOLUME_ALSA (vol)->_priv == NULL) -+ g_object_unref (vol); -+#endif -+#ifdef HAVE_OSS -+ vol = ACME_VOLUME (g_object_new (acme_volume_oss_get_type (), NULL)); -+ return vol; -+#endif -+ return NULL; -+} -+ -diff --git a/plugins/media-keys/actions/acme-volume.h b/plugins/media-keys/actions/acme-volume.h -new file mode 100644 -index 0000000..ec5ee3d ---- /dev/null -+++ b/plugins/media-keys/actions/acme-volume.h -@@ -0,0 +1,63 @@ -+/* acme-volume.h -+ -+ Copyright (C) 2002, 2003 Bastien Nocera -+ -+ 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> -+ */ -+ -+#ifndef _ACME_VOLUME_H -+#define _ACME_VOLUME_H -+ -+#include <glib.h> -+#include <glib-object.h> -+ -+G_BEGIN_DECLS -+ -+#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 { -+ GObject parent; -+} AcmeVolume; -+ -+typedef struct { -+ GObjectClass parent; -+ -+ void (* set_volume) (AcmeVolume *self, int val); -+ int (* get_volume) (AcmeVolume *self); -+ void (* set_mute) (AcmeVolume *self, gboolean val); -+ int (* get_mute) (AcmeVolume *self); -+ int (* get_threshold) (AcmeVolume *self); -+} AcmeVolumeClass; -+ -+GType acme_volume_get_type (void); -+int acme_volume_get_volume (AcmeVolume *self); -+void acme_volume_set_volume (AcmeVolume *self, int val); -+gboolean acme_volume_get_mute (AcmeVolume *self); -+void acme_volume_set_mute (AcmeVolume *self, -+ gboolean val); -+void acme_volume_mute_toggle (AcmeVolume *self); -+int acme_volume_get_threshold (AcmeVolume *self); -+AcmeVolume *acme_volume_new (void); -+ -+G_END_DECLS -+ -+#endif /* _ACME_VOLUME_H */ -diff --git a/plugins/media-keys/gsd-media-keys-manager.c b/plugins/media-keys/gsd-media-keys-manager.c -index d35048c..205d25b 100644 ---- a/plugins/media-keys/gsd-media-keys-manager.c -+++ b/plugins/media-keys/gsd-media-keys-manager.c -@@ -48,11 +48,12 @@ - - #include "eggaccelerators.h" - #include "acme.h" --#include "gsd-media-keys-window.h" -- - #ifdef HAVE_PULSE - #include "gvc-mixer-control.h" -+#else -+#include "actions/acme-volume.h" - #endif /* HAVE_PULSE */ -+#include "gsd-media-keys-window.h" - - #define GSD_DBUS_PATH "/org/gnome/SettingsDaemon" - #define GSD_DBUS_NAME "org.gnome.SettingsDaemon" -@@ -90,6 +91,8 @@ struct GsdMediaKeysManagerPrivate - /* Number of expected update signals, zero meaning we - * shouldn't be showing any update dialogues */ - guint num_expected_update_signals; -+#else -+ AcmeVolume *volume; - #endif /* HAVE_PULSE */ - GtkWidget *dialog; - GConfClient *conf_client; -@@ -650,40 +653,75 @@ on_stream_event_notify (GObject *object, - { - update_dialog (manager); - } -- -+#endif /* HAVE_PULSE */ - static void - do_sound_action (GsdMediaKeysManager *manager, - int type) - { - gboolean muted; -+#ifdef HAVE_PULSE - guint vol, norm_vol_step; - int vol_step; -+#else -+ int vol; -+ int vol_step; -+ GError *error = NULL; -+#endif - -+#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, - GCONF_MISC_DIR "/volume_step", -- NULL); -+ &error); - -- if (vol_step <= 0 || vol_step > 100) -+#ifdef HAVE_PULSE -+ if (vol_step <= 0 || vol_step > 100) { -+#else -+ if (error) { -+#endif - vol_step = VOLUME_STEP; -+ g_error_free (error); -+ } - -+#ifdef HAVE_PULSE - norm_vol_step = PA_VOLUME_NORM * vol_step / 100; -+#else -+ if (vol_step > 0) { -+ int threshold = acme_volume_get_threshold (manager->priv->volume); -+ if (vol_step < threshold) -+ vol_step = threshold; -+ g_debug ("Using volume step of %d", vol_step); -+ } -+#endif - - /* FIXME: this is racy */ -+#ifdef HAVE_PULSE - vol = gvc_mixer_stream_get_volume (manager->priv->stream); - muted = gvc_mixer_stream_get_is_muted (manager->priv->stream); - /* By default, we would be showing a dialogue - * based on the current values, eg. an unchanged dialogue */ - manager->priv->num_expected_update_signals = 0; -+#else -+ vol = acme_volume_get_volume (manager->priv->volume); -+ muted = acme_volume_get_mute (manager->priv->volume); -+#endif - - switch (type) { - case MUTE_KEY: -+#ifdef HAVE_PULSE - manager->priv->num_expected_update_signals = 1; - 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)) { - manager->priv->num_expected_update_signals = 2; - gvc_mixer_stream_change_is_muted (manager->priv->stream, !muted); -@@ -692,18 +730,29 @@ do_sound_action (GsdMediaKeysManager *manager, - manager->priv->num_expected_update_signals = 1; - gvc_mixer_stream_change_volume (manager->priv->stream, vol - norm_vol_step); - } -+#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) { - if (vol == 0) { -+#ifdef HAVE_PULSE - manager->priv->num_expected_update_signals = 2; - gvc_mixer_stream_change_volume (manager->priv->stream, vol + norm_vol_step); - gvc_mixer_stream_change_is_muted (manager->priv->stream, !muted); - } else { - manager->priv->num_expected_update_signals = 1; - gvc_mixer_stream_change_is_muted (manager->priv->stream, !muted); -+#else -+ acme_volume_set_volume (manager->priv->volume, vol + vol_step); -+#endif - } - } else { -+#ifdef HAVE_PULSE - if (vol < MAX_VOLUME) { - manager->priv->num_expected_update_signals = 1; - if (vol + norm_vol_step >= MAX_VOLUME) { -@@ -712,17 +761,37 @@ do_sound_action (GsdMediaKeysManager *manager, - gvc_mixer_stream_change_volume (manager->priv->stream, vol + norm_vol_step); - } - } -+#else -+ acme_volume_set_volume (manager->priv->volume, vol + vol_step); -+#endif - } - break; - } - -+#ifdef HAVE_PULSE - /* We didn't actually make any changes, so force showing the dialogue */ - if (manager->priv->num_expected_update_signals == 0) { - manager->priv->num_expected_update_signals = 1; - update_dialog (manager); - } -+#else -+ muted = acme_volume_get_mute (manager->priv->volume); -+ vol = acme_volume_get_volume (manager->priv->volume); -+ -+ /* FIXME: AcmeVolume should probably emit signals -+ instead of doing it like this */ -+ dialog_init (manager); -+ gsd_media_keys_window_set_volume_muted (GSD_MEDIA_KEYS_WINDOW (manager->priv->dialog), -+ muted); -+ gsd_media_keys_window_set_volume_level (GSD_MEDIA_KEYS_WINDOW (manager->priv->dialog), -+ vol); -+ gsd_media_keys_window_set_action (GSD_MEDIA_KEYS_WINDOW (manager->priv->dialog), -+ GSD_MEDIA_KEYS_WINDOW_ACTION_VOLUME); -+ dialog_show (manager); -+#endif - } - -+#ifdef HAVE_PULSE - static void - update_default_sink (GsdMediaKeysManager *manager) - { -@@ -887,9 +956,7 @@ do_action (GsdMediaKeysManager *manager, - case MUTE_KEY: - case VOLUME_DOWN_KEY: - case VOLUME_UP_KEY: --#ifdef HAVE_PULSE - do_sound_action (manager, type); --#endif /* HAVE_PULSE */ - break; - case POWER_KEY: - do_exit_action (manager); -@@ -1069,13 +1136,13 @@ gsd_media_keys_manager_start (GsdMediaKeysManager *manager, - { - gnome_settings_profile_start (NULL); - --#ifdef HAVE_PULSE - /* initialise Volume handler - * - * We do this one here to force checking gstreamer cache, etc. - * The rest (grabbing and setting the keys) can happen in an - * idle. - */ -+#ifdef HAVE_PULSE - gnome_settings_profile_start ("gvc_mixer_control_new"); - - manager->priv->volume = gvc_mixer_control_new (); -@@ -1092,6 +1159,10 @@ gsd_media_keys_manager_start (GsdMediaKeysManager *manager, - gvc_mixer_control_open (manager->priv->volume); - - gnome_settings_profile_end ("gvc_mixer_control_new"); -+#else -+ 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); - -@@ -1164,12 +1235,12 @@ gsd_media_keys_manager_stop (GsdMediaKeysManager *manager) - g_object_unref (priv->stream); - priv->stream = NULL; - } -+#endif /* HAVE_PULSE */ - - if (priv->volume) { - g_object_unref (priv->volume); - priv->volume = NULL; - } --#endif /* HAVE_PULSE */ - - if (priv->dialog != NULL) { - gtk_widget_destroy (priv->dialog); --- -1.6.1.2 - diff --git a/gnome-base/gnome-settings-daemon/files/gnome-settings-daemon-2.26.0-readd-gst-vol-control-support.patch b/gnome-base/gnome-settings-daemon/files/gnome-settings-daemon-2.26.0-readd-gst-vol-control-support.patch new file mode 100644 index 00000000..c849cded --- /dev/null +++ b/gnome-base/gnome-settings-daemon/files/gnome-settings-daemon-2.26.0-readd-gst-vol-control-support.patch @@ -0,0 +1,915 @@ + configure.ac | 40 +++ + plugins/media-keys/Makefile.am | 23 ++- + plugins/media-keys/actions/Makefile.am | 44 +++ + plugins/media-keys/actions/acme-volume.c | 402 +++++++++++++++++++++++++++ + plugins/media-keys/actions/acme-volume.h | 56 ++++ + plugins/media-keys/gsd-media-keys-manager.c | 98 ++++++-- + 6 files changed, 640 insertions(+), 23 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 9cff33f..4b69370 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -253,11 +253,49 @@ if test x$WANT_PULSE = xyes ; then + AC_DEFINE(HAVE_PULSE, 1, [Define if PULSE sound server should be used])], + [have_pulse=false]) + fi ++ + 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_gstreamer" = "xyes"; then ++ GST_LIBS="$GST_LIBS -lgstinterfaces-0.10 -lgstaudio-0.10" ++ 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 + # --------------------------------------------------------------------------- +@@ -355,6 +393,7 @@ plugins/housekeeping/Makefile + plugins/keybindings/Makefile + plugins/keyboard/Makefile + plugins/media-keys/Makefile ++plugins/media-keys/actions/Makefile + plugins/media-keys/cut-n-paste/Makefile + plugins/mouse/Makefile + plugins/screensaver/Makefile +@@ -397,6 +436,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 b308edb..34aa464 100644 +--- a/plugins/media-keys/Makefile.am ++++ b/plugins/media-keys/Makefile.am +@@ -1,11 +1,12 @@ + NULL = + + SUBDIRS = +-plugin_LTLIBRARIES = ++plugin_LTLIBRARIES = libmedia-keys.la + + if HAVE_PULSE + SUBDIRS += cut-n-paste +-plugin_LTLIBRARIES += libmedia-keys.la ++else ++SUBDIRS += actions + endif + + BUILT_SOURCES = \ +@@ -39,7 +40,6 @@ libmedia_keys_la_SOURCES = \ + libmedia_keys_la_CPPFLAGS = \ + -I$(top_srcdir)/gnome-settings-daemon \ + -I$(top_srcdir)/plugins/common \ +- -I$(top_srcdir)/plugins/media-keys/cut-n-paste \ + -DPIXMAPDIR=\""$(pkgdatadir)"\" \ + -DGLADEDIR=\""$(pkgdatadir)"\" \ + -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \ +@@ -55,7 +55,6 @@ libmedia_keys_la_LDFLAGS = \ + libmedia_keys_la_LIBADD = \ + $(top_builddir)/gnome-settings-daemon/libgsd-plugins.la \ + $(top_builddir)/plugins/common/libcommon.la \ +- $(top_builddir)/plugins/media-keys/cut-n-paste/libgvc.la \ + $(SETTINGS_PLUGIN_LIBS) \ + $(XF86MISC_LIBS) + +@@ -77,7 +76,6 @@ test_media_window_SOURCES = \ + + test_media_window_CPPFLAGS = \ + -I$(top_srcdir)/gnome-settings-daemon \ +- -I$(top_srcdir)/plugins/media-keys/cut-n-paste \ + -DPIXMAPDIR=\""$(pkgdatadir)"\" \ + -DGLADEDIR=\""$(pkgdatadir)"\" \ + -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \ +@@ -105,7 +103,6 @@ test_media_keys_SOURCES = \ + test_media_keys_CPPFLAGS = \ + -I$(top_srcdir)/gnome-settings-daemon \ + -I$(top_srcdir)/plugins/common \ +- -I$(top_srcdir)/plugins/media-keys/cut-n-paste \ + -DPIXMAPDIR=\""$(pkgdatadir)"\" \ + -DGLADEDIR=\""$(pkgdatadir)"\" \ + -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \ +@@ -124,7 +121,17 @@ test_media_keys_LDADD = \ + $(GST_LIBS) + + if HAVE_PULSE ++libmedia_keys_la_CPPFLAGS += -I$(top_builddir)/plugins/media-keys/cut-n-paste ++libmedia_keys_la_LIBADD += $(top_builddir)/plugins/media-keys/cut-n-paste/libgvc.la ++test_media_window_CPPFLAGS += -I$(top_builddir)/plugins/media-keys/cut-n-paste ++test_media_keys_CPPFLAGS += -I$(top_builddir)/plugins/media-keys/cut-n-paste + test_media_keys_LDADD += $(top_builddir)/plugins/media-keys/cut-n-paste/libgvc.la ++else ++libmedia_keys_la_CPPFLAGS += -I$(top_builddir)/plugins/media-keys/actions ++libmedia_keys_la_LIBADD += $(top_builddir)/plugins/media-keys/actions/libacme.la ++test_media_window_CPPFLAGS += -I$(top_builddir)/plugins/media-keys/actions ++test_media_keys_CPPFLAGS += -I$(top_builddir)/plugins/media-keys/actions ++test_media_keys_LDADD += $(top_builddir)/plugins/media-keys/actions/libacme.la + endif + + gladedir = $(pkgdatadir) +@@ -137,7 +144,11 @@ pixmaps_DATA = \ + acme-eject.png \ + $(NULL) + ++if HAVE_PULSE + DIST_SUBDIRS = cut-n-paste ++else ++DIST_SUBDIRS = actions ++endif + + EXTRA_DIST = \ + gsd-media-keys-manager.xml \ +diff --git a/plugins/media-keys/actions/Makefile.am b/plugins/media-keys/actions/Makefile.am +new file mode 100644 +index 0000000..4bf215a +--- /dev/null ++++ b/plugins/media-keys/actions/Makefile.am +@@ -0,0 +1,44 @@ ++NULL = ++ ++noinst_LTLIBRARIES = libacme.la ++ ++libacme_la_SOURCES = \ ++ ../acme.h \ ++ $(NULL) ++ ++libacme_la_CPPFLAGS = \ ++ -I$(top_srcdir)/gnome-settings-daemon \ ++ -I$(top_srcdir)/plugins/common \ ++ -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \ ++ $(AM_CPPFLAGS) ++ ++libacme_la_CFLAGS = \ ++ $(SETTINGS_PLUGIN_CFLAGS) \ ++ $(AM_CFLAGS) ++ ++libacme_la_LIBADD = \ ++ $(NULL) ++ ++if HAVE_GSTREAMER ++libacme_la_SOURCES += \ ++ acme-volume.c \ ++ acme-volume.h \ ++ $(NULL) ++libacme_la_CFLAGS += $(GST_CFLAGS) ++libacme_la_LIBADD += $(GST_LIBS) ++endif ++ ++gladedir = $(pkgdatadir) ++glade_DATA = \ ++ ../acme.glade \ ++ $(NULL) ++ ++pixmapsdir = $(pkgdatadir) ++pixmaps_DATA = \ ++ ../acme-eject.png \ ++ $(NULL) ++ ++EXTRA_DIST = \ ++ $(glade_DATA) \ ++ $(pixmaps_DATA) \ ++ $(NULL) +diff --git a/plugins/media-keys/actions/acme-volume.c b/plugins/media-keys/actions/acme-volume.c +new file mode 100644 +index 0000000..e468669 +--- /dev/null ++++ b/plugins/media-keys/actions/acme-volume.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 "acme-volume.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; ++ ++ /* 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/actions/acme-volume.h b/plugins/media-keys/actions/acme-volume.h +new file mode 100644 +index 0000000..c14ebc8 +--- /dev/null ++++ b/plugins/media-keys/actions/acme-volume.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 d35048c..affa602 100644 +--- a/plugins/media-keys/gsd-media-keys-manager.c ++++ b/plugins/media-keys/gsd-media-keys-manager.c +@@ -48,11 +48,12 @@ + + #include "eggaccelerators.h" + #include "acme.h" +-#include "gsd-media-keys-window.h" +- + #ifdef HAVE_PULSE + #include "gvc-mixer-control.h" ++#else ++#include "actions/acme-volume.h" + #endif /* HAVE_PULSE */ ++#include "gsd-media-keys-window.h" + + #define GSD_DBUS_PATH "/org/gnome/SettingsDaemon" + #define GSD_DBUS_NAME "org.gnome.SettingsDaemon" +@@ -90,6 +91,8 @@ struct GsdMediaKeysManagerPrivate + /* Number of expected update signals, zero meaning we + * shouldn't be showing any update dialogues */ + guint num_expected_update_signals; ++#else ++ AcmeVolume *volume; + #endif /* HAVE_PULSE */ + GtkWidget *dialog; + GConfClient *conf_client; +@@ -131,9 +134,8 @@ init_screens (GsdMediaKeysManager *manager) + GdkScreen *screen; + + screen = gdk_display_get_screen (display, i); +- if (screen == NULL) { ++ if (screen == NULL) + continue; +- } + manager->priv->screens = g_slist_append (manager->priv->screens, screen); + } + +@@ -650,40 +652,66 @@ on_stream_event_notify (GObject *object, + { + update_dialog (manager); + } +- ++#endif /* HAVE_PULSE */ + static void + do_sound_action (GsdMediaKeysManager *manager, + int type) + { + gboolean muted; ++#ifdef HAVE_PULSE + guint vol, norm_vol_step; + int vol_step; +- + if (manager->priv->stream == NULL) ++#else ++ int vol; ++ int vol_step; ++ GError *error = NULL; ++ if (manager->priv->volume == NULL) ++#endif + return; + + vol_step = gconf_client_get_int (manager->priv->conf_client, + GCONF_MISC_DIR "/volume_step", +- NULL); ++ &error); + +- if (vol_step <= 0 || vol_step > 100) ++#ifdef HAVE_PULSE ++ if (vol_step <= 0 || vol_step > 100) { ++#else ++ if (error) { ++#endif + vol_step = VOLUME_STEP; ++ g_error_free (error); ++ } + ++#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); ++ + /* By default, we would be showing a dialogue + * based on the current values, eg. an unchanged dialogue */ + manager->priv->num_expected_update_signals = 0; +- ++#else ++ if (vol_step > 0) { ++ int 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: ++#ifdef HAVE_PULSE + manager->priv->num_expected_update_signals = 1; + 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)) { + manager->priv->num_expected_update_signals = 2; + gvc_mixer_stream_change_is_muted (manager->priv->stream, !muted); +@@ -692,18 +720,31 @@ do_sound_action (GsdMediaKeysManager *manager, + manager->priv->num_expected_update_signals = 1; + gvc_mixer_stream_change_volume (manager->priv->stream, vol - norm_vol_step); + } ++#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) { + if (vol == 0) { ++#ifdef HAVE_PULSE + manager->priv->num_expected_update_signals = 2; + gvc_mixer_stream_change_volume (manager->priv->stream, vol + norm_vol_step); + gvc_mixer_stream_change_is_muted (manager->priv->stream, !muted); + } else { + manager->priv->num_expected_update_signals = 1; + gvc_mixer_stream_change_is_muted (manager->priv->stream, !muted); ++#else ++ acme_volume_set_volume (manager->priv->volume, vol + vol_step); ++ /* We need to unmute otherwise vol is blocked (and muted) */ ++ acme_volume_set_mute (manager->priv->volume, FALSE); ++#endif + } +- } else { ++ } else { ++#ifdef HAVE_PULSE + if (vol < MAX_VOLUME) { + manager->priv->num_expected_update_signals = 1; + if (vol + norm_vol_step >= MAX_VOLUME) { +@@ -712,17 +753,38 @@ do_sound_action (GsdMediaKeysManager *manager, + gvc_mixer_stream_change_volume (manager->priv->stream, vol + norm_vol_step); + } + } ++#else ++ acme_volume_set_volume (manager->priv->volume, vol + vol_step); ++#endif + } + break; + } + ++#ifdef HAVE_PULSE + /* We didn't actually make any changes, so force showing the dialogue */ + if (manager->priv->num_expected_update_signals == 0) { + manager->priv->num_expected_update_signals = 1; + update_dialog (manager); + } +-} ++#else ++ muted = acme_volume_get_mute (manager->priv->volume); ++ vol = acme_volume_get_volume (manager->priv->volume); + ++ /* FIXME: AcmeVolume should probably emit signals ++ instead of doing it like this */ ++ dialog_init (manager); ++ gsd_media_keys_window_set_volume_muted (GSD_MEDIA_KEYS_WINDOW (manager->priv->dialog), ++ muted); ++ gsd_media_keys_window_set_volume_level (GSD_MEDIA_KEYS_WINDOW (manager->priv->dialog), ++ vol); ++ gsd_media_keys_window_set_action (GSD_MEDIA_KEYS_WINDOW (manager->priv->dialog), ++ GSD_MEDIA_KEYS_WINDOW_ACTION_VOLUME); ++ dialog_show (manager); ++#endif ++ } ++ ++ ++#ifdef HAVE_PULSE + static void + update_default_sink (GsdMediaKeysManager *manager) + { +@@ -887,9 +949,7 @@ do_action (GsdMediaKeysManager *manager, + case MUTE_KEY: + case VOLUME_DOWN_KEY: + case VOLUME_UP_KEY: +-#ifdef HAVE_PULSE + do_sound_action (manager, type); +-#endif /* HAVE_PULSE */ + break; + case POWER_KEY: + do_exit_action (manager); +@@ -1069,13 +1129,13 @@ gsd_media_keys_manager_start (GsdMediaKeysManager *manager, + { + gnome_settings_profile_start (NULL); + +-#ifdef HAVE_PULSE + /* initialise Volume handler + * + * We do this one here to force checking gstreamer cache, etc. + * The rest (grabbing and setting the keys) can happen in an + * idle. + */ ++#ifdef HAVE_PULSE + gnome_settings_profile_start ("gvc_mixer_control_new"); + + manager->priv->volume = gvc_mixer_control_new (); +@@ -1092,6 +1152,10 @@ gsd_media_keys_manager_start (GsdMediaKeysManager *manager, + gvc_mixer_control_open (manager->priv->volume); + + gnome_settings_profile_end ("gvc_mixer_control_new"); ++#else ++ 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); + +@@ -1164,12 +1228,12 @@ gsd_media_keys_manager_stop (GsdMediaKeysManager *manager) + g_object_unref (priv->stream); + priv->stream = NULL; + } ++#endif /* HAVE_PULSE */ + + if (priv->volume) { + g_object_unref (priv->volume); + priv->volume = NULL; + } +-#endif /* HAVE_PULSE */ + + if (priv->dialog != NULL) { + gtk_widget_destroy (priv->dialog); |