diff -Naur graphlcd-0.1.4.orig/display.c graphlcd-0.1.4/display.c
--- graphlcd-0.1.4.orig/display.c	2007-02-04 23:10:36.609384554 +0100
+++ graphlcd-0.1.4/display.c	2007-02-04 23:17:48.756350745 +0100
@@ -115,6 +115,7 @@
     nCurrentBrightness = -1;
     LastTimeBrightness = 0;
     bBrightnessActive = true;
+	LastTimeSA.Set(0);
 }
 
 cGraphLCDDisplay::~cGraphLCDDisplay()
@@ -373,6 +374,11 @@
                             update = true;
                         }
 
+						if ( LastTimeSA.TimedOut() )
+                           {
+                               update = true;
+                               LastTimeSA.Set(1000);
+                           }
                         // update Display every second or due to an update
                         if (CurrTime != LastTime || update)
                         {
@@ -1460,6 +1466,8 @@
                           nTopY + nProgressbarHeight,
                           GLCD::clrBlack, false);
 
+	DisplaySA();
+
     if (1 < replay.total && 1 < replay.current) // Don't show full progressbar for endless streams
     {
         bitmap->DrawRectangle(FRAME_SPACE_X,
@@ -1945,3 +1953,141 @@
     }
     mutex.Unlock();
 }
+
+void cGraphLCDDisplay::DisplaySA()
+{
+// Spectrum Analyzer visualization
+   if ( GraphLCDSetup.enableSpectrumAnalyzer )
+   {
+       if (cPluginManager::CallFirstService(SPAN_GET_BAR_HEIGHTS_ID, NULL))
+       {
+           Span_GetBarHeights_v1_0 GetBarHeights;
+
+           int bandsSA = 20;
+           int falloffSA = 8;
+           int channelsSA = 1;
+
+           unsigned int bar;
+           unsigned int *barHeights = new unsigned int[bandsSA];
+           unsigned int *barHeightsLeftChannel = new unsigned int[bandsSA];
+           unsigned int *barHeightsRightChannel = new unsigned int[bandsSA];
+           unsigned int volumeLeftChannel;
+           unsigned int volumeRightChannel;
+           unsigned int volumeBothChannels;
+           unsigned int *barPeaksBothChannels = new unsigned int[bandsSA];
+           unsigned int *barPeaksLeftChannel = new unsigned int[bandsSA];
+           unsigned int *barPeaksRightChannel = new unsigned int[bandsSA];
+
+           GetBarHeights.bands                     = bandsSA;
+           GetBarHeights.barHeights                = barHeights;
+           GetBarHeights.barHeightsLeftChannel     = barHeightsLeftChannel;
+           GetBarHeights.barHeightsRightChannel    = barHeightsRightChannel;
+           GetBarHeights.volumeLeftChannel         = &volumeLeftChannel;
+           GetBarHeights.volumeRightChannel        = &volumeRightChannel;
+           GetBarHeights.volumeBothChannels        = &volumeBothChannels;
+           GetBarHeights.name                      = "graphlcd";
+           GetBarHeights.falloff                   = falloffSA;
+           GetBarHeights.barPeaksBothChannels      = barPeaksBothChannels;
+           GetBarHeights.barPeaksLeftChannel       = barPeaksLeftChannel;
+           GetBarHeights.barPeaksRightChannel      = barPeaksRightChannel;
+
+           if ( cPluginManager::CallFirstService(SPAN_GET_BAR_HEIGHTS_ID, &GetBarHeights ))
+           {
+               int i;
+               int barWidth = 2;
+               int saStartX = FRAME_SPACE_X;
+               int saEndX = saStartX + barWidth*bandsSA*2 + bandsSA/4 - 1;
+               int saStartY = FRAME_SPACE_Y;
+               int saEndY = FRAME_SPACE_Y + bitmap->Height()/2 - 3;
+
+               LastTimeSA.Set(100);
+
+               if ( GraphLCDSetup.SAShowVolume )
+               {
+
+                   saStartX = FRAME_SPACE_X  + bitmap->Width()/2 - (barWidth*bandsSA*2 + bandsSA/4)/2 - 2;
+                   saEndX = saStartX + barWidth*bandsSA*2 + bandsSA/4 - 1;
+
+                   // left volume
+                   bitmap->DrawRectangle(FRAME_SPACE_X,
+                       saStartY,
+                       saStartX-1,
+                       saEndY + 1,
+                       GLCD::clrWhite, true);
+
+                   for ( i=0; (i<logo->Width()/2-2) && (i<3*(volumeLeftChannel*saStartX)/100); i++)
+                   {
+                       bitmap->DrawRectangle(saStartX - i - 2,
+                           saStartY + saEndY/2 - i,
+                           saStartX - i - 4,
+                           saStartY + saEndY/2 + i,
+                           GLCD::clrBlack, true);
+                   }
+
+                   // right volume
+                   bitmap->DrawRectangle(saEndX + 1,
+                       saStartY,
+                       bitmap->Width() - 1,
+                       saEndY + 1,
+                       GLCD::clrWhite, true);
+
+                   for ( i=0; (i<logo->Width()/2-2) && (i<3*(volumeRightChannel*saStartX)/100); i++)
+                   {
+                       bitmap->DrawRectangle(saEndX + 2 + i,
+                           saStartY + saEndY/2 - i,
+                           saEndX + i + 4,
+                           saStartY + saEndY/2 + i,
+                           GLCD::clrBlack, true);
+                   }
+               }
+               // black background
+               bitmap->DrawRectangle(saStartX,
+                   saStartY,
+                   saEndX,
+                   saEndY + 1,
+                   GLCD::clrBlack, true);
+
+               for ( i=0; i < bandsSA; i++ )
+               {
+/*                 if ( channelsSA == 2 )
+                   {
+                       bar = barHeightsLeftChannel[i];
+                       bar = barHeightsRightChannel[i];
+                   }*/
+                   if ( channelsSA == 1)
+                   {
+                       // the bar
+                       bar = (barHeights[i]*(saEndY-saStartY))/100;
+                       bitmap->DrawRectangle(saStartX + barWidth*2*(i)+ barWidth + 1,
+                           saEndY,
+                           saStartX + barWidth*2*(i) + barWidth+ barWidth + 1,
+                           saEndY - bar,
+                           GLCD::clrWhite, true);
+
+                       // the peak
+                       bar = (barPeaksBothChannels[i]*(saEndY-saStartY))/100;
+                       if ( bar > 0 )
+                       {
+                           bitmap->DrawRectangle(saStartX + barWidth*2*(i)+ barWidth + 1,
+                               saEndY - bar,
+                               saStartX + barWidth*2*(i) + barWidth+ barWidth + 1,
+                               saEndY - bar+1,
+                               GLCD::clrWhite, true);
+                       }
+                   }
+               }
+           }
+
+           delete [] barHeights;
+           delete [] barHeightsLeftChannel;
+           delete [] barHeightsRightChannel;
+           delete [] barPeaksBothChannels;
+           delete [] barPeaksLeftChannel;
+           delete [] barPeaksRightChannel;
+       }
+   }
+}
+
+//#############################################################################################
+
+
diff -Naur graphlcd-0.1.4.orig/display.h graphlcd-0.1.4/display.h
--- graphlcd-0.1.4.orig/display.h	2007-02-04 23:10:36.609384554 +0100
+++ graphlcd-0.1.4/display.h	2007-02-04 23:20:24.209000170 +0100
@@ -29,10 +29,33 @@
 #include <vdr/thread.h>
 #include <vdr/player.h>
 
+#define SPAN_CLIENT_CHECK_ID   "Span-ClientCheck-v1.0"
+#define SPAN_GET_BAR_HEIGHTS_ID "Span-GetBarHeights-v1.0"
 
 #define LCDMAXCARDS 4
 static const int kMaxTabCount = 10;
 
+struct Span_Client_Check_1_0 {
+   bool *isActive;
+   bool *isRunning;
+};
+
+struct Span_GetBarHeights_v1_0 {
+   unsigned int bands;         // number of bands to compute
+   unsigned int *barHeights;       // the heights of the bars of the two channels combined
+   unsigned int *barHeightsLeftChannel;    // the heights of the bars of the left channel
+   unsigned int *barHeightsRightChannel;   // the heights of the bars of the right channel
+   unsigned int *volumeLeftChannel;    // the volume of the left channels
+   unsigned int *volumeRightChannel;   // the volume of the right channels
+   unsigned int *volumeBothChannels;   // the combined volume of the two channels
+   const char *name;           // name of the plugin that wants to get the data
+                       // (must be unique for each client!)
+   unsigned int falloff;                   // bar falloff value
+   unsigned int *barPeaksBothChannels;     // bar peaks of the two channels combined
+   unsigned int *barPeaksLeftChannel;      // bar peaks of the left channel
+   unsigned int *barPeaksRightChannel;     // bar peaks of the right channel
+};
+ 
 enum ThreadState
 {
     Normal,
@@ -104,6 +127,7 @@
     time_t LastTime;
     time_t LastTimeCheckSym;
     time_t LastTimeModSym;
+	cTimeMs LastTimeSA;
     struct timeval CurrTimeval;
     struct timeval UpdateAt;
 
@@ -125,6 +149,7 @@
     void DisplayTextItem();
     void DisplayColorButtons();
     void DisplayVolume();
+	void DisplaySA();
 
     void UpdateIn(long usec);
     bool CheckAndUpdateSymbols();
diff -Naur graphlcd-0.1.4.orig/i18n.c graphlcd-0.1.4/i18n.c
--- graphlcd-0.1.4.orig/i18n.c	2007-02-04 23:10:38.792567843 +0100
+++ graphlcd-0.1.4/i18n.c	2007-02-04 23:23:31.966096053 +0100
@@ -966,5 +966,53 @@
 # endif
 #endif
     },
+{
+       "Show spectrum analyzer",
+       "Zeige Spectrum Analyzer",
+       "",// TODO Slovenski
+       "",// TODO Italiano
+       "",// TODO Nederlands
+       "",// TODO Portuguçês
+       "",// TODO Franais
+       "",// TODO Norsk
+       "",// TODO Suomi
+       "",// TODO Polski
+       "",// TODO Español
+       "",// TODO Ellinika
+       "",// TODO Svenska
+       "",// TODO Romnâã
+       "",// TODO Magyar
+       "",// TODO Catalàà
+#if VDRVERSNUM > 10302
+       "",// TODO Russian
+# if VDRVERSNUM > 10307
+       "",// TODO Croatian
+# endif
+#endif
+   },
+   {
+       "Show SA volume",
+       "Zeige SA Lautstrke",
+       "",// TODO Slovenski
+       "",// TODO Italiano
+       "",// TODO Nederlands
+       "",// TODO Portugus
+       "",// TODO Franêçais
+       "",// TODO Norsk
+       "",// TODO Suomi
+       "",// TODO Polski
+       "",// TODO Español
+       "",// TODO Ellinika
+       "",// TODO Svenska
+       "",// TODO Romnâã
+       "",// TODO Magyar
+       "",// TODO Catal
+#if VDRVERSNUM > 10302
+       "",// TODO Russian
+# if VDRVERSNUM > 10307
+       "",// TODO Croatian
+# endif
+#endif
+   },
     { NULL }
 };
diff -Naur graphlcd-0.1.4.orig/menu.c graphlcd-0.1.4/menu.c
--- graphlcd-0.1.4.orig/menu.c	2007-02-04 23:10:38.862563031 +0100
+++ graphlcd-0.1.4/menu.c	2007-02-04 23:24:53.710477952 +0100
@@ -101,4 +101,6 @@
     SetupStore("BrightnessActive", GraphLCDSetup.BrightnessActive = newGraphLCDSetup.BrightnessActive);
     SetupStore("BrightnessIdle", GraphLCDSetup.BrightnessIdle = newGraphLCDSetup.BrightnessIdle);
     SetupStore("BrightnessDelay", GraphLCDSetup.BrightnessDelay = newGraphLCDSetup.BrightnessDelay);
+	SetupStore("enableSpectrumAnalyzer", GraphLCDSetup.enableSpectrumAnalyzer = newGraphLCDSetup.enableSpectrumAnalyzer);
+	SetupStore("SAShowVolume", GraphLCDSetup.SAShowVolume = newGraphLCDSetup.SAShowVolume);
 }
diff -Naur graphlcd-0.1.4.orig/plugin.c graphlcd-0.1.4/plugin.c
--- graphlcd-0.1.4.orig/plugin.c	2007-02-04 23:10:38.862563031 +0100
+++ graphlcd-0.1.4/plugin.c	2007-02-04 23:26:57.655292837 +0100
@@ -54,6 +54,7 @@
     virtual cOsdObject * MainMenuAction();
     virtual cMenuSetupPage * SetupMenu();
     virtual bool SetupParse(const char * Name, const char * Value);
+	virtual bool Service(const char *Id, void *Data);
 };
 
 cPluginGraphLCD::cPluginGraphLCD()
@@ -243,8 +244,24 @@
     else if (!strcasecmp(Name, "BrightnessActive")) GraphLCDSetup.BrightnessActive = atoi(Value);
     else if (!strcasecmp(Name, "BrightnessIdle")) GraphLCDSetup.BrightnessIdle = atoi(Value);
     else if (!strcasecmp(Name, "BrightnessDelay")) GraphLCDSetup.BrightnessDelay = atoi(Value);
+	else if (!strcasecmp(Name, "enableSpectrumAnalyzer")) GraphLCDSetup.enableSpectrumAnalyzer = atoi(Value);
+	else if (!strcasecmp(Name, "SAShowVolume")) GraphLCDSetup.SAShowVolume = atoi(Value);
     else return false;
     return true;
 }
 
+bool cPluginGraphLCD::Service(const char *Id, void *Data)
+{
+   if (strcmp(Id, SPAN_CLIENT_CHECK_ID) == 0)
+   {
+       if ( GraphLCDSetup.enableSpectrumAnalyzer && (Data != NULL) )
+       {
+           *((Span_Client_Check_1_0*)Data)->isActive = true;
+       }
+       return true;
+   }
+
+   return false;
+}
+
 VDRPLUGINCREATOR(cPluginGraphLCD); // Don't touch this!
diff -Naur graphlcd-0.1.4.orig/setup.c graphlcd-0.1.4/setup.c
--- graphlcd-0.1.4.orig/setup.c	2007-02-04 23:10:38.865896137 +0100
+++ graphlcd-0.1.4/setup.c	2007-02-04 23:27:59.671030635 +0100
@@ -52,7 +52,9 @@
     ScrollTime(500),
     BrightnessActive(100),
     BrightnessIdle(100),
-    BrightnessDelay(30)
+    BrightnessDelay(30),
+	enableSpectrumAnalyzer(1),
+	SAShowVolume(1)
 {
 }
 
diff -Naur graphlcd-0.1.4.orig/setup.h graphlcd-0.1.4/setup.h
--- graphlcd-0.1.4.orig/setup.h	2007-02-04 23:10:38.865896137 +0100
+++ graphlcd-0.1.4/setup.h	2007-02-04 23:28:55.347204140 +0100
@@ -54,6 +54,8 @@
     int BrightnessActive;
     int BrightnessIdle;
     int BrightnessDelay;
+	int enableSpectrumAnalyzer;
+	int SAShowVolume;
 
 public:
     cGraphLCDSetup(void);
