diff options
author | Ronald Bultje <rbultje@src.gnome.org> | 2004-09-16 20:43:20 +0000 |
---|---|---|
committer | Ronald Bultje <rbultje@src.gnome.org> | 2004-09-16 20:43:20 +0000 |
commit | 579256754603e0f216b81fc1f3b0b12128761480 (patch) | |
tree | 4a9a7739201dcc6442220465b9db191863303962 /mixer/applet.c | |
parent | 9f29e7a305e3bcce46cb0341e12278b9873bced8 (diff) |
New mixer. See ChangeLog files or bugzilla bugs for details.
Diffstat (limited to 'mixer/applet.c')
-rw-r--r-- | mixer/applet.c | 898 |
1 files changed, 898 insertions, 0 deletions
diff --git a/mixer/applet.c b/mixer/applet.c new file mode 100644 index 000000000..8d57f4e77 --- /dev/null +++ b/mixer/applet.c @@ -0,0 +1,898 @@ +/* GNOME Volume Applet + * Copyright (C) 2004 Ronald Bultje <rbultje@ronald.bitfreak.net> + * + * applet.c: the main applet + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <string.h> + +#include <libgnomeui/libgnomeui.h> +#include <gdk/gdkkeysyms.h> +#include <gtk/gtk.h> + +#include "applet.h" +#include "keys.h" +#include "preferences.h" + +#define IS_PANEL_HORIZONTAL(o) \ + (o == PANEL_APPLET_ORIENT_UP || o == PANEL_APPLET_ORIENT_DOWN) + +static void gnome_volume_applet_class_init (GnomeVolumeAppletClass *klass); +static void gnome_volume_applet_init (GnomeVolumeApplet *applet); +static void gnome_volume_applet_dispose (GObject *object); + +static void gnome_volume_applet_popup_dock (GnomeVolumeApplet *applet); +static void gnome_volume_applet_popdown_dock (GnomeVolumeApplet *applet); + +static gboolean gnome_volume_applet_scroll (GtkWidget *widget, + GdkEventScroll *event); +static gboolean gnome_volume_applet_button (GtkWidget *widget, + GdkEventButton *event); +static gboolean gnome_volume_applet_key (GtkWidget *widget, + GdkEventKey *event); + +static void gnome_volume_applet_orientation (PanelApplet *applet, + PanelAppletOrient orient); +static void gnome_volume_applet_size (PanelApplet *applet, + guint size); + +static void gnome_volume_applet_refresh (GnomeVolumeApplet *applet); +static gboolean cb_check (gpointer data); + +static void cb_volume (GtkAdjustment *adj, + gpointer data); + +static void cb_gconf (GConfClient *client, + guint connection_id, + GConfEntry *entry, + gpointer data); + +static void cb_verb (BonoboUIComponent *uic, + gpointer data, + const gchar *verbname); + +static PanelAppletClass *parent_class = NULL; +static struct { + gchar *filename; + GdkPixbuf *pixbuf; +} pix[] = { + { PIXDIR "/volume-mute.png", NULL }, + { PIXDIR "/volume-zero.png", NULL }, + { PIXDIR "/volume-min.png", NULL }, + { PIXDIR "/volume-medium.png", NULL }, + { PIXDIR "/volume-max.png", NULL }, + { NULL, NULL } +}; + +GType +gnome_volume_applet_get_type (void) +{ + static GType gnome_volume_applet_type = 0; + + if (!gnome_volume_applet_type) { + static const GTypeInfo gnome_volume_applet_info = { + sizeof (GnomeVolumeAppletClass), + NULL, + NULL, + (GClassInitFunc) gnome_volume_applet_class_init, + NULL, + NULL, + sizeof (GnomeVolumeApplet), + 0, + (GInstanceInitFunc) gnome_volume_applet_init, + NULL + }; + + gnome_volume_applet_type = + g_type_register_static (PANEL_TYPE_APPLET, + "GnomeVolumeApplet", + &gnome_volume_applet_info, 0); + } + + return gnome_volume_applet_type; +} + +static void +gnome_volume_applet_class_init (GnomeVolumeAppletClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GtkWidgetClass *gtkwidget_class = GTK_WIDGET_CLASS (klass); + PanelAppletClass *panelapplet_class = PANEL_APPLET_CLASS (klass); + gint n; + + parent_class = g_type_class_ref (PANEL_TYPE_APPLET); + + gobject_class->dispose = gnome_volume_applet_dispose; + gtkwidget_class->key_press_event = gnome_volume_applet_key; + gtkwidget_class->button_press_event = gnome_volume_applet_button; + gtkwidget_class->scroll_event = gnome_volume_applet_scroll; + panelapplet_class->change_orient = gnome_volume_applet_orientation; + panelapplet_class->change_size = gnome_volume_applet_size; + + /* FIXME: + * - style-set, change-background. + */ + + /* init pixbufs */ + for (n = 0; pix[n].filename != NULL; n++) { + pix[n].pixbuf = gdk_pixbuf_new_from_file (pix[n].filename, NULL); + } +} + +static void +gnome_volume_applet_init (GnomeVolumeApplet *applet) +{ + GtkWidget *image, *dock; + GtkTooltips *tooltips; + + applet->timeout = 0; + applet->elements = NULL; + applet->client = gconf_client_get_default (); + applet->mixer = NULL; + applet->track = NULL; + applet->lock = FALSE; + applet->state = -1; + applet->prefs = NULL; + + /* icon (our main UI) */ + image = gtk_image_new (); + applet->image = GTK_IMAGE (image); + gtk_container_add (GTK_CONTAINER (applet), image); + gtk_widget_show (image); + + /* dock window (expanded UI) */ + applet->pop = FALSE; + + /* tooltip over applet */ + tooltips = gtk_tooltips_new (); + gtk_tooltips_set_tip (tooltips, GTK_WIDGET (applet), + _("Volume Control"), NULL); + + /* other stuff */ + panel_applet_add_preferences (PANEL_APPLET (applet), + "/schemas/apps/mixer_applet/prefs", + NULL); + panel_applet_set_flags (PANEL_APPLET (applet), + PANEL_APPLET_EXPAND_MINOR); +} + +void +gnome_volume_applet_setup (GnomeVolumeApplet *applet, + GList *elements) +{ + GConfValue *value; + GtkObject *adj; + GstElement *active_element; + GstMixerTrack *active_track; + const GList *item; + gint page; + static const BonoboUIVerb verbs[] = { + BONOBO_UI_UNSAFE_VERB ("RunMixer", cb_verb), + BONOBO_UI_UNSAFE_VERB ("Mute", cb_verb), + BONOBO_UI_UNSAFE_VERB ("Help", cb_verb), + BONOBO_UI_UNSAFE_VERB ("About", cb_verb), + BONOBO_UI_UNSAFE_VERB ("Pref", cb_verb), + BONOBO_UI_VERB_END + }; + + /* default element to first */ + g_return_if_fail (elements != NULL); + active_element = elements->data; + + applet->elements = elements; + + /* get active element, if any (otherwise we use the default) */ + if ((value = gconf_client_get (applet->client, + GNOME_VOLUME_APPLET_KEY_ACTIVE_ELEMENT, + NULL)) != NULL && + value->type == GCONF_VALUE_STRING) { + const gchar *active_el_str, *cur_el_str; + + active_el_str = gconf_value_get_string (value); + for (item = elements; item != NULL; item = item->next) { + cur_el_str = g_object_get_data (item->data, "gnome-volume-applet-name"); + if (!strcmp (active_el_str, cur_el_str)) { + active_element = item->data; + break; + } + } + } + + /* use the active element */ + gst_element_set_state (active_element, GST_STATE_READY); + applet->mixer = GST_MIXER (active_element); + gst_object_ref (GST_OBJECT (active_element)); + + /* default track: first */ + item = gst_mixer_list_tracks (applet->mixer); + active_track = item->data; + /* FIXME: + * - what if first has 0 channels? + */ + + /* get active track, if any (otherwise we use the default) */ + if ((value = gconf_client_get (applet->client, + GNOME_VOLUME_APPLET_KEY_ACTIVE_TRACK, + NULL)) != NULL && + value->type == GCONF_VALUE_STRING) { + const gchar *track_name = gconf_value_get_string (value); + + for ( ; item != NULL; item = item->next) { + GstMixerTrack *track = item->data; + + if (!track->num_channels) + continue; + + if (!strcmp (track_name, track->label)) { + active_track = item->data; + break; + } else if (!track && + GST_MIXER_TRACK_HAS_FLAG (track, + GST_MIXER_TRACK_MASTER)) { + active_track = item->data; + } + } + } + + /* use the active track */ + applet->track = active_track; + g_object_ref (G_OBJECT (active_track)); + + /* tell the dock */ + page = (applet->track->max_volume - applet->track->min_volume) / 10; + adj = gtk_adjustment_new (0, applet->track->min_volume, + applet->track->max_volume, + (page / 5 > 0) ? page / 5 : 1, + page, 0); + gnome_volume_applet_dock_change (applet->dock, + GTK_ADJUSTMENT (adj)); + g_signal_connect (adj, "value-changed", + G_CALLBACK (cb_volume), applet); + + gnome_volume_applet_refresh (applet); + applet->timeout = g_timeout_add (100, cb_check, applet); + + /* menu - done here because bonobo is intialized now */ + panel_applet_setup_menu_from_file (PANEL_APPLET (applet), + NULL, + "GNOME_MixerApplet.xml", + NULL, verbs, applet); + + /* gconf */ + gconf_client_add_dir (applet->client, GNOME_VOLUME_APPLET_KEY_DIR, + GCONF_CLIENT_PRELOAD_RECURSIVE, NULL); + gconf_client_notify_add (applet->client, GNOME_VOLUME_APPLET_KEY_DIR, + cb_gconf, applet, NULL, NULL); + + gtk_widget_show (GTK_WIDGET (applet)); +} + +static void +gnome_volume_applet_dispose (GObject *object) +{ + GnomeVolumeApplet *applet = GNOME_VOLUME_APPLET (object); + + gnome_volume_applet_popdown_dock (applet); + + if (applet->elements) { + GList *item; + + for (item = applet->elements; item != NULL; item = item->next) { + GstElement *element = GST_ELEMENT (item->data); + + gst_element_set_state (element, GST_STATE_NULL); + g_free (g_object_get_data (G_OBJECT (element), + "gnome-volume-applet-name")); + gst_object_unref (GST_OBJECT (element)); + } + g_list_free (applet->elements); + applet->elements = NULL; + } + + if (applet->track) { + g_object_unref (G_OBJECT (applet->track)); + applet->track = NULL; + } + + if (applet->mixer) { + gst_object_unref (GST_OBJECT (applet->mixer)); + applet->mixer = NULL; + } + + if (applet->timeout) { + g_source_remove (applet->timeout); + applet->timeout = 0; + } + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +/* + * popup (show) or popdown (hide) the dock. + */ + +static void +gnome_volume_applet_popup_dock (GnomeVolumeApplet *applet) +{ + GtkWidget *widget = GTK_WIDGET (applet); + gint x, y; + + /* show (before reposition, so size allocation is done) */ + gtk_widget_show (GTK_WIDGET (applet->dock)); + + /* reposition */ + gdk_window_get_origin (widget->window, &x, &y); + switch (panel_applet_get_orient (PANEL_APPLET (applet))) { + case PANEL_APPLET_ORIENT_DOWN: + x += widget->allocation.x; + x -= (GTK_WIDGET (applet->dock)->allocation.width - + widget->allocation.width) / 2; + y += widget->allocation.height + widget->allocation.y; + break; + case PANEL_APPLET_ORIENT_UP: + x += widget->allocation.x; + x -= (GTK_WIDGET (applet->dock)->allocation.width - + widget->allocation.width) / 2; + y += widget->allocation.y; + y -= GTK_WIDGET (applet->dock)->allocation.height; + break; + case PANEL_APPLET_ORIENT_RIGHT: + x += widget->allocation.width + widget->allocation.x; + y += widget->allocation.y; + y -= (GTK_WIDGET (applet->dock)->allocation.height - + widget->allocation.height) / 2; + break; + case PANEL_APPLET_ORIENT_LEFT: + x += widget->allocation.x; + x -= GTK_WIDGET (applet->dock)->allocation.width; + y += widget->allocation.y; + y -= (GTK_WIDGET (applet->dock)->allocation.height - + widget->allocation.height) / 2; + break; + default: + g_assert_not_reached (); + } + gtk_window_move (GTK_WINDOW (applet->dock), x, y); + + /* grab input */ + gtk_widget_grab_focus (widget); + gtk_grab_add (widget); + gdk_pointer_grab (widget->window, TRUE, + GDK_BUTTON_PRESS_MASK | + GDK_BUTTON_RELEASE_MASK | + GDK_POINTER_MOTION_MASK, + NULL, NULL, GDK_CURRENT_TIME); + gdk_keyboard_grab (widget->window, TRUE, GDK_CURRENT_TIME); + + /* keep state */ + applet->pop = TRUE; +} + +static void +gnome_volume_applet_popdown_dock (GnomeVolumeApplet *applet) +{ + GtkWidget *widget = GTK_WIDGET (applet); + + if (!applet->pop) + return; + + /* release input */ + gdk_keyboard_ungrab (GDK_CURRENT_TIME); + gdk_pointer_ungrab (GDK_CURRENT_TIME); + gtk_grab_remove (widget); + + /* hide */ + gtk_widget_hide (GTK_WIDGET (applet->dock)); + + /* keep state */ + applet->pop = FALSE; +} + +static void +gnome_volume_applet_pop_dock (GnomeVolumeApplet *applet) +{ + if (applet->pop) { + gnome_volume_applet_popdown_dock (applet); + } else { + gnome_volume_applet_popup_dock (applet); + } +} + +/* + * Toggle mute. + */ + +static void +gnome_volume_applet_toggle_mute (GnomeVolumeApplet *applet) +{ + if (GST_MIXER_TRACK_HAS_FLAG (applet->track, + GST_MIXER_TRACK_MUTE)) { + gst_mixer_set_mute (applet->mixer, applet->track, FALSE); + } else { + gst_mixer_set_mute (applet->mixer, applet->track, TRUE); + } +} + +/* + * Run g-v-c. + */ + +static void +gnome_volume_applet_run_mixer (GnomeVolumeApplet *applet) +{ + GError *error = NULL; + + gdk_spawn_command_line_on_screen ( + gtk_widget_get_screen (GTK_WIDGET (applet)), + "gnome-volume-control", &error); + + if (error) { + GtkWidget *dialog; + + dialog = gtk_message_dialog_new (NULL, 0, GTK_MESSAGE_ERROR, + GTK_BUTTONS_CLOSE, + _("Failed to start Volume Control: %s"), + error->message); + g_signal_connect (dialog, "response", + G_CALLBACK (gtk_widget_destroy), NULL); + gtk_widget_show (dialog); + g_error_free (error); + } +} + +/* + * Control events, change volume and so on. + */ + +static gboolean +gnome_volume_applet_scroll (GtkWidget *widget, + GdkEventScroll *event) +{ + GnomeVolumeApplet *applet = GNOME_VOLUME_APPLET (widget); + + if (event->type == GDK_SCROLL) { + switch (event->direction) { + case GDK_SCROLL_UP: + case GDK_SCROLL_DOWN: { + GtkAdjustment *adj = gtk_range_get_adjustment (applet->dock->scale); + gint volume = adj->value; + + if (event->direction == GDK_SCROLL_UP) { + volume += adj->step_increment; + if (volume > adj->upper) + volume = adj->upper; + } else { + volume -= adj->step_increment; + if (volume < adj->lower) + volume = adj->lower; + } + + gtk_range_set_value (applet->dock->scale, volume); + return TRUE; + } + default: + break; + } + } + + return GTK_WIDGET_CLASS (parent_class)->scroll_event (widget, event); +} + +static gboolean +gnome_volume_applet_button (GtkWidget *widget, + GdkEventButton *event) +{ + GnomeVolumeApplet *applet = GNOME_VOLUME_APPLET (widget); + + if (event->window != GTK_WIDGET (applet)->window) { + gnome_volume_applet_popdown_dock (applet); + return TRUE; + } else { + switch (event->button) { + case 1: + switch (event->type) { + case GDK_BUTTON_PRESS: + gnome_volume_applet_pop_dock (applet); + return TRUE; + case GDK_2BUTTON_PRESS: + gnome_volume_applet_popdown_dock (applet); + gnome_volume_applet_run_mixer (applet); + return TRUE; + default: + break; + } + break; + case 3: + if (applet->pop) { + gnome_volume_applet_popdown_dock (applet); + return TRUE; + } + break; + default: + break; + } + } + + return GTK_WIDGET_CLASS (parent_class)->button_press_event (widget, event); +} + +static gboolean +gnome_volume_applet_key (GtkWidget *widget, + GdkEventKey *event) +{ + GnomeVolumeApplet *applet = GNOME_VOLUME_APPLET (widget); + + switch (event->keyval) { + case GDK_KP_Enter: + case GDK_ISO_Enter: + case GDK_3270_Enter: + case GDK_Return: + case GDK_space: + case GDK_KP_Space: + gnome_volume_applet_pop_dock (applet); + return TRUE; + case GDK_m: + if (event->state == GDK_CONTROL_MASK) { + gnome_volume_applet_toggle_mute (applet); + return TRUE; + } + break; + case GDK_o: + if (event->state == GDK_CONTROL_MASK) { + gnome_volume_applet_run_mixer (applet); + return TRUE; + } + break; + case GDK_Escape: + gnome_volume_applet_popdown_dock (applet); + return TRUE; + case GDK_Page_Up: + case GDK_Page_Down: + case GDK_Up: + case GDK_Down: { + GtkAdjustment *adj = gtk_range_get_adjustment (applet->dock->scale); + gint volume = adj->value, increment; + + if (event->keyval == GDK_Up || event->keyval == GDK_Down) + increment = adj->step_increment; + else + increment = adj->page_increment; + + if (event->keyval == GDK_Page_Up || event->keyval == GDK_Up) { + volume += increment; + if (volume > adj->upper) + volume = adj->upper; + } else { + volume -= increment; + if (volume < adj->lower) + volume = adj->lower; + } + + gtk_range_set_value (applet->dock->scale, volume); + return TRUE; + } + default: + break; + } + + return GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event); +} + +/* + * Change orientation or size of panel. + */ + +static void +gnome_volume_applet_orientation (PanelApplet *_applet, + PanelAppletOrient orientation) +{ + GnomeVolumeApplet *applet = GNOME_VOLUME_APPLET (_applet); + GtkAdjustment *adj = NULL; + GtkWidget *dock; + + if (applet->dock) { + adj = gtk_range_get_adjustment (applet->dock->scale); + g_object_ref (G_OBJECT (adj)); + gtk_widget_destroy (GTK_WIDGET (applet->dock)); + } + dock = gnome_volume_applet_dock_new (IS_PANEL_HORIZONTAL (orientation) ? + GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL); + gtk_widget_set_parent (dock, GTK_WIDGET (applet)); + applet->dock = GNOME_VOLUME_APPLET_DOCK (dock); + gnome_volume_applet_dock_change (applet->dock, adj); + + if (PANEL_APPLET_CLASS (parent_class)->change_orient) + PANEL_APPLET_CLASS (parent_class)->change_orient (_applet, orientation); +} + +static void +gnome_volume_applet_size (PanelApplet *applet, + guint size) +{ + gnome_volume_applet_refresh (GNOME_VOLUME_APPLET (applet)); + + if (PANEL_APPLET_CLASS (parent_class)->change_size) + PANEL_APPLET_CLASS (parent_class)->change_size (applet, size); +} + +/* + * Volume changed. + */ + +static void +cb_volume (GtkAdjustment *adj, + gpointer data) +{ + GnomeVolumeApplet *applet = data; + gint *volumes, n; + + if (applet->lock) + return; + applet->lock = TRUE; + + volumes = g_new (gint, applet->track->num_channels); + for (n = 0; n < applet->track->num_channels; n++) + volumes[n] = gtk_adjustment_get_value (adj); + gst_mixer_set_volume (applet->mixer, applet->track, volumes); + g_free (volumes); + + applet->lock = FALSE; +} + +/* + * Automatic timer. Check for changes. + */ + +#define STATE(vol,m) ((vol << 1) | m) + +static void +gnome_volume_applet_refresh (GnomeVolumeApplet *applet) +{ + BonoboUIComponent *component; + GdkPixbuf *scaled, *orig; + guint size; + gint n, *volumes, volume = 0; + gboolean mute; + + /* build-up phase */ + if (!applet->track) + return; + + volumes = g_new (gint, applet->track->num_channels); + gst_mixer_get_volume (applet->mixer, applet->track, volumes); + for (n = 0; n < applet->track->num_channels; n++) + volume += volumes[n]; + volume /= applet->track->num_channels; + g_free (volumes); + mute = GST_MIXER_TRACK_HAS_FLAG (applet->track, + GST_MIXER_TRACK_MUTE); + + n = 4 * volume / (applet->track->max_volume - + applet->track->min_volume) + 1; + if (n <= 0) + n = 1; + if (n >= 5) + n = 4; + + if (STATE (n, mute) != applet->state) { + if (mute) { + orig = gdk_pixbuf_copy (pix[n].pixbuf); + gdk_pixbuf_composite (pix[0].pixbuf, orig, 0, 0, + gdk_pixbuf_get_width (orig), + gdk_pixbuf_get_height (orig), + 0, 0, 1.0, 1.0, + GDK_INTERP_BILINEAR, 255); + } else { + orig = pix[n].pixbuf; + } + + size = panel_applet_get_size (PANEL_APPLET (applet)); + scaled = gdk_pixbuf_scale_simple (orig, size, size, + GDK_INTERP_BILINEAR); + gtk_image_set_from_pixbuf (applet->image, scaled); + if (mute) + gdk_pixbuf_unref (orig); + gdk_pixbuf_unref (scaled); + + applet->state = STATE (n, mute); + } + + applet->lock = TRUE; + gtk_range_set_value (applet->dock->scale, volume); + applet->lock = FALSE; + + /* update mute status (bonobo) */ + component = panel_applet_get_popup_component (PANEL_APPLET (applet)); + bonobo_ui_component_set_prop (component, + "/commands/Mute", + "state", mute ? "1" : "0", NULL); +} + +static gboolean +cb_check (gpointer data) +{ + gnome_volume_applet_refresh (GNOME_VOLUME_APPLET (data)); + + return TRUE; +} + +/* + * GConf callback. + */ + +static void +cb_gconf (GConfClient *client, + guint connection_id, + GConfEntry *entry, + gpointer data) +{ + GnomeVolumeApplet *applet = data; + GConfValue *value; + const gchar *str; + const GList *item; + GstMixerTrack *active_track = NULL; + gboolean newdevice = FALSE; + + if ((value = gconf_entry_get_value (entry)) != NULL && + (value->type == GCONF_VALUE_STRING) && + (str = gconf_value_get_string (value)) != NULL) { + if (!strcmp (gconf_entry_get_key (entry), + GNOME_VOLUME_APPLET_KEY_ACTIVE_ELEMENT)) { + for (item = applet->elements; item != NULL; item = item->next) { + gchar *cur_el_str = g_object_get_data (item->data, + "gnome-volume-applet-name"); + + if (!strcmp (cur_el_str, str)) { + GstElement *old_element = GST_ELEMENT (applet->mixer); + + /* change element */ + gst_element_set_state (item->data, GST_STATE_READY); + gst_object_replace ((GstObject **) &applet->mixer, item->data); + gst_element_set_state (old_element, GST_STATE_NULL); + + newdevice = TRUE; + active_track = gst_mixer_list_tracks (applet->mixer)->data; + str = applet->track->label; + break; + } + } + } + + if (!strcmp (gconf_entry_get_key (entry), + GNOME_VOLUME_APPLET_KEY_ACTIVE_TRACK) || + newdevice) { + for (item = gst_mixer_list_tracks (applet->mixer); + item != NULL; item = item->next) { + GstMixerTrack *track = item->data; + + if (track->num_channels <= 0) + continue; + + if (!strcmp (str, track->label)) { + active_track = track; + break; + } else if (newdevice && !active_track && + GST_MIXER_TRACK_HAS_FLAG (track, + GST_MIXER_TRACK_MASTER)) { + active_track = item->data; + } + } + + if (active_track) { + GtkObject *adj; + gint page; + + g_object_unref (G_OBJECT (applet->track)); + applet->track = active_track; + g_object_ref (G_OBJECT (active_track)); + + /* dock */ + page = (applet->track->max_volume - applet->track->min_volume) / 10; + adj = gtk_adjustment_new (0, applet->track->min_volume, + applet->track->max_volume, + (page / 5 > 0) ? page / 5 : 1, + page, 0); + gnome_volume_applet_dock_change (applet->dock, + GTK_ADJUSTMENT (adj)); + g_signal_connect (adj, "value-changed", + G_CALLBACK (cb_volume), applet); + + /* if preferences window is open, update */ + if (applet->prefs) { + gnome_volume_applet_preferences_change ( + GNOME_VOLUME_APPLET_PREFERENCES (applet->prefs), + applet->mixer, applet->track); + } + } + } + } +} + +/* + * bonobo verb callback. + */ + +static void +cb_prefs_destroy (GtkWidget *widget, + gpointer data) +{ + GNOME_VOLUME_APPLET (data)->prefs = NULL; +} + +static void +cb_verb (BonoboUIComponent *uic, + gpointer data, + const gchar *verbname) +{ + GnomeVolumeApplet *applet = GNOME_VOLUME_APPLET (data); + + if (!strcmp (verbname, "RunMixer")) { + gnome_volume_applet_run_mixer (applet); + } else if (!strcmp (verbname, "Mute")) { + gnome_volume_applet_toggle_mute (applet); + } else if (!strcmp (verbname, "Help")) { + GError *error = NULL; + + gnome_help_display_on_screen ("mixer_applet2", NULL, + gtk_widget_get_screen (GTK_WIDGET (applet)), + &error); + + if (error) { + GtkWidget *dialog; + + dialog = gtk_message_dialog_new (NULL, 0, GTK_MESSAGE_ERROR, + GTK_BUTTONS_CLOSE, + _("Failed to display help: %s"), + error->message); + g_signal_connect (dialog, "response", + G_CALLBACK (gtk_widget_destroy), NULL); + gtk_widget_show (dialog); + g_error_free (error); + } + } else if (!strcmp (verbname, "About")) { + GtkWidget *about; + const gchar *authors[] = { "Ronald Bultje <rbultje@ronald.bitfreak.net>", + NULL }; + + about = gnome_about_new (_("Volume Applet"), + VERSION, + "(c) 2004 Ronald Bultje", + _("A GNOME/GStreamer-based volume control applet"), + authors, NULL, NULL, + NULL); + + gtk_widget_show (about); + } else if (!strcmp (verbname, "Pref")) { + if (applet->prefs) + return; + + applet->prefs = gnome_volume_applet_preferences_new (applet->client, + applet->elements, + applet->mixer, + applet->track); + g_signal_connect (applet->prefs, "destroy", + G_CALLBACK (cb_prefs_destroy), applet); + gtk_widget_show (applet->prefs); + } else { + g_warning ("Unknown bonobo command '%s'", verbname); + } +} |