98230d2
Index: applet.c
98230d2
===================================================================
98230d2
--- applet.c	(revision 10436)
98230d2
+++ applet.c	(working copy)
98230d2
@@ -79,7 +79,12 @@
98230d2
 						 PanelAppletOrient orient);
98230d2
 
98230d2
 static void	gnome_volume_applet_refresh	(GnomeVolumeApplet *applet,
98230d2
-						 gboolean           force_refresh);
98230d2
+						 gboolean           force_refresh,
98230d2
+						 gdouble            volume,
98230d2
+						 gint               mute);
98230d2
+
98230d2
+static void     cb_notify_message (GstBus *bus, GstMessage *message, gpointer data);
98230d2
+
98230d2
 static gboolean	cb_check			(gpointer   data);
98230d2
 
98230d2
 static void	cb_volume			(GtkAdjustment *adj,
98230d2
@@ -242,6 +247,12 @@
98230d2
   /* i18n */
98230d2
   ao = gtk_widget_get_accessible (GTK_WIDGET (applet));
98230d2
   atk_object_set_name (ao, _("Volume Control"));
98230d2
+
98230d2
+  /* Bus for notifications */
98230d2
+  applet->bus = gst_bus_new ();
98230d2
+  gst_bus_add_signal_watch (applet->bus);
98230d2
+  g_signal_connect (G_OBJECT (applet->bus), "message::element", 
98230d2
+       (GCallback) cb_notify_message, applet);
98230d2
 }
98230d2
 
98230d2
 /* Parse the list of tracks that are stored in GConf */
98230d2
@@ -368,12 +379,33 @@
98230d2
     return FALSE;
98230d2
 
98230d2
   applet->mixer = g_object_ref (active_element);
98230d2
+  gst_element_set_bus (GST_ELEMENT (applet->mixer), applet->bus);
98230d2
   applet->tracks = active_tracks;
98230d2
   g_list_foreach (applet->tracks, (GFunc) g_object_ref, NULL);
98230d2
 
98230d2
   return TRUE;
98230d2
 }
98230d2
 
98230d2
+static void
98230d2
+gnome_volume_applet_setup_timeout (GnomeVolumeApplet *applet)
98230d2
+{
98230d2
+  gboolean need_timeout = TRUE;
98230d2
+  need_timeout = ((gst_mixer_get_mixer_flags (GST_MIXER (applet->mixer)) &
98230d2
+      GST_MIXER_FLAG_AUTO_NOTIFICATIONS) == 0);
98230d2
+
98230d2
+  if (need_timeout) {
98230d2
+    if (applet->timeout == 0) {
98230d2
+      applet->timeout = g_timeout_add (100, cb_check, applet);
98230d2
+    }
98230d2
+  }
98230d2
+  else {
98230d2
+    if (applet->timeout != 0) {
98230d2
+      g_source_remove (applet->timeout);
98230d2
+      applet->timeout = 0;
98230d2
+    }
98230d2
+  }
98230d2
+}
98230d2
+
98230d2
 gboolean
98230d2
 gnome_volume_applet_setup (GnomeVolumeApplet *applet,
98230d2
 			   GList *elements)
98230d2
@@ -435,10 +467,9 @@
98230d2
   component = panel_applet_get_popup_component (PANEL_APPLET (applet));
98230d2
   g_signal_connect (component, "ui-event", G_CALLBACK (cb_ui_event), applet);
98230d2
 
98230d2
-  gnome_volume_applet_refresh (applet, TRUE);
98230d2
-  if (res) {
98230d2
-    applet->timeout = g_timeout_add (100, cb_check, applet);
98230d2
-  }
98230d2
+  gnome_volume_applet_refresh (applet, TRUE, -1, -1);
98230d2
+  if (res)
98230d2
+    gnome_volume_applet_setup_timeout (applet);
98230d2
 
98230d2
   if (res) {
98230d2
     /* gconf */
98230d2
@@ -479,6 +510,11 @@
98230d2
     g_list_free (applet->elements);
98230d2
     applet->elements = NULL;
98230d2
   }
98230d2
+  gst_bus_remove_signal_watch (applet->bus);
98230d2
+  if (applet->bus) {
98230d2
+    gst_object_unref (applet->bus);
98230d2
+    applet->bus = NULL;
98230d2
+  }
98230d2
 
98230d2
   if (applet->tracks) {
98230d2
     g_list_foreach (applet->tracks, (GFunc) g_object_unref, NULL);
98230d2
@@ -677,7 +713,7 @@
98230d2
 
98230d2
   /* update graphic - this should happen automagically after the next
98230d2
    * idle call, but apparently doesn't for some people... */
98230d2
-  gnome_volume_applet_refresh (applet, TRUE);
98230d2
+  gnome_volume_applet_refresh (applet, TRUE, -1, mute);
98230d2
 }
98230d2
 
98230d2
 /*
98230d2
@@ -940,7 +976,7 @@
98230d2
   }
98230d2
 
98230d2
   init_pixbufs (applet);
98230d2
-  gnome_volume_applet_refresh (applet, TRUE);
98230d2
+  gnome_volume_applet_refresh (applet, TRUE, -1, -1);
98230d2
 }
98230d2
 
98230d2
 static void
98230d2
@@ -990,15 +1026,23 @@
98230d2
 {
98230d2
   int range = track->max_volume - track->min_volume;
98230d2
   gdouble scale = ((gdouble) range) / 100;
98230d2
-  int *volumes, n;
98230d2
+  int *volumes, n, volint;
98230d2
 
98230d2
-  volume *= scale;
98230d2
-  volume += track->min_volume;
98230d2
+  if (volume == 1.0) {
98230d2
+    volint = track->max_volume;
98230d2
+  } else if (volume == 0.0) {
98230d2
+    volint = track->min_volume;
98230d2
+  } else {
98230d2
+    volume *= scale;
98230d2
+    volume += track->min_volume;
98230d2
+    volint = lrint (volume);
98230d2
+  }
98230d2
 
98230d2
   volumes = g_new (gint, track->num_channels);
98230d2
   for (n = 0; n < track->num_channels; n++)
98230d2
-    volumes[n] = lrint (volume);
98230d2
+    volumes[n] = volint;
98230d2
   gst_mixer_set_volume (mixer, track, volumes);
98230d2
+
98230d2
   g_free (volumes);
98230d2
 }
98230d2
 
98230d2
@@ -1049,6 +1093,8 @@
98230d2
 
98230d2
   applet->lock = FALSE;
98230d2
   applet->force_next_update = TRUE;
98230d2
+
98230d2
+  gnome_volume_applet_refresh (GNOME_VOLUME_APPLET (data), FALSE, v, -1);
98230d2
 }
98230d2
 
98230d2
 /*
98230d2
@@ -1059,31 +1105,40 @@
98230d2
 
98230d2
 static void
98230d2
 gnome_volume_applet_refresh (GnomeVolumeApplet *applet,
98230d2
-			     gboolean           force_refresh)
98230d2
+			     gboolean           force_refresh,
98230d2
+			     gdouble            volume,
98230d2
+			     gint               mute)
98230d2
 {
98230d2
   BonoboUIComponent *component;
98230d2
   GdkPixbuf *pixbuf;
98230d2
   gint n;
98230d2
-  gdouble volume;
98230d2
-  gboolean mute, did_change;
98230d2
+  gboolean show_mute, did_change;
98230d2
   gchar *tooltip_str;
98230d2
   GstMixerTrack *first_track;
98230d2
   GString *track_names;
98230d2
   GList *iter;
98230d2
 
98230d2
+  show_mute = 0;
98230d2
+
98230d2
   if (!applet->mixer) {
98230d2
     n = 0;
98230d2
-    mute = FALSE;
98230d2
+    show_mute = 1;
98230d2
+    mute = 0;
98230d2
   } else if (!applet->tracks) {
98230d2
     return;
98230d2
   } else {
98230d2
-    /* only first track */
98230d2
     first_track = g_list_first (applet->tracks)->data;
98230d2
-    volume = gnome_volume_applet_get_volume (applet->mixer, first_track);
98230d2
-    mute = GST_MIXER_TRACK_HAS_FLAG (first_track,
98230d2
-				     GST_MIXER_TRACK_MUTE);
98230d2
+
98230d2
+    if (volume == -1) {
98230d2
+      /* only first track */
98230d2
+      volume = gnome_volume_applet_get_volume (applet->mixer, first_track);
98230d2
+    }
98230d2
+    if (mute == -1) {
98230d2
+      mute = GST_MIXER_TRACK_HAS_FLAG (first_track,
98230d2
+				       GST_MIXER_TRACK_MUTE) ? 1 : 0;
98230d2
+    }
98230d2
     if (volume <= 0) {
98230d2
-	mute = TRUE;
98230d2
+	show_mute = 1;
98230d2
 	n = 0;
98230d2
     }
98230d2
     else {
98230d2
@@ -1101,7 +1156,7 @@
98230d2
   applet->force_next_update = FALSE;
98230d2
 
98230d2
   if (did_change) {
98230d2
-    if (mute) {
98230d2
+    if (show_mute) {
98230d2
       pixbuf = applet->pix[0];
98230d2
     } else {
98230d2
       pixbuf = applet->pix[n];
98230d2
@@ -1125,7 +1180,7 @@
98230d2
       track_names = g_string_append (track_names, track->label);
98230d2
   }
98230d2
 
98230d2
-  if (mute) {
98230d2
+  if (show_mute) {
98230d2
     tooltip_str = g_strdup_printf (_("%s: muted"), track_names->str);
98230d2
   } else {
98230d2
     /* Translator comment: I'm not all too sure if this makes sense
1a7d652
@@ -1152,10 +1207,56 @@
98230d2
 				"state", mute ? "1" : "0", NULL);
98230d2
 }
98230d2
 
98230d2
+static void
98230d2
+cb_notify_message (GstBus *bus, GstMessage *message, gpointer data)
98230d2
+{
98230d2
+  GnomeVolumeApplet *applet = GNOME_VOLUME_APPLET (data);
98230d2
+  GstMixerMessageType type;
98230d2
+  GstMixerTrack *first_track;
98230d2
+  GstMixerTrack *track = NULL;
98230d2
+  gint mute;
98230d2
+  gdouble volume;
98230d2
+
98230d2
+  if (applet->tracks == NULL || 
98230d2
+      GST_MESSAGE_SRC (message) != GST_OBJECT (applet->mixer)) {
98230d2
+    /* No tracks, or not from our mixer - can't update anything anyway */
98230d2
+    return; 
98230d2
+  }
98230d2
+
98230d2
+  volume = mute = -1;
98230d2
+
98230d2
+  first_track = g_list_first (applet->tracks)->data;
98230d2
+
98230d2
+  /* This code only calls refresh if the first_track changes, because the
98230d2
+   * refresh code only retrieves the current value from that track anyway */
98230d2
+  type = gst_mixer_message_get_type (message);
98230d2
+  if (type == GST_MIXER_MESSAGE_MUTE_TOGGLED) {
98230d2
+    gboolean muted;
98230d2
+    gst_mixer_message_parse_mute_toggled (message, &track, &muted);
98230d2
+    mute = muted ? 1 : 0;
98230d2
+  }
1a7d652
+  else if (type == GST_MIXER_MESSAGE_VOLUME_CHANGED) {
98230d2
+    gint n, num_channels, *vols;
98230d2
+    volume = 0.0;
98230d2
+
98230d2
+    gst_mixer_message_parse_volume_changed (message, &track, &vols, &num_channels);
98230d2
+    for (n = 0; n < num_channels; n++)
98230d2
+      volume += vols[n];
98230d2
+    volume /= track->num_channels;
98230d2
+    volume = 100 * volume / (track->max_volume - track->min_volume);
1a7d652
+  } else
1a7d652
+  {
1a7d652
+    return;
98230d2
+  }
98230d2
+
98230d2
+  if (first_track == track)
98230d2
+    gnome_volume_applet_refresh (GNOME_VOLUME_APPLET (data), FALSE, volume, mute);
98230d2
+}
98230d2
+
98230d2
 static gboolean
98230d2
 cb_check (gpointer data)
98230d2
 {
98230d2
-  gnome_volume_applet_refresh (GNOME_VOLUME_APPLET (data), FALSE);
98230d2
+  gnome_volume_applet_refresh (GNOME_VOLUME_APPLET (data), FALSE, -1, -1);
98230d2
 
98230d2
   return TRUE;
98230d2
 }
1a7d652
@@ -1214,6 +1315,8 @@
98230d2
             /* save */
98230d2
             gst_object_replace ((GstObject **) &applet->mixer, item->data);
98230d2
             gst_element_set_state (old_element, GST_STATE_NULL);
98230d2
+
98230d2
+            gnome_volume_applet_setup_timeout (applet);
98230d2
             newdevice = TRUE;
98230d2
           }
98230d2
           break;
1a7d652
@@ -1374,7 +1477,7 @@
98230d2
   GnomeVolumeApplet *applet = GNOME_VOLUME_APPLET (data);
98230d2
 
98230d2
   init_pixbufs (applet);
98230d2
-  gnome_volume_applet_refresh (applet, TRUE);
98230d2
+  gnome_volume_applet_refresh (applet, TRUE, -1, -1);
98230d2
 }
98230d2
 
98230d2
 /*
98230d2
Index: applet.h
98230d2
===================================================================
98230d2
--- applet.h	(revision 10436)
98230d2
+++ applet.h	(working copy)
98230d2
@@ -71,6 +71,7 @@
98230d2
 
98230d2
   /* element */
98230d2
   GstMixer *mixer;
98230d2
+  GstBus *bus;
98230d2
   gboolean lock;
98230d2
   gint state;
98230d2
   GList *tracks;