diff --git a/browser-plugin/totem-plugin-viewer.c b/browser-plugin/totem-plugin-viewer.c
index 89dae3d..5a0237b 100644
--- a/browser-plugin/totem-plugin-viewer.c
+++ b/browser-plugin/totem-plugin-viewer.c
@@ -59,8 +59,8 @@ GtkWidget *totem_statusbar_create (void);
 GtkWidget *totem_volume_create (void);
 GtkWidget *totem_pp_create (void);
 
-#define VOLUME_DOWN_OFFSET -8
-#define VOLUME_UP_OFFSET 8
+#define VOLUME_DOWN_OFFSET (-0.08)
+#define VOLUME_UP_OFFSET (0.08)
 
 /* For newer D-Bus version */
 #ifndef DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT
@@ -1352,7 +1352,7 @@ totem_embedded_construct (TotemEmbedded *emb,
 	BvwUseType type;
 	GError *err = NULL;
 	GConfClient *gc;
-	int volume;
+	double volume;
 
 	if (xid != 0) {
 		g_assert (!emb->hidden);
@@ -1438,7 +1438,7 @@ totem_embedded_construct (TotemEmbedded *emb,
 			  G_CALLBACK (on_play_pause), emb);
 
 	gc = gconf_client_get_default ();
-	volume = gconf_client_get_int (gc, GCONF_PREFIX"/volume", NULL);
+	volume = ((double) gconf_client_get_int (gc, GCONF_PREFIX"/volume", NULL)) / 100.0;
 	g_object_unref (G_OBJECT (gc));
 
 	bacon_video_widget_set_volume (emb->bvw, volume);
diff --git a/src/backend/bacon-video-widget-gst-0.10.c b/src/backend/bacon-video-widget-gst-0.10.c
index df96398..ce63f82 100644
--- a/src/backend/bacon-video-widget-gst-0.10.c
+++ b/src/backend/bacon-video-widget-gst-0.10.c
@@ -1021,7 +1021,7 @@ bacon_video_widget_class_init (BaconVideoWidgetClass * klass)
                                                      0, G_MAXINT, 0,
                                                      G_PARAM_READABLE));
   g_object_class_install_property (object_class, PROP_STREAM_LENGTH,
-                                   g_param_spec_int64 ("stream_length", NULL,
+	                           g_param_spec_int64 ("stream-length", NULL,
                                                      NULL, 0, G_MAXINT64, 0,
                                                      G_PARAM_READABLE));
   g_object_class_install_property (object_class, PROP_PLAYING,
@@ -1033,9 +1033,9 @@ bacon_video_widget_class_init (BaconVideoWidgetClass * klass)
                                                          NULL, FALSE,
                                                          G_PARAM_READABLE));
   g_object_class_install_property (object_class, PROP_VOLUME,
-                                     g_param_spec_int ("volume", NULL, NULL,
-                                                     0, 100, 0,
-                                                     G_PARAM_READABLE));
+	                           g_param_spec_double ("volume", NULL, NULL,
+	                                                0.0, 1.0, 0.0,
+	                                                G_PARAM_READWRITE));
   g_object_class_install_property (object_class, PROP_SHOWCURSOR,
                                    g_param_spec_boolean ("showcursor", NULL,
                                                          NULL, FALSE,
@@ -1961,6 +1961,9 @@ bacon_video_widget_set_property (GObject * object, guint property_id,
       bacon_video_widget_set_show_visuals (bvw,
       g_value_get_boolean (value));
       break;
+    case PROP_VOLUME:
+      bacon_video_widget_set_volume (bvw, g_value_get_double (value));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
       break;
@@ -2000,7 +2003,7 @@ bacon_video_widget_get_property (GObject * object, guint property_id,
       bacon_video_widget_get_show_cursor (bvw));
       break;
     case PROP_VOLUME:
-      g_value_set_int (value, bacon_video_widget_get_volume (bvw));
+      g_value_set_double (value, bacon_video_widget_get_volume (bvw));
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -3169,33 +3172,31 @@ bacon_video_widget_can_set_volume (BaconVideoWidget * bvw)
 }
 
 void
-bacon_video_widget_set_volume (BaconVideoWidget * bvw, int volume)
+bacon_video_widget_set_volume (BaconVideoWidget * bvw, double volume)
 {
-  g_return_if_fail (bvw != NULL);
   g_return_if_fail (BACON_IS_VIDEO_WIDGET (bvw));
   g_return_if_fail (GST_IS_ELEMENT (bvw->priv->play));
 
   if (bacon_video_widget_can_set_volume (bvw) != FALSE)
   {
-    volume = CLAMP (volume, 0, 100);
+    volume = CLAMP (volume, 0.0, 1.0);
     g_object_set (bvw->priv->play, "volume",
-                  (gdouble) (1. * volume / 100), NULL);
+	          (gdouble) volume, NULL);
     g_object_notify (G_OBJECT (bvw), "volume");
   }
 }
 
-int
+double
 bacon_video_widget_get_volume (BaconVideoWidget * bvw)
 {
-  gdouble vol;
+  double vol;
 
-  g_return_val_if_fail (bvw != NULL, -1);
-  g_return_val_if_fail (BACON_IS_VIDEO_WIDGET (bvw), -1);
-  g_return_val_if_fail (GST_IS_ELEMENT (bvw->priv->play), -1);
+  g_return_val_if_fail (BACON_IS_VIDEO_WIDGET (bvw), 0.0);
+  g_return_val_if_fail (GST_IS_ELEMENT (bvw->priv->play), 0.0);
 
   g_object_get (G_OBJECT (bvw->priv->play), "volume", &vol, NULL);
 
-  return (gint) (vol * 100 + 0.5);
+  return vol;
 }
 
 gboolean
diff --git a/src/backend/bacon-video-widget-xine.c b/src/backend/bacon-video-widget-xine.c
index bf93cb0..1afda38 100644
--- a/src/backend/bacon-video-widget-xine.c
+++ b/src/backend/bacon-video-widget-xine.c
@@ -169,7 +169,7 @@ struct BaconVideoWidgetPrivate {
 	/* Other stuff */
 	int xpos, ypos;
 	guint tick_id;
-	int volume;
+	double volume;
 	BaconVideoWidgetAudioOutType audio_out_type;
 	TvOutType tvout;
 	int stream_length;
@@ -331,8 +331,9 @@ bacon_video_widget_class_init (BaconVideoWidgetClass *klass)
 			g_param_spec_boolean ("seekable", NULL, NULL,
 				FALSE, G_PARAM_READABLE));
 	g_object_class_install_property (object_class, PROP_VOLUME,
-			g_param_spec_int ("volume", NULL, NULL,
-				0, 100, 0, G_PARAM_READABLE));
+	                g_param_spec_double ("volume", NULL, NULL,
+	                        0.0, 1.0, 0.0,
+	                        G_PARAM_READWRITE));
 	g_object_class_install_property (object_class, PROP_SHOWCURSOR,
 			g_param_spec_boolean ("showcursor", NULL, NULL,
 				FALSE, G_PARAM_READWRITE));
@@ -430,7 +431,7 @@ bacon_video_widget_init (BaconVideoWidget *bvw)
 	bvw->priv = g_new0 (BaconVideoWidgetPrivate, 1);
 	bvw->priv->xine = xine_new ();
 	bvw->priv->cursor_shown = TRUE;
-	bvw->priv->volume = 0;
+	bvw->priv->volume = 0.0;
 
 	bvw->priv->init_width = 0;
 	bvw->priv->init_height = 0;
@@ -1625,8 +1626,11 @@ bacon_video_widget_unrealize (GtkWidget *widget)
 	/* Save the current volume */
 	if (bacon_video_widget_can_set_volume (bvw) != FALSE)
 	{
+	        int vol;
+
+	        vol = (bvw->priv->volume * 100.0 + 0.5);
 		gconf_client_set_int (bvw->priv->gc, GCONF_PREFIX"/volume",
-				bvw->priv->volume, NULL);
+				CLAMP (vol, 0, 100), NULL);
 	}
 
 	/* Kill the TV out */
@@ -2631,6 +2635,9 @@ bacon_video_widget_set_property (GObject *object, guint property_id,
 		bacon_video_widget_set_show_visuals (bvw,
 				g_value_get_boolean (value));
 		break;
+	case PROP_VOLUME:
+	        bacon_video_widget_set_volume (bvw, g_value_get_double (value));
+	        break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 	}
@@ -2670,7 +2677,7 @@ bacon_video_widget_get_property (GObject *object, guint property_id,
 				bacon_video_widget_get_show_cursor (bvw));
 		break;
 	case PROP_VOLUME:
-		g_value_set_int (value, bvw->priv->volume);
+		g_value_set_double (value, bvw->priv->volume);
 		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -2842,31 +2849,31 @@ bacon_video_widget_can_set_volume (BaconVideoWidget *bvw)
 }
 
 void
-bacon_video_widget_set_volume (BaconVideoWidget *bvw, int volume)
+bacon_video_widget_set_volume (BaconVideoWidget *bvw, double volume)
 {
-	g_return_if_fail (bvw != NULL);
 	g_return_if_fail (BACON_IS_VIDEO_WIDGET (bvw));
 	g_return_if_fail (bvw->priv->xine != NULL);
 
 	if (bacon_video_widget_can_set_volume (bvw) != FALSE)
 	{
+		bvw->priv->volume = volume;
+
+	        volume = volume * 100 + 0.5;
 		volume = CLAMP (volume, 0, 100);
 		xine_set_param (bvw->priv->stream,
 				XINE_PARAM_AUDIO_AMP_LEVEL, volume);
-		bvw->priv->volume = volume;
 		g_object_notify (G_OBJECT (bvw), "volume");
 	}
 }
 
-int
+double
 bacon_video_widget_get_volume (BaconVideoWidget *bvw)
 {
-	g_return_val_if_fail (bvw != NULL, 0);
-	g_return_val_if_fail (BACON_IS_VIDEO_WIDGET (bvw), 0);
-	g_return_val_if_fail (bvw->priv->xine != NULL, 0);
+	g_return_val_if_fail (BACON_IS_VIDEO_WIDGET (bvw), 0.0);
+	g_return_val_if_fail (bvw->priv->xine != NULL, 0.0);
 
 	if (bacon_video_widget_can_set_volume (bvw) == FALSE)
-		return 0;
+		return 0.0;
 
 	return bvw->priv->volume;
 }
diff --git a/src/backend/bacon-video-widget.h b/src/backend/bacon-video-widget.h
index c98e68f..61285fc 100644
--- a/src/backend/bacon-video-widget.h
+++ b/src/backend/bacon-video-widget.h
@@ -145,8 +145,8 @@ void bacon_video_widget_close                    (BaconVideoWidget *bvw);
 /* Audio volume */
 gboolean bacon_video_widget_can_set_volume       (BaconVideoWidget *bvw);
 void bacon_video_widget_set_volume               (BaconVideoWidget *bvw,
-						  int volume);
-int bacon_video_widget_get_volume                (BaconVideoWidget *bvw);
+						  double volume);
+double bacon_video_widget_get_volume             (BaconVideoWidget *bvw);
 
 /* Properties */
 void bacon_video_widget_set_logo		 (BaconVideoWidget *bvw,
diff --git a/src/totem-private.h b/src/totem-private.h
index 54bc635..be08de9 100644
--- a/src/totem-private.h
+++ b/src/totem-private.h
@@ -114,7 +114,7 @@ struct TotemObject {
 
 	/* Volume */
 	GtkWidget *volume;
-	gfloat prev_volume;
+	gdouble prev_volume;
 	int volume_first_time;
 	gboolean volume_sensitive;
 
@@ -177,8 +177,8 @@ GtkWidget *totem_volume_create (void);
 #define SEEK_FORWARD_OFFSET 60
 #define SEEK_BACKWARD_OFFSET -15
 
-#define VOLUME_DOWN_OFFSET -8
-#define VOLUME_UP_OFFSET 8
+#define VOLUME_DOWN_OFFSET (-0.08)
+#define VOLUME_UP_OFFSET (0.08)
 
 #define ZOOM_IN_OFFSET 1
 #define ZOOM_OUT_OFFSET -1
diff --git a/src/totem.c b/src/totem.c
index 1f77e7c..5743158 100644
--- a/src/totem.c
+++ b/src/totem.c
@@ -28,10 +28,12 @@
 
 #include "config.h"
 
+#include <stdlib.h>
+#include <math.h>
+
 #include <glib/gi18n.h>
 #include <gtk/gtk.h>
 #include <gdk/gdkkeysyms.h>
-#include <stdlib.h>
 
 #ifndef HAVE_GTK_ONLY
 #include <gnome.h>
@@ -86,6 +88,8 @@
 
 #define BVW_VBOX_BORDER_WIDTH 1
 
+#define VOLUME_EPSILON (1e-10)
+
 static const GtkTargetEntry target_table[] = {
 	{ "text/uri-list", 0, 0 },
 	{ "_NETSCAPE_URL", 0, 1 },
@@ -210,10 +214,13 @@ totem_action_exit (Totem *totem)
 		gdk_display_sync (display);
 
 	if (totem->bvw) {
+	        int vol;
+
+	        vol = bacon_video_widget_get_volume (totem->bvw) * 100.0 + 0.5;
 		//FIXME move the volume to the static file?
 		gconf_client_set_int (totem->gc,
 				GCONF_PREFIX"/volume",
-				bacon_video_widget_get_volume (totem->bvw),
+				CLAMP (vol, 0, 100),
 				NULL);
 		totem_action_save_size (totem);
 	}
@@ -928,8 +935,8 @@ totem_action_set_mrl_with_warning (Totem *totem, const char *mrl,
 		caps = bacon_video_widget_can_set_volume (totem->bvw);
 		totem_main_set_sensitivity ("tmw_volume_button", caps);
 		totem_main_set_sensitivity ("tcw_volume_button", caps);
-		totem_action_set_sensitivity ("volume-up", caps && totem->prev_volume < 100);
-		totem_action_set_sensitivity ("volume-down", caps && totem->prev_volume > 0);
+	        totem_action_set_sensitivity ("volume-up", caps && totem->prev_volume < (1.0 - VOLUME_EPSILON));
+	        totem_action_set_sensitivity ("volume-down", caps && totem->prev_volume > VOLUME_EPSILON);
 		totem->volume_sensitive = caps;
 
 		/* Take a screenshot */
@@ -1142,9 +1149,9 @@ totem_action_zoom_reset (Totem *totem)
 }
 
 void
-totem_action_volume_relative (Totem *totem, int off_pct)
+totem_action_volume_relative (Totem *totem, double off_pct)
 {
-	int vol;
+	double vol;
 
 	if (bacon_video_widget_can_set_volume (totem->bvw) == FALSE)
 		return;
@@ -1530,22 +1537,25 @@ update_current_time (BaconVideoWidget *bvw,
 static void
 update_volume_sliders (Totem *totem)
 {
-	int volume;
+	double volume;
 	GtkAction *action;
 
 	volume = bacon_video_widget_get_volume (totem->bvw);
 
-	if (totem->volume_first_time || (totem->prev_volume != volume &&
-				totem->prev_volume != -1 && volume != -1))
+	if (totem->volume_first_time ||
+	    totem->prev_volume >= 0. &&
+	    abs (totem->prev_volume - volume) > VOLUME_EPSILON)
 	{
 		totem->volume_first_time = 0;
+
 		gtk_scale_button_set_value (GTK_SCALE_BUTTON (totem->volume), volume);
+		gtk_adjustment_set_value (totem->fs_voladj, volume);
 
 		action = gtk_action_group_get_action (totem->main_action_group, "volume-down");
-		gtk_action_set_sensitive (action, volume > 0 && totem->volume_sensitive);
-
+		gtk_action_set_sensitive (action, volume > VOLUME_EPSILON && totem->volume_sensitive);
+		
 		action = gtk_action_group_get_action (totem->main_action_group, "volume-up");
-		gtk_action_set_sensitive (action, volume < 100 && totem->volume_sensitive);
+		gtk_action_set_sensitive (action, volume < (1.0 - VOLUME_EPSILON) && totem->volume_sensitive);
 	}
 
 	totem->prev_volume = volume;
@@ -1999,7 +2009,7 @@ totem_action_remote (Totem *totem, TotemRemoteCommand cmd, const char *url)
 		// TODO - how to see if can, and play the DVD (like the menu item)
 		break;
 	case TOTEM_REMOTE_COMMAND_MUTE:
-		totem_action_volume_relative (totem, -100);
+		totem_action_volume_relative (totem, -1.0);
 		break;
 	default:
 		handled = FALSE;
@@ -3159,8 +3169,8 @@ video_widget_create (Totem *totem)
 	gtk_widget_show (GTK_WIDGET (totem->bvw));
 
 	bacon_video_widget_set_volume (totem->bvw,
-			gconf_client_get_int (totem->gc,
-				GCONF_PREFIX"/volume", NULL));
+			((double) gconf_client_get_int (totem->gc,
+				GCONF_PREFIX"/volume", NULL)) / 100.0);
 	g_signal_connect (G_OBJECT (totem->bvw), "notify::volume",
 			G_CALLBACK (property_notify_cb_volume), totem);
 	g_signal_connect (G_OBJECT (totem->bvw), "notify::logo-mode",
@@ -3283,7 +3293,7 @@ main (int argc, char **argv)
 	}
 
 	/* Init totem itself */
-	totem->prev_volume = -1;
+	totem->prev_volume = -1.;
 	totem->cursor_shown = TRUE;
 
 	/* Main window */
diff --git a/src/totem.h b/src/totem.h
index 52f53d3..80dc022 100644
--- a/src/totem.h
+++ b/src/totem.h
@@ -122,7 +122,7 @@ void	totem_action_next			(Totem *totem);
 void	totem_action_previous			(Totem *totem);
 void	totem_action_seek_time			(Totem *totem, gint64 sec);
 void	totem_action_seek_relative		(Totem *totem, int off_sec);
-void	totem_action_volume_relative		(Totem *totem, int off_pct);
+void	totem_action_volume_relative		(Totem *totem, double off_pct);
 gboolean totem_action_set_mrl			(Totem *totem,
 						 const char *mrl);
 void	totem_action_set_mrl_and_play		(Totem *totem,
