diff options
Diffstat (limited to 'gst-mixer/src/volume.c')
-rw-r--r-- | gst-mixer/src/volume.c | 651 |
1 files changed, 0 insertions, 651 deletions
diff --git a/gst-mixer/src/volume.c b/gst-mixer/src/volume.c deleted file mode 100644 index 9a1aaac..0000000 --- a/gst-mixer/src/volume.c +++ /dev/null @@ -1,651 +0,0 @@ -/* MATE Volume Control - * Copyright (C) 2003-2004 Ronald Bultje <[email protected]> - * - * volume.c: representation of a track's volume channels - * - * This 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. - * - * This 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 this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#define _ISOC99_SOURCE - -#include <math.h> -#include <glib/gi18n.h> -#include <gdk/gdkx.h> -#include <gtk/gtk.h> - -#include "volume.h" -#include "button.h" - -G_DEFINE_TYPE (MateVolumeControlVolume, mate_volume_control_volume, GTK_TYPE_FIXED) - - -static void mate_volume_control_volume_class_init (MateVolumeControlVolumeClass *klass); -static void mate_volume_control_volume_init (MateVolumeControlVolume *el); -static void mate_volume_control_volume_dispose (GObject *object); - -#if GTK_CHECK_VERSION (3, 0, 0) -static void mate_volume_control_volume_get_preferred_width (GtkWidget *widget, - gint *minimum_width, - gint *natural_width); -static void mate_volume_control_volume_get_preferred_height (GtkWidget *widget, - gint *minimum_height, - gint *natural_height); -#else -static void mate_volume_control_volume_size_req (GtkWidget *widget, - GtkRequisition *req); -#endif -static void mate_volume_control_volume_size_alloc (GtkWidget *widget, - GtkAllocation *alloc); -#if GTK_CHECK_VERSION (3, 0, 0) -static gboolean mate_volume_control_volume_draw (GtkWidget *widget, - cairo_t *cr); -#else -static gboolean mate_volume_control_volume_expose (GtkWidget *widget, - GdkEventExpose *expose); -#endif - -static void cb_volume_changed (GtkAdjustment *adj, - gpointer data); -static void cb_lock_toggled (GtkToggleButton *button, - gpointer data); - -static gboolean cb_check (gpointer data); - - -static void -mate_volume_control_volume_class_init (MateVolumeControlVolumeClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - GtkWidgetClass *gtkwidget_class = GTK_WIDGET_CLASS (klass); - - gobject_class->dispose = mate_volume_control_volume_dispose; - gtkwidget_class->size_allocate = mate_volume_control_volume_size_alloc; -#if GTK_CHECK_VERSION (3, 0, 0) - gtkwidget_class->get_preferred_width = mate_volume_control_volume_get_preferred_width; - gtkwidget_class->get_preferred_height = mate_volume_control_volume_get_preferred_height; - gtkwidget_class->draw = mate_volume_control_volume_draw; -#else - gtkwidget_class->size_request = mate_volume_control_volume_size_req; - gtkwidget_class->expose_event = mate_volume_control_volume_expose; -#endif -} - -static void -mate_volume_control_volume_init (MateVolumeControlVolume *vol) -{ - #if GTK_CHECK_VERSION(2,18,0) - gtk_widget_set_has_window (GTK_WIDGET (vol), TRUE); - #else - gtk_fixed_set_has_window (GTK_FIXED (vol), TRUE); - #endif - - vol->mixer = NULL; - vol->track = NULL; - vol->padding = 6; - vol->scales = NULL; - vol->button = NULL; - vol->locked = FALSE; - vol->id = 0; -} - -static GtkWidget * -get_scale (MateVolumeControlVolume *vol, - gint num_chan, - gint volume) -{ - GtkWidget *slider; -#if GTK_CHECK_VERSION (3, 0, 0) - GtkAdjustment *adj; -#else - GtkObject *adj; -#endif - AtkObject *accessible; - gchar *accessible_name; - - adj = gtk_adjustment_new (volume, - vol->track->min_volume, vol->track->max_volume, - (vol->track->max_volume - vol->track->min_volume) / 100.0, - (vol->track->max_volume - vol->track->min_volume) / 10.0, 0.0); - g_signal_connect (adj, "value_changed", - G_CALLBACK (cb_volume_changed), vol); -#if GTK_CHECK_VERSION (3, 0, 0) - slider = gtk_vscale_new (adj); -#else - slider = gtk_vscale_new (GTK_ADJUSTMENT (adj)); -#endif - gtk_scale_set_draw_value (GTK_SCALE (slider), FALSE); - gtk_range_set_inverted (GTK_RANGE (slider), TRUE); - - /* a11y */ - accessible = gtk_widget_get_accessible (slider); - if (GTK_IS_ACCESSIBLE (accessible)) { - if (vol->track->num_channels == 1) { - accessible_name = g_strdup_printf (_("Track %s"), - vol->track->label); - } else { - gchar *accessible_desc = g_strdup_printf (_("Channel %d of track %s"), - num_chan + 1, - vol->track->label); - accessible_name = g_strdup_printf (_("Track %s, channel %d"), - vol->track->label, num_chan + 1); - atk_object_set_description (accessible, accessible_desc); - g_free (accessible_desc); - } - atk_object_set_name (accessible, accessible_name); - g_free (accessible_name); - } - - return slider; -} - -static void -get_button (MateVolumeControlVolume *vol, - gint *volumes) -{ - AtkObject *accessible; - gchar *accessible_name, *msg; - gint n; - - msg = g_strdup_printf (_("Lock channels for %s together"), vol->track->label); - vol->button = mate_volume_control_button_new ("chain.png", - "chain-broken.png", - msg); - g_free (msg); - g_signal_connect (vol->button, "clicked", - G_CALLBACK (cb_lock_toggled), vol); - for (n = 1; n < vol->track->num_channels; n++) { - /* default, unlocked */ - if (volumes[n] != volumes[0]) - break; - } - mate_volume_control_button_set_active (MATE_VOLUME_CONTROL_BUTTON (vol->button), - n == vol->track->num_channels); - - /* a11y */ - accessible = gtk_widget_get_accessible (vol->button); - if (GTK_IS_ACCESSIBLE (accessible)) { - accessible_name = g_strdup_printf (_("Track %s: lock channels together"), - vol->track->label); - atk_object_set_name (accessible, accessible_name); - g_free (accessible_name); - } -} - -GtkWidget * -mate_volume_control_volume_new (GstMixer *mixer, - GstMixerTrack *track, - gint padding) -{ - MateVolumeControlVolume *vol; - gint *volumes, n; - gchar *msg, *chan; - gboolean need_timeout = TRUE; - - need_timeout = ((gst_mixer_get_mixer_flags (GST_MIXER (mixer)) & - GST_MIXER_FLAG_AUTO_NOTIFICATIONS) == 0); - - /* volume */ - vol = g_object_new (MATE_VOLUME_CONTROL_TYPE_VOLUME, NULL); - gst_object_ref (GST_OBJECT (mixer)); - vol->mixer = mixer; - vol->track = g_object_ref (G_OBJECT (track)); - if (padding >= 0) - vol->padding = padding; - - /* sliders */ - volumes = g_new0 (gint, track->num_channels); - gst_mixer_get_volume (mixer, track, volumes); - for (n = 0; n < track->num_channels; n++) { - GtkWidget *slider; - - /* we will reposition the widget once we're drawing up */ - slider = get_scale (vol, n, volumes[n]); - gtk_fixed_put (GTK_FIXED (vol), slider, 0, 0); - gtk_widget_show (slider); - vol->scales = g_list_append (vol->scales, slider); - - /* somewhat dirty hack that will suffice for now. 1 chan - * means mono, two means stereo (left/right) and > 2 means - * alsa, where channel order is front, rear, center, lfe, - * side. */ - if (vol->track->num_channels == 1) { - chan = _("mono"); - } else if (vol->track->num_channels == 2) { - chan = (n == 0) ? _("left") : _("right"); - } else { - switch (n) { - case 0: chan = _("front left"); break; - case 1: chan = _("front right"); break; - case 2: chan = _("rear left"); break; - case 3: chan = _("rear right"); break; - case 4: chan = _("front center"); break; - /* Translators: This is the name of a surround sound channel. It - * stands for "Low-Frequency Effects". If you're not sure that - * this has an established and different translation in your - * language, leave it unchanged. */ - case 5: chan = _("LFE"); break; - case 6: chan = _("side left"); break; - case 7: chan = _("side right"); break; - default: chan = _("unknown"); break; - } - } - - /* Here, we can actually tell people that this - * is a slider that will change channel X. */ - msg = g_strdup_printf (_("Volume of %s channel on %s"), - chan, vol->track->label); - gtk_widget_set_tooltip_text (slider, msg); - g_free (msg); - } - - /* chainbutton */ - get_button (vol, volumes); - if (track->num_channels > 1) { - gtk_fixed_put (GTK_FIXED (vol), vol->button, 0, 0); - gtk_widget_show (vol->button); - } - - g_free (volumes); - - /* GStreamer signals */ - if (need_timeout) - vol->id = g_timeout_add (100, cb_check, vol); - - return GTK_WIDGET (vol); -} - -static void -mate_volume_control_volume_dispose (GObject *object) -{ - MateVolumeControlVolume *vol = MATE_VOLUME_CONTROL_VOLUME (object); - - if (vol->id != 0) { - g_source_remove (vol->id); - vol->id = 0; - } - - if (vol->track) { - g_object_unref (G_OBJECT (vol->track)); - vol->track = NULL; - } - - if (vol->mixer) { - gst_object_unref (GST_OBJECT (vol->mixer)); - vol->mixer = NULL; - } - - if (vol->scales) { - g_list_free (vol->scales); - vol->scales = NULL; - } - - G_OBJECT_CLASS (mate_volume_control_volume_parent_class)->dispose (object); -} - -/* - * Gtk/GDK virtual functions for size negotiation. - */ - -static void -mate_volume_control_volume_size_req (GtkWidget *widget, - GtkRequisition *req) -{ - MateVolumeControlVolume *vol = MATE_VOLUME_CONTROL_VOLUME (widget); - GtkRequisition but_req, scale_req; - - /* request size of kids */ -#if GTK_CHECK_VERSION (3, 0, 0) - gtk_widget_get_preferred_size (vol->button, &but_req, NULL); - gtk_widget_get_preferred_size (vol->scales->data, &scale_req, NULL); -#else - GTK_WIDGET_GET_CLASS (vol->button)->size_request (vol->button, &but_req); - GTK_WIDGET_GET_CLASS (vol->scales->data)->size_request (vol->scales->data, - &scale_req); -#endif - if (scale_req.height < 100) - scale_req.height = 100; - - /* calculate our own size from that */ - req->width = scale_req.width * vol->track->num_channels + - vol->padding * (vol->track->num_channels - 1); - req->height = scale_req.height + but_req.height /*+ vol->padding*/; -} - -#if GTK_CHECK_VERSION (3, 0, 0) -static void -mate_volume_control_volume_get_preferred_width (GtkWidget *widget, - gint *minimum_width, - gint *natural_width) -{ - GtkRequisition req; - mate_volume_control_volume_size_req (widget, &req); - *minimum_width = *natural_width = req.width; -} - -static void -mate_volume_control_volume_get_preferred_height (GtkWidget *widget, - gint *minimum_height, - gint *natural_height) -{ - GtkRequisition req; - mate_volume_control_volume_size_req (widget, &req); - *minimum_height = *natural_height = req.height; -} -#endif - -static void -mate_volume_control_volume_size_alloc (GtkWidget *widget, - GtkAllocation *alloc) -{ - MateVolumeControlVolume *vol = MATE_VOLUME_CONTROL_VOLUME (widget); - GtkRequisition but_req, scale_req; - GtkAllocation but_all, scale_all; - gint x_offset, but_deco_width, n = 0; - GList *scales; - GtkAllocation allocation; - - /* loop? */ - gtk_widget_get_allocation (widget, &allocation); - if (alloc->x == allocation.x && - alloc->y == allocation.y && - alloc->width == allocation.width && - alloc->height == allocation.height) - return; - - /* request size of kids */ -#if GTK_CHECK_VERSION (3, 0, 0) - gtk_widget_get_preferred_size (vol->button, &but_req, NULL); - gtk_widget_get_preferred_size (vol->scales->data, &scale_req, NULL); -#else - GTK_WIDGET_GET_CLASS (vol->button)->size_request (vol->button, &but_req); - GTK_WIDGET_GET_CLASS (vol->scales->data)->size_request (vol->scales->data, - &scale_req); -#endif - - /* calculate */ - x_offset = (alloc->width - ((vol->track->num_channels * scale_req.width) + - (vol->track->num_channels - 1) * vol->padding)) / 2; - scale_all.width = scale_req.width; - scale_all.height = alloc->height - but_req.height; - scale_all.y = 0; - but_deco_width = alloc->width - (2 * x_offset); - but_all.width = but_req.width; - but_all.height = but_req.height; - but_all.x = x_offset + (but_deco_width - but_req.width) / 2; - but_all.y = alloc->height - but_req.height; - - /* tell sliders */ - for (scales = vol->scales; scales != NULL; scales = scales->next, n++) { - scale_all.x = x_offset + n * (scale_req.width + vol->padding); - gtk_fixed_move (GTK_FIXED (vol), scales->data, scale_all.x, scale_all.y); - gtk_widget_set_size_request (scales->data, scale_all.width, scale_all.height); - } - - /* tell button */ - if (vol->track->num_channels > 1) { - gtk_fixed_move (GTK_FIXED (vol), vol->button, but_all.x, but_all.y); - gtk_widget_set_size_request (vol->button, but_all.width, but_all.height); - } - - /* parent will resize window */ - GTK_WIDGET_CLASS (mate_volume_control_volume_parent_class)->size_allocate (widget, alloc); -} - -static gboolean -#if GTK_CHECK_VERSION (3, 0, 0) -mate_volume_control_volume_draw (GtkWidget *widget, - cairo_t *cr) -#else -mate_volume_control_volume_expose (GtkWidget *widget, - GdkEventExpose *expose) -#endif -{ - GtkAllocation allocation; - MateVolumeControlVolume *vol = MATE_VOLUME_CONTROL_VOLUME (widget); - -#if !GTK_CHECK_VERSION (3, 0, 0) - /* clear background */ - gtk_widget_get_allocation (widget, &allocation); - gdk_window_clear_area (gtk_widget_get_window (widget), 0, 0, - allocation.width, - allocation.height); -#endif - - if (vol->track->num_channels > 1) { - gint x_offset, y_offset, height, width; - GtkRequisition scale_req, but_req; - GdkPoint points[3]; - GtkStyle *style; - GtkStateType state; - - /* request size of kids */ -#if GTK_CHECK_VERSION (3, 0, 0) - gtk_widget_get_preferred_size (vol->button, &but_req, NULL); - gtk_widget_get_preferred_size (vol->scales->data, &scale_req, NULL); -#else - GTK_WIDGET_GET_CLASS (vol->button)->size_request (vol->button, &but_req); - GTK_WIDGET_GET_CLASS (vol->scales->data)->size_request (vol->scales->data, - &scale_req); -#endif - - /* calculate */ - gtk_widget_get_allocation (widget, &allocation); - x_offset = (allocation.width - - ((vol->track->num_channels * scale_req.width) + - (vol->track->num_channels - 1) * vol->padding)) / 2; - y_offset = allocation.height - but_req.height; - width = allocation.width - (2 * x_offset + but_req.width); - height = but_req.height / 2; - points[0].y = y_offset + 3; - points[1].y = points[2].y = points[0].y + height - 3; - - /* draw chainbutton decorations */ - style = gtk_widget_get_style (widget); - state = gtk_widget_get_state (widget); - - points[0].x = points[1].x = x_offset + 3; - points[2].x = points[0].x + width - 6; -#if GTK_CHECK_VERSION (3, 0, 0) - cairo_move_to (cr, points[0].x, points[0].x); - cairo_line_to (cr, points[1].x, points[1].x); - cairo_move_to (cr, points[1].x, points[1].x); - cairo_line_to (cr, points[2].x, points[2].x); - cairo_move_to (cr, points[0].x, points[0].x); -#else - gtk_paint_polygon (style, gtk_widget_get_window (widget), - state, - GTK_SHADOW_ETCHED_IN, - &expose->area, widget, "hseparator", - points, 3, FALSE); -#endif - - points[0].x = points[1].x = allocation.width - x_offset - 3; - points[2].x = points[0].x - width + 6; -#if GTK_CHECK_VERSION (3, 0, 0) - cairo_move_to (cr, points[0].x, points[0].x); - cairo_line_to (cr, points[1].x, points[1].x); - cairo_move_to (cr, points[1].x, points[1].x); - cairo_line_to (cr, points[2].x, points[2].x); - cairo_move_to (cr, points[0].x, points[0].x); -#else - gtk_paint_polygon (style, gtk_widget_get_window (widget), - state, - GTK_SHADOW_ETCHED_IN, - &expose->area, widget, "hseparator", - points, 3, FALSE); -#endif - -#if GTK_CHECK_VERSION (3, 0, 0) - cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE); - cairo_set_line_width (cr, 1.0); - cairo_set_source_rgb (cr, 0, 0, 0); - cairo_stroke (cr); -#endif - } - - /* take care of redrawing the kids */ -#if GTK_CHECK_VERSION (3, 0, 0) - return GTK_WIDGET_CLASS (mate_volume_control_volume_parent_class)->draw (widget, cr); -#else - return GTK_WIDGET_CLASS (mate_volume_control_volume_parent_class)->expose_event (widget, expose); -#endif -} - -/* - * Signals handlers. - */ - -static void -cb_volume_changed (GtkAdjustment *_adj, - gpointer data) -{ - MateVolumeControlVolume *vol = data; - gint *volumes, i = 0; - GList *scales; - - if (vol->locked) - return; - vol->locked = TRUE; - volumes = g_new (gint, vol->track->num_channels); - - for (scales = vol->scales; scales != NULL; scales = scales->next) { - GtkAdjustment *adj = gtk_range_get_adjustment (scales->data); - - if (mate_volume_control_button_get_active ( - MATE_VOLUME_CONTROL_BUTTON (vol->button))) { - gtk_adjustment_set_value (adj, gtk_adjustment_get_value (_adj)); - volumes[i++] = rint (gtk_adjustment_get_value (_adj)); - } else { - volumes[i++] = rint (gtk_adjustment_get_value (adj)); - } - } - - gst_mixer_set_volume (vol->mixer, vol->track, volumes); - - g_free (volumes); - vol->locked = FALSE; -} - -static void -cb_lock_toggled (GtkToggleButton *button, - gpointer data) -{ - MateVolumeControlVolume *vol = data; - - if (mate_volume_control_button_get_active ( - MATE_VOLUME_CONTROL_BUTTON (vol->button))) { - /* get the mean value, and set it on the first adjustment. - * the cb_volume_changed () callback will take care of the - * rest. */ - gint volume = 0, num = 0; - GList *scales; - - for (scales = vol->scales ; scales != NULL; scales = scales->next) { - GtkAdjustment *adj = gtk_range_get_adjustment (scales->data); - - num++; - volume += gtk_adjustment_get_value (adj); - } - - /* safety check */ - if (vol->scales != NULL) { - gtk_adjustment_set_value (gtk_range_get_adjustment (vol->scales->data), - volume / num); - } - } -} - -/* - * See if our volume is zero. - */ - -void -mate_volume_control_volume_ask (MateVolumeControlVolume * vol, - gboolean *real_zero, gboolean *slider_zero) -{ - GList *scales; - gint *volumes, n, tot = 0; - - volumes = g_new (gint, vol->track->num_channels); - gst_mixer_get_volume (vol->mixer, vol->track, volumes); - for (n = 0; n < vol->track->num_channels; n++) - tot += volumes[n]; - g_free (volumes); - *real_zero = (tot == 0); - - *slider_zero = TRUE; - for (n = 0, scales = vol->scales; - scales != NULL; scales = scales->next, n++) { - GtkAdjustment *adj = gtk_range_get_adjustment (scales->data); - - if (rint (gtk_adjustment_get_value (adj)) != 0) { - *slider_zero = FALSE; - break; - } - } -} - - -void -mate_volume_control_volume_update (MateVolumeControlVolume *vol) -{ - gint *volumes, n; - GList *scales; - - /* don't do callbacks */ - if (vol->locked) - return; - - vol->locked = TRUE; - - volumes = g_new (gint, vol->track->num_channels); - gst_mixer_get_volume (vol->mixer, vol->track, volumes); - - /* did we change? */ - for (n = 0, scales = vol->scales; - scales != NULL; scales = scales->next, n++) { - GtkAdjustment *adj = gtk_range_get_adjustment (scales->data); - - if ((gint) gtk_adjustment_get_value (adj) != volumes[n]) { - gtk_range_set_value (scales->data, volumes[n]); - } - - /* should we release lock? */ - if (volumes[n] != volumes[0]) { - mate_volume_control_button_set_active ( - MATE_VOLUME_CONTROL_BUTTON (vol->button), FALSE); - } - } - - g_free (volumes); - vol->locked = FALSE; -} - -/* - * Timeout to check for volume changes. - */ - -static gboolean -cb_check (gpointer data) -{ - mate_volume_control_volume_update (data); - - return TRUE; -} |