Fix mute handling, particularly for devices without hardware mute support

* actions/Makefile.am:
* actions/acme-volume-gstreamer.c:
(acme_volume_gstreamer_set_mute), (update_state),
(acme_volume_gstreamer_get_mute),
(acme_volume_gstreamer_get_volume),
(acme_volume_gstreamer_set_volume):
Fix mute handling, particularly for devices without hardware
mute support or with applications that use volume=0 for mute.
Also fix the fact that we linked against all of ALSA, OSS and
GStreamer if they were all available; default to GStreamer.
Fixes #306036.
This commit is contained in:
Ronald Bultje 2005-06-05 13:04:26 +00:00
parent 7fdb798d4d
commit 6ce4e37a4f
3 changed files with 83 additions and 33 deletions

View file

@ -1,3 +1,17 @@
2005-06-05 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
* actions/Makefile.am:
* actions/acme-volume-gstreamer.c:
(acme_volume_gstreamer_set_mute), (update_state),
(acme_volume_gstreamer_get_mute),
(acme_volume_gstreamer_get_volume),
(acme_volume_gstreamer_set_volume):
Fix mute handling, particularly for devices without hardware
mute support or with applications that use volume=0 for mute.
Also fix the fact that we linked against all of ALSA, OSS and
GStreamer if they were all available; default to GStreamer.
Fixes #306036.
2005-06-03 Anders Carlsson <andersca@imendio.com> 2005-06-03 Anders Carlsson <andersca@imendio.com>
* Makefile.am: * Makefile.am:

View file

@ -1,25 +1,30 @@
INCLUDES = $(GNOME_CFLAGS) -I$(top_srcdir) $(GST_CFLAGS) INCLUDES = $(GNOME_CFLAGS) -I$(top_srcdir) $(GST_CFLAGS)
noinst_LTLIBRARIES = libacme.la noinst_LTLIBRARIES = libacme.la
libacme_la_SOURCES = \ libacme_la_SOURCES = \
acme-volume.c acme-volume.h \ acme-volume.c acme-volume.h
acme-volume-dummy.c acme-volume-dummy.h
libacme_la_LIBADD = \
$(GST_LIBS) $(ALSA_LIBS)
libacme_la_LIBADD =
if HAVE_GSTREAMER
INCLUDES += -DHAVE_GSTREAMER
libacme_la_SOURCES += acme-volume-gstreamer.c acme-volume-gstreamer.h
libacme_la_LIBADD += $(GST_LIBS)
else # HAVE_GSTREAMER
if HAVE_ALSA if HAVE_ALSA
INCLUDES += -DHAVE_ALSA INCLUDES += -DHAVE_ALSA
libacme_la_SOURCES += acme-volume-alsa.c acme-volume-alsa.h libacme_la_SOURCES += acme-volume-alsa.c acme-volume-alsa.h
endif libacme_la_LIBADD += $(ALSA_LIBS)
else # HAVE_ALSA
if HAVE_OSS if HAVE_OSS
INCLUDES += -DHAVE_OSS INCLUDES += -DHAVE_OSS
libacme_la_SOURCES += acme-volume-oss.c acme-volume-oss.h libacme_la_SOURCES += acme-volume-oss.c acme-volume-oss.h
endif else # HAVE_OSS
libacme_la_SOURCES += acme-volume-dummy.c acme-volume-dummy.h
endif # HAVE_OSS
endif # HAVE_ALSA
endif # HAVE_GSTREAMER
if HAVE_FB if HAVE_FB
INCLUDES += -DHAVE_FB INCLUDES += -DHAVE_FB
@ -29,9 +34,9 @@ endif
if HAVE_GSTREAMER if HAVE_GSTREAMER
INCLUDES += -DHAVE_GSTREAMER INCLUDES += -DHAVE_GSTREAMER
libacme_la_SOURCES += acme-volume-gstreamer.c acme-volume-gstreamer.h libacme_la_SOURCES += acme-volume-gstreamer.c acme-volume-gstreamer.h
libacme_la_LIBADD += $(GST_LIBS)
endif endif
Datadir = $(datadir)/control-center-2.0/interfaces/ Datadir = $(datadir)/control-center-2.0/interfaces/
Data_DATA = acme.glade Data_DATA = acme.glade
@ -42,8 +47,8 @@ EXTRA_DIST = \
acme-volume-alsa.c acme-volume-alsa.h \ acme-volume-alsa.c acme-volume-alsa.h \
acme-volume-gstreamer.c acme-volume-gstreamer.h \ acme-volume-gstreamer.c acme-volume-gstreamer.h \
acme-volume-oss.c acme-volume-oss.h \ acme-volume-oss.c acme-volume-oss.h \
acme-volume-dummy.c acme-volume-dummy.h \
acme-fb-level.c acme-fb-level.h \ acme-fb-level.c acme-fb-level.h \
acme.h \ acme.h \
acme.glade \ acme.glade \
$(pixmaps_DATA) $(pixmaps_DATA)

View file

@ -40,6 +40,7 @@ struct AcmeVolumeGStreamerPrivate
GstMixer *mixer; GstMixer *mixer;
GstMixerTrack *track; GstMixerTrack *track;
guint timer_id; guint timer_id;
gint state;
}; };
static GObjectClass *parent_class = NULL; static GObjectClass *parent_class = NULL;
@ -88,60 +89,85 @@ acme_volume_gstreamer_set_mute (AcmeVolume *vol, gboolean val)
self->_priv->track, self->_priv->track,
val); val);
if (val)
self->_priv->state |= 1;
else {
GstMixerTrack *track = self->_priv->track;
gint *volumes, n;
self->_priv->state &= ~1;
volumes = g_new0 (gint, track->num_channels);
for (n = 0; n < track->num_channels; n++)
volumes[n] = (self->_priv->state >> 1) /
track->num_channels;
gst_mixer_set_volume (self->_priv->mixer, track, volumes);
g_free (volumes);
}
acme_volume_gstreamer_close (self); acme_volume_gstreamer_close (self);
} }
static void
update_state (AcmeVolumeGStreamer * self)
{
gint *volumes, vol = 0, n;
GstMixerTrack *track = self->_priv->track;
/* 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);
/* update mute flag, and volume if not muted */
if (GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_MUTE) ||
(vol == 0 && (self->_priv->state >> 1) != 0))
self->_priv->state |= 1;
else
self->_priv->state = vol << 1;
}
static gboolean static gboolean
acme_volume_gstreamer_get_mute (AcmeVolume *vol) acme_volume_gstreamer_get_mute (AcmeVolume *vol)
{ {
AcmeVolumeGStreamer *self = (AcmeVolumeGStreamer *) vol; AcmeVolumeGStreamer *self = (AcmeVolumeGStreamer *) vol;
gboolean mute;
if (acme_volume_gstreamer_open (self) == FALSE) if (acme_volume_gstreamer_open (self) == FALSE)
return FALSE; return FALSE;
mute = GST_MIXER_TRACK_HAS_FLAG (self->_priv->track, update_state (self);
GST_MIXER_TRACK_MUTE);
acme_volume_gstreamer_close (self); acme_volume_gstreamer_close (self);
return mute; return (self->_priv->state & 1);
} }
static int static int
acme_volume_gstreamer_get_volume (AcmeVolume *vol) acme_volume_gstreamer_get_volume (AcmeVolume *vol)
{ {
gint i, vol_total = 0, *volumes;
double volume; double volume;
AcmeVolumeGStreamer *self = (AcmeVolumeGStreamer *) vol; AcmeVolumeGStreamer *self = (AcmeVolumeGStreamer *) vol;
GstMixerTrack *track; GstMixerTrack *track = self->_priv->track;
if (acme_volume_gstreamer_open (self) == FALSE) if (acme_volume_gstreamer_open (self) == FALSE)
return 0; return 0;
track = self->_priv->track; update_state (self);
volumes = g_new0 (gint, track->num_channels); /* normalize to [0,100] scale that acme wants */
gst_mixer_get_volume (self->_priv->mixer, track, volumes); volume = (self->_priv->state >> 1) / (double) track->num_channels;
for (i = 0; i < track->num_channels; ++i) volume = 100 * (volume - track->min_volume) /
vol_total += volumes[i]; (track->max_volume - track->min_volume);
g_free (volumes);
acme_volume_gstreamer_close (self); acme_volume_gstreamer_close (self);
volume = vol_total / (double)track->num_channels;
/* Normalize the volume to the [0, 100] scale that acme expects. */
volume = 100 * (volume - track->min_volume) / (track->max_volume - track->min_volume);
return (gint) volume; return (gint) volume;
} }
static void static void
acme_volume_gstreamer_set_volume (AcmeVolume *vol, int val) acme_volume_gstreamer_set_volume (AcmeVolume *vol, int val)
{ {
gint i, *volumes; gint i, *volumes, volume;
double volume;
AcmeVolumeGStreamer *self = (AcmeVolumeGStreamer *) vol; AcmeVolumeGStreamer *self = (AcmeVolumeGStreamer *) vol;
GstMixerTrack *track; GstMixerTrack *track;
@ -152,7 +178,8 @@ acme_volume_gstreamer_set_volume (AcmeVolume *vol, int val)
val = CLAMP (val, 0, 100); val = CLAMP (val, 0, 100);
/* Rescale the volume from [0, 100] to [track min, track max]. */ /* Rescale the volume from [0, 100] to [track min, track max]. */
volume = (val / 100.0) * (track->max_volume - track->min_volume) + track->min_volume; volume = (val / 100.0) * (track->max_volume - track->min_volume) +
track->min_volume;
volumes = g_new (gint, track->num_channels); volumes = g_new (gint, track->num_channels);
for (i = 0; i < track->num_channels; ++i) for (i = 0; i < track->num_channels; ++i)
@ -160,6 +187,10 @@ acme_volume_gstreamer_set_volume (AcmeVolume *vol, int val)
gst_mixer_set_volume (self->_priv->mixer, track, volumes); gst_mixer_set_volume (self->_priv->mixer, track, volumes);
g_free (volumes); g_free (volumes);
/* update state */
self->_priv->state = (self->_priv->state & 1) |
((volume * track->num_channels) << 1);
acme_volume_gstreamer_close (self); acme_volume_gstreamer_close (self);
} }