diff --git a/envy24control/levelmeters.c b/envy24control/levelmeters.c
index fa44979..dd8f75e 100644
--- a/envy24control/levelmeters.c
+++ b/envy24control/levelmeters.c
@@ -1,6 +1,8 @@
 /*****************************************************************************
    levelmeters.c - Stereo level meters
    Copyright (C) 2000 by Jaroslav Kysela <perex@perex.cz>
+   Missing peak-level meter feature implented by NPM:
+   Copyright (C) 2010 by Niels Mayer <NielsMayer@gmail.com>
    
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
@@ -19,11 +21,10 @@
 
 #include "envy24control.h"
 
-static GdkGC *penGreenShadow[21] = { NULL, };
+static GdkGC *penWhiteLight[21] = { NULL, };
 static GdkGC *penGreenLight[21] = { NULL, };
-static GdkGC *penOrangeShadow[21] = { NULL, };
+static GdkGC *penBackground[21] = { NULL, };
 static GdkGC *penOrangeLight[21] = { NULL, };
-static GdkGC *penRedShadow[21] = { NULL, };
 static GdkGC *penRedLight[21] = { NULL, };
 static GdkPixmap *pixmap[21] = { NULL, };
 static snd_ctl_elem_value_t *peaks;
@@ -38,16 +39,49 @@ static void update_peak_switch(void)
 		g_print("Unable to read peaks: %s\n", snd_strerror(err));
 }
 
+/*
+ * Niels Mayer (NPM) Jul-11-10: Fixing https://bugzilla.redhat.com/show_bug.cgi?id=602903
+ * by implementing peak-level meters. The http://alsa.cybermirror.org/manuals/icensemble/envy24.pdf
+ * soundchip provides hardware level meters and these are returned via ALSA as such:
+ * >> amixer -c M66 cget iface=PCM,name='Multi Track Peak',numid=45
+ *  ; type=INTEGER,access=r-------,values=22,min=0,max=255,step=0
+ *  : values=0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,198,255,198 
+ * These globals store the peak levels of the meters across callbacks.
+ */
+#define RESET 9
+#define MULTI_TRACK_PEAK_CHANNELS 22
+// NPM: Note special case in original envy24control code, which puts stereo mix track at
+// "index 0" which is actually "(peaks, 20)" and "(peaks, 21)" cases below
+// thus peak_lmix <--> peak_levels[IDX_LMIX] ; peak_rmix <--> peak_levels[IDX_RMIX]
+#define IDX_LMIX 20
+#define IDX_RMIX 21
+static int peak_levels[MULTI_TRACK_PEAK_CHANNELS] = {0,};
+static int peak_changed[MULTI_TRACK_PEAK_CHANNELS] = {0,};
+static int previous_levels[MULTI_TRACK_PEAK_CHANNELS] = {0,};
+/* NPM: changed for https://bugzilla.redhat.com/show_bug.cgi?id=602903 */
 static void get_levels(int idx, int *l1, int *l2)
 {
-	*l1 = *l2 = 0;
-	
-	if (idx == 0) {
-		*l1 = snd_ctl_elem_value_get_integer(peaks, 20);
-		*l2 = snd_ctl_elem_value_get_integer(peaks, 21);
-	} else {
-		*l1 = *l2 = snd_ctl_elem_value_get_integer(peaks, idx - 1);
-	}
+  *l1 = *l2 = 0;
+  if (idx == 0) { //special case idx=0 as digital mix pair
+    if ((peak_changed[IDX_LMIX] != RESET) && (peak_changed[IDX_RMIX] != RESET)) { /* don't change values if doing "Reset Peaks" */
+      if ((*l1 = snd_ctl_elem_value_get_integer(peaks, 20)) > peak_levels[IDX_LMIX]) {
+	peak_levels[IDX_LMIX] = (*l1);
+	peak_changed[IDX_LMIX] = TRUE;
+      }
+      if ((*l2 = snd_ctl_elem_value_get_integer(peaks, 21)) > peak_levels[IDX_RMIX]) {
+	peak_levels[IDX_RMIX] = (*l2);
+	peak_changed[IDX_RMIX] = TRUE;
+      }
+    }
+  }
+  else {
+    if (peak_changed[idx-1] != RESET) {
+      if ((*l1 = snd_ctl_elem_value_get_integer(peaks, idx - 1)) > peak_levels[idx - 1]) {
+	peak_levels[idx - 1] = (*l1);
+	peak_changed[idx - 1] = TRUE;
+      }
+    }
+  }
 }
 
 static GdkGC *get_pen(int idx, int nRed, int nGreen, int nBlue)
@@ -79,73 +113,216 @@ static int get_index(gchar *name)
 	return result;
 }
 
+/*
+ * NPM: per http://alsa.cybermirror.org/manuals/icensemble/envy24.pdf the
+ * the values in each entry of iface=PCM,name='Multi Track Peak',numid=45
+ * represent: "Peak data derived from the absolute value of 9 msb. 00h
+ * min - FFh max volume. Reading the register resets the meter to 00h."
+ */
+#define NUM_METERING_LEVELS 256 
+#define GET_COLOR_FOR_PEAKLEVEL(level) \
+  (level > 224)                        \
+      ? (penRedLight[idx])             \
+      : ((level > 192)                 \
+	 ? (penOrangeLight[idx])       \
+	 : ((level > 128)              \
+	    ? (penWhiteLight[idx])     \
+	    : (penGreenLight[idx])))   
+
+/* 
+ * NPM: Called by redraw_meters(), this is the normal case 
+ * where we draw the meter and peaks, if changed.
+ */
+static void draw_meters_and_peaks(int idx, int width, int height, int level1, int level2, 
+				  int stereo, int segment_width)
+{
+  int meter1 = (stereo)
+    ? (int) ( (((double)peak_levels[IDX_LMIX])
+	       / ((double)NUM_METERING_LEVELS))
+	      * ((double)height))
+    : (int) ( (((double)peak_levels[idx - 1])
+	       / ((double)NUM_METERING_LEVELS))
+	      * ((double)height));
+  int meter2 = (stereo)
+    ? (int) ( (((double)peak_levels[IDX_RMIX])
+	       / ((double)NUM_METERING_LEVELS))
+	      * ((double)height))
+    : 0;
+  int peak1 = height - meter1;
+  int peak2 = (stereo) ? height - meter2: 0;
+  /*
+   * draw the peaks, if changed
+   */
+  if ( (stereo && (peak_changed[IDX_LMIX] || peak_changed[IDX_RMIX]))
+       || peak_changed[idx-1]) {
+    int peak2_level, peak1_level = (stereo) ? peak_levels[IDX_LMIX] : peak_levels[idx-1];
+    //POTENTIAL X-EFFICIENCY HACK: skip drawing the line: instead of drawing 
+    //a line, just don't refresh the part of therectangle that created the peak, 
+    //and always clear from below that peak using Y=peak1+1 so as to leave behind the
+    //top line of pixels from the peak that caused the peak. Not as if that's a big efficiency
+    //win, not like setting proper clip regions and computing "damage areas"..
+    gdk_draw_line(pixmap[idx],
+		  GET_COLOR_FOR_PEAKLEVEL(peak1_level),
+		  //X1
+		  6,
+		  //Y1
+		  peak1 - 1,
+		  //X2
+		  5 + segment_width,
+		  //Y2
+		  peak1 - 1
+		  );
+    if (stereo && peak_changed[IDX_RMIX]) { //for stereo, draw RMIX, but skip redraw if same
+      peak2_level = peak_levels[IDX_RMIX];
+      gdk_draw_line(pixmap[idx],
+		    GET_COLOR_FOR_PEAKLEVEL(peak2_level),
+		    //X1
+		    2 + (width / 2),
+		    //Y1
+		    peak2 - 1,
+		    //X2
+		    1 + (width / 2) + segment_width,
+		    //Y2
+		    peak2 - 1
+		    );
+      peak_changed[IDX_RMIX] = FALSE;
+    }
+    if (stereo) {
+      if (peak_changed[IDX_LMIX])
+	peak_changed[IDX_LMIX] = FALSE;
+    }
+    else
+      peak_changed[idx-1] = FALSE;
+  }
+   
+  /*
+   * draw the meters
+   * level1 at 0 --> no dspl
+   * level1 at 1 --> draw rectange at (1/255)*height
+   * level1 at 255 --> draw rectangle (255/255)*height
+   */
+  meter1 = (int) ((((double)level1)
+		   / ((double)NUM_METERING_LEVELS))
+		  * (double)height);
+  if (stereo)
+    meter2 = (int) ((((double)level2)
+		     / ((double)NUM_METERING_LEVELS))
+		    * (double)height);
+  if (level1 != (stereo ? previous_levels[IDX_LMIX] : previous_levels[idx-1]) ) { //skip redraw if same
+    gdk_draw_rectangle(pixmap[idx],
+		       penBackground[idx],
+		       TRUE,
+		       //X
+		       6,                               // draw black downward from peak
+		       //Y
+		       peak1,
+		       //WIDTH
+		       segment_width,
+		       //HEIGHT
+		       height - meter1 - peak1
+		       );
+    gdk_draw_rectangle(pixmap[idx],
+		       penGreenLight[idx],
+		       TRUE,
+		       //X
+		       6,
+		       //Y
+		       height - meter1,
+		       //WIDTH
+		       segment_width,
+		       //HEIGHT
+		       meter1
+		       );                             
+    /* save current level value, skip redraw next time if no change */
+    if (stereo)
+      previous_levels[IDX_LMIX] = level1;
+    else
+      previous_levels[idx-1] = level1;
+  }
+  if (stereo && (level2 != previous_levels[IDX_RMIX])) { //for stereo, draw RMIX, but skip redraw if same
+    gdk_draw_rectangle(pixmap[idx],
+		       penBackground[idx],
+		       TRUE,
+		       //X
+		       2 + (width / 2),
+		       //Y
+		       peak2,
+		       //WIDTH
+		       segment_width,
+		       //HEIGHT
+		       height - meter2 - peak2
+		       );
+    gdk_draw_rectangle(pixmap[idx],
+		       penOrangeLight[idx],
+		       TRUE,
+		       //X
+		       2 + (width / 2),
+		       //Y
+		       height - meter2,
+		       //WIDTH
+		       segment_width,
+		       //HEIGHT
+		       meter2
+		       );
+    /* save current level value, skip redraw next time if no change */
+    previous_levels[IDX_RMIX] = level2; 
+  }
+}
+
+/*
+ * NPM: Called by redraw_meters(), this is a special case for when "Reset
+ * Peaks" is clicked: then just refresh meters, ignore value, clear RESET
+ * and let the next pass-through draw for the first time in the cleared
+ * meter...
+ */
+static void draw_meters_reset(int idx, int width, int height, int level1, int level2, 
+				int stereo, int segment_width)
+{
+  gdk_draw_rectangle(pixmap[idx],
+		     penBackground[idx], 
+		     TRUE,
+		     //X
+		     6,
+		     //Y
+		     0,
+		     //WIDTH
+		     segment_width,
+		     //HEIGHT
+		     height
+		     );
+  if (stereo) {
+    gdk_draw_rectangle(pixmap[idx],
+		       penBackground[idx], 
+		       TRUE,
+		       //X
+		       2 + (width / 2),
+		       //Y
+		       0,
+		       //WIDTH
+		       segment_width,
+		       //HEIGHT
+		       height
+		       );
+    peak_changed[IDX_LMIX] = FALSE;
+    peak_changed[IDX_RMIX] = FALSE;
+  }
+  else {
+    peak_changed[idx-1] = FALSE;
+  }
+}
+
 static void redraw_meters(int idx, int width, int height, int level1, int level2)
 {
-	int stereo = idx == 0;
-	int segment_width = stereo ? (width / 2) - 8 : width - 12;
-	int segments = (height - 6) / 4;
-	int green_segments = (segments / 4) * 3;
-	int red_segments = 2;
-	int orange_segments = segments - green_segments - red_segments;
-	int seg;
-	int segs_on1 = ((segments * level1) + 128) / 255;
-	int segs_on2 = ((segments * level2) + 128) / 255;
+  int stereo = (idx == 0);
+  int segment_width = (stereo)
+    ? (width / 2) - 8
+    : width - 12;
 
-	// g_print("segs_on1 = %i (%i), segs_on2 = %i (%i)\n", segs_on1, level1, segs_on2, level2);
-	for (seg = 0; seg < green_segments; seg++) {
-		gdk_draw_rectangle(pixmap[idx],
-				   segs_on1 > 0 ? penGreenLight[idx] : penGreenShadow[idx],
-				   TRUE,
-				   6, 3 + ((segments - seg - 1) * 4),
-				   segment_width,
-				   3);
-		if (stereo)
-			gdk_draw_rectangle(pixmap[idx],
-					   segs_on2 > 0 ? penGreenLight[idx] : penGreenShadow[idx],
-					   TRUE,
-					   2 + (width / 2),
-					   3 + ((segments - seg - 1) * 4),
-					   segment_width,
-					   3);
-		segs_on1--;
-		segs_on2--;
-	}
-	for (seg = green_segments; seg < green_segments + orange_segments; seg++) {
-		gdk_draw_rectangle(pixmap[idx],
-				   segs_on1 > 0 ? penOrangeLight[idx] : penOrangeShadow[idx],
-				   TRUE,
-				   6, 3 + ((segments - seg - 1) * 4),
-				   segment_width,
-				   3);
-		if (stereo)
-			gdk_draw_rectangle(pixmap[idx],
-					   segs_on2 > 0 ? penOrangeLight[idx] : penOrangeShadow[idx],
-					   TRUE,
-					   2 + (width / 2),
-					   3 + ((segments - seg - 1) * 4),
-					   segment_width,
-					   3);
-		segs_on1--;
-		segs_on2--;
-	}
-	for (seg = green_segments + orange_segments; seg < segments; seg++) {
-		gdk_draw_rectangle(pixmap[idx],
-				   segs_on1 > 0 ? penRedLight[idx] : penRedShadow[idx],
-				   TRUE,
-				   6, 3 + ((segments - seg - 1) * 4),
-				   segment_width,
-				   3);
-		if (stereo)
-			gdk_draw_rectangle(pixmap[idx],
-					   segs_on2 > 0 ? penRedLight[idx] : penRedShadow[idx],
-					   TRUE,
-					   2 + (width / 2),
-					   3 + ((segments - seg - 1) * 4),
-					   segment_width,
-					   3);
-		segs_on1--;
-		segs_on2--;
-	}
+  if ( (stereo && ((peak_changed[IDX_LMIX] == RESET) || (peak_changed[IDX_RMIX] == RESET)))
+       || peak_changed[idx-1] == RESET)	//needs full refresh, reset peaks button was clicked
+    draw_meters_reset(idx, width, height, level1, level2, stereo, segment_width);
+  else 
+    draw_meters_and_peaks(idx, width, height, level1, level2, stereo, segment_width);
 }
 
 gint level_meters_configure_event(GtkWidget *widget, GdkEventConfigure *event)
@@ -158,11 +335,10 @@ gint level_meters_configure_event(GtkWidget *widget, GdkEventConfigure *event)
 				     widget->allocation.width,
 				     widget->allocation.height,
 				     -1);
-	penGreenShadow[idx] = get_pen(idx, 0, 0x77ff, 0);
+	penWhiteLight[idx] = get_pen(idx, 0xffff, 0xffff, 0xffff);
 	penGreenLight[idx] = get_pen(idx, 0, 0xffff, 0);
-	penOrangeShadow[idx] = get_pen(idx, 0xddff, 0x55ff, 0);
-	penOrangeLight[idx] = get_pen(idx, 0xffff, 0x99ff, 0);
-	penRedShadow[idx] = get_pen(idx, 0xaaff, 0, 0);
+	penBackground[idx] = get_pen(idx, 0x1111, 0x5511, 0);
+	penOrangeLight[idx] = get_pen(idx, 0xff11, 0x9911, 0);
 	penRedLight[idx] = get_pen(idx, 0xffff, 0, 0);
 	gdk_draw_rectangle(pixmap[idx],
 			   widget->style->black_gc,
@@ -170,6 +346,9 @@ gint level_meters_configure_event(GtkWidget *widget, GdkEventConfigure *event)
 			   0, 0,
 			   widget->allocation.width,
 			   widget->allocation.height);
+
+	level_meters_reset_peaks(NULL, NULL); /* NPM */
+
 	// g_print("configure: %i:%i\n", widget->allocation.width, widget->allocation.height);
 	redraw_meters(idx, widget->allocation.width, widget->allocation.height, 0, 0);
 	return TRUE;
@@ -255,8 +434,18 @@ gint level_meters_timeout_callback(gpointer data)
 	return TRUE;
 }
 
+
+/* NPM fixed lack of implementation ( https://bugzilla.redhat.com/show_bug.cgi?id=602903 )*/
 void level_meters_reset_peaks(GtkButton *button, gpointer data)
 {
+  int i;
+  for (i = 0; i < MULTI_TRACK_PEAK_CHANNELS ; i++) {
+    peak_levels[i] = 0;
+    previous_levels[i] = 0;
+    peak_changed[i] = RESET;
+  }
+
+  level_meters_timeout_callback((gpointer) data);
 }
 
 void level_meters_init(void)
