Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--configure.ac2
-rw-r--r--src/sugar/Makefile.am5
-rw-r--r--src/sugar/_sugarext.defs68
-rw-r--r--src/sugar/_sugarext.override1
-rw-r--r--src/sugar/acme-volume-alsa.c329
-rw-r--r--src/sugar/acme-volume-alsa.h47
-rw-r--r--src/sugar/acme-volume.c127
-rw-r--r--src/sugar/acme-volume.h63
8 files changed, 641 insertions, 1 deletions
diff --git a/configure.ac b/configure.ac
index 1d0ac21..bd052ed 100644
--- a/configure.ac
+++ b/configure.ac
@@ -19,7 +19,7 @@ AM_CHECK_PYTHON_HEADERS(,[AC_MSG_ERROR(could not find Python headers)])
AC_PATH_PROG(PYGTK_CODEGEN, pygtk-codegen-2.0, no)
-PKG_CHECK_MODULES(EXT, pygtk-2.0 gtk+-2.0)
+PKG_CHECK_MODULES(EXT, pygtk-2.0 gtk+-2.0 sm ice alsa)
PYGTK_DEFSDIR=`$PKG_CONFIG --variable=defsdir pygtk-2.0`
AC_SUBST(PYGTK_DEFSDIR)
diff --git a/src/sugar/Makefile.am b/src/sugar/Makefile.am
index 06500f7..ef7e634 100644
--- a/src/sugar/Makefile.am
+++ b/src/sugar/Makefile.am
@@ -14,6 +14,7 @@ pkgpyexecdir = $(pythondir)/sugar
pkgpyexec_LTLIBRARIES = _sugarext.la
_sugarext_la_CFLAGS = \
+ -DHAVE_ALSA \
$(WARN_CFLAGS) \
$(EXT_CFLAGS) \
$(PYTHON_INCLUDES)
@@ -24,6 +25,10 @@ _sugarext_la_LIBADD = $(EXT_LIBS) -lSM -lICE
_sugarext_la_SOURCES = \
$(BUILT_SOURCES) \
_sugarextmodule.c \
+ acme-volume.h \
+ acme-volume.c \
+ acme-volume-alsa.h \
+ acme-volume-alsa.c \
gsm-app.h \
gsm-app.c \
gsm-client.h \
diff --git a/src/sugar/_sugarext.defs b/src/sugar/_sugarext.defs
index a3d0f71..32ea18a 100644
--- a/src/sugar/_sugarext.defs
+++ b/src/sugar/_sugarext.defs
@@ -64,6 +64,20 @@
(gtype-id "GSM_TYPE_SESSION")
)
+(define-object Volume
+ (in-module "Acme")
+ (parent "GObject")
+ (c-name "AcmeVolume")
+ (gtype-id "ACME_TYPE_VOLUME")
+)
+
+(define-object VolumeAlsa
+ (in-module "Acme")
+ (parent "AcmeVolume")
+ (c-name "AcmeVolumeAlsa")
+ (gtype-id "ACME_TYPE_VOLUME_ALSA")
+)
+
;; Enumerations and flags ...
(define-enum IconEntryPosition
@@ -391,3 +405,57 @@
(return-type "GsmSession*")
)
+;; From acme-volume.h
+
+(define-function acme_volume_get_type
+ (c-name "acme_volume_get_type")
+ (return-type "GType")
+)
+
+(define-method get_volume
+ (of-object "AcmeVolume")
+ (c-name "acme_volume_get_volume")
+ (return-type "int")
+)
+
+(define-method set_volume
+ (of-object "AcmeVolume")
+ (c-name "acme_volume_set_volume")
+ (return-type "none")
+ (parameters
+ '("int" "val")
+ )
+)
+
+(define-method get_mute
+ (of-object "AcmeVolume")
+ (c-name "acme_volume_get_mute")
+ (return-type "gboolean")
+)
+
+(define-method set_mute
+ (of-object "AcmeVolume")
+ (c-name "acme_volume_set_mute")
+ (return-type "none")
+ (parameters
+ '("gboolean" "val")
+ )
+)
+
+(define-method mute_toggle
+ (of-object "AcmeVolume")
+ (c-name "acme_volume_mute_toggle")
+ (return-type "none")
+)
+
+(define-method get_threshold
+ (of-object "AcmeVolume")
+ (c-name "acme_volume_get_threshold")
+ (return-type "int")
+)
+
+(define-function acme_volume_new
+ (c-name "acme_volume_new")
+ (is-constructor-of "AcmeVolume")
+ (return-type "AcmeVolume*")
+)
diff --git a/src/sugar/_sugarext.override b/src/sugar/_sugarext.override
index c6a7ae0..5a0608d 100644
--- a/src/sugar/_sugarext.override
+++ b/src/sugar/_sugarext.override
@@ -12,6 +12,7 @@ headers
#include "sexy-icon-entry.h"
#include "gsm-session.h"
#include "gsm-xsmp.h"
+#include "acme-volume-alsa.h"
#include "eggsmclient.h"
#include "eggsmclient-private.h"
diff --git a/src/sugar/acme-volume-alsa.c b/src/sugar/acme-volume-alsa.c
new file mode 100644
index 0000000..0462ed1
--- /dev/null
+++ b/src/sugar/acme-volume-alsa.c
@@ -0,0 +1,329 @@
+/* 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>
+ */
+
+#ifdef HAVE_CONFIG
+#include "config.h"
+#endif
+
+#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/src/sugar/acme-volume-alsa.h b/src/sugar/acme-volume-alsa.h
new file mode 100644
index 0000000..b179a24
--- /dev/null
+++ b/src/sugar/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_alsa_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/src/sugar/acme-volume.c b/src/sugar/acme-volume.c
new file mode 100644
index 0000000..09ae1d2
--- /dev/null
+++ b/src/sugar/acme-volume.c
@@ -0,0 +1,127 @@
+/* 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>
+ */
+
+#ifdef HAVE_CONFIG
+#include "config.h"
+#endif
+#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/src/sugar/acme-volume.h b/src/sugar/acme-volume.h
new file mode 100644
index 0000000..ec5ee3d
--- /dev/null
+++ b/src/sugar/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 */