diff options
author | Nirbheek Chauhan <nirbheek.chauhan@gmail.com> | 2009-02-10 12:26:11 +0530 |
---|---|---|
committer | Nirbheek Chauhan <nirbheek.chauhan@gmail.com> | 2009-02-10 12:26:11 +0530 |
commit | 79433d416e392f084a0014f753f238c9f6df43f4 (patch) | |
tree | 4ec0dd75d7af00a89571e56d29f9f5c2ee15bbee /gnome-base/gnome-settings-daemon/files | |
parent | gnome-extra/evolution-data-server: Add missing patch, bug #257698. (diff) | |
download | gnome-79433d416e392f084a0014f753f238c9f6df43f4.tar.gz gnome-79433d416e392f084a0014f753f238c9f6df43f4.tar.bz2 gnome-79433d416e392f084a0014f753f238c9f6df43f4.zip |
Non-pulse support for gnome-base/gnome-settings-daemon
- gnome-settings-daemon completely removed support for gstreamer and alsa and
only supported pulseaudio for volume control via media keys
- The added patch #ifdefs in the older code if HAVE_PULSE is not defined
- The changed libnotify patch is from trunk, and must be applied before the
pulse patch.
Diffstat (limited to 'gnome-base/gnome-settings-daemon/files')
2 files changed, 2077 insertions, 10 deletions
diff --git a/gnome-base/gnome-settings-daemon/files/gnome-settings-daemon-2.25.90-libnotify-automagic.patch b/gnome-base/gnome-settings-daemon/files/gnome-settings-daemon-2.25.90-libnotify-automagic.patch index eee4f65b..0c1f651c 100644 --- a/gnome-base/gnome-settings-daemon/files/gnome-settings-daemon-2.25.90-libnotify-automagic.patch +++ b/gnome-base/gnome-settings-daemon/files/gnome-settings-daemon-2.25.90-libnotify-automagic.patch @@ -1,6 +1,8 @@ ---- configure.ac 2008-10-09 00:03:09.000000000 +0200 -+++ configure.ac.new 2008-10-09 00:03:46.000000000 +0200 -@@ -87,9 +87,16 @@ +diff --git a/configure.ac b/configure.ac +index 506c4e4..aa55fc1 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -89,9 +89,19 @@ dnl --------------------------------------------------------------------------- dnl - Check for libnotify dnl --------------------------------------------------------------------------- @@ -8,15 +10,27 @@ - [AC_DEFINE(HAVE_LIBNOTIFY, 1, [Define if libnotify is available]) - have_libnotify=yes], [have_libnotify=no]) +have_libnotify=no -+AC_ARG_ENABLE(libnotify, -+ AS_HELP_STRING([--disable-libnotify], [Enable nice notifications]), -+ , enable_libnotify=yes) ++AC_ARG_WITH(libnotify, ++ AC_HELP_STRING([--without-libnotify], [Disable notifications (default: auto)]), ++ with_libnotify=$withval, with_libnotify=auto) + -+if test "x$enable_libnotify" = "xyes"; then -+ have_libnotify=yes -+ PKG_CHECK_MODULES(LIBNOTIFY, libnotify >= $LIBNOTIFY_REQUIRED_VERSION) -+ AC_DEFINE(HAVE_LIBNOTIFY, 1, [Define if libnotify is available]) ++if test "x$with_libnotify" != "xno"; then ++ PKG_CHECK_MODULES(LIBNOTIFY, libnotify >= $LIBNOTIFY_REQUIRED_VERSION, ++ [AC_DEFINE(HAVE_LIBNOTIFY, 1, [Define if libnotify is available]) ++ have_libnotify=yes], have_libnotify=no) ++ if test "x$have_libnotify" = xno -a "x$with_libnotify" = xyes; then ++ AC_MSG_ERROR([libnotify support requested but libraries not found]) ++ fi +fi AC_SUBST(LIBNOTIFY_CFLAGS) AC_SUBST(LIBNOTIFY_LIBS) +@@ -386,7 +396,7 @@ echo " + + dbus-1 system.d dir: ${DBUS_SYS_DIR} + ++ Libnotify support: ${have_libnotify} + PulseAudio support: ${have_pulse} +- + Profiling support: ${enable_profiling} + " diff --git a/gnome-base/gnome-settings-daemon/files/gnome-settings-daemon-2.25.90-readd-AcmeVolume-support.patch b/gnome-base/gnome-settings-daemon/files/gnome-settings-daemon-2.25.90-readd-AcmeVolume-support.patch new file mode 100644 index 00000000..9e9d2872 --- /dev/null +++ b/gnome-base/gnome-settings-daemon/files/gnome-settings-daemon-2.25.90-readd-AcmeVolume-support.patch @@ -0,0 +1,2053 @@ +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 + |