diff -Nur -x '*.orig' -x '*~' gnome-settings-daemon-2.22.0/plugins/media-keys/actions/acme-volume.c gnome-settings-daemon-2.22.0.new/plugins/media-keys/actions/acme-volume.c
--- gnome-settings-daemon-2.22.0/plugins/media-keys/actions/acme-volume.c	2008-01-28 06:55:51.000000000 -0500
+++ gnome-settings-daemon-2.22.0.new/plugins/media-keys/actions/acme-volume.c	2008-03-22 12:19:40.000000000 -0400
@@ -32,6 +32,7 @@
 #include "acme-volume-gstreamer.h"
 #endif
 #include "acme-volume-dummy.h"
+#include "acme-volume-thinkpad.h"
 
 static GObjectClass *parent_class = NULL;
 
@@ -96,9 +97,17 @@
 	ACME_VOLUME_GET_CLASS (self)->set_mute (self, !muted);
 }
 
-AcmeVolume *acme_volume_new (void)
+AcmeVolume *acme_volume_new (GType vol_handler)
 {
-	AcmeVolume *vol;
+  AcmeVolume *vol;
+  /* Check if we should be doing ThinkPad volume handling rather
+     than the sftware stuff*/	
+  if(vol_handler == acme_volume_thinkpad_get_type ())
+    {
+      vol = ACME_VOLUME (g_object_new (acme_volume_thinkpad_get_type (),
+				       NULL));
+      return vol;
+    }
 
 #ifdef HAVE_GSTREAMER
 	vol = ACME_VOLUME (g_object_new (acme_volume_gstreamer_get_type (), NULL));
diff -Nur -x '*.orig' -x '*~' gnome-settings-daemon-2.22.0/plugins/media-keys/actions/acme-volume.h gnome-settings-daemon-2.22.0.new/plugins/media-keys/actions/acme-volume.h
--- gnome-settings-daemon-2.22.0/plugins/media-keys/actions/acme-volume.h	2007-12-24 06:18:48.000000000 -0500
+++ gnome-settings-daemon-2.22.0.new/plugins/media-keys/actions/acme-volume.h	2008-03-22 12:19:40.000000000 -0400
@@ -54,7 +54,7 @@
 void acme_volume_set_mute			(AcmeVolume *self,
 						 gboolean val);
 void acme_volume_mute_toggle			(AcmeVolume * self);
-AcmeVolume *acme_volume_new			(void);
+AcmeVolume *acme_volume_new			(GType vol_handler);
 
 G_END_DECLS
 
diff -Nur -x '*.orig' -x '*~' gnome-settings-daemon-2.22.0/plugins/media-keys/actions/acme-volume-thinkpad.c gnome-settings-daemon-2.22.0.new/plugins/media-keys/actions/acme-volume-thinkpad.c
--- gnome-settings-daemon-2.22.0/plugins/media-keys/actions/acme-volume-thinkpad.c	1969-12-31 19:00:00.000000000 -0500
+++ gnome-settings-daemon-2.22.0.new/plugins/media-keys/actions/acme-volume-thinkpad.c	2008-03-22 12:19:40.000000000 -0400
@@ -0,0 +1,145 @@
+/* acme-volume-thinkpad.c
+   
+   Adds Thinkpad volume reading.  Based on acme-volume-dummy.c
+
+   The Gnome 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.
+
+   The Gnome 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 the Gnome Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.
+
+   Based on acme-volume-dummy.c by Bastien Nocera <hadess@hadess.net>
+ */
+
+#include "config.h"
+#include "acme-volume-thinkpad.h"
+#include <stdio.h>
+
+static GObjectClass *parent_class = NULL;
+
+static int acme_volume_thinkpad_get_volume (AcmeVolume *self);
+static void acme_volume_thinkpad_set_volume (AcmeVolume *self, int val);
+
+static int parse_acpi(int * level, int * muteStatus);
+
+static void
+acme_volume_thinkpad_finalize (GObject *object)
+{
+	g_return_if_fail (object != NULL);
+	g_return_if_fail (ACME_IS_VOLUME_THINKPAD (object));
+
+	G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+acme_volume_thinkpad_set_mute (AcmeVolume *vol, gboolean val)
+{
+  /* No need to set anything.  Hardware takes care of it. */
+}
+
+static gboolean
+acme_volume_thinkpad_get_mute (AcmeVolume *vol)
+{
+        int volume,mute;
+	if(parse_acpi(&volume,&mute))
+	  return mute;
+  	return FALSE;
+}
+
+static int
+acme_volume_thinkpad_get_volume (AcmeVolume *vol)
+{
+        int volume,mute;
+	if(parse_acpi(&volume,&mute))
+	  {
+	    //Convert to a value between 0 and 100
+	    return CLAMP (volume*7, 0, 100);
+	  }
+	else
+	  return -1;
+}
+
+static void
+acme_volume_thinkpad_set_volume (AcmeVolume *vol, int val)
+{
+  /* No need to set anything.  Hardware takes care of it. */
+}
+
+static void
+acme_volume_thinkpad_init (AcmeVolume *vol)
+{
+}
+
+static void
+acme_volume_thinkpad_class_init (AcmeVolumeThinkpadClass *klass)
+{
+	AcmeVolumeClass *volume_class = ACME_VOLUME_CLASS (klass);
+	G_OBJECT_CLASS (klass)->finalize = acme_volume_thinkpad_finalize;
+
+	parent_class = g_type_class_peek_parent (klass);
+
+	volume_class->set_volume = acme_volume_thinkpad_set_volume;
+	volume_class->get_volume = acme_volume_thinkpad_get_volume;
+	volume_class->set_mute = acme_volume_thinkpad_set_mute;
+	volume_class->get_mute = acme_volume_thinkpad_get_mute;
+}
+
+GType acme_volume_thinkpad_get_type (void)
+{
+	static GType object_type = 0;
+
+	if (!object_type)
+	{
+		static const GTypeInfo object_info =
+		{
+			sizeof (AcmeVolumeThinkpadClass),
+			NULL,         /* base_init */
+			NULL,         /* base_finalize */
+			(GClassInitFunc) acme_volume_thinkpad_class_init,
+			NULL,         /* class_finalize */
+			NULL,         /* class_data */
+			sizeof (AcmeVolumeThinkpad),
+			0,            /* n_preallocs */
+			(GInstanceInitFunc) acme_volume_thinkpad_init
+		};
+
+		object_type = g_type_register_static (ACME_TYPE_VOLUME,
+				"AcmeVolumeThinkpad", &object_info, 0);
+	}
+
+	return object_type;
+}
+
+/* A simple function which parses the ACPI data.  This requires a acpi
+   kernel module supporting IBM thinkpads.*/
+static int
+parse_acpi(int * level, int * muteStatus)
+{
+  FILE * fd;
+  char muteString[4];
+  int numRetreived;
+
+  fd = fopen("/proc/acpi/ibm/volume","r");
+  if(fd == 0)
+    {
+      return -1;
+    }
+
+  numRetreived = fscanf(fd,"level:  %d  mute: %3s",level,muteString);
+  if(numRetreived != 2)
+    return -1;
+
+  // zero if "off" 1 if "on"
+  *muteStatus = strcmp(muteString,"off");
+  
+  return 1;
+}
diff -Nur -x '*.orig' -x '*~' gnome-settings-daemon-2.22.0/plugins/media-keys/actions/acme-volume-thinkpad.h gnome-settings-daemon-2.22.0.new/plugins/media-keys/actions/acme-volume-thinkpad.h
--- gnome-settings-daemon-2.22.0/plugins/media-keys/actions/acme-volume-thinkpad.h	1969-12-31 19:00:00.000000000 -0500
+++ gnome-settings-daemon-2.22.0.new/plugins/media-keys/actions/acme-volume-thinkpad.h	2008-03-22 12:19:40.000000000 -0400
@@ -0,0 +1,45 @@
+/* acme-volume-thinkpad.h
+
+   Adds Thinkpad Volume. Based on acme-volume-dummy.h by Bastien Nocera
+
+   The Gnome 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.
+
+   The Gnome 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 the Gnome Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.
+
+ */
+
+#include <glib.h>
+#include <glib-object.h>
+#include "acme-volume.h"
+
+#define ACME_TYPE_VOLUME_THINKPAD	(acme_volume_get_type ())
+#define ACME_VOLUME_THINKPAD(obj)		(G_TYPE_CHECK_INSTANCE_CAST ((obj), ACME_TYPE_VOLUME_THINKPAD, AcmeVolumeThinkpad))
+#define ACME_VOLUME_THINKPAD_CLASS(klass)	(G_TYPE_CHECK_CLASS_CAST ((klass), ACME_TYPE_VOLUME_THINKPAD, AcmeVolumeThinkpadClass))
+#define ACME_IS_VOLUME_THINKPAD(obj)	(G_TYPE_CHECK_INSTANCE_TYPE ((obj), ACME_TYPE_VOLUME_THINKPAD))
+#define ACME_VOLUME_THINKPAD_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS ((obj), ACME_TYPE_VOLUME_THINKPAD, AcmeVolumeThinkpadClass))
+
+typedef struct AcmeVolumeThinkpad AcmeVolumeThinkpad;
+typedef struct AcmeVolumeThinkpadClass AcmeVolumeThinkpadClass;
+
+struct AcmeVolumeThinkpad {
+	AcmeVolume parent;
+};
+
+struct AcmeVolumeThinkpadClass {
+	AcmeVolumeClass parent;
+};
+
+GType acme_volume_thinkpad_get_type		(void);
+AcmeVolume* acme_volume_thinkpad_new		(void);
+
diff -Nur -x '*.orig' -x '*~' gnome-settings-daemon-2.22.0/plugins/media-keys/actions/Makefile.am gnome-settings-daemon-2.22.0.new/plugins/media-keys/actions/Makefile.am
--- gnome-settings-daemon-2.22.0/plugins/media-keys/actions/Makefile.am	2008-02-08 07:29:11.000000000 -0500
+++ gnome-settings-daemon-2.22.0.new/plugins/media-keys/actions/Makefile.am	2008-03-22 12:19:40.000000000 -0400
@@ -8,6 +8,8 @@
 	acme-volume.h 		\
 	acme-volume-dummy.c 	\
 	acme-volume-dummy.h	\
+	acme-volume-thinkpad.c	\
+	acme-volume-thinkpad.h	\
 	$(NULL)
 
 libacme_la_CPPFLAGS = \
diff -Nur -x '*.orig' -x '*~' gnome-settings-daemon-2.22.0/plugins/media-keys/gsd-media-keys-manager.c gnome-settings-daemon-2.22.0.new/plugins/media-keys/gsd-media-keys-manager.c
--- gnome-settings-daemon-2.22.0/plugins/media-keys/gsd-media-keys-manager.c	2008-03-22 12:19:21.000000000 -0400
+++ gnome-settings-daemon-2.22.0.new/plugins/media-keys/gsd-media-keys-manager.c	2008-03-22 12:19:40.000000000 -0400
@@ -993,6 +993,7 @@
                               GError             **error)
 {
         GSList *l;
+        char * vol_handler;
 
         g_debug ("Starting media_keys manager");
 
@@ -1007,7 +1008,16 @@
         init_kbd (manager);
 
         /* initialise Volume handler */
-        manager->priv->volume = acme_volume_new ();
+        vol_handler = gconf_client_get_string (manager->priv->conf_client,
+					       GCONF_MISC_DIR "/hwvol", NULL);
+        if ((vol_handler != NULL) && (strcmp (vol_handler, "thinkpad") == 0))
+		manager->priv->volume = 
+                        acme_volume_new(acme_volume_thinkpad_get_type ());
+	else
+		 manager->priv->volume= acme_volume_new(0);
+
+	g_free(vol_handler);
+        
 
         /* Start filtering the events */
         for (l = manager->priv->screens; l != NULL; l = l->next) {
