video filter module - for thehomebrewAmbiLight (AtmoLight) [2/3]: atmo-video_filter...
authorAntoine Cellerier <dionoea@videolan.org>
Tue, 12 Feb 2008 22:21:25 +0000 (22:21 +0000)
committerAntoine Cellerier <dionoea@videolan.org>
Tue, 12 Feb 2008 22:21:25 +0000 (22:21 +0000)
29 files changed:
modules/video_filter/atmo/AtmoCalculations.cpp [new file with mode: 0644]
modules/video_filter/atmo/AtmoCalculations.h [new file with mode: 0644]
modules/video_filter/atmo/AtmoConfig.cpp [new file with mode: 0644]
modules/video_filter/atmo/AtmoConfig.h [new file with mode: 0644]
modules/video_filter/atmo/AtmoConnection.cpp [new file with mode: 0644]
modules/video_filter/atmo/AtmoConnection.h [new file with mode: 0644]
modules/video_filter/atmo/AtmoDefs.h [new file with mode: 0644]
modules/video_filter/atmo/AtmoDynData.cpp [new file with mode: 0644]
modules/video_filter/atmo/AtmoDynData.h [new file with mode: 0644]
modules/video_filter/atmo/AtmoExternalCaptureInput.cpp [new file with mode: 0644]
modules/video_filter/atmo/AtmoExternalCaptureInput.h [new file with mode: 0644]
modules/video_filter/atmo/AtmoInput.cpp [new file with mode: 0644]
modules/video_filter/atmo/AtmoInput.h [new file with mode: 0644]
modules/video_filter/atmo/AtmoLiveView.cpp [new file with mode: 0644]
modules/video_filter/atmo/AtmoLiveView.h [new file with mode: 0644]
modules/video_filter/atmo/AtmoOutputFilter.cpp [new file with mode: 0644]
modules/video_filter/atmo/AtmoOutputFilter.h [new file with mode: 0644]
modules/video_filter/atmo/AtmoSerialConnection.cpp [new file with mode: 0644]
modules/video_filter/atmo/AtmoSerialConnection.h [new file with mode: 0644]
modules/video_filter/atmo/AtmoThread.cpp [new file with mode: 0644]
modules/video_filter/atmo/AtmoThread.h [new file with mode: 0644]
modules/video_filter/atmo/AtmoTools.cpp [new file with mode: 0644]
modules/video_filter/atmo/AtmoTools.h [new file with mode: 0644]
modules/video_filter/atmo/AtmoZoneDefinition.cpp [new file with mode: 0644]
modules/video_filter/atmo/AtmoZoneDefinition.h [new file with mode: 0644]
modules/video_filter/atmo/COPYING.txt [new file with mode: 0644]
modules/video_filter/atmo/Modules.am [new file with mode: 0644]
modules/video_filter/atmo/README.txt [new file with mode: 0644]
modules/video_filter/atmo/atmo.cpp [new file with mode: 0644]

diff --git a/modules/video_filter/atmo/AtmoCalculations.cpp b/modules/video_filter/atmo/AtmoCalculations.cpp
new file mode 100644 (file)
index 0000000..b8d4443
--- /dev/null
@@ -0,0 +1,461 @@
+/*
+ * calculations.c: calculations needed by the input devices
+ *
+ * See the README file for copyright information and how to reach the author.
+ *
+ * $Id$
+ */
+#include <stdlib.h>
+#include <string.h>
+
+
+#include "AtmoDefs.h"
+#include "AtmoCalculations.h"
+#include "AtmoConfig.h"
+#include "AtmoZoneDefinition.h"
+
+
+// set accuracy of color calculation
+#define h_MAX   255
+#define s_MAX   255
+#define v_MAX   255
+
+// macros
+#define MIN(X, Y)  ((X) < (Y) ? (X) : (Y))
+#define MAX(X, Y)  ((X) > (Y) ? (X) : (Y))
+#define POS_DIV(a, b)  ( (a)/(b) + ( ((a)%(b) >= (b)/2 ) ? 1 : 0) )
+
+tColorPacket CalcColorsAnalyzeHSV(CAtmoConfig *pAtmoConfig, tHSVColor *HSV_Img)
+{
+  int i; // counter
+
+  // static tWeightPacket Weight[IMAGE_SIZE];
+  // Flip instead having a array with (64x48) entries of values for each channel
+  // I have x arrays of 64x48 so each channel has its own array...
+  // (or gradient which is use to judge about the pixels)
+  static int Weight[ATMO_NUM_CHANNELS][IMAGE_SIZE];
+
+  /***************************************************************************/
+  /* Weight                                                                  */
+  /***************************************************************************/
+  static int LastEdgeWeighting = -1;
+  static int LastWidescreenMode = -1;
+
+  int AtmoSetup_EdgeWeighting  = pAtmoConfig->getLiveView_EdgeWeighting();
+  int AtmoSetup_WidescreenMode = pAtmoConfig->getLiveView_WidescreenMode();
+  int AtmoSetup_DarknessLimit  = pAtmoConfig->getLiveView_DarknessLimit();
+  int AtmoSetup_BrightCorrect  = pAtmoConfig->getLiveView_BrightCorrect();
+  int AtmoSetup_SatWinSize     = pAtmoConfig->getLiveView_SatWinSize();
+
+
+  // calculate only if setup has changed
+  if ((AtmoSetup_EdgeWeighting != LastEdgeWeighting) ||
+      (AtmoSetup_WidescreenMode != LastWidescreenMode))
+  {
+     for(i =0 ;i < ATMO_NUM_CHANNELS; i++)
+         pAtmoConfig->getZoneDefinition(i)->UpdateWeighting(&Weight[i][0],
+                                                            AtmoSetup_WidescreenMode,
+                                                            AtmoSetup_EdgeWeighting);
+    /*
+
+    original code from VDR sources... my one is just more flexible?*g*
+
+       i = 0;
+    for (int row = 0; row < CAP_HEIGHT; row++)
+    {
+         float row_norm = (float)row / ((float)CAP_HEIGHT - 1.0f);       // [0;Height] -> [0;1]
+         float weight_3 = pow(1.0f - row_norm, AtmoSetup_EdgeWeighting); // top
+         float weight_4 = pow(row_norm, AtmoSetup_EdgeWeighting);       // bottom
+
+      for (int column = 0; column < CAP_WIDTH; column++)
+      {
+        // if widescreen mode, top and bottom of the picture are not
+        if ((AtmoSetup_WidescreenMode == 1) && ((row <= CAP_HEIGHT/8) || (row >= (7*CAP_HEIGHT)/8)))
+        {
+          Weight[i].channel[0] = Weight[i].channel[1] = Weight[i].channel[2] = Weight[i].channel[3] = Weight[i].channel[4] = 0;
+        }
+        else
+        {
+          float column_norm = (float)column / ((float)CAP_WIDTH - 1.0f); // [0;Width] -> [0;1]
+                 Weight[i].channel[0] = 255;
+                 Weight[i].channel[1] = (int)(255.0 * (float)pow((1.0 - column_norm), AtmoSetup_EdgeWeighting));
+                 Weight[i].channel[2] = (int)(255.0 * (float)pow(column_norm, AtmoSetup_EdgeWeighting));
+          Weight[i].channel[3] = (int)(255.0 * (float)weight_3);
+          Weight[i].channel[4] = (int)(255.0 * (float)weight_4);
+        }
+        i++;
+      }
+    }
+    */
+       LastEdgeWeighting = AtmoSetup_EdgeWeighting;
+    LastWidescreenMode = AtmoSetup_WidescreenMode;
+  }
+
+  /***************************************************************************/
+  /* Hue                                                                     */
+  /***************************************************************************/
+
+  /*----------------------------*/
+  /* hue histogram builtup      */
+  /*----------------------------*/
+  // HSV histogram
+  long int hue_hist[ATMO_NUM_CHANNELS][h_MAX+1];
+  // clean histogram
+  memset(&hue_hist, 0, sizeof(hue_hist));
+
+  i = 0;
+  for (int row = 0; row < CAP_HEIGHT; row++)
+  {
+    for (int column = 0; column < CAP_WIDTH; column++)
+    {
+      // forget black bars: perform calculations only if pixel has some luminosity
+         if (HSV_Img[i].v > 10*AtmoSetup_DarknessLimit)
+      {
+        // builtup histogram for the 5 channels
+        for (int channel = 0; channel < ATMO_NUM_CHANNELS; channel++)
+        {
+          // Add weight to channel
+          hue_hist[channel][HSV_Img[i].h] += Weight[channel][i] * HSV_Img[i].v;
+        }
+      }
+      i++;
+    }
+  }
+
+  /*----------------------------*/
+  /* hue histogram windowing    */
+  /*----------------------------*/
+  // windowed HSV histogram
+  long int w_hue_hist[ATMO_NUM_CHANNELS][h_MAX+1];
+  // clean windowed histogram
+  memset(&w_hue_hist, 0, sizeof(w_hue_hist));
+  // steps in each direction; eg. 2 => -2 -1 0 1 2 windowing
+  int hue_windowsize = pAtmoConfig->getLiveView_HueWinSize();
+
+  for (i = 0; i < h_MAX+1; i++) // walk through histogram [0;h_MAX]
+  {
+    // windowing from -hue_windowsize -> +hue_windowsize
+    for (int mywin = -hue_windowsize; mywin < hue_windowsize+1; mywin++)
+    {
+      // adressed histogram candlestick
+      int myidx = i + mywin;
+
+      // handle beginning of windowing -> roll back
+      if (myidx < 0)     { myidx = myidx + h_MAX + 1; }
+
+      // handle end of windowing -> roll forward
+      if (myidx > h_MAX) { myidx = myidx - h_MAX - 1; }
+
+      // Apply windowing to all 5 channels
+      for (int channel = 0; channel < ATMO_NUM_CHANNELS; channel++)
+      {
+        // apply lite triangular window design with gradient of 10% per discrete step
+        w_hue_hist[channel][i] += hue_hist[channel][myidx] * ((hue_windowsize+1)-abs(mywin)); // apply window
+      }
+    }
+  }
+
+  /*--------------------------------------*/
+  /* analyze histogram for most used hue  */
+  /*--------------------------------------*/
+  // index of last maximum
+  static int most_used_hue_last[ATMO_NUM_CHANNELS] = {0, 0, 0, 0, 0};
+
+  // resulting hue for each channel
+  int most_used_hue[ATMO_NUM_CHANNELS];
+  memset(&most_used_hue, 0, sizeof(most_used_hue));
+
+  for (int channel = 0; channel < ATMO_NUM_CHANNELS; channel++)
+  {
+    int value = 0;
+    for (i = 0; i < h_MAX+1; i++) // walk through histogram
+    {
+      if (w_hue_hist[channel][i] > value) // if new value bigger then old one
+      {
+        most_used_hue[channel] = i;     // remember index
+        value = w_hue_hist[channel][i]; // and value
+      }
+    }
+
+    float percent = (float)w_hue_hist[channel][most_used_hue_last[channel]] / (float)value;
+    if (percent > 0.93f) // less than 7% difference?
+    {
+      most_used_hue[channel] = most_used_hue_last[channel]; // use last index
+    }
+    most_used_hue_last[channel] = most_used_hue[channel]; // save current index of most used hue
+  }
+
+  /***************************************************************************/
+  /* saturation                                                              */
+  /***************************************************************************/
+  // sat histogram
+  long int sat_hist[ATMO_NUM_CHANNELS][s_MAX+1];
+  // hue of the pixel we are working at
+  int pixel_hue = 0;
+  // clean histogram
+  memset(&sat_hist, 0, sizeof(sat_hist));
+
+  /*--------------------------------------*/
+  /* saturation histogram builtup         */
+  /*--------------------------------------*/
+  i = 0;
+  for (int row = 0; row < CAP_HEIGHT; row++)
+  {
+    for (int column = 0; column < CAP_WIDTH; column++)
+    {
+      // forget black bars: perform calculations only if pixel has some luminosity
+         if (HSV_Img[i].v > 10*AtmoSetup_DarknessLimit)
+      {
+        // find histogram position for pixel
+        pixel_hue = HSV_Img[i].h;
+
+        // TODO:   brightness calculation(if we require it some time)
+
+        for (int channel = 0; channel < ATMO_NUM_CHANNELS; channel++)
+        {
+          // only use pixel for histogram if hue is near most_used_hue
+          if ((pixel_hue > most_used_hue[channel] - hue_windowsize) &&
+              (pixel_hue < most_used_hue[channel] + hue_windowsize))
+          {
+            // build histogram
+            // sat_hist[channel][HSV_Img[i].s] += Weight[i].channel[channel] * HSV_Img[i].v;
+            sat_hist[channel][HSV_Img[i].s] += Weight[channel][i] * HSV_Img[i].v;
+          }
+        }
+      }
+      i++;
+    }
+  }
+
+  /*--------------------------------------*/
+  /* saturation histogram windowing       */
+  /*--------------------------------------*/
+   // windowed HSV histogram
+   long int w_sat_hist[ATMO_NUM_CHANNELS][s_MAX+1];
+   // clean windowed histogram
+   memset(&w_sat_hist, 0, sizeof(w_sat_hist));
+   // steps in each direction; eg. 2 => -2 -1 0 1 2 windowing
+   int sat_windowsize = AtmoSetup_SatWinSize;
+
+   // walk through histogram [0;h_MAX]
+   for (i = 0; i < s_MAX + 1; i++)
+   {
+     // windowing from -hue_windowsize -> +hue_windowsize
+     for (int mywin = -sat_windowsize; mywin < sat_windowsize+1; mywin++)
+     {
+       // adressed histogram candlestick
+       int myidx = i + mywin;
+
+       // handle beginning of windowing -> roll back
+       if (myidx < 0)     { myidx = myidx + s_MAX + 1; }
+
+       // handle end of windowing -> roll forward
+       if (myidx > h_MAX) { myidx = myidx - s_MAX - 1; }
+
+       for (int channel = 0; channel < ATMO_NUM_CHANNELS; channel++)
+       {
+         /*
+            apply lite triangular window design with
+            gradient of 10% per discrete step
+         */
+         w_sat_hist[channel][i] += sat_hist[channel][myidx] *
+                                  ((sat_windowsize+1)-abs(mywin)); // apply window
+       }
+     }
+   }
+
+  /*--------------------------------------*/
+  /* analyze histogram for most used sat  */
+  /*--------------------------------------*/
+   // resulting sat (most_used_hue) for each channel
+  int most_used_sat[ATMO_NUM_CHANNELS];
+  memset(&most_used_sat, 0, sizeof(most_used_sat));
+
+  for (int channel = 0; channel < ATMO_NUM_CHANNELS; channel++)
+  {
+    int value = 0;
+    // walk trough histogram
+    for (i = 0; i < s_MAX+1; i++)
+    {
+      // if new value bigger then old one
+      if (w_sat_hist[channel][i] > value)
+      {
+        // remember index
+        most_used_sat[channel] = i;
+        // and value
+        value = w_sat_hist[channel][i];
+      }
+    }
+  }
+
+  /*----------------------------------------------------------*/
+  /* calculate average brightness within HSV image            */
+  /* uniform Brightness for all channels is calculated        */
+  /*----------------------------------------------------------*/
+  int l_counter = 0;
+  // average brightness (value)
+  long int value_avg = 0;
+
+  // TODO: extract into a function? in sat-histo-built
+
+  i = 0;
+  for (int row = 0; row < CAP_HEIGHT; row++)
+  {
+    for (int column = 0; column < CAP_WIDTH; column++)
+    {
+      // find average value: only use bright pixels for luminance average
+         if (HSV_Img[i].v > 10*AtmoSetup_DarknessLimit)
+      {
+        // build brightness average
+        value_avg += HSV_Img[i].v;
+        l_counter++;
+      }
+      i++;
+    }
+  }
+
+  // calculate brightness average
+  if (l_counter > 0) { value_avg = value_avg / l_counter; }
+    else { value_avg = 10 * AtmoSetup_DarknessLimit; }
+
+  /*----------------------------*/
+  /* adjust and copy results    */
+  /*----------------------------*/
+  tHSVColor hsv_pixel;
+  // storage container for resulting RGB values
+  tColorPacket ColorChannels;
+
+  for (int channel = 0; channel < ATMO_NUM_CHANNELS; channel++)
+  {
+    // copy values
+    hsv_pixel.h = most_used_hue[channel];
+    hsv_pixel.s = most_used_sat[channel];
+
+    // adjust brightness
+    int new_value = (int) ((float)value_avg * ((float)AtmoSetup_BrightCorrect / 100.0));
+    if (new_value > 255) { new_value = 255; } // ensure brightness isn't set too high
+    hsv_pixel.v = (unsigned char)new_value;
+
+    // convert back to rgb
+    ColorChannels.channel[channel] = HSV2RGB(hsv_pixel);
+  }
+  return ColorChannels;
+}
+
+tHSVColor RGB2HSV(tRGBColor color)
+{
+ int min, max, delta;
+ int r, g, b;
+ int h = 0;
+ tHSVColor hsv;
+
+ r = color.r;
+ g = color.g;
+ b = color.b;
+
+ min = MIN(MIN(r, g), b);
+ max = MAX(MAX(r, g), b);
+
+ delta = max - min;
+
+ hsv.v = (unsigned char) POS_DIV( max*v_MAX, 255 );
+
+ if (delta == 0) // This is a gray, no chroma...
+ {
+   h = 0;        // HSV results = 0 / 1
+   hsv.s = 0;
+ }
+ else // Chromatic data...
+ {
+   hsv.s = (unsigned char) POS_DIV( (delta*s_MAX) , max );
+
+   int dr = (max - r) + 3*delta;
+   int dg = (max - g) + 3*delta;
+   int db = (max - b) + 3*delta;
+   int divisor = 6*delta;
+
+   if (r == max)
+   {
+     h = POS_DIV(( (db - dg) * h_MAX ) , divisor);
+   }
+   else if (g == max)
+   {
+     h = POS_DIV( ((dr - db) * h_MAX) , divisor) + (h_MAX/3);
+   }
+   else if (b == max)
+   {
+     h = POS_DIV(( (dg - dr) * h_MAX) , divisor) + (h_MAX/3)*2;
+   }
+
+   if ( h < 0 )     { h += h_MAX; }
+   if ( h > h_MAX ) { h -= h_MAX; }
+ }
+ hsv.h = (unsigned char)h;
+
+ return hsv;
+}
+
+tRGBColor HSV2RGB(tHSVColor color)
+{
+ tRGBColor rgb = {0, 0, 0};
+
+ float h = (float)color.h/(float)h_MAX;
+ float s = (float)color.s/(float)s_MAX;
+ float v = (float)color.v/(float)v_MAX;
+
+ if (s == 0)
+ {
+   rgb.r = (int)((v*255.0)+0.5);
+   rgb.g = rgb.r;
+   rgb.b = rgb.r;
+ }
+ else
+ {
+   h = h * 6.0f;
+   if (h == 6.0) { h = 0.0; }
+   int i = (int)h;
+
+   float f = h - i;
+   float p = v*(1.0f-s);
+   float q = v*(1.0f-(s*f));
+   float t = v*(1.0f-(s*(1.0f-f)));
+
+   if (i == 0)
+   {
+     rgb.r = (int)((v*255.0)+0.5);
+     rgb.g = (int)((t*255.0)+0.5);
+     rgb.b = (int)((p*255.0)+0.5);
+   }
+   else if (i == 1)
+   {
+     rgb.r = (int)((q*255.0)+0.5);
+     rgb.g = (int)((v*255.0)+0.5);
+     rgb.b = (int)((p*255.0)+0.5);
+   }
+   else if (i == 2)
+   {
+     rgb.r = (int)((p*255.0)+0.5);
+     rgb.g = (int)((v*255.0)+0.5);
+     rgb.b = (int)((t*255.0)+0.5);
+   }
+   else if (i == 3)
+   {
+     rgb.r = (int)((p*255.0)+0.5);
+     rgb.g = (int)((q*255.0)+0.5);
+     rgb.b = (int)((v*255.0)+0.5);
+   }
+   else if (i == 4)
+   {
+     rgb.r = (int)((t*255.0)+0.5);
+     rgb.g = (int)((p*255.0)+0.5);
+     rgb.b = (int)((v*255.0)+0.5);
+   }
+   else
+   {
+     rgb.r = (int)((v*255.0)+0.5);
+     rgb.g = (int)((p*255.0)+0.5);
+     rgb.b = (int)((q*255.0)+0.5);
+   }
+ }
+ return rgb;
+}
diff --git a/modules/video_filter/atmo/AtmoCalculations.h b/modules/video_filter/atmo/AtmoCalculations.h
new file mode 100644 (file)
index 0000000..e825803
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * AtmoCalculations.h: see calculations.h of the linux version... one to one copy
+ * calculations.h: calculations needed by the input devices
+ *
+ * See the README.txt file for copyright information and how to reach the author(s).
+ *
+ * $Id$
+ */
+
+#ifndef _AtmoCalculations_h_
+#define _AtmoCalculations_h_
+
+#include "AtmoDefs.h"
+#include "AtmoConfig.h"
+
+
+tColorPacket CalcColorsAnalyzeHSV(CAtmoConfig *pAtmoConfig, tHSVColor *HSV_Img);
+
+tHSVColor RGB2HSV(tRGBColor color);
+tRGBColor HSV2RGB(tHSVColor color);
+
+#endif
diff --git a/modules/video_filter/atmo/AtmoConfig.cpp b/modules/video_filter/atmo/AtmoConfig.cpp
new file mode 100644 (file)
index 0000000..9c22d8e
--- /dev/null
@@ -0,0 +1,252 @@
+/*
+ * AtmoConfig.cpp: Class for holding all configuration values of AtmoWin - stores
+ * the values and retrieves its values from registry
+ *
+ * See the README.txt file for copyright information and how to reach the author(s).
+ *
+ * $Id$
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "AtmoConfig.h"
+
+/* Import Hint
+
+   if somebody Adds new config option this has to be done in the following
+   files and includes!
+
+   AtmoConfig.h  -- extend class definition!, and add get... and set... Methods!
+                    so that the real variables are still hidden inside the class!
+   AtmoConfigRegistry.cpp --> SaveToRegistry();
+   AtmoConfigRegistry.cpp --> LoadFromRegistry();
+   AtmoConfig.cpp --> Assign( ... );
+
+*/
+
+CAtmoConfig::CAtmoConfig()
+{
+  // setup basic configruation structures...
+  m_IsShowConfigDialog = 0;
+  m_eAtmoConnectionType = actSerialPort;
+  for(int i=0;i<10;i++)
+      m_ChannelAssignments[i] = NULL;
+#if defined (_ATMO_VLC_PLUGIN_)
+  m_devicename = NULL;
+#endif
+  // load all config values with there defaults
+  LoadDefaults();
+
+  //   CAtmoZoneDefinition *m_ZoneDefinitions[ATMO_NUM_CHANNELS];
+  // generate default channel parameters which may be loaded later from .bmp files
+  for(int i=0;i<ATMO_NUM_CHANNELS;i++) {
+      m_ZoneDefinitions[i] = new CAtmoZoneDefinition();
+      m_ZoneDefinitions[i]->setZoneNumber(i);
+      switch(i) {
+          case 0:  // summary channel
+              m_ZoneDefinitions[i]->Fill(255);
+              break;
+          case 1: // left channel
+              m_ZoneDefinitions[i]->FillGradientFromLeft();
+              break;
+          case 2: // right channel
+              m_ZoneDefinitions[i]->FillGradientFromRight();
+              break;
+          case 3: // top channel
+              m_ZoneDefinitions[i]->FillGradientFromTop();
+              break;
+          case 4: // bottom channel
+              m_ZoneDefinitions[i]->FillGradientFromBottom();
+              break;
+      }
+  }
+}
+
+CAtmoConfig::~CAtmoConfig() {
+   // and finally cleanup...
+   clearAllChannelMappings();
+#if !defined (WIN32)
+   if(m_devicename)
+      free(m_devicename);
+#endif
+}
+
+void CAtmoConfig::LoadDefaults() {
+    //    m_eAtmoConnectionType = actSerialPort;
+    //    m_Comport
+
+    m_eEffectMode = emDisabled;
+
+    m_WhiteAdjustment_Red    = 255;
+    m_WhiteAdjustment_Green  = 255;
+    m_WhiteAdjustment_Blue   = 255;
+       m_UseSoftwareWhiteAdj    = 1;
+
+       m_ColorChanger_iSteps    = 50;
+       m_ColorChanger_iDelay    = 25;
+
+       m_LrColorChanger_iSteps  = 50;
+       m_LrColorChanger_iDelay  = 25;
+
+    m_IsSetShutdownColor     = 1;
+       m_ShutdownColor_Red      = 0;
+       m_ShutdownColor_Green    = 0;
+       m_ShutdownColor_Blue     = 0;
+
+    m_StaticColor_Red        = 127; // ??
+    m_StaticColor_Green      = 192;
+    m_StaticColor_Blue       = 255;
+
+    m_LiveViewFilterMode         = afmCombined;
+    m_LiveViewFilter_PercentNew  = 50;
+    m_LiveViewFilter_MeanLength  = 300;
+    m_LiveViewFilter_MeanThreshold   = 40;
+
+    m_LiveView_EdgeWeighting  = 8;
+    m_LiveView_BrightCorrect  = 100;
+    m_LiveView_DarknessLimit  = 5;
+    m_LiveView_HueWinSize     = 3;
+    m_LiveView_SatWinSize     = 3;
+    m_LiveView_WidescreenMode = 0;
+
+    m_LiveView_HOverscanBorder  = 0;
+    m_LiveView_VOverscanBorder  = 0;
+    m_LiveView_DisplayNr        = 0;
+    m_LiveView_FrameDelay       = 0;
+
+
+    m_Hardware_global_gamma    = 128;
+    m_Hardware_global_contrast = 100;
+    m_Hardware_contrast_red    = 100;
+    m_Hardware_contrast_green  = 100;
+    m_Hardware_contrast_blue   = 100;
+
+    m_Hardware_gamma_red       = 22;
+    m_Hardware_gamma_green     = 22;
+    m_Hardware_gamma_blue      = 22;
+
+    clearAllChannelMappings();
+    m_CurrentChannelAssignment = 0;
+    tChannelAssignment *temp = temp = new tChannelAssignment;
+    temp->system = true;
+    for(int i=0;i<ATMO_NUM_CHANNELS;i++)
+        temp->mappings[i] = i;
+    strcpy(temp->name,"Standard");
+    this->m_ChannelAssignments[0] =  temp;
+}
+
+void CAtmoConfig::Assign(CAtmoConfig *pAtmoConfigSrc) {
+
+#if defined(_ATMO_VLC_PLUGIN_)
+    this->setSerialDevice(pAtmoConfigSrc->getSerialDevice());
+#else
+    this->m_Comport                  = pAtmoConfigSrc->m_Comport;
+#endif
+
+    this->m_eAtmoConnectionType      = pAtmoConfigSrc->m_eAtmoConnectionType;
+    this->m_eEffectMode              = pAtmoConfigSrc->m_eEffectMode;
+
+    this->m_WhiteAdjustment_Red      = pAtmoConfigSrc->m_WhiteAdjustment_Red;
+    this->m_WhiteAdjustment_Green    = pAtmoConfigSrc->m_WhiteAdjustment_Green;
+    this->m_WhiteAdjustment_Blue     = pAtmoConfigSrc->m_WhiteAdjustment_Blue;
+    this->m_UseSoftwareWhiteAdj      = pAtmoConfigSrc->m_UseSoftwareWhiteAdj;
+
+    this->m_IsSetShutdownColor       = pAtmoConfigSrc->m_IsSetShutdownColor;
+    this->m_ShutdownColor_Red        = pAtmoConfigSrc->m_ShutdownColor_Red;
+    this->m_ShutdownColor_Green      = pAtmoConfigSrc->m_ShutdownColor_Green;
+    this->m_ShutdownColor_Blue       = pAtmoConfigSrc->m_ShutdownColor_Blue;
+
+    this->m_ColorChanger_iSteps      = pAtmoConfigSrc->m_ColorChanger_iSteps;
+    this->m_ColorChanger_iDelay      = pAtmoConfigSrc->m_ColorChanger_iDelay;
+
+    this->m_LrColorChanger_iSteps    = pAtmoConfigSrc->m_LrColorChanger_iSteps;
+    this->m_LrColorChanger_iDelay    = pAtmoConfigSrc->m_LrColorChanger_iDelay;
+
+    this->m_StaticColor_Red          = pAtmoConfigSrc->m_StaticColor_Red;
+    this->m_StaticColor_Green        = pAtmoConfigSrc->m_StaticColor_Green;
+    this->m_StaticColor_Blue         = pAtmoConfigSrc->m_StaticColor_Blue;
+
+    this->m_LiveViewFilterMode             = pAtmoConfigSrc->m_LiveViewFilterMode;
+    this->m_LiveViewFilter_PercentNew      = pAtmoConfigSrc->m_LiveViewFilter_PercentNew;
+    this->m_LiveViewFilter_MeanLength      = pAtmoConfigSrc->m_LiveViewFilter_MeanLength;
+    this->m_LiveViewFilter_MeanThreshold   = pAtmoConfigSrc->m_LiveViewFilter_MeanThreshold;
+
+
+    this->m_LiveView_EdgeWeighting  =  pAtmoConfigSrc->m_LiveView_EdgeWeighting;
+    this->m_LiveView_BrightCorrect  =  pAtmoConfigSrc->m_LiveView_BrightCorrect;
+    this->m_LiveView_DarknessLimit  =  pAtmoConfigSrc->m_LiveView_DarknessLimit;
+    this->m_LiveView_HueWinSize     =  pAtmoConfigSrc->m_LiveView_HueWinSize;
+    this->m_LiveView_SatWinSize     =  pAtmoConfigSrc->m_LiveView_SatWinSize;
+    this->m_LiveView_WidescreenMode =  pAtmoConfigSrc->m_LiveView_WidescreenMode;
+
+    this->m_LiveView_HOverscanBorder  = pAtmoConfigSrc->m_LiveView_HOverscanBorder;
+    this->m_LiveView_VOverscanBorder  = pAtmoConfigSrc->m_LiveView_VOverscanBorder;
+    this->m_LiveView_DisplayNr        = pAtmoConfigSrc->m_LiveView_DisplayNr;
+    this->m_LiveView_FrameDelay       = pAtmoConfigSrc->m_LiveView_FrameDelay;
+
+    clearChannelMappings();
+    for(int i=1;i<pAtmoConfigSrc->getNumChannelAssignments();i++) {
+        tChannelAssignment *ta = pAtmoConfigSrc->m_ChannelAssignments[i];
+        if(ta!=NULL) {
+            tChannelAssignment *dest = this->m_ChannelAssignments[i];
+            if(dest == NULL) {
+               dest = new tChannelAssignment;
+               this->m_ChannelAssignments[i] = dest;
+            }
+            memcpy(dest, ta, sizeof(tChannelAssignment));
+        }
+    }
+}
+
+
+
+int CAtmoConfig::getNumChannelAssignments() {
+    int z=0;
+    for(int i=0;i<10;i++)
+        if(this->m_ChannelAssignments[i]!=NULL) z++;
+    return z;
+}
+
+void CAtmoConfig::clearChannelMappings() {
+    for(int i=1;i<10;i++) {
+        tChannelAssignment *ca = m_ChannelAssignments[i];
+        if(ca!=NULL)
+           delete ca;
+        m_ChannelAssignments[i] = NULL;
+    }
+}
+
+void CAtmoConfig::clearAllChannelMappings() {
+    for(int i=0;i<10;i++) {
+        tChannelAssignment *ca = m_ChannelAssignments[i];
+        if(ca!=NULL)
+           delete ca;
+        m_ChannelAssignments[i] = NULL;
+    }
+}
+
+void CAtmoConfig::AddChannelAssignment(tChannelAssignment *ta) {
+    for(int i=0;i<10;i++) {
+        if(m_ChannelAssignments[i] == NULL) {
+           m_ChannelAssignments[i] = ta;
+           break;
+        }
+    }
+}
+
+void CAtmoConfig::SetChannelAssignment(int index, tChannelAssignment *ta) {
+     if(m_ChannelAssignments[index]!=NULL)
+        delete m_ChannelAssignments[index];
+     m_ChannelAssignments[index] = ta;
+}
+
+CAtmoZoneDefinition *CAtmoConfig::getZoneDefinition(int zoneIndex) {
+    if(zoneIndex < 0)
+       return NULL;
+    if(zoneIndex >= ATMO_NUM_CHANNELS)
+       return NULL;
+    return m_ZoneDefinitions[zoneIndex];
+
+}
+
diff --git a/modules/video_filter/atmo/AtmoConfig.h b/modules/video_filter/atmo/AtmoConfig.h
new file mode 100644 (file)
index 0000000..7d3b6d6
--- /dev/null
@@ -0,0 +1,269 @@
+/*
+ * AtmoConfig.h: Class for holding all configuration values of AtmoWin
+ *
+ * See the README.txt file for copyright information and how to reach the author(s).
+ *
+ * $Id$
+ */
+
+#ifndef _AtmoConfig_h_
+#define _AtmoConfig_h_
+
+#include "AtmoDefs.h"
+#include "AtmoZoneDefinition.h"
+
+#if defined(_ATMO_VLC_PLUGIN_)
+#   include <stdlib.h>
+#   include <string.h>
+#endif
+
+
+class CAtmoConfig {
+
+    protected:
+          int m_IsShowConfigDialog;    
+#if defined(_ATMO_VLC_PLUGIN_)
+       char *m_devicename;
+#else
+          int m_Comport;
+#endif
+       enum AtmoConnectionType m_eAtmoConnectionType;
+       enum EffectMode m_eEffectMode;
+
+    protected:
+       ATMO_BOOL m_UseSoftwareWhiteAdj;
+       int m_WhiteAdjustment_Red;
+       int m_WhiteAdjustment_Green;
+       int m_WhiteAdjustment_Blue;
+
+    protected:
+       int m_IsSetShutdownColor;
+          int m_ShutdownColor_Red;
+          int m_ShutdownColor_Green;
+          int m_ShutdownColor_Blue;
+
+    protected:
+       /* Config Values for Color Changer */
+       int m_ColorChanger_iSteps;
+       int m_ColorChanger_iDelay;
+
+    protected:
+        /* Config  values for the primitive Left Right Color Changer */
+       int m_LrColorChanger_iSteps;
+       int m_LrColorChanger_iDelay;
+
+    protected:
+       /* the static background color */
+       int m_StaticColor_Red;
+       int m_StaticColor_Green;
+       int m_StaticColor_Blue;
+
+    protected:
+        /*
+           one for System + 9 for userdefined channel
+           assignments (will it be enough?)
+        */
+        tChannelAssignment *m_ChannelAssignments[10];
+        int m_CurrentChannelAssignment;
+
+    protected:
+        CAtmoZoneDefinition *m_ZoneDefinitions[ATMO_NUM_CHANNELS];
+
+
+    protected:
+        /* Live View Parameters (most interesting) */
+        AtmoFilterMode m_LiveViewFilterMode;
+        int m_LiveViewFilter_PercentNew;
+        int m_LiveViewFilter_MeanLength;
+        int m_LiveViewFilter_MeanThreshold;
+
+        // weighting of distance to edge
+        int m_LiveView_EdgeWeighting; //  = 8;
+        // brightness correction
+        int m_LiveView_BrightCorrect; //  = 100;
+        // darkness limit (pixels below this value will be ignored)
+        int m_LiveView_DarknessLimit; //  = 5;
+        // Windowing size for hue histogram building
+        int m_LiveView_HueWinSize;    //  = 3;
+        // Windowing size for sat histogram building
+        int m_LiveView_SatWinSize;    //  = 3;
+        /*
+          special (hack) for ignorning black borders durring
+          playback of letterboxed material on a 16:9 output device
+        */
+        int m_LiveView_WidescreenMode; // = 0
+
+        // border from source image which should be ignored
+        // the values are only used by the Win32 GDI Screen capture
+        int m_LiveView_HOverscanBorder;
+        int m_LiveView_VOverscanBorder;
+        int m_LiveView_DisplayNr;
+
+        /*
+           a special delay to get the light in sync with the video
+           was required because the frames will pass my VLC filter some [ms]
+           before they become visible on screen with this delay - screenoutput
+           and light timing could be "synchronized"
+        */
+        int m_LiveView_FrameDelay;
+
+    protected:
+         /* values of the last hardware white adjustment (only for hardware with new firmware) */
+         int m_Hardware_global_gamma;
+         int m_Hardware_global_contrast;
+         int m_Hardware_contrast_red;
+         int m_Hardware_contrast_green;
+         int m_Hardware_contrast_blue;
+         int m_Hardware_gamma_red;
+         int m_Hardware_gamma_green;
+         int m_Hardware_gamma_blue;
+
+    public:
+       CAtmoConfig();
+       virtual ~CAtmoConfig();
+       virtual void SaveSettings() {}
+       virtual void LoadSettings() {};
+       void LoadDefaults();
+
+       /*
+         function to copy  the values of one configuration object to another
+         will be used in windows settings dialog as backup if the user
+         presses cancel
+       */
+       void Assign(CAtmoConfig *pAtmoConfigSrc);
+
+    public:
+        int isShowConfigDialog()            { return m_IsShowConfigDialog; }
+        void setShowConfigDialog(int value) { m_IsShowConfigDialog = value; }
+
+#if defined(_ATMO_VLC_PLUGIN_)
+        char *getSerialDevice()               { return m_devicename; }
+        void setSerialDevice(char *newdevice) { if(m_devicename) free(m_devicename); if(newdevice) m_devicename = strdup(newdevice); else m_devicename = NULL; }
+#else
+        int getComport()                    { return m_Comport; }
+        void setComport(int value)          { m_Comport = value; }
+#endif
+
+        int getWhiteAdjustment_Red() { return m_WhiteAdjustment_Red;  }
+        void setWhiteAdjustment_Red(int value) { m_WhiteAdjustment_Red = value; }
+        int getWhiteAdjustment_Green() { return m_WhiteAdjustment_Green;  }
+        void setWhiteAdjustment_Green(int value) { m_WhiteAdjustment_Green = value; }
+        int getWhiteAdjustment_Blue() { return m_WhiteAdjustment_Blue;  }
+        void setWhiteAdjustment_Blue(int value) { m_WhiteAdjustment_Blue = value; }
+        ATMO_BOOL isUseSoftwareWhiteAdj() { return m_UseSoftwareWhiteAdj; }
+        void setUseSoftwareWhiteAdj(ATMO_BOOL value) { m_UseSoftwareWhiteAdj = value; }
+
+        int isSetShutdownColor()     { return m_IsSetShutdownColor; }
+        void SetSetShutdownColor(int value) { m_IsSetShutdownColor = value; }
+        int getShutdownColor_Red()   { return m_ShutdownColor_Red; }
+        void setShutdownColor_Red(int value) { m_ShutdownColor_Red = value; }
+        int getShutdownColor_Green() { return m_ShutdownColor_Green; }
+        void setShutdownColor_Green(int value) { m_ShutdownColor_Green = value; }
+        int getShutdownColor_Blue()  { return m_ShutdownColor_Blue; }
+        void setShutdownColor_Blue(int value) { m_ShutdownColor_Blue=value; }
+
+        int getColorChanger_iSteps() { return m_ColorChanger_iSteps; }
+        void setColorChanger_iSteps(int value) { m_ColorChanger_iSteps = value; }
+        int getColorChanger_iDelay() { return m_ColorChanger_iDelay; }
+        void setColorChanger_iDelay(int value) { m_ColorChanger_iDelay = value; }
+
+        int getLrColorChanger_iSteps() { return m_LrColorChanger_iSteps; }
+        void setLrColorChanger_iSteps(int value) { m_LrColorChanger_iSteps = value; }
+        int getLrColorChanger_iDelay() { return m_LrColorChanger_iDelay; }
+        void setLrColorChanger_iDelay(int value) { m_LrColorChanger_iDelay = value; }
+
+        int getStaticColor_Red()   { return m_StaticColor_Red;   }
+        void setStaticColor_Red(int value)  { m_StaticColor_Red=value; }
+        int getStaticColor_Green() { return m_StaticColor_Green; }
+        void setStaticColor_Green(int value) { m_StaticColor_Green=value; }
+        int getStaticColor_Blue()  { return m_StaticColor_Blue;  }
+        void  setStaticColor_Blue(int value) { m_StaticColor_Blue=value; }
+
+
+        AtmoConnectionType getConnectionType() { return m_eAtmoConnectionType; }
+        void setConnectionType(AtmoConnectionType value) { m_eAtmoConnectionType = value; }
+
+        EffectMode getEffectMode() { return m_eEffectMode; }
+        void setEffectMode(EffectMode value) { m_eEffectMode = value; }
+
+        AtmoFilterMode getLiveViewFilterMode() { return m_LiveViewFilterMode; }
+        void setLiveViewFilterMode(AtmoFilterMode value) { m_LiveViewFilterMode = value; }
+
+        int getLiveViewFilter_PercentNew() { return m_LiveViewFilter_PercentNew; }
+        void setLiveViewFilter_PercentNew(int value) { m_LiveViewFilter_PercentNew=value; }
+        int getLiveViewFilter_MeanLength() { return m_LiveViewFilter_MeanLength; }
+        void setLiveViewFilter_MeanLength(int value) { m_LiveViewFilter_MeanLength = value; }
+        int getLiveViewFilter_MeanThreshold() { return m_LiveViewFilter_MeanThreshold; }
+        void setLiveViewFilter_MeanThreshold(int value) { m_LiveViewFilter_MeanThreshold = value; }
+
+        int getLiveView_EdgeWeighting() { return m_LiveView_EdgeWeighting; }
+        void setLiveView_EdgeWeighting(int value) { m_LiveView_EdgeWeighting=value; }
+
+        int getLiveView_BrightCorrect() { return m_LiveView_BrightCorrect; }
+        void setLiveView_BrightCorrect(int value) { m_LiveView_BrightCorrect=value; }
+
+        int getLiveView_DarknessLimit() { return m_LiveView_DarknessLimit; }
+        void setLiveView_DarknessLimit(int value) { m_LiveView_DarknessLimit=value; }
+
+        int getLiveView_HueWinSize() { return m_LiveView_HueWinSize; }
+        void setLiveView_HueWinSize(int value) { m_LiveView_HueWinSize=value; }
+
+        int getLiveView_SatWinSize() { return m_LiveView_SatWinSize; }
+        void setLiveView_SatWinSize(int value) { m_LiveView_SatWinSize=value; }
+
+        int getLiveView_WidescreenMode() { return m_LiveView_WidescreenMode; }
+        void setLiveView_WidescreenMode(int value) { m_LiveView_WidescreenMode=value; }
+
+        int getLiveView_HOverscanBorder() { return m_LiveView_HOverscanBorder; }
+        void setLiveView_HOverscanBorder(int value) { m_LiveView_HOverscanBorder = value; }
+
+        int getLiveView_VOverscanBorder() { return m_LiveView_VOverscanBorder; }
+        void setLiveView_VOverscanBorder(int value) { m_LiveView_VOverscanBorder = value; }
+
+        int getLiveView_DisplayNr() { return m_LiveView_DisplayNr; }
+        void setLiveView_DisplayNr(int value) { m_LiveView_DisplayNr = value; }
+
+        int getLiveView_FrameDelay() { return m_LiveView_FrameDelay; }
+        void setLiveView_FrameDelay(int delay) { m_LiveView_FrameDelay = delay; }
+
+        int getHardware_global_gamma() { return m_Hardware_global_gamma ; }
+        void setHardware_global_gamma(int value) { m_Hardware_global_gamma=value; }
+
+        int getHardware_global_contrast() { return m_Hardware_global_contrast; }
+        void setHardware_global_contrast(int value) { m_Hardware_global_contrast=value; }
+
+        int getHardware_contrast_red() { return m_Hardware_contrast_red; }
+        void setHardware_contrast_red(int value) { m_Hardware_contrast_red=value; }
+
+        int getHardware_contrast_green() { return m_Hardware_contrast_green; }
+        void setHardware_contrast_green(int value) { m_Hardware_contrast_green=value; }
+
+        int getHardware_contrast_blue() { return m_Hardware_contrast_blue; }
+        void setHardware_contrast_blue(int value) { m_Hardware_contrast_blue=value; }
+
+        int getHardware_gamma_red() { return m_Hardware_gamma_red; }
+        void setHardware_gamma_red(int value) { m_Hardware_gamma_red=value; }
+
+        int getHardware_gamma_green() { return m_Hardware_gamma_green; }
+        void setHardware_gamma_green(int value) { m_Hardware_gamma_green=value; }
+
+        int getHardware_gamma_blue() { return m_Hardware_gamma_blue; }
+        void setHardware_gamma_blue(int value) { m_Hardware_gamma_blue=value; }
+
+        tChannelAssignment *getChannelAssignment(int nummer) {
+            return this->m_ChannelAssignments[nummer];
+        }
+        int getCurrentChannelAssignment() { return m_CurrentChannelAssignment; }
+        void setCurrentChannelAssignment(int index) { m_CurrentChannelAssignment = index; }
+
+        int getNumChannelAssignments();
+        void clearChannelMappings();
+        void clearAllChannelMappings();
+        void AddChannelAssignment(tChannelAssignment *ta);
+        void SetChannelAssignment(int index, tChannelAssignment *ta);
+
+        CAtmoZoneDefinition *getZoneDefinition(int zoneIndex);
+
+};
+
+#endif
diff --git a/modules/video_filter/atmo/AtmoConnection.cpp b/modules/video_filter/atmo/AtmoConnection.cpp
new file mode 100644 (file)
index 0000000..f887845
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * AtmoConnection.cpp: generic/abstract class defining all methods for the
+ * communication with the hardware
+ *
+ * See the README.txt file for copyright information and how to reach the author(s).
+ *
+ * $Id$
+ */
+#include "AtmoConnection.h"
+
+CAtmoConnection::CAtmoConnection(CAtmoConfig *cfg)
+{
+       this->m_pAtmoConfig = cfg;      
+    if(cfg->getNumChannelAssignments()>0) {
+        tChannelAssignment *ca = cfg->getChannelAssignment(0);
+        for(int i=0;i<ATMO_NUM_CHANNELS;i++) {
+            m_ChannelAssignment[i] = ca->mappings[i];
+        }
+    } else {
+        for(int i=0;i<ATMO_NUM_CHANNELS;i++) {
+            m_ChannelAssignment[i] = i;
+        }
+    }
+}
+
+void CAtmoConnection::SetChannelAssignment(tChannelAssignment *ca) {
+     for(int i=0;i<ATMO_NUM_CHANNELS;i++) {
+         m_ChannelAssignment[i] = ca->mappings[i];
+     }
+}
+
+CAtmoConnection::~CAtmoConnection(void)
+{
+  if(isOpen())
+     CloseConnection();
+}
diff --git a/modules/video_filter/atmo/AtmoConnection.h b/modules/video_filter/atmo/AtmoConnection.h
new file mode 100644 (file)
index 0000000..a7e6e97
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * AtmoConnection.h: generic/abstract class defining all methods for the
+ * communication with the hardware
+ *
+ * See the README.txt file for copyright information and how to reach the author(s).
+ *
+ * $Id$
+ */
+#ifndef _AtmoConnection_h_
+#define _AtmoConnection_h_
+
+#include "AtmoDefs.h"
+#include "AtmoConfig.h"
+
+class CAtmoConnection
+{
+protected:
+       CAtmoConfig *m_pAtmoConfig;
+    int m_ChannelAssignment[ATMO_NUM_CHANNELS];
+
+public:
+       CAtmoConnection(CAtmoConfig *cfg);
+       virtual ~CAtmoConnection(void);
+       virtual ATMO_BOOL OpenConnection() { return false; }
+       virtual void CloseConnection() {};
+       virtual ATMO_BOOL isOpen(void) { return false; }
+
+    virtual ATMO_BOOL SendData(unsigned char numChannels,
+                               int red[],
+                               int green[],
+                               int blue[]) { return false; }
+
+    virtual ATMO_BOOL SendData(tColorPacket data) { return false; }
+
+    virtual ATMO_BOOL setChannelColor(int channel, tRGBColor color) { return false; }
+    virtual ATMO_BOOL setChannelValues(int numValues,unsigned char *channel_values) { return false; }
+
+    virtual ATMO_BOOL HardwareWhiteAdjust(int global_gamma,
+                                          int global_contrast,
+                                          int contrast_red,
+                                          int contrast_green,
+                                          int contrast_blue,
+                                          int gamma_red,
+                                          int gamma_green,
+                                          int gamma_blue,
+                                          ATMO_BOOL storeToEeprom) { return false; }
+
+    virtual void SetChannelAssignment(tChannelAssignment *ca);
+
+};
+
+#endif
diff --git a/modules/video_filter/atmo/AtmoDefs.h b/modules/video_filter/atmo/AtmoDefs.h
new file mode 100644 (file)
index 0000000..d6ced77
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * AtmoDefs.h: a lot of globals defines for the color computation - most of this file
+ * is an one  to one copy of "defs.h" from Atmo VDR Plugin
+ *
+ * See the README.txt file for copyright information and how to reach the author(s).
+ *
+ * $Id$
+ */
+
+#ifndef _AtmoDefs_h_
+#define _AtmoDefs_h_
+
+#if defined(__LIBVLC__)
+#   include "config.h"
+#   include <vlc/vlc.h>
+
+/* some things need to be changed if this code is used inside VideoLan Filter Module */
+#   define _ATMO_VLC_PLUGIN_
+#   define ATMO_BOOL vlc_bool_t
+#   define ATMO_TRUE VLC_TRUE
+#   define ATMO_FALSE VLC_FALSE
+
+#else
+
+    typedef int ATMO_BOOL;
+#   define ATMO_TRUE   1
+#   define ATMO_FALSE  0
+
+#endif
+
+
+#if !defined(WIN32)
+
+#define INVALID_HANDLE_VALUE -1
+typedef int HANDLE;
+typedef unsigned long DWORD;
+
+#define BI_RGB 0L
+
+#if !defined(_BITMAPFILEHEADER_)
+#define _BITMAPFILEHEADER_
+typedef struct
+#ifdef HAVE_ATTRIBUTE_PACKED
+    __attribute__((__packed__))
+#endif
+{
+        uint16_t   bfType;
+        uint32_t   bfSize;
+        uint16_t   bfReserved1;
+        uint16_t   bfReserved2;
+        uint32_t   bfOffBits;
+} BITMAPFILEHEADER, *LPBITMAPFILEHEADER, *PBITMAPFILEHEADER;
+#endif
+
+#endif
+
+
+
+#define FCC(ch4) ((((DWORD)(ch4) & 0xFF) << 24) |     \
+                  (((DWORD)(ch4) & 0xFF00) << 8) |    \
+                  (((DWORD)(ch4) & 0xFF0000) >> 8) |  \
+                  (((DWORD)(ch4) & 0xFF000000) >> 24))
+
+// maximal Anzahl Kanäle...
+#define ATMO_NUM_CHANNELS   5
+
+// capture width/height
+#define CAP_WIDTH    64
+#define CAP_HEIGHT   48
+
+// imagesize
+#define IMAGE_SIZE   (CAP_WIDTH * CAP_HEIGHT)
+
+
+enum AtmoConnectionType
+{
+      actSerialPort = 0,
+      actDummy = 1,
+      actDMX = 2
+};
+static const char *AtmoDeviceTypes[] = {
+      "Atmo",
+      "Dummy",
+      "DMX"
+  };
+#define ATMO_DEVICE_COUNT 3
+
+#if defined(_ATMO_VLC_PLUGIN_)
+enum EffectMode {
+      emUndefined = -1,
+      emDisabled = 0,
+      emStaticColor = 1,
+      emLivePicture = 2
+   };
+#else
+enum EffectMode {
+      emUndefined = -1,
+      emDisabled = 0,
+      emStaticColor = 1,
+      emLivePicture = 2,
+      emColorChange = 3,
+      emLrColorChange = 4
+   };
+#endif
+
+
+
+
+enum AtmoFilterMode {
+     afmNoFilter,
+     afmCombined,
+     afmPercent
+};
+
+typedef struct {
+    ATMO_BOOL system;
+    char name[64];
+    int mappings[ATMO_NUM_CHANNELS];
+} tChannelAssignment;
+
+
+// --- tRGBColor --------------------------------------------------------------
+typedef struct
+{
+  unsigned char r, g, b;
+} tRGBColor;
+
+// --- tColorPacket -----------------------------------------------------------
+typedef struct
+{
+  tRGBColor channel[ATMO_NUM_CHANNELS];
+} tColorPacket;
+
+// --- tRGBColorLongInt -------------------------------------------------------
+typedef struct
+{
+  long int r, g, b;
+} tRGBColorLongInt;
+
+// --- tColorPacketLongInt ----------------------------------------------------
+typedef struct
+{
+  tRGBColorLongInt channel[ATMO_NUM_CHANNELS];
+} tColorPacketLongInt;
+
+// --- tWeightPacket ----------------------------------------------------------
+typedef struct
+{
+  int channel[ATMO_NUM_CHANNELS];
+} tWeightPacket;
+
+// --- tHSVColor --------------------------------------------------------------
+typedef struct
+{
+  unsigned char h, s, v;
+} tHSVColor;
+
+#endif
diff --git a/modules/video_filter/atmo/AtmoDynData.cpp b/modules/video_filter/atmo/AtmoDynData.cpp
new file mode 100644 (file)
index 0000000..5b39a37
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * AtmoDynData.cpp: class for holding all variable data - which may be
+ * passed between function calls, into threads instead of the use
+ * of global variables
+ *
+ * See the README.txt file for copyright information and how to reach the author(s).
+ *
+ * $Id$
+ */
+
+#include "AtmoDynData.h"
+
+#if defined(_ATMO_VLC_PLUGIN_)
+CAtmoDynData::CAtmoDynData(vlc_object_t *p_atmo_filter, CAtmoConfig *pAtmoConfig) {
+    this->p_atmo_filter     = p_atmo_filter;
+    this->m_pAtmoConfig     = pAtmoConfig;
+    this->m_pAtmoConnection = NULL;
+    this->m_pCurrentEffectThread = NULL;
+
+    vlc_mutex_init( p_atmo_filter, &m_lock );
+
+}
+#else
+CAtmoDynData::CAtmoDynData(HINSTANCE hInst, CAtmoConfig *pAtmoConfig, CAtmoDisplays *pAtmoDisplays) {
+    this->m_pAtmoConfig     = pAtmoConfig;
+    this->m_pAtmoDisplays   = pAtmoDisplays;
+    this->m_pAtmoConnection = NULL;
+    this->m_pCurrentEffectThread = NULL;
+    this->m_hInst = hInst;
+    InitializeCriticalSection(&m_RemoteCallCriticalSection);
+}
+#endif
+
+CAtmoDynData::~CAtmoDynData(void)
+{
+#if defined(_ATMO_VLC_PLUGIN_)
+    vlc_mutex_destroy( &m_lock );
+#else
+    DeleteCriticalSection(&m_RemoteCallCriticalSection);
+#endif
+}
+
+void CAtmoDynData::LockCriticalSection() {
+#if defined(_ATMO_VLC_PLUGIN_)
+    vlc_mutex_lock( &m_lock );
+#else
+    EnterCriticalSection(&m_RemoteCallCriticalSection);
+#endif
+}
+
+void CAtmoDynData::UnLockCriticalSection() {
+#if defined(_ATMO_VLC_PLUGIN_)
+    vlc_mutex_unlock( &m_lock );
+#else
+    LeaveCriticalSection(&m_RemoteCallCriticalSection);
+#endif
+}
diff --git a/modules/video_filter/atmo/AtmoDynData.h b/modules/video_filter/atmo/AtmoDynData.h
new file mode 100644 (file)
index 0000000..0894898
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * AtmoDynData.h: class for holding all variable data - which may be passed
+ * between function calls, into threads instead of the use of global variables
+ *
+ * See the README.txt file for copyright information and how to reach the author(s).
+ *
+ * $Id$
+ */
+#ifndef _AtmoDynData_h_
+#define _AtmoDynData_h_
+
+#include "AtmoDefs.h"
+
+#include "AtmoThread.h"
+#include "AtmoConfig.h"
+#include "AtmoConnection.h"
+
+#if !defined(_ATMO_VLC_PLUGIN_)
+#    include "AtmoDisplays.h"
+#else
+#    include <vlc/vlc.h>
+#    include <vlc_threads_funcs.h>
+#endif
+
+/*
+  the idea behind this class is to avoid a mix of persistent value and
+  volatile values in CAtmoConfig class because some parameters and variables
+  exists only for the current process and won't be stored to the registry
+
+  (Simple thought its a container... )
+
+  you ask? why I didn't used a struct for it? ..mmh I like classes?
+
+  Problem: MultiThreading! todo semaphore, mutex!
+
+  Allways stop the current effect Thread before changing AtmoConnection or
+  AtmoConfig!
+*/
+class CAtmoDynData
+{
+private:
+    CThread *m_pCurrentEffectThread;
+    CAtmoConnection *m_pAtmoConnection;
+    CAtmoConfig *m_pAtmoConfig;
+
+#if !defined(_ATMO_VLC_PLUGIN_)
+    CAtmoDisplays *m_pAtmoDisplays;
+    HINSTANCE m_hInst;
+    CRITICAL_SECTION m_RemoteCallCriticalSection;
+#else
+    vlc_object_t *p_atmo_filter;
+    vlc_mutex_t  m_lock;
+#endif
+
+
+public:
+#if !defined(_ATMO_VLC_PLUGIN_)
+     CAtmoDynData(HINSTANCE hInst,
+                  CAtmoConfig *pAtmoConfig,
+                  CAtmoDisplays *pAtmoDisplays);
+#else
+     CAtmoDynData(vlc_object_t *p_atmo_filter,
+                  CAtmoConfig *pAtmoConfig);
+#endif
+    ~CAtmoDynData(void);
+
+    CThread *getEffectThread()           { return m_pCurrentEffectThread; }
+    void setEffectThread(CThread *value) { m_pCurrentEffectThread = value; }
+
+    CAtmoConnection *getAtmoConnection() { return m_pAtmoConnection; }
+    void setAtmoConnection(CAtmoConnection *value) { m_pAtmoConnection = value; }
+
+    CAtmoConfig *getAtmoConfig() { return m_pAtmoConfig; }
+
+#if !defined(_ATMO_VLC_PLUGIN_)
+    CAtmoDisplays *getAtmoDisplays() { return m_pAtmoDisplays; }
+    HINSTANCE getHinstance() { return m_hInst; }
+#else
+    vlc_object_t *getAtmoFilter() { return p_atmo_filter; }
+#endif
+
+    void LockCriticalSection();
+    void UnLockCriticalSection();
+};
+
+#endif
diff --git a/modules/video_filter/atmo/AtmoExternalCaptureInput.cpp b/modules/video_filter/atmo/AtmoExternalCaptureInput.cpp
new file mode 100644 (file)
index 0000000..1dc6aaa
--- /dev/null
@@ -0,0 +1,303 @@
+/*
+ * AtmoExternalCaptureInput.cpp: Datasource which gets its data via a COM object call
+ * or some other external method.
+ *
+ *
+ * See the README.txt file for copyright information and how to reach the author(s).
+ *
+ * $Id$
+*/
+
+#include "AtmoExternalCaptureInput.h"
+#include "AtmoTools.h"
+
+#if defined(_ATMO_VLC_PLUGIN_)
+
+CAtmoExternalCaptureInput::CAtmoExternalCaptureInput(CAtmoDynData *pAtmoDynData) :
+                           CAtmoInput(pAtmoDynData),
+                           CThread(pAtmoDynData->getAtmoFilter())
+{
+    m_pCurrentFramePixels = NULL;
+    vlc_cond_init( this->m_pAtmoThread, &m_WakeupCond );
+    vlc_mutex_init( m_pAtmoThread, &m_WakeupLock );
+    msg_Dbg( m_pAtmoThread, "CAtmoExternalCaptureInput created.");
+
+}
+
+#else
+
+CAtmoExternalCaptureInput::CAtmoExternalCaptureInput(CAtmoDynData *pAtmoDynData) :
+                           CAtmoInput(pAtmoDynData)
+{
+    m_hWakeupEvent = CreateEvent(NULL,ATMO_FALSE,ATMO_FALSE,NULL);
+    m_pCurrentFramePixels = NULL;
+}
+
+#endif
+
+CAtmoExternalCaptureInput::~CAtmoExternalCaptureInput(void)
+{
+   /* if there is still an unprocessed bufferpicture do kill it */
+   if(m_pCurrentFramePixels != NULL)
+      free(m_pCurrentFramePixels);
+
+#if defined(_ATMO_VLC_PLUGIN_)
+    vlc_cond_destroy( &m_WakeupCond );
+    vlc_mutex_destroy(&m_WakeupLock);
+    msg_Dbg( m_pAtmoThread, "CAtmoExternalCaptureInput destroyed.");
+#else
+    CloseHandle(m_hWakeupEvent);
+#endif
+}
+
+ATMO_BOOL CAtmoExternalCaptureInput::Open()
+{
+    this->Run();
+    return ATMO_TRUE;
+}
+
+// Closes the input-device.
+// Returns true if the input-device was closed successfully.
+ATMO_BOOL CAtmoExternalCaptureInput::Close(void)
+{
+    this->Terminate();
+    return ATMO_TRUE;
+}
+
+tColorPacket CAtmoExternalCaptureInput::GetColorPacket(void)
+{
+    return this->m_ColorPacket;
+}
+
+/*
+  this method will be called from another thread or possible the COM Server to feed
+  new pixeldata into the calculation process it doest just the following:
+  1: check if last buffer was allready processed (!m_pCurrentFramePixels)
+  2. copy the bitmap info structure into the threads own one
+  3. alloc memory for frame
+  4. copy sourcepixeldata into own buffer...
+  5. let the thread wake up and return imediately to the caller
+  so that the real videoout wouldn't be stop for a too long time
+*/
+void CAtmoExternalCaptureInput::DeliverNewSourceDataPaket(BITMAPINFOHEADER *bmpInfoHeader,void *pixelData)
+{
+    /*
+       normaly we should protect this area of code by critical_section or a mutex,
+       but I think we can omit this here because the timing this method is called
+       is really slow (in terms of the speed of a modern computer?)
+       so it's nearly impossible that two frames are delivert in the same time
+       the test needs and malloc needs...
+    */
+    if( !m_pCurrentFramePixels )
+    {
+        // Last Frame was processed... take this one...
+        memcpy(&m_CurrentFrameHeader,bmpInfoHeader,bmpInfoHeader->biSize);
+        int PixelDataSize = m_CurrentFrameHeader.biHeight * m_CurrentFrameHeader.biWidth;
+        switch(m_CurrentFrameHeader.biBitCount) {
+            case 8:  /* PixelDataSize = PixelDataSize; */ break;
+            case 16: PixelDataSize = PixelDataSize * 2; break;
+            case 24: PixelDataSize = PixelDataSize * 3; break;
+            case 32: PixelDataSize = PixelDataSize * 4; break;
+        }
+        m_pCurrentFramePixels = malloc(PixelDataSize);
+        memcpy(m_pCurrentFramePixels,pixelData,PixelDataSize);
+    }
+#if defined(_ATMO_VLC_PLUGIN_)
+   vlc_mutex_lock( &m_WakeupLock );
+   vlc_cond_signal( &m_WakeupCond );
+   vlc_mutex_unlock( &m_WakeupLock );
+#else
+    SetEvent(m_hWakeupEvent);
+#endif
+}
+
+
+
+/*
+ the real thread Method which is processing the pixeldata into the hardware channel
+ values - which are used by the thread AtmoLiveView...
+*/
+#if defined (_ATMO_VLC_PLUGIN_)
+
+DWORD CAtmoExternalCaptureInput::Execute(void)
+{
+    msg_Dbg( m_pAtmoThread, "CAtmoExternalCaptureInput::Execute(void)");
+    int i = 0;
+
+    vlc_mutex_lock( &m_WakeupLock );
+
+    while ((this->m_bTerminated == ATMO_FALSE) && (this->m_pAtmoThread->b_die == VLC_FALSE)) {
+          int value = vlc_cond_timedwait(&m_WakeupCond, &m_WakeupLock, mdate() + I64C(75000));
+          if(!value) {
+             /* DeliverNewSourceDataPaket delivered new work for me... get it! */
+             CalcColors(); // read picture and calculate colors
+             this->m_FrameArrived = ATMO_TRUE;
+          }
+          i++;
+          if(i == 100) {
+             i = 0;
+#if !defined(WIN32)
+/* kludge for pthreads? using the same condition variable too often results in hanging the pthread
+   call inside vlc_cond_timedwait...
+*/
+#ifdef _ATMO_KLUDGE_
+             vlc_cond_destroy( &m_WakeupCond );
+             vlc_cond_init( m_pAtmoThread, &m_WakeupCond );
+#endif
+#endif
+          }
+    }
+    vlc_mutex_unlock( &m_WakeupLock );
+
+    return 0;
+}
+
+#else
+
+DWORD CAtmoExternalCaptureInput::Execute(void) {
+    HANDLE handles[2];
+    handles[0] = this->m_hTerminateEvent;
+    handles[1] = m_hWakeupEvent;
+
+    while (this->m_bTerminated == ATMO_FALSE) {
+           DWORD event = WaitForMultipleObjects(2,handles,ATMO_FALSE,INFINITE);
+           if(event == WAIT_OBJECT_0) {
+              // Terminate Thread Event was set... say good bye...!
+              break;
+           }
+           if(event == (WAIT_OBJECT_0+1)) {
+              CalcColors(); // read picture and calculate colors
+              this->m_FrameArrived = ATMO_TRUE;
+           }
+    }
+    return 0;
+}
+
+#endif
+
+
+void CAtmoExternalCaptureInput::WaitForNextFrame(DWORD timeout)
+{
+    this->m_FrameArrived = ATMO_FALSE;
+    for(DWORD i=0;(i<timeout) && !m_FrameArrived;i++)
+#if defined (_ATMO_VLC_PLUGIN_)
+        msleep(1000);
+#else
+        Sleep(1);
+#endif
+
+    if(this->m_pAtmoDynData)
+    {
+        CAtmoConfig *cfg = this->m_pAtmoDynData->getAtmoConfig();
+        if(cfg)
+        {
+            int delay = cfg->getLiveView_FrameDelay();
+            if(delay > 0)
+            {
+#if defined (_ATMO_VLC_PLUGIN_)
+              msleep(delay * 1000);
+#else
+              Sleep(delay);
+#endif
+            }
+        }
+    }
+}
+
+void CAtmoExternalCaptureInput::CalcColors() {
+     // take data from m_CurrentFrameHeader and m_pCurrentFramePixels .. process for atmo ...
+    tHSVColor HSV_Img[IMAGE_SIZE];
+    tRGBColor pixelColor;
+    int srcIndex,index = 0;
+    memset(&HSV_Img,0,sizeof(HSV_Img));
+
+     // Convert Data to HSV values.. bla bla....
+    if(m_pCurrentFramePixels!=NULL)
+    {
+        if((m_CurrentFrameHeader.biWidth == CAP_WIDTH) && (m_CurrentFrameHeader.biHeight == CAP_HEIGHT))
+        {
+
+          // HSVI = HSV Image allready in right format just copy the easiest task
+          // und weiterverarbeiten lassen
+          if(m_CurrentFrameHeader.biCompression ==  FCC('HSVI'))
+          {
+              memcpy( &HSV_Img, m_pCurrentFramePixels, CAP_WIDTH * CAP_HEIGHT * sizeof(tHSVColor));
+          }
+          else if(m_CurrentFrameHeader.biCompression == BI_RGB)
+          {
+             if(m_CurrentFrameHeader.biBitCount == 16)
+             {
+                 unsigned short *buffer = (unsigned short *)m_pCurrentFramePixels;
+
+                 for(int y=0;y<CAP_HEIGHT;y++)
+                 {
+                     srcIndex = y * CAP_WIDTH;
+                     for(int x=0;x<CAP_WIDTH;x++)
+                     {
+                         pixelColor.b = (buffer[srcIndex] & 31) << 3;
+                         pixelColor.g = ((buffer[srcIndex] >> 5) & 31) << 3;
+                         pixelColor.r = ((buffer[srcIndex] >> 10) & 63) << 2;
+                         srcIndex++;
+                         HSV_Img[index++] = RGB2HSV(pixelColor);
+                     }
+                 }
+             }
+             else if(m_CurrentFrameHeader.biBitCount == 24)
+             {
+                 for(int y=0;y<CAP_HEIGHT;y++)
+                 {
+                     srcIndex = y * (CAP_WIDTH*3);
+                     for(int x=0;x<CAP_WIDTH;x++)
+                     {
+                         pixelColor.b = ((unsigned char *)m_pCurrentFramePixels)[srcIndex++];
+                         pixelColor.g = ((unsigned char *)m_pCurrentFramePixels)[srcIndex++];
+                         pixelColor.r = ((unsigned char *)m_pCurrentFramePixels)[srcIndex++];
+                         HSV_Img[index++] = RGB2HSV(pixelColor);
+                     }
+                 }
+             }
+             else if(m_CurrentFrameHeader.biBitCount == 32)
+             {
+                 for(int y=0;y<CAP_HEIGHT;y++)
+                 {
+                     srcIndex = y * (CAP_WIDTH*4);
+                     for(int x=0;x<CAP_WIDTH;x++)
+                     {
+                         pixelColor.b = ((unsigned char *)m_pCurrentFramePixels)[srcIndex++];
+                         pixelColor.g = ((unsigned char *)m_pCurrentFramePixels)[srcIndex++];
+                         pixelColor.r = ((unsigned char *)m_pCurrentFramePixels)[srcIndex++];
+                         srcIndex++;
+                         HSV_Img[index++] = RGB2HSV(pixelColor);
+                     }
+                 }
+             }
+          }
+       }
+
+       /*
+          if the image color format wasn't recognized - the output
+          will be black (memset)
+       */
+
+       /*
+          now convert the pixeldata into one RGB trippel for each channel,
+          this is done by some very sophisticated methods and statistics ...
+
+          the only thing I know - the pixel priority is controled by some
+          gradients for each edge of the picture
+
+          (sorry I don't know how it exactly works because the formulars
+           are done by some one else...)
+       */
+       m_ColorPacket = CalcColorsAnalyzeHSV(this->m_pAtmoDynData->getAtmoConfig(), HSV_Img);
+
+       /* remove the source buffe */
+       free(m_pCurrentFramePixels);
+       /*
+          the buffer zereo so that deliver new data paket will wakeup the
+          thread on  the next frame again
+       */
+       m_pCurrentFramePixels = NULL;
+    }
+}
+
diff --git a/modules/video_filter/atmo/AtmoExternalCaptureInput.h b/modules/video_filter/atmo/AtmoExternalCaptureInput.h
new file mode 100644 (file)
index 0000000..354033c
--- /dev/null
@@ -0,0 +1,83 @@
+#ifndef _AtmoExternalCaptureInput_h_
+#define _AtmoExternalCaptureInput_h_
+
+#include "AtmoDefs.h"
+
+#if defined(WIN32)
+#   include <windows.h>
+# else
+#   if defined(_ATMO_VLC_PLUGIN_)
+       // need bitmap info header
+#      include <vlc_codecs.h>
+#   endif
+#endif
+
+#if !defined(_ATMO_VLC_PLUGIN_)
+#  include <comdef.h>          
+#  include "AtmoWin_h.h"
+#endif
+
+#include "AtmoInput.h"
+#include "AtmoThread.h"
+#include "AtmoConfig.h"
+#include "AtmoDynData.h"
+#include "AtmoCalculations.h"
+
+
+class CAtmoExternalCaptureInput :
+      public CAtmoInput,
+      public CThread
+{
+protected:
+#if defined(_ATMO_VLC_PLUGIN_)
+    vlc_cond_t   m_WakeupCond;
+    vlc_mutex_t  m_WakeupLock;
+#else
+    HANDLE m_hWakeupEvent;
+#endif
+
+    BITMAPINFOHEADER m_CurrentFrameHeader;
+    void *m_pCurrentFramePixels;
+
+    virtual DWORD Execute(void);
+    void CalcColors();
+
+public:
+    /*
+       this method is called from the com server AtmoLiveViewControlImpl!
+       or inside videolan from the filter method to start a new processing
+    */
+    void DeliverNewSourceDataPaket(BITMAPINFOHEADER *bmpInfoHeader,void *pixelData);
+
+public:
+    CAtmoExternalCaptureInput(CAtmoDynData *pAtmoDynData);
+    virtual ~CAtmoExternalCaptureInput(void);
+
+    /*
+       Opens the input-device. Parameters (e.g. the device-name)
+       Returns true if the input-device was opened successfully.
+       input-device can be the GDI surface of screen (windows only)
+       or the videolan filter
+    */
+    virtual ATMO_BOOL Open(void);
+
+    /*
+     Closes the input-device.
+     Returns true if the input-device was closed successfully.
+    */
+    virtual ATMO_BOOL Close(void);
+
+    /*
+      this method is called from the AtmoLiveView thread - to get the
+      new color packet (a packet is an RGB triple for each channel)
+    */
+    virtual tColorPacket GetColorPacket(void);
+
+    /*
+      this method is also called from the AtmoLiveView thread - to
+      resync on a frame
+    */
+    virtual void WaitForNextFrame(DWORD timeout);
+};
+
+#endif
diff --git a/modules/video_filter/atmo/AtmoInput.cpp b/modules/video_filter/atmo/AtmoInput.cpp
new file mode 100644 (file)
index 0000000..3cf6ef1
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * AtmoInput.cpp:  abstract class for retrieving precalculated image data
+ * from different sources in the live view mode
+ *
+ *
+ * See the README.txt file for copyright information and how to reach the author(s).
+ *
+ * $Id$
+ */
+
+#include "AtmoInput.h"
+
+CAtmoInput::CAtmoInput(CAtmoDynData *pAtmoDynData)
+{
+  this->m_pAtmoDynData = pAtmoDynData;
+}
+
+CAtmoInput::~CAtmoInput(void)
+{
+}
+
+void CAtmoInput::WaitForNextFrame(DWORD timeout)
+{
+    return;
+}
+
diff --git a/modules/video_filter/atmo/AtmoInput.h b/modules/video_filter/atmo/AtmoInput.h
new file mode 100644 (file)
index 0000000..aecbd06
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * AtmoInput.h:  abstract class for retrieving precalculated image data from
+ * different sources in the live view mode
+ *
+ *
+ * See the README.txt file for copyright information and how to reach the author(s).
+ *
+ * $Id$
+ */
+#ifndef _AtmoInput_h_
+#define _AtmoInput_h_
+
+#include "AtmoDefs.h"
+#include "AtmoDynData.h"
+
+/*
+  basic definition of an AtmoLight data/image source ...
+*/
+class CAtmoInput {
+
+protected:
+    tColorPacket m_ColorPacket;
+    volatile ATMO_BOOL m_FrameArrived;
+    CAtmoDynData *m_pAtmoDynData;
+
+public:
+    CAtmoInput(CAtmoDynData *pAtmoDynData);
+    virtual ~CAtmoInput(void);
+
+    // Opens the input-device.
+    // Returns true if the input-device was opened successfully.
+    virtual ATMO_BOOL Open(void) { return ATMO_FALSE; }
+
+    // Closes the input-device.
+    // Returns true if the input-device was closed successfully.
+    virtual ATMO_BOOL Close(void) { return ATMO_FALSE; }
+
+    // Returns the calculated tColorPacket for further processing (e.g. filtering).
+    virtual tColorPacket GetColorPacket(void) { return m_ColorPacket; }
+
+    // wait for the arrival of the next frame...(to come in sync again)
+    virtual void WaitForNextFrame(DWORD timeout);
+};
+
+#endif
diff --git a/modules/video_filter/atmo/AtmoLiveView.cpp b/modules/video_filter/atmo/AtmoLiveView.cpp
new file mode 100644 (file)
index 0000000..5db300b
--- /dev/null
@@ -0,0 +1,261 @@
+/*
+ * AtmoLiveView.cpp:  this effect outputs colors as result of a picture
+ * content (most complex effect) see thread.c of the linux VDR version -
+ * to fully understand what happens here..
+ *
+ * See the README.txt file for copyright information and how to reach the author(s).
+ *
+ * $Id$
+ */
+#include "AtmoDefs.h"
+#include "AtmoLiveView.h"
+#include "AtmoOutputFilter.h"
+#include "AtmoTools.h"
+
+#if defined(_ATMO_VLC_PLUGIN_)
+# include <vlc/vlc.h>
+#else
+#  include "AtmoGdiDisplayCaptureInput.h"
+#endif
+
+#include "AtmoExternalCaptureInput.h"
+
+
+#if defined(_ATMO_VLC_PLUGIN_)
+
+CAtmoLiveView::CAtmoLiveView(CAtmoDynData *pAtmoDynData) :
+               CThread(pAtmoDynData->getAtmoFilter())
+{
+    this->m_pAtmoDynData    = pAtmoDynData;
+    m_pAtmoInput = NULL;
+}
+
+#else
+
+CAtmoLiveView::CAtmoLiveView(CAtmoDynData *pAtmoDynData)
+{
+    this->m_pAtmoDynData  = pAtmoDynData;
+    m_LiveViewSource = lvsGDI;
+    m_CurrentLiveViewSource = lvsGDI;
+    m_InputChangedEvent = CreateEvent(NULL,ATMO_FALSE,ATMO_FALSE,NULL);
+    m_pAtmoInput = NULL;
+    InitializeCriticalSection(&m_InputChangeCriticalSection);
+}
+
+#endif
+
+
+CAtmoLiveView::~CAtmoLiveView(void)
+{
+#if !defined(_ATMO_VLC_PLUGIN_)
+   DeleteCriticalSection(&m_InputChangeCriticalSection);
+   CloseHandle(m_InputChangedEvent);
+#endif
+}
+
+
+
+#if !defined(_ATMO_VLC_PLUGIN_)
+
+STDMETHODIMP CAtmoLiveView::setLiveViewSource(enum ComLiveViewSource dwModus)
+{
+    if(dwModus != m_LiveViewSource) {
+       m_LiveViewSource = dwModus;
+       /*
+         you may ask why I don't use a critical section here and directly acces the
+         the variable of the Thread?
+         Just because you would need very much / often entering / leaving the critical
+         section ... and in this case It could be avoid ...
+
+         assigning the value to the "mirror" variable m_LiveViewSource which is compare
+         in every run of the thread with its current value ... if there is a change
+         the thread can proceed switching the live source ... until this is done
+         the thread calling this method is waiting...
+       */
+
+       // I don't expect that it will take longer than 500ms to switch...
+       if(WaitForSingleObject(m_InputChangedEvent,500) == WAIT_TIMEOUT)
+          return S_FALSE; // if not so the switch seems be have failed (badly)
+    }
+    return S_OK;
+}
+
+STDMETHODIMP CAtmoLiveView::getCurrentLiveViewSource(enum ComLiveViewSource *modus) {
+     *modus = m_LiveViewSource;
+     return S_OK;
+}
+
+#endif
+
+
+DWORD CAtmoLiveView::Execute(void)
+{
+#if defined(_ATMO_VLC_PLUGIN_)
+      mtime_t ticks;
+#else
+      DWORD ticks;
+#endif
+      int i_frame_counter = 0;
+      CAtmoInput *newInput,*oldInput;
+      tColorPacket ColorPacket;
+
+      CAtmoConnection *pAtmoConnection = this->m_pAtmoDynData->getAtmoConnection();
+      if((pAtmoConnection == NULL) || (pAtmoConnection->isOpen() == ATMO_FALSE)) return 0;
+
+      CAtmoConfig *pAtmoConfig = this->m_pAtmoDynData->getAtmoConfig();
+
+      /*
+         this object does post processing of the pixel data
+         like jump /scenechange detection fading over the colors
+      */
+      CAtmoOutputFilter *filter = new CAtmoOutputFilter(this->m_pAtmoDynData->getAtmoConfig());
+
+
+
+#if defined(_ATMO_VLC_PLUGIN_)
+      /* this thread is the data preprocess which gets the real 64x48 pixel
+         and converts them into the RGB channel values - this is done in
+         another thread to keep this thread at a constant timing - to that
+         color output is updated 25 times a second
+      */
+      m_pAtmoInput = new CAtmoExternalCaptureInput(m_pAtmoDynData);
+#else
+      if(m_LiveViewSource == lvsGDI)
+         m_pAtmoInput = new CAtmoGdiDisplayCaptureInput(m_pAtmoDynData);
+      else
+         m_pAtmoInput = new CAtmoExternalCaptureInput(m_pAtmoDynData);
+#endif
+
+      if(m_pAtmoInput->Open() == ATMO_TRUE)
+      {
+          /*
+            wait for the first frame to go in sync with the other thread
+          */
+#if defined(_ATMO_VLC_PLUGIN_)
+          msg_Dbg( m_pAtmoThread, "CAtmoLiveView::Execute(void)");
+#endif
+          m_pAtmoInput->WaitForNextFrame(500);
+
+          while(this->m_bTerminated == ATMO_FALSE)
+          {
+              /*  atmoInput - capture Thread Running... */
+#if defined(_ATMO_VLC_PLUGIN_)
+                ticks = mdate();
+#else
+                ticks = GetTickCount();
+#endif
+
+                /* grab current Packet from Input! */
+                ColorPacket = m_pAtmoInput->GetColorPacket();
+
+                /* pass it through the outputfilters! */
+                ColorPacket = filter->Filtering(ColorPacket);
+
+                /* apply gamma later ;-) not implemented yet */
+                ColorPacket = CAtmoTools::ApplyGamma(pAtmoConfig, ColorPacket);
+
+                /*
+                   apply white calibration - only if it is not
+                   done by the hardware
+                 */
+                if(pAtmoConfig->isUseSoftwareWhiteAdj())
+                   ColorPacket = CAtmoTools::WhiteCalibration(pAtmoConfig,
+                                                              ColorPacket);
+
+                /* send color data to the the hardware... */
+                pAtmoConnection->SendData(ColorPacket);
+
+                /*
+                   experimental do sync every 100 Frames to the image producer
+                   thread because GetTickCount precision is really poor ;-)
+                */
+                i_frame_counter++;
+                if(i_frame_counter == 100) {
+                   m_pAtmoInput->WaitForNextFrame(50);
+                   i_frame_counter = 0;
+#if !defined(WIN32)
+/* kludge for pthreads? when running GDB debugger using the same condition variable
+   to often results in haging wait timedout...
+*/
+#ifdef _ATMO_KLUDGE_
+                   vlc_mutex_lock( &m_TerminateLock );
+                   vlc_cond_destroy( &m_TerminateCond );
+                   vlc_cond_init( m_pAtmoThread, &m_TerminateCond );
+                   vlc_mutex_unlock( &m_TerminateLock );
+#endif
+#endif
+                   continue;
+                }
+
+
+#if !defined(_ATMO_VLC_PLUGIN_)
+                /*
+                  Check if Input Source has changed - through an async
+                  call from the com interface?
+                */
+                if(m_CurrentLiveViewSource != m_LiveViewSource) {
+                   oldInput = m_pAtmoInput;
+                   m_pAtmoInput = NULL;
+
+                   if(m_LiveViewSource == lvsGDI) {
+                      // create new GDI Input Source...
+                      newInput = new CAtmoGdiDisplayCaptureInput(m_pAtmoDynData);
+                      newInput->Open(); // should not fail now... hope is the best!
+                   } else if(m_LiveViewSource == lvsExternal) {
+                      newInput = new CAtmoExternalCaptureInput(m_pAtmoDynData);
+                      newInput->Open();
+                   }
+                   m_CurrentLiveViewSource = m_LiveViewSource;
+
+                   m_pAtmoInput = newInput;
+
+                   oldInput->Close();
+                   delete oldInput;
+
+                   /*
+                     signal the call to the method "setLiveViewSource" the source
+                     was switched...
+                   */
+                   SetEvent(m_InputChangedEvent);
+                   // do sync with input thread
+                   m_pAtmoInput->WaitForNextFrame(100);
+                   continue;
+                }
+#endif
+
+                /*
+                   calculate RunTime of thread abbove (doesn't work well - so
+                   this threads comes out of sync with Image producer and the
+                   framerate (25fps) drifts away
+               */
+#if defined(_ATMO_VLC_PLUGIN_)
+                ticks = ((mdate() - ticks) + 999)/1000;
+#else
+                ticks = GetTickCount() - ticks;
+#endif
+                if(ticks < 40)
+                {
+                    // ThreadSleep -> AtmoThread.cpp
+                    if(this->ThreadSleep(40 - ticks)==ATMO_FALSE)
+                      break;
+                }
+          }
+
+          /* shutdown the input processor thread */
+          m_pAtmoInput->Close();
+      }
+
+      delete m_pAtmoInput;
+      m_pAtmoInput = NULL;
+
+#if !defined(_ATMO_VLC_PLUGIN_)
+      /*
+        if there is a pending call to setLiveViewSource let him surely return before
+        destroying the thread and this class instance...
+      */
+      SetEvent(m_InputChangedEvent);
+#endif
+      delete filter;
+      return 0;
+}
+
diff --git a/modules/video_filter/atmo/AtmoLiveView.h b/modules/video_filter/atmo/AtmoLiveView.h
new file mode 100644 (file)
index 0000000..20da086
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * AtmoLiveView.h:  this effect outputs colors as result of a picture content
+ * (most complex effect) see thread.c of the linux version - to fully understand
+ * what happes here..
+ *
+ * See the README.txt file for copyright information and how to reach the author(s).
+ *
+ * $Id$
+ */
+#ifndef _AtmoLiveView_h_
+#define _AtmoLiveView_h_
+
+#include "AtmoDefs.h"
+
+#if !defined(_ATMO_VLC_PLUGIN_)
+#   include <comdef.h>         
+#   include "AtmoWin_h.h"
+#   include <windows.h>
+#endif
+
+#include "AtmoThread.h"
+#include "AtmoConfig.h"
+#include "AtmoConnection.h"
+#include "AtmoInput.h"
+
+class CAtmoLiveView :  public CThread
+{
+protected:
+       virtual DWORD Execute(void);
+
+#if !defined(_ATMO_VLC_PLUGIN_)
+public:
+    STDMETHODIMP setLiveViewSource(enum ComLiveViewSource dwModus);
+    STDMETHODIMP getCurrentLiveViewSource(enum ComLiveViewSource *modus);
+#endif
+
+protected:
+    CAtmoDynData *m_pAtmoDynData;
+    CAtmoInput *m_pAtmoInput;
+
+#if !defined(_ATMO_VLC_PLUGIN_)
+    ComLiveViewSource m_LiveViewSource;
+    ComLiveViewSource m_CurrentLiveViewSource;
+    CRITICAL_SECTION m_InputChangeCriticalSection;
+    HANDLE m_InputChangedEvent;
+#endif
+
+public:
+    CAtmoLiveView(CAtmoDynData *pAtmoDynData);
+    virtual ~CAtmoLiveView(void);
+
+    CAtmoInput *getAtmoInput() { return m_pAtmoInput; }
+
+#if !defined(_ATMO_VLC_PLUGIN_)
+    ComLiveViewSource getLiveViewSource() { return m_CurrentLiveViewSource; }
+#endif
+};
+
+#endif
diff --git a/modules/video_filter/atmo/AtmoOutputFilter.cpp b/modules/video_filter/atmo/AtmoOutputFilter.cpp
new file mode 100644 (file)
index 0000000..a4e8637
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ * AtmoOutputFilter.cpp: Post Processor for the color data retrieved from
+ * a CAtmoInput
+ *
+ * mostly 1:1 from vdr-linux-src "filter.c" copied
+ *
+ * See the README.txt file for copyright information and how to reach the author(s).
+ *
+ * $Id$
+ */
+
+#include <string.h>
+#include "AtmoOutputFilter.h"
+
+
+CAtmoOutputFilter::CAtmoOutputFilter(CAtmoConfig *atmoConfig)
+{
+   this->m_pAtmoConfig = atmoConfig;
+   ResetFilter();
+}
+
+CAtmoOutputFilter::~CAtmoOutputFilter(void)
+{
+}
+
+void CAtmoOutputFilter::ResetFilter(void)
+{
+  // reset filter values
+  MeanFilter(true);
+  PercentFilter(true);
+}
+
+tColorPacket CAtmoOutputFilter::Filtering(tColorPacket ColorPacket)
+{
+  filter_input = ColorPacket;
+
+  switch (m_pAtmoConfig->getLiveViewFilterMode())
+  {
+    case afmNoFilter:
+         filter_output = filter_input;
+    break;
+
+    case afmCombined:
+         MeanFilter(false);
+    break;
+
+    case afmPercent:
+         PercentFilter(false);
+    break;
+
+    default:
+         filter_output = filter_input;
+    break;
+  }
+
+  return filter_output;
+}
+
+void CAtmoOutputFilter::PercentFilter(ATMO_BOOL init)
+{
+  // last values needed for the percentage filter
+  static tColorPacket filter_output_old;
+
+  if (init) // Initialization
+  {
+    memset(&filter_output_old, 0, sizeof(filter_output_old));
+    return;
+  }
+
+  int percentNew = this->m_pAtmoConfig->getLiveViewFilter_PercentNew();
+
+  for (int ch = 0; ch < ATMO_NUM_CHANNELS; ch++)
+  {
+       filter_output.channel[ch].r = (filter_input.channel[ch].r *
+         (100-percentNew) + filter_output_old.channel[ch].r * percentNew) / 100;
+       
+    filter_output.channel[ch].g = (filter_input.channel[ch].g *
+         (100-percentNew) + filter_output_old.channel[ch].g * percentNew) / 100;
+
+       filter_output.channel[ch].b = (filter_input.channel[ch].b *
+         (100-percentNew) + filter_output_old.channel[ch].b * percentNew) / 100;
+  }
+
+  filter_output_old = filter_output;
+}
+
+void CAtmoOutputFilter::MeanFilter(ATMO_BOOL init)
+{
+  // needed vor the running mean value filter
+  static tColorPacketLongInt mean_sums;
+  static tColorPacket mean_values;
+  // needed for the percentage filter
+  static tColorPacket filter_output_old;
+  static int filter_length_old;
+  char reinitialize = 0;
+
+  if (init) // Initialization
+  {
+    memset(&filter_output_old, 0, sizeof(filter_output_old));
+    memset(&mean_sums, 0, sizeof(mean_sums));
+    memset(&mean_values, 0, sizeof(mean_values));
+    return;
+  }
+  int AtmoSetup_Filter_MeanLength = m_pAtmoConfig->getLiveViewFilter_MeanLength();
+  int AtmoSetup_Filter_PercentNew = m_pAtmoConfig->getLiveViewFilter_PercentNew();
+  int AtmoSetup_Filter_MeanThreshold = m_pAtmoConfig->getLiveViewFilter_MeanThreshold();
+
+  // if filter_length has changed
+  if (filter_length_old != AtmoSetup_Filter_MeanLength)
+  {
+    // force reinitialization of the filter
+    reinitialize = 1;
+  }
+  filter_length_old = AtmoSetup_Filter_MeanLength;
+
+  if (filter_length_old < 20) filter_length_old = 20; // avoid division by 0
+
+  for (int ch = 0; ch < ATMO_NUM_CHANNELS; ch++)
+  {
+    // calculate the mean-value filters
+    mean_sums.channel[ch].r +=
+         (long int)(filter_input.channel[ch].r - mean_values.channel[ch].r); // red
+    mean_values.channel[ch].r = mean_sums.channel[ch].r / ((long int)filter_length_old / 20);
+
+    mean_sums.channel[ch].g +=
+        (long int)(filter_input.channel[ch].g - mean_values.channel[ch].g); // green
+    mean_values.channel[ch].g = mean_sums.channel[ch].g / ((long int)filter_length_old / 20);
+
+    mean_sums.channel[ch].b +=
+        (long int)(filter_input.channel[ch].b - mean_values.channel[ch].b); // blue
+    mean_values.channel[ch].b = mean_sums.channel[ch].b / ((long int)filter_length_old / 20);
+
+    // check, if there is a jump -> check if differences between actual values and filter values are too big
+
+    long int dist; // distance between the two colors in the 3D RGB space
+    dist = (mean_values.channel[ch].r - filter_input.channel[ch].r) *
+           (mean_values.channel[ch].r - filter_input.channel[ch].r) +
+           (mean_values.channel[ch].g - filter_input.channel[ch].g) *
+           (mean_values.channel[ch].g - filter_input.channel[ch].g) +
+           (mean_values.channel[ch].b - filter_input.channel[ch].b) *
+           (mean_values.channel[ch].b - filter_input.channel[ch].b);
+
+    /*
+       if (dist > 0) { dist = (long int)sqrt((double)dist); }
+       avoid sqrt(0) (TODO: necessary?)
+       I think its cheaper to calculate the square of something ..? insteas geting the square root?
+    */
+    double distMean = ((double)AtmoSetup_Filter_MeanThreshold * 3.6f);
+    distMean = distMean * distMean;
+
+    /*
+      compare calculated distance with the filter threshold
+         if ((dist > (long int)((double)AtmoSetup.Filter_MeanThreshold * 3.6f)) || ( reinitialize == 1))
+   */
+
+       if ((dist > distMean) || ( reinitialize == 1))
+    {
+      // filter jump detected -> set the long filters to the result of the short filters
+      filter_output.channel[ch] = mean_values.channel[ch] = filter_input.channel[ch];
+
+      mean_sums.channel[ch].r = filter_input.channel[ch].r *
+                                (filter_length_old / 20);
+      mean_sums.channel[ch].g = filter_input.channel[ch].g *
+                                (filter_length_old / 20);
+      mean_sums.channel[ch].b = filter_input.channel[ch].b *
+                                (filter_length_old / 20);
+    }
+    else
+    {
+      // apply an additional percent filter and return calculated values
+
+         filter_output.channel[ch].r = (mean_values.channel[ch].r *
+          (100-AtmoSetup_Filter_PercentNew) +
+          filter_output_old.channel[ch].r * AtmoSetup_Filter_PercentNew) / 100;
+
+         filter_output.channel[ch].g = (mean_values.channel[ch].g *
+          (100-AtmoSetup_Filter_PercentNew) +
+          filter_output_old.channel[ch].g * AtmoSetup_Filter_PercentNew) / 100;
+
+         filter_output.channel[ch].b = (mean_values.channel[ch].b *
+          (100-AtmoSetup_Filter_PercentNew) +
+          filter_output_old.channel[ch].b * AtmoSetup_Filter_PercentNew) / 100;
+    }
+  }
+  filter_output_old = filter_output;
+}
diff --git a/modules/video_filter/atmo/AtmoOutputFilter.h b/modules/video_filter/atmo/AtmoOutputFilter.h
new file mode 100644 (file)
index 0000000..e6397ac
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * AtmoOutputFilter.h: Post Processor for the color data retrieved from a CAtmoInput
+ *
+ * mostly 1:1 from Linux-src "filter.c" copied
+ *
+ * See the README.txt file for copyright information and how to reach the author(s).
+ *
+ * $Id$
+ */
+#ifndef _AtmoOutputFilter_h_
+#define _AtmoOutputFilter_h_
+
+
+#include "AtmoConfig.h"
+#include "AtmoDefs.h"
+
+class CAtmoOutputFilter
+{
+private:
+  tColorPacket filter_input;  // input of the filter
+  tColorPacket filter_output; // output of the filter
+
+  void PercentFilter(ATMO_BOOL init);
+  void MeanFilter(ATMO_BOOL init);
+
+  CAtmoConfig *m_pAtmoConfig;
+public:
+
+public:
+    CAtmoOutputFilter(CAtmoConfig *atmoConfig);
+    virtual ~CAtmoOutputFilter(void);
+    void ResetFilter(void);
+    tColorPacket Filtering(tColorPacket ColorPacket);
+};
+
+#endif
diff --git a/modules/video_filter/atmo/AtmoSerialConnection.cpp b/modules/video_filter/atmo/AtmoSerialConnection.cpp
new file mode 100644 (file)
index 0000000..020ca14
--- /dev/null
@@ -0,0 +1,273 @@
+/*
+ * AtmoSerialConnection.cpp: Class for communication with the serial hardware of
+ * Atmo Light, opens and configures the serial port
+ *
+ * See the README.txt file for copyright information and how to reach the author(s).
+ *
+ * $Id$
+ */
+
+
+#include "AtmoDefs.h"
+#include "AtmoSerialConnection.h"
+
+
+#include <stdio.h>
+#include <fcntl.h>
+
+#include <sys/stat.h>
+
+#if !defined(WIN32)
+#include <termios.h>
+#include <unistd.h>
+#endif
+
+/*
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+#include <vdr/tools.h>
+*/
+
+
+CAtmoSerialConnection::CAtmoSerialConnection(CAtmoConfig *cfg) : CAtmoConnection(cfg) {
+    m_hComport = INVALID_HANDLE_VALUE;
+}
+
+CAtmoSerialConnection::~CAtmoSerialConnection() {
+   CloseConnection();
+}
+
+ATMO_BOOL CAtmoSerialConnection::OpenConnection() {
+#if defined(_ATMO_VLC_PLUGIN_)
+     char *serdevice = m_pAtmoConfig->getSerialDevice();
+     if(!serdevice)
+        return ATMO_FALSE;
+#else
+     int portNummer = m_pAtmoConfig->getComport();
+     m_dwLastWin32Error = 0;
+        if(portNummer < 1) return ATMO_FALSE; // make no real sense;-)
+#endif
+
+        CloseConnection();
+
+#if !defined(_ATMO_VLC_PLUGIN_)
+     char comport[16];  // com4294967295
+     sprintf(comport,"com%d",portNummer);
+#endif
+
+#if defined(WIN32)
+
+#  if defined(_ATMO_VLC_PLUGIN_)
+     m_hComport = CreateFile(serdevice, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
+#  else
+     m_hComport = CreateFile(comport, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
+#  endif
+     if(m_hComport == INVALID_HANDLE_VALUE) {
+//      we have a problem here can't open com port... somebody else may use it?
+//         m_dwLastWin32Error = GetLastError();
+           return ATMO_FALSE;
+     }
+     /* change serial settings (Speed, stopbits etc.) */
+     DCB dcb; // für comport-parameter
+     dcb.DCBlength = sizeof(DCB);
+     GetCommState (m_hComport, &dcb); // ger current serialport settings
+     dcb.BaudRate  = 38400;        // set speed
+     dcb.ByteSize  = 8;            // set databits
+     dcb.Parity    = NOPARITY;     // set parity
+     dcb.StopBits  = ONESTOPBIT;   // set one stop bit
+     SetCommState (m_hComport, &dcb);    // apply settings
+
+#else
+
+     int bconst = B38400;
+#  if defined(_ATMO_VLC_PLUGIN_)
+     m_hComport = open(serdevice,O_RDWR |O_NOCTTY);
+#  else
+     m_hComport = open(comport,O_RDWR | O_NOCTTY);
+#  endif
+     if(m_hComport < 0) {
+           return ATMO_FALSE;
+     }
+
+     struct termios tio;
+     memset(&tio,0,sizeof(tio));
+     tio.c_cflag = (CS8 | CREAD | HUPCL | CLOCAL);
+     tio.c_iflag = (INPCK | BRKINT);
+     cfsetispeed(&tio, bconst);
+     cfsetospeed(&tio, bconst);
+     if(!tcsetattr(m_hComport, TCSANOW, &tio)) {
+         tcflush(m_hComport, TCIOFLUSH);
+     } else {
+         // can't change parms
+        close(m_hComport);
+        m_hComport = -1;
+        return false;
+     }
+
+#endif
+
+     return true;
+}
+
+void CAtmoSerialConnection::CloseConnection() {
+  if(m_hComport!=INVALID_HANDLE_VALUE) {
+#if defined(WIN32)
+     CloseHandle(m_hComport);
+#else
+     close(m_hComport);
+#endif
+        m_hComport = INVALID_HANDLE_VALUE;
+  }
+}
+
+ATMO_BOOL CAtmoSerialConnection::isOpen(void) {
+        return (m_hComport != INVALID_HANDLE_VALUE);
+}
+
+ATMO_BOOL CAtmoSerialConnection::HardwareWhiteAdjust(int global_gamma,
+                                                     int global_contrast,
+                                                     int contrast_red,
+                                                     int contrast_green,
+                                                     int contrast_blue,
+                                                     int gamma_red,
+                                                     int gamma_green,
+                                                     int gamma_blue,
+                                                     ATMO_BOOL storeToEeprom) {
+     if(m_hComport == INVALID_HANDLE_VALUE)
+           return ATMO_FALSE;
+
+     DWORD iBytesWritten;
+/*
+[0] = 255
+[1] = 00
+[2] = 00
+[3] = 101
+
+[4]  brightness  0..255 ?
+
+[5]  Contrast Red     11 .. 100
+[6]  Contrast  Green  11 .. 100
+[7]  Contrast  Blue   11 .. 100
+
+[8]   Gamma Red    11 .. 35
+[9]   Gamma Red    11 .. 35
+[10]  Gamma Red    11 .. 35
+
+[11]  Globale Contrast  11 .. 100
+
+[12]  Store Data: 199 (else 0)
+
+*/
+     unsigned char sendBuffer[16];
+     sendBuffer[0] = 0xFF;
+     sendBuffer[1] = 0x00;
+     sendBuffer[2] = 0x00;
+     sendBuffer[3] = 101;
+
+     sendBuffer[4] = (global_gamma & 255);
+
+     sendBuffer[5] = (contrast_red & 255);
+     sendBuffer[6] = (contrast_green & 255);
+     sendBuffer[7] = (contrast_blue & 255);
+
+     sendBuffer[8]  = (gamma_red & 255);
+     sendBuffer[9]  = (gamma_green & 255);
+     sendBuffer[10] = (gamma_blue & 255);
+
+     sendBuffer[11] = (global_contrast & 255);
+
+     if(storeToEeprom == ATMO_TRUE)
+        sendBuffer[12] = 199; // store to eeprom!
+     else
+        sendBuffer[12] = 0;
+
+#if defined(WIN32)
+     WriteFile(m_hComport, sendBuffer, 13, &iBytesWritten, NULL); // send to COM-Port
+#else
+     iBytesWritten = write(m_hComport, sendBuffer, 13);
+     tcdrain(m_hComport);
+#endif
+
+     return (iBytesWritten == 13) ? ATMO_TRUE : ATMO_FALSE;
+}
+
+
+ATMO_BOOL CAtmoSerialConnection::SendData(tColorPacket data) {
+   if(m_hComport == INVALID_HANDLE_VALUE)
+         return ATMO_FALSE;
+
+   unsigned char buffer[19];
+   DWORD iBytesWritten;
+
+   buffer[0] = 0xFF;  // Start Byte
+   buffer[1] = 0x00;  // Start channel 0
+   buffer[2] = 0x00;  // Start channel 0
+   buffer[3] = 15; //
+   int iBuffer = 4;
+   for(int i=0;i<5;i++) {
+       if(m_ChannelAssignment[i]>=0) {
+          buffer[iBuffer++] = data.channel[m_ChannelAssignment[i]].r;
+          buffer[iBuffer++] = data.channel[m_ChannelAssignment[i]].g;
+          buffer[iBuffer++] = data.channel[m_ChannelAssignment[i]].b;
+       } else {
+          buffer[iBuffer++] = 0;
+          buffer[iBuffer++] = 0;
+          buffer[iBuffer++] = 0;
+       }
+   }
+
+#if defined(WIN32)
+   WriteFile(m_hComport, buffer, 19, &iBytesWritten, NULL); // send to COM-Port
+#else
+   iBytesWritten = write(m_hComport, buffer, 19);
+   tcdrain(m_hComport);
+#endif
+
+   return (iBytesWritten == 19) ? ATMO_TRUE : ATMO_FALSE;
+}
+
+ATMO_BOOL CAtmoSerialConnection::SendData(unsigned char numChannels,
+                                          int red[],
+                                          int green[],
+                                          int blue[])
+{
+   if(m_hComport == INVALID_HANDLE_VALUE)
+         return ATMO_FALSE;
+
+   DWORD bufSize = 4 + numChannels*3;
+   unsigned char *buffer = new unsigned char[bufSize];
+   DWORD iBytesWritten;
+
+   buffer[0] = 0xFF;  // Start Byte
+   buffer[1] = 0x00;  // Start Kanal 0
+   buffer[2] = 0x00;  // Start Kanal 0
+   buffer[3] = numChannels * 3; //
+   int iBuffer = 4;
+   for(int i=0;i<numChannels;i++) {
+       if(m_ChannelAssignment[i]>=0) {
+          buffer[iBuffer++] = red[m_ChannelAssignment[i]] & 255;
+          buffer[iBuffer++] = green[m_ChannelAssignment[i]] & 255;
+          buffer[iBuffer++] = blue[m_ChannelAssignment[i]] & 255;
+       } else {
+          buffer[iBuffer++] = 0;
+          buffer[iBuffer++] = 0;
+          buffer[iBuffer++] = 0;
+       }
+   }
+
+#if defined(WIN32)
+   WriteFile(m_hComport, buffer, bufSize, &iBytesWritten, NULL);
+#else
+   iBytesWritten = write(m_hComport, buffer, bufSize);
+   tcdrain(m_hComport);
+#endif
+
+   delete buffer;
+
+   return (iBytesWritten == bufSize) ? ATMO_TRUE : ATMO_FALSE;
+}
+
diff --git a/modules/video_filter/atmo/AtmoSerialConnection.h b/modules/video_filter/atmo/AtmoSerialConnection.h
new file mode 100644 (file)
index 0000000..22ddb72
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * AtmoCom.h: Class for communication with the serial hardware of Atmo Light,
+ * opens and configures the serial port
+ *
+ * See the README.txt file for copyright information and how to reach the author(s).
+ *
+ * $Id$
+ */
+#ifndef _AtmoSerialConnection_h_
+#define _AtmoSerialConnection_h_
+
+#include "AtmoDefs.h"
+#include "AtmoConnection.h"
+#include "AtmoConfig.h"
+
+#if defined(WIN32)
+#   include <windows.h>
+#endif
+
+
+class CAtmoSerialConnection : public CAtmoConnection {
+    private:
+        HANDLE m_hComport;
+
+#if defined(WIN32)
+        DWORD  m_dwLastWin32Error;
+    public:
+        DWORD getLastError() { return m_dwLastWin32Error; }
+#endif
+
+    public:
+       CAtmoSerialConnection(CAtmoConfig *cfg);
+       virtual ~CAtmoSerialConnection(void);
+
+          virtual ATMO_BOOL OpenConnection();
+
+       virtual void CloseConnection();
+
+       virtual ATMO_BOOL isOpen(void);
+
+       virtual ATMO_BOOL SendData(unsigned char numChannels,
+                                  int red[],
+                                  int green[],
+                                  int blue[]);
+
+       virtual ATMO_BOOL SendData(tColorPacket data);
+
+       virtual ATMO_BOOL HardwareWhiteAdjust(int global_gamma,
+                                             int global_contrast,
+                                             int contrast_red,
+                                             int contrast_green,
+                                             int contrast_blue,
+                                             int gamma_red,
+                                             int gamma_green,
+                                             int gamma_blue,
+                                             ATMO_BOOL storeToEeprom);
+};
+
+#endif
diff --git a/modules/video_filter/atmo/AtmoThread.cpp b/modules/video_filter/atmo/AtmoThread.cpp
new file mode 100644 (file)
index 0000000..706b4ce
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * AtmoThread.cpp: Base thread class for all threads inside AtmoWin
+ *
+ * See the README.txt file for copyright information and how to reach the author(s).
+ *
+ * $Id$
+ */
+#include "AtmoThread.h"
+
+#if defined(_ATMO_VLC_PLUGIN_)
+
+CThread::CThread(vlc_object_t *pOwner)
+{
+    int err;
+    m_pAtmoThread = (atmo_thread_t *)vlc_object_create( pOwner,
+                                                        sizeof(atmo_thread_t) );
+    if(m_pAtmoThread)
+    {
+        m_pAtmoThread->p_thread = this;
+        this->m_pOwner = pOwner;
+
+        vlc_object_attach( m_pAtmoThread, m_pOwner);
+
+        vlc_mutex_init( m_pAtmoThread, &m_TerminateLock );
+        err = vlc_cond_init( m_pAtmoThread, &m_TerminateCond );
+        if(err) {
+           msg_Err( m_pAtmoThread, "vlc_cond_init failed %d",err);
+        }
+    }
+}
+
+#else
+
+CThread::CThread(void)
+{
+  m_hThread = CreateThread(NULL, 0, CThread::ThreadProc ,
+                           this, CREATE_SUSPENDED, &m_dwThreadID);
+  m_hTerminateEvent = CreateEvent(NULL,ATMO_FALSE,ATMO_FALSE,NULL);
+}
+
+#endif
+
+
+
+#if defined(_ATMO_VLC_PLUGIN_)
+
+CThread::~CThread(void)
+{
+  if(m_pAtmoThread)
+  {
+      vlc_mutex_destroy( &m_TerminateLock );
+      vlc_cond_destroy( &m_TerminateCond );
+      vlc_object_detach(m_pAtmoThread);
+      vlc_object_destroy(m_pAtmoThread);
+  }
+}
+
+#else
+
+CThread::~CThread(void)
+{
+  CloseHandle(m_hThread);      
+  CloseHandle(m_hTerminateEvent);
+}
+
+#endif
+
+#if defined(_ATMO_VLC_PLUGIN_)
+
+void CThread::ThreadProc(atmo_thread_t *pAtmoThread)
+{
+      CThread *pThread = (CThread *)pAtmoThread->p_thread;
+      if(pThread) {
+         // give feedback I'am running?
+         vlc_thread_ready( pThread->m_pAtmoThread );
+
+            pThread->Execute();
+
+      }
+}
+
+#else
+
+DWORD WINAPI CThread::ThreadProc(LPVOID lpParameter)
+{
+          CThread *aThread = (CThread *)lpParameter;
+          if(aThread)
+             return aThread->Execute();
+          else
+                 return (DWORD)-1;
+}
+
+#endif
+
+
+DWORD CThread::Execute(void)
+{
+  /*
+    to do implement! override!
+
+       while(!bTerminated) {
+        ...
+       }
+  */   
+ return 0;
+}
+
+void CThread::Terminate(void)
+{
+   // Set Termination Flag and EventObject!
+   // and wait for Termination
+   m_bTerminated = ATMO_TRUE;
+
+#if defined(_ATMO_VLC_PLUGIN_)
+   if(m_pAtmoThread)
+   {
+      vlc_mutex_lock( &m_TerminateLock );
+      vlc_cond_signal( &m_TerminateCond  );
+      vlc_mutex_unlock( &m_TerminateLock );
+      vlc_object_kill( m_pAtmoThread );
+
+      vlc_thread_join( m_pAtmoThread );
+   }
+#else
+   SetEvent(m_hTerminateEvent);
+   WaitForSingleObject(m_hThread,INFINITE);
+#endif
+}
+
+void CThread::Run()
+{
+   m_bTerminated = ATMO_FALSE;
+
+#if defined(_ATMO_VLC_PLUGIN_)
+   m_pAtmoThread->b_die = VLC_FALSE;
+   if(vlc_thread_create( m_pAtmoThread,
+                         "Atmo-CThread-Class",
+                         CThread::ThreadProc,
+                         VLC_THREAD_PRIORITY_LOW,
+                         VLC_FALSE ))
+   {
+      msg_Err( m_pOwner, "cannot launch one of the AtmoLight threads");
+   }
+
+#else
+
+   ResetEvent(m_hTerminateEvent);
+   ResumeThread(m_hThread);
+
+#endif
+}
+
+/*
+   does a sleep if the sleep was interrupted through
+   the thread kill event return false...
+*/
+ATMO_BOOL CThread::ThreadSleep(DWORD millisekunden)
+{
+#if defined(_ATMO_VLC_PLUGIN_)
+     vlc_mutex_lock( &m_TerminateLock );
+     int value = vlc_cond_timedwait(&m_TerminateCond,
+                                    &m_TerminateLock,
+                                    mdate() + (mtime_t)(millisekunden * 1000));
+     vlc_mutex_unlock( &m_TerminateLock );
+     return (value != 0);
+
+#else
+     DWORD res = WaitForSingleObject(m_hTerminateEvent,millisekunden);
+        return (res == WAIT_TIMEOUT);
+#endif
+}
+
diff --git a/modules/video_filter/atmo/AtmoThread.h b/modules/video_filter/atmo/AtmoThread.h
new file mode 100644 (file)
index 0000000..1289823
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * AtmoThread.h: Base thread class for all threads inside AtmoWin
+ *
+ *
+ * See the README.txt file for copyright information and how to reach the author(s).
+ *
+ * $Id$
+ */
+#ifndef _AtmoThread_h_
+#define _AtmoThread_h_
+
+#include "AtmoDefs.h"
+
+#if defined(_ATMO_VLC_PLUGIN_)
+// use threading stuff from videolan!
+#   include <vlc/vlc.h>
+#   include <vlc_threads_funcs.h>
+#   include <vlc_threads.h>
+
+    typedef struct
+    {
+      VLC_COMMON_MEMBERS
+      void *p_thread; /* cast to CThread * */
+    } atmo_thread_t;
+
+#else
+#   include <windows.h>
+#endif
+
+class CThread
+{
+protected:
+
+#if defined(_ATMO_VLC_PLUGIN_)
+
+    atmo_thread_t *m_pAtmoThread;
+    vlc_mutex_t  m_TerminateLock;
+    vlc_cond_t   m_TerminateCond;
+    vlc_object_t *m_pOwner;
+
+#else
+
+    HANDLE m_hThread;
+       DWORD m_dwThreadID;
+       HANDLE m_hTerminateEvent;
+
+#endif
+
+    volatile ATMO_BOOL m_bTerminated;
+
+private:
+
+#if defined(_ATMO_VLC_PLUGIN_)
+    static void ThreadProc(atmo_thread_t *pAtmoThread);
+#else
+       static DWORD WINAPI ThreadProc(LPVOID lpParameter);
+#endif
+
+protected:
+       virtual DWORD Execute(void);
+       ATMO_BOOL ThreadSleep(DWORD millisekunden);
+
+public:
+#if defined(_ATMO_VLC_PLUGIN_)
+       CThread(vlc_object_t *pOwner);
+#else
+       CThread(void);
+#endif
+
+    virtual ~CThread(void);
+
+    void Terminate(void);
+    void Run();
+
+};
+
+#endif
+
diff --git a/modules/video_filter/atmo/AtmoTools.cpp b/modules/video_filter/atmo/AtmoTools.cpp
new file mode 100644 (file)
index 0000000..09eb4ba
--- /dev/null
@@ -0,0 +1,276 @@
+/*
+ * AtmoTools.cpp: Collection of tool and helperfunction
+ *
+ * See the README.txt file for copyright information and how to reach the author(s).
+ *
+ * $Id$
+ */
+
+#include "AtmoTools.h"
+#include "AtmoLiveView.h"
+#include "AtmoSerialConnection.h"
+
+#if !defined(_ATMO_VLC_PLUGIN_)
+#   include "AtmoColorChanger.h"
+#   include "AtmoLeftRightColorChanger.h"
+#   include "AtmoDummyConnection.h"
+#   include "AtmoDmxSerialConnection.h"
+#endif
+
+
+CAtmoTools::CAtmoTools(void)
+{
+}
+
+CAtmoTools::~CAtmoTools(void)
+{
+}
+
+void CAtmoTools::ShowShutdownColor(CAtmoDynData *pDynData)
+{
+    pDynData->LockCriticalSection();
+
+    CAtmoConnection *atmoConnection = pDynData->getAtmoConnection();
+    CAtmoConfig *atmoConfig = pDynData->getAtmoConfig();
+    if((atmoConnection != NULL) && (atmoConfig!=NULL)) {
+       int r[ATMO_NUM_CHANNELS],g[ATMO_NUM_CHANNELS],b[ATMO_NUM_CHANNELS],i;
+       // set a special color? on shutdown of the software? mostly may use black or so ...
+       // if this function ist disabled ... atmo will continuing to show the last color...
+       if(atmoConnection->isOpen() == ATMO_TRUE) {
+               if(atmoConfig->isSetShutdownColor() == 1) {
+                       for(i=0;i<ATMO_NUM_CHANNELS;i++) {
+                               r[i] = atmoConfig->getShutdownColor_Red();
+                               g[i] = atmoConfig->getShutdownColor_Green();
+                               b[i] = atmoConfig->getShutdownColor_Blue();
+                       }
+                atmoConnection->SendData(ATMO_NUM_CHANNELS,r,g,b);
+               }
+       }
+       }
+
+    pDynData->UnLockCriticalSection();
+}
+
+EffectMode CAtmoTools::SwitchEffect(CAtmoDynData *pDynData, EffectMode newEffectMode)
+{
+    // may need a critical section??
+    if(pDynData == NULL) {
+       return emUndefined;
+    }
+    pDynData->LockCriticalSection();
+
+    CAtmoConfig *atmoConfig = pDynData->getAtmoConfig();
+    if(atmoConfig == NULL) {
+       pDynData->UnLockCriticalSection();
+       return emUndefined;
+    }
+    CAtmoConnection *atmoConnection = pDynData->getAtmoConnection();
+
+    EffectMode oldEffectMode = atmoConfig->getEffectMode();
+    CThread *currentEffect = pDynData->getEffectThread();
+
+    // stop and delete/cleanup current Effect Thread...
+    pDynData->setEffectThread(NULL);
+    if(currentEffect!=NULL) {
+       currentEffect->Terminate();
+       delete currentEffect;
+       currentEffect = NULL;
+    }
+
+    if((atmoConnection!=NULL) && (atmoConnection->isOpen()==ATMO_TRUE)) {
+        // neuen EffectThread nur mit aktiver Connection starten...
+
+        switch(newEffectMode) {
+            case emDisabled:
+                break;
+
+            case emStaticColor:
+                    // get values from config - and put them to all channels?
+                    int r[ATMO_NUM_CHANNELS],g[ATMO_NUM_CHANNELS],b[ATMO_NUM_CHANNELS];
+                    for(int i=0;i<ATMO_NUM_CHANNELS;i++) {
+                        r[i] = (atmoConfig->getStaticColor_Red()   * atmoConfig->getWhiteAdjustment_Red())/255;
+                        g[i] = (atmoConfig->getStaticColor_Green() * atmoConfig->getWhiteAdjustment_Green())/255;
+                        b[i] = (atmoConfig->getStaticColor_Blue()  * atmoConfig->getWhiteAdjustment_Blue())/255;
+                    }
+                    atmoConnection->SendData(ATMO_NUM_CHANNELS,r,g,b);
+                break;
+
+            case emLivePicture:
+                currentEffect = new CAtmoLiveView(pDynData);
+                break;
+
+#if !defined(_ATMO_VLC_PLUGIN_)
+            case emColorChange:
+                currentEffect = new CAtmoColorChanger(atmoConnection, atmoConfig);
+                break;
+#endif
+
+#if !defined(_ATMO_VLC_PLUGIN_)
+            case emLrColorChange:
+                currentEffect = new CAtmoLeftRightColorChanger(atmoConnection, atmoConfig);
+                break;
+#endif
+        }
+
+    }
+
+    atmoConfig->setEffectMode(newEffectMode);
+
+    pDynData->setEffectThread(currentEffect);
+
+    if(currentEffect!=NULL)
+       currentEffect->Run();
+
+    pDynData->UnLockCriticalSection();
+    return oldEffectMode;
+}
+
+ATMO_BOOL CAtmoTools::RecreateConnection(CAtmoDynData *pDynData)
+{
+    pDynData->LockCriticalSection();
+
+    CAtmoConnection *current = pDynData->getAtmoConnection();
+    AtmoConnectionType act = pDynData->getAtmoConfig()->getConnectionType();
+    pDynData->setAtmoConnection(NULL);
+    if(current != NULL) {
+       current->CloseConnection();
+       delete current;
+    }
+
+    switch(act) {
+           case actSerialPort: {
+               CAtmoSerialConnection *tempConnection = new CAtmoSerialConnection(pDynData->getAtmoConfig());
+               if(tempConnection->OpenConnection() == ATMO_FALSE) {
+#if !defined(_ATMO_VLC_PLUGIN_)
+                  char errorMsgBuf[200];
+                  sprintf(errorMsgBuf,"Failed to open serial port com%d with errorcode: %d (0x%x)",
+                            pDynData->getAtmoConfig()->getComport(),
+                            tempConnection->getLastError(),
+                            tempConnection->getLastError()
+                        );
+                  MessageBox(0,errorMsgBuf,"Error",MB_ICONERROR | MB_OK);
+#endif
+                  delete tempConnection;
+
+                  pDynData->UnLockCriticalSection();
+                  return ATMO_FALSE;
+               }
+               pDynData->setAtmoConnection(tempConnection);
+
+               CAtmoTools::SetChannelAssignment(pDynData,
+                           pDynData->getAtmoConfig()->getCurrentChannelAssignment());
+
+               pDynData->UnLockCriticalSection();
+               return ATMO_TRUE;
+           }
+
+#if !defined(_ATMO_VLC_PLUGIN_)
+           case actDummy: {
+               CAtmoDummyConnection *tempConnection = new CAtmoDummyConnection(pDynData->getHinstance(),
+                                                                               pDynData->getAtmoConfig());
+               if(tempConnection->OpenConnection() == ATMO_FALSE) {
+                  delete tempConnection;
+
+                  pDynData->UnLockCriticalSection();
+                  return ATMO_FALSE;
+               }
+               pDynData->setAtmoConnection(tempConnection);
+
+               CAtmoTools::SetChannelAssignment(pDynData, pDynData->getAtmoConfig()->getCurrentChannelAssignment());
+
+               pDynData->UnLockCriticalSection();
+               return ATMO_TRUE;
+           }
+
+           case actDMX: {
+               // create here your DMX connections... instead of the dummy....
+               CAtmoDmxSerialConnection *tempConnection = new CAtmoDmxSerialConnection(pDynData->getAtmoConfig());
+               if(tempConnection->OpenConnection() == ATMO_FALSE) {
+                  delete tempConnection;
+
+                  pDynData->UnLockCriticalSection();
+                  return ATMO_FALSE;
+               }
+               pDynData->setAtmoConnection(tempConnection);
+
+               CAtmoTools::SetChannelAssignment(pDynData, pDynData->getAtmoConfig()->getCurrentChannelAssignment());
+
+               pDynData->UnLockCriticalSection();
+               return ATMO_TRUE;
+           }
+#endif
+
+           default: {
+               pDynData->UnLockCriticalSection();
+               return ATMO_FALSE;
+           }
+    }
+}
+
+tColorPacket CAtmoTools::WhiteCalibration(CAtmoConfig *pAtmoConfig, tColorPacket ColorPacket)
+{
+    int w_adj_red   = pAtmoConfig->getWhiteAdjustment_Red();
+    int w_adj_green = pAtmoConfig->getWhiteAdjustment_Green();
+    int w_adj_blue  = pAtmoConfig->getWhiteAdjustment_Blue();
+
+    for (int i = 0; i < ATMO_NUM_CHANNELS; i++)  {
+        ColorPacket.channel[i].r = (unsigned char)(((int)w_adj_red   * (int)ColorPacket.channel[i].r)   / 255);
+        ColorPacket.channel[i].g = (unsigned char)(((int)w_adj_green * (int)ColorPacket.channel[i].g) / 255);
+        ColorPacket.channel[i].b = (unsigned char)(((int)w_adj_blue  * (int)ColorPacket.channel[i].b)  / 255);
+    }
+    return ColorPacket;
+}
+
+tColorPacket CAtmoTools::ApplyGamma(CAtmoConfig *pAtmoConfig, tColorPacket ColorPacket)
+{
+  return ColorPacket;
+}
+
+int CAtmoTools::SetChannelAssignment(CAtmoDynData *pDynData, int index)
+{
+    CAtmoConfig *pAtmoConfig = pDynData->getAtmoConfig();
+    CAtmoConnection *pAtmoConnection = pDynData->getAtmoConnection();
+    int oldIndex = pAtmoConfig->getCurrentChannelAssignment();
+
+    tChannelAssignment *ca = pAtmoConfig->getChannelAssignment(index);
+    if((ca!=NULL) && (pAtmoConnection!=NULL)) {
+        pAtmoConnection->SetChannelAssignment(ca);
+        pAtmoConfig->setCurrentChannelAssignment(index);
+    }
+    return oldIndex;
+}
+
+
+#if !defined(_ATMO_VLC_PLUGIN_)
+
+void CAtmoTools::SaveBitmap(HDC hdc,HBITMAP hBmp,char *fileName) {
+     BITMAPINFO bmpInfo;
+     BITMAPFILEHEADER  bmpFileHeader;
+     ZeroMemory(&bmpInfo, sizeof(BITMAPINFO));
+     bmpInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
+
+     GetDIBits(hdc,hBmp,0,0,NULL,&bmpInfo,DIB_RGB_COLORS);
+     if(bmpInfo.bmiHeader.biSizeImage<=0)
+        bmpInfo.bmiHeader.biSizeImage=bmpInfo.bmiHeader.biWidth * abs(bmpInfo.bmiHeader.biHeight)*(bmpInfo.bmiHeader.biBitCount+7)/8;
+     void *pBuf = malloc(bmpInfo.bmiHeader.biSizeImage);
+     bmpInfo.bmiHeader.biCompression=BI_RGB;
+
+     GetDIBits(hdc,hBmp,0,bmpInfo.bmiHeader.biHeight,pBuf, &bmpInfo, DIB_RGB_COLORS);
+
+
+     bmpFileHeader.bfReserved1=0;
+     bmpFileHeader.bfReserved2=0;
+     bmpFileHeader.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+bmpInfo.bmiHeader.biSizeImage;
+     bmpFileHeader.bfType='MB';
+     bmpFileHeader.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
+
+     FILE *fp = NULL;
+     fp = fopen(fileName,"wb");
+     fwrite(&bmpFileHeader,sizeof(BITMAPFILEHEADER),1,fp);
+     fwrite(&bmpInfo.bmiHeader,sizeof(BITMAPINFOHEADER),1,fp);
+     fwrite(pBuf,bmpInfo.bmiHeader.biSizeImage,1,fp);
+     fclose(fp);
+}
+
+#endif
+
diff --git a/modules/video_filter/atmo/AtmoTools.h b/modules/video_filter/atmo/AtmoTools.h
new file mode 100644 (file)
index 0000000..d80ea07
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * AtmoTools.h: Collection of tool and helperfunction
+ *
+ * See the README.txt file for copyright information and how to reach the author(s).
+ *
+ * $Id$
+ */
+#ifndef _AtmoTools_h_
+#define _AtmoTools_h_
+
+#include "AtmoDefs.h"
+
+#include "AtmoConfig.h"
+#include "AtmoConnection.h"
+#include "AtmoDynData.h"
+
+/*
+  implements some tool functions - for use in different classes - and cases!
+
+  to avoid copy and paste code ...
+*/
+class CAtmoTools
+{
+private:
+    CAtmoTools(void);
+    ~CAtmoTools(void);
+public:
+    static EffectMode SwitchEffect(CAtmoDynData *pDynData, EffectMode newEffectMode);
+    static void ShowShutdownColor(CAtmoDynData *pDynData);
+    static ATMO_BOOL RecreateConnection(CAtmoDynData *pDynData);
+
+    static tColorPacket WhiteCalibration(CAtmoConfig *pAtmoConfig, tColorPacket ColorPacket);
+    static tColorPacket ApplyGamma(CAtmoConfig *pAtmoConfig, tColorPacket ColorPacket);
+
+    static int SetChannelAssignment(CAtmoDynData *pDynData, int index);
+
+#if !defined(_ATMO_VLC_PLUGIN_)
+    static void SaveBitmap(HDC hdc,HBITMAP hBmp,char *fileName);
+#endif
+};
+
+#endif
diff --git a/modules/video_filter/atmo/AtmoZoneDefinition.cpp b/modules/video_filter/atmo/AtmoZoneDefinition.cpp
new file mode 100644 (file)
index 0000000..854a9e2
--- /dev/null
@@ -0,0 +1,226 @@
+
+#include "AtmoDefs.h"
+
+#if defined (WIN32)
+#  include <windows.h>
+#else
+#  include <vlc_codecs.h>
+#endif
+
+#include <math.h>
+#include <stdio.h>
+#include "AtmoZoneDefinition.h"
+
+CAtmoZoneDefinition::CAtmoZoneDefinition(void)
+{
+}
+
+CAtmoZoneDefinition::~CAtmoZoneDefinition(void)
+{
+}
+
+void CAtmoZoneDefinition::Fill(unsigned char value)
+{
+  for(int i=0; i < IMAGE_SIZE; i++)
+      m_BasicWeight[i] = value;
+}
+
+// max weight to left
+void CAtmoZoneDefinition::FillGradientFromLeft()
+{
+   int index = 0;
+   unsigned char col_norm;
+   for(int row=0; row < CAP_HEIGHT; row++) {
+       for(int col=0; col < CAP_WIDTH; col++) {
+           // should be a value between 0 .. 255?
+           col_norm = (255 * (CAP_WIDTH-col-1)) / (CAP_WIDTH-1);
+           m_BasicWeight[index++] = col_norm;
+       }
+   }
+}
+
+// max weight to right
+void CAtmoZoneDefinition::FillGradientFromRight()
+{
+   int index = 0;
+   unsigned char col_norm;
+   for(int row=0; row < CAP_HEIGHT; row++) {
+      for(int col=0; col < CAP_WIDTH; col++) {
+          col_norm = (255 * col) / (CAP_WIDTH-1); // should be a value between 0 .. 255?
+          m_BasicWeight[index++] = col_norm;
+       }
+   }
+}
+
+// max weight from top
+void CAtmoZoneDefinition::FillGradientFromTop()
+{
+   int index = 0;
+   unsigned char row_norm;
+   for(int row=0; row < CAP_HEIGHT; row++) {
+       row_norm = (255 * (CAP_HEIGHT-row-1)) / (CAP_HEIGHT-1); // should be a value between 0 .. 255?
+       for(int col=0; col < CAP_WIDTH; col++) {
+           m_BasicWeight[index++] = row_norm;
+       }
+   }
+}
+
+// max weight from bottom
+void CAtmoZoneDefinition::FillGradientFromBottom()
+{
+   int index = 0;
+   unsigned char row_norm;
+   for(int row=0; row < CAP_HEIGHT; row++) {
+       row_norm = (255 * row) / (CAP_HEIGHT-1); // should be a value between 0 .. 255?
+       for(int col=0; col < CAP_WIDTH; col++) {
+           m_BasicWeight[index++] = row_norm;
+       }
+   }
+}
+
+
+int CAtmoZoneDefinition::LoadGradientFromBitmap(char *pszBitmap)
+{
+  // transform 256 color image (gray scale!)
+  // into m_basicWeight or use the GREEN value of a 24bit image!
+  // channel of a true color bitmap!
+  BITMAPINFO bmpInfo;
+  BITMAPFILEHEADER  bmpFileHeader;
+
+  /*
+#define ATMO_LOAD_GRADIENT_OK  0
+#define ATMO_LOAD_GRADIENT_FAILED_SIZE    1
+#define ATMO_LOAD_GRADIENT_FAILED_HEADER  2
+  */
+
+
+   FILE *bmp = fopen(pszBitmap, "rb");
+   if(!bmp)
+     return ATMO_LOAD_GRADIENT_FILENOTFOND;
+
+    if(fread(&bmpFileHeader, sizeof(BITMAPFILEHEADER), 1, bmp) != 1)
+    {
+        fclose(bmp);
+        return ATMO_LOAD_GRADIENT_FAILED_SIZE;
+    }
+
+    if(bmpFileHeader.bfType != 'MB')
+    {
+        fclose(bmp);
+        return ATMO_LOAD_GRADIENT_FAILED_HEADER;
+    }
+
+    if(fread(&bmpInfo, sizeof(BITMAPINFO), 1, bmp) != 1)
+    {
+        fclose(bmp);
+        return ATMO_LOAD_GRADIENT_FAILED_SIZE;
+    }
+
+    if(bmpInfo.bmiHeader.biCompression != BI_RGB)
+    {
+        fclose(bmp);
+        return ATMO_LOAD_GRADIENT_FAILED_FORMAT;
+    }
+    if((bmpInfo.bmiHeader.biBitCount != 8) && (bmpInfo.bmiHeader.biBitCount != 24))
+    {
+        fclose(bmp);
+        return ATMO_LOAD_GRADIENT_FAILED_FORMAT;
+    }
+
+    int width = bmpInfo.bmiHeader.biWidth;
+    int height = bmpInfo.bmiHeader.biHeight;
+    ATMO_BOOL invertDirection = (height > 0);
+    height = abs(height);
+    if((width != CAP_WIDTH) || (height != CAP_HEIGHT))
+    {
+        fclose(bmp);
+        return ATMO_LOAD_GRADIENT_FAILED_SIZE;
+    }
+
+    fseek(bmp, bmpFileHeader.bfOffBits, SEEK_SET);
+
+    int imageSize = width * height * bmpInfo.bmiHeader.biBitCount/8;
+
+    unsigned char *pixelBuffer = (unsigned char *)malloc(imageSize);
+    if(fread(pixelBuffer,imageSize,1,bmp) != 1)
+    {
+        fclose(bmp);
+        return ATMO_LOAD_GRADIENT_FAILED_SIZE;
+    }
+
+    if(bmpInfo.bmiHeader.biBitCount == 8)
+    {
+        int ydest;
+        for(int y=0;y < CAP_HEIGHT; y++) {
+            if(invertDirection) {
+                ydest = (CAP_HEIGHT - y - 1);
+            } else {
+                ydest = y;
+            }
+            for(int x=0;x < CAP_WIDTH; x++) {
+                // palette should be grey scale - so that index 0 is black and
+                // index 255 means white!
+                // everything else would produce funny results!
+                m_BasicWeight[ydest * CAP_WIDTH + x] =
+                    pixelBuffer[y * CAP_WIDTH + x];
+            }
+        }
+    }
+
+    if(bmpInfo.bmiHeader.biBitCount == 24)
+    {
+        int ydest;
+        for(int y=0;y < CAP_HEIGHT; y++) {
+            if(invertDirection) {
+                ydest = (CAP_HEIGHT - y - 1);
+            } else {
+                ydest = y;
+            }
+            for(int x=0;x < CAP_WIDTH; x++) {
+                // use the green value as reference...
+                m_BasicWeight[ydest * CAP_WIDTH + x] =
+                    pixelBuffer[y * CAP_WIDTH * 3 + (x*3) + 1 ];
+            }
+        }
+    }
+    free(pixelBuffer);
+    fclose(bmp);
+
+    return ATMO_LOAD_GRADIENT_OK;
+}
+
+
+void CAtmoZoneDefinition::UpdateWeighting(int *destWeight,
+                                          int WidescreenMode,
+                                          int newEdgeWeightning)
+{
+  /*
+    use the values in m_BasicWeight and newWeightning to
+    update the direct control array for the output thread!
+  */
+
+  int index = 0;
+  for(int row=0; row < CAP_HEIGHT; row++) {
+      for(int col=0; col < CAP_HEIGHT; col++) {
+          if ((WidescreenMode == 1) && ((row <= CAP_HEIGHT/8) || (row >= (7*CAP_HEIGHT)/8)))
+          {
+             destWeight[index] = 0;
+          } else {
+             destWeight[index] = (int)(255.0 * (float)pow( ((float)m_BasicWeight[index])/255.0 , newEdgeWeightning));
+          }
+          index++;
+      }
+  }
+}
+
+void CAtmoZoneDefinition::setZoneNumber(int num)
+{
+    m_zonenumber = num;
+}
+
+int CAtmoZoneDefinition::getZoneNumber()
+{
+    return m_zonenumber;
+}
+
+
diff --git a/modules/video_filter/atmo/AtmoZoneDefinition.h b/modules/video_filter/atmo/AtmoZoneDefinition.h
new file mode 100644 (file)
index 0000000..96c798f
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef _AtmoZoneDefinition_h_
+#define _AtmoZoneDefinition_h_
+
+#include "AtmoDefs.h"
+
+#define ATMO_LOAD_GRADIENT_OK  0
+#define ATMO_LOAD_GRADIENT_FILENOTFOND    1
+#define ATMO_LOAD_GRADIENT_FAILED_SIZE    2
+#define ATMO_LOAD_GRADIENT_FAILED_HEADER  3
+#define ATMO_LOAD_GRADIENT_FAILED_FORMAT  4
+
+
+class CAtmoZoneDefinition
+{
+private:
+    int m_zonenumber; // just for identification and channel assignment!
+    unsigned char m_BasicWeight[IMAGE_SIZE];
+
+public:
+    CAtmoZoneDefinition(void);
+    ~CAtmoZoneDefinition(void);
+
+    void Fill(unsigned char value);
+    void FillGradientFromLeft();
+    void FillGradientFromRight();
+    void FillGradientFromTop();
+    void FillGradientFromBottom();
+
+    int LoadGradientFromBitmap(char *pszBitmap);
+
+    void UpdateWeighting(int *destWeight,
+                         int WidescreenMode,
+                         int newEdgeWeightning);
+
+    void setZoneNumber(int num);
+    int getZoneNumber();
+};
+
+#endif
diff --git a/modules/video_filter/atmo/COPYING.txt b/modules/video_filter/atmo/COPYING.txt
new file mode 100644 (file)
index 0000000..f90922e
--- /dev/null
@@ -0,0 +1,340 @@
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program 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 General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/modules/video_filter/atmo/Modules.am b/modules/video_filter/atmo/Modules.am
new file mode 100644 (file)
index 0000000..3263cd5
--- /dev/null
@@ -0,0 +1,2 @@
+SOURCES_atmo = atmo.cpp AtmoDefs.h AtmoCalculations.cpp AtmoCalculations.h AtmoConfig.cpp AtmoConfig.h AtmoConnection.cpp AtmoConnection.h AtmoDynData.cpp AtmoDynData.h AtmoExternalCaptureInput.cpp AtmoExternalCaptureInput.h AtmoInput.cpp AtmoInput.h AtmoLiveView.cpp AtmoLiveView.h AtmoOutputFilter.cpp AtmoOutputFilter.h AtmoSerialConnection.cpp AtmoSerialConnection.h AtmoThread.cpp AtmoThread.h AtmoTools.cpp AtmoTools.h AtmoZoneDefinition.cpp AtmoZoneDefinition.h 
+
diff --git a/modules/video_filter/atmo/README.txt b/modules/video_filter/atmo/README.txt
new file mode 100644 (file)
index 0000000..a48353a
--- /dev/null
@@ -0,0 +1,52 @@
+This piece of software is based on the software and descriptions mentioned below -
+
+
+(re)Written by:              Igor / Atmo (aka André Weber)  - WeberAndre@gmx.de
+                             Matthiaz    
+                             MacGyver2k
+
+if you need to contact one of us - come to www.vdr-portal.de 
+
+http://www.vdr-portal.de/board/thread.php?threadid=59294 -- Description and Development of the Windows Software
+http://www.vdr-portal.de/board/thread.php?threadid=48574 -- Description and Development of the Hardware part
+
+
+See the file COPYING.txt for license information.
+
+Original Readme - of the Linux Version - from where some code was used
+to do the color calculations ...
+
+######################################################################
+This is the Atmolight-plugin for the Video Disk Recorder (VDR).
+
+Written by:                  Eike Edener   <vdr@edener.de>
+
+Project's homepage:          www.edener.de
+
+Latest version available at: www.edener.de
+
+See the file COPYING for license information.
+
+Requirements: a full-featured DVB-card or
+              softdevice-plugin (2006-12-03: CVS-version necessary)
+
+Description: Plugin for the Atmolight.
+
+----------------------------------------------------------------------
+
+for detailed informations visit the VDR-Wiki:
+http://www.vdr-wiki.de/wiki/index.php/Atmo-plugin
+
+Development:
+http://www.vdr-portal.de/board/thread.php?threadid=48574
+
+Known bugs:
+n/a
+
+----------------------------------------------------------------------
+
+NOTE:
+-------
+If you want to change the Atmolight color from outside,
+you can do this with a script using SVDRP-commands
+(see scripts/disco.sh).
diff --git a/modules/video_filter/atmo/atmo.cpp b/modules/video_filter/atmo/atmo.cpp
new file mode 100644 (file)
index 0000000..00909b3
--- /dev/null
@@ -0,0 +1,2283 @@
+/*****************************************************************************
+* atmo.cpp : "Atmo Light" video filter
+*****************************************************************************
+* Copyright (C) 2000-2006 the VideoLAN team
+* $Id$
+*
+* Authors: André Weber (WeberAndre@gmx.de)
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program 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 General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+*****************************************************************************/
+
+/*****************************************************************************
+* Preamble
+*****************************************************************************/
+#include <stdlib.h>                                      /* malloc(), free() */
+#include <string.h>
+#include <math.h>                                            /* sin(), cos() */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+// #define __ATMO_DEBUG__
+// [:Zs]+$
+#include <vlc/vlc.h>
+#include <vlc_vout.h>
+
+#include <vlc_playlist.h>
+#include "vlc_filter.h"
+
+#include "AtmoDefs.h"
+#include "AtmoDynData.h"
+#include "AtmoLiveView.h"
+#include "AtmoTools.h"
+#include "AtmoExternalCaptureInput.h"
+#include "AtmoConfig.h"
+#include "AtmoConnection.h"
+#include "AtmoSerialConnection.h"
+
+
+/*****************************************************************************
+* Local prototypes
+*****************************************************************************/
+/* directly to vlc related functions required that the module is accepted */
+static int  CreateFilter    ( vlc_object_t * );
+static void DestroyFilter   ( vlc_object_t * );
+static picture_t * Filter( filter_t *, picture_t *);
+
+/* callback for global variable state pause / continue / stop events */
+static void AddStateVariableCallback( filter_t *);
+static void DelStateVariableCallback( filter_t *);
+static int StateCallback(vlc_object_t *, char const *,
+                         vlc_value_t, vlc_value_t, void *);
+
+/* callback for variable crop-update */
+static void AddCropVariableCallback( filter_t *);
+static void DelCropVariableCallback( filter_t *);
+static int CropCallback(vlc_object_t *, char const *,
+                        vlc_value_t, vlc_value_t, void *);
+
+/* callback for atmo settings variables whose change
+   should be immediately realized and applied to output
+*/
+static void DelAtmoSettingsVariablesCallbacks(filter_t *);
+static void AddAtmoSettingsVariablesCallbacks(filter_t *);
+static int AtmoSettingsCallback(vlc_object_t *, char const *,
+                                vlc_value_t, vlc_value_t, void *);
+
+
+#if defined(__ATMO_DEBUG__)
+static void atmo_parse_crop(char *psz_cropconfig,
+                            video_format_t fmt_in,
+                            video_format_t fmt_render,
+                            int &i_visible_width,
+                            int &i_visible_height,
+                            int &i_x_offset,
+                            int &i_y_offset );
+#endif
+
+
+/* function to shutdown the fade thread which is started on pause*/
+static void CheckAndStopFadeThread(filter_t *);
+
+/* extracts a small RGB (BGR) Image from an YUV image */
+static void ExtractMiniImage_YUV(filter_sys_t *, picture_t *, uint8_t *);
+
+#if defined(__ATMO_DEBUG__)
+void SaveBitmap(filter_sys_t *p_sys, uint8_t *p_pixels, char *psz_filename);
+#endif
+
+/*****************************************************************************
+* External Prototypes for the AtmoCtrlLib.DLL
+*****************************************************************************/
+/*
+* if effectmode = emLivePicture then the source could be GDI (Screencapture)
+* or External - this means another application delivers Pixeldata to AtmoWin
+* Clientsoftware through  AtmoCtrlLib.DLL and the COM Api
+*/
+#define lvsGDI           0
+#define lvsExternal      1
+
+
+/*
+strings for settings menus and hints
+*/
+#define MODULE_DESCRIPTION N_ ( \
+ "This module allows to control an so called AtmoLight device which "\
+ "is connected to your computer.\n"\
+ "AtmoLight is the homebrew version of that what Philips calls AmbiLight.\n"\
+ "If you need further informations feel free to visit us at\n\n"\
+ "http://www.vdr-wiki.de/wiki/index.php/Atmo-plugin\n"\
+ "http://www.vdr-wiki.de/wiki/index.php/AtmoWin\n\n"\
+ "there you will find detailed descriptions how to build it for your self and "\
+ "where you can get the required parts and so on.\n There you can also see "\
+ "pictures and some movies showing such a device in live action...")
+
+
+
+#if defined( __ATMO_DEBUG__ )
+#   define SAVEFRAMES_TEXT     N_("Save Debug Frames")
+#   define SAVEFRAMES_LONGTEXT N_("Writes every 128th miniframe to a folder.")
+#   define FRAMEPATH_TEXT      N_("Debug Frame Folder")
+#   define FRAMEPATH_LONGTEXT  N_("defines the path where the debugframes " \
+                                  "should be saved")
+#endif
+
+#define WIDTH_TEXT             N_("Extracted Image Width")
+#define WIDTH_LONGTEXT         N_("defines the width of the mini image for " \
+                                  "further processing (64 is default)")
+
+#define HEIGHT_TEXT            N_("Extracted Image Height")
+#define HEIGHT_LONGTEXT        N_("defines the height of the mini image for " \
+                                  "further processing (48 is default)")
+
+#define PCOLOR_TEXT            N_("use Pause Color")
+#define PCOLOR_LONGTEXT        N_("use the color defined below if the user " \
+                          "paused the video.(have light to get another beer?)")
+#define PCOLOR_RED_TEXT        N_("Pause-Red")
+#define PCOLOR_RED_LONGTEXT    N_("the red component of pause color")
+#define PCOLOR_GREEN_TEXT      N_("Pause-Green")
+#define PCOLOR_GREEN_LONGTEXT  N_("the green component of pause color")
+#define PCOLOR_BLUE_TEXT       N_("Pause-Blue")
+#define PCOLOR_BLUE_LONGTEXT   N_("the blue component of pause color")
+#define FADESTEPS_TEXT         N_("Pause-Fadesteps")
+#define FADESTEPS_LONGTEXT     N_("Number of steps to change current color " \
+                                  "to pause color (each step takes 40ms)")
+
+#define ECOLOR_RED_TEXT        N_("End-Red")
+#define ECOLOR_RED_LONGTEXT    N_("the red component of the shutdown color")
+#define ECOLOR_GREEN_TEXT      N_("End-Green")
+#define ECOLOR_GREEN_LONGTEXT  N_("the green component of the shutdown color")
+#define ECOLOR_BLUE_TEXT       N_("End-Blue")
+#define ECOLOR_BLUE_LONGTEXT   N_("the blue component of the shutdown color")
+#define EFADESTEPS_TEXT        N_("End-Fadesteps")
+#define EFADESTEPS_LONGTEXT  N_("Number of steps to change current color to " \
+                             "end color for dimming up the light in cinema " \
+                             "style... (each step takes 40ms)")
+
+#define USEWHITEADJ_TEXT       N_("Use Software White adjust")
+#define USEWHITEADJ_LONGTEXT   N_("Should the buildin driver do a white " \
+                                  "adjust or you LED stripes? recommend.")
+#define WHITE_RED_TEXT         N_("White Red")
+#define WHITE_RED_LONGTEXT     N_("Red value of a pure white on your "\
+                                  "LED stripes.")
+#define WHITE_GREEN_TEXT       N_("White Green")
+#define WHITE_GREEN_LONGTEXT   N_("Green value of a pure white on your "\
+                                  "LED stripes.")
+#define WHITE_BLUE_TEXT        N_("White Blue")
+#define WHITE_BLUE_LONGTEXT    N_("Blue value of a pure white on your "\
+                                  "LED stripes.")
+
+#define SERIALDEV_TEXT         N_("Serial Port/Device")
+#define SERIALDEV_LONGTEXT   N_("Name of the serial port where the AtmoLight "\
+                       "controller is attached to\n on Windows usually "\
+                       "something like COM1 or COM2 on Linux /dev/ttyS01 f.e.")
+
+#define EDGE_TEXT            N_("Edge Weightning")
+#define EDGE_LONGTEXT        N_("increasing this value will result in color "\
+                                "more depending on the border of the frame")
+#define BRIGHTNESS_TEXT     N_("Brightness")
+#define BRIGHTNESS_LONGTEXT N_("overall Brightness of you LED stripes")
+#define DARKNESS_TEXT       N_("Darkness Limit")
+#define DARKNESS_LONGTEXT   N_("pixels with a saturation lower than this will "\
+                               "be ignored should be greater than one for "\
+                               "letterboxed videos")
+#define HUEWINSIZE_TEXT     N_("Hue windowing")
+#define HUEWINSIZE_LONGTEXT N_("used for statistics")
+#define SATWINSIZE_TEXT     N_("Sat windowing")
+#define SATWINSIZE_LONGTEXT N_("used for statistics")
+
+#define MEANLENGTH_TEXT     N_("Filter length [ms]")
+#define MEANLENGTH_LONGTEXT N_("Time it takes until a color is complete "\
+                                "changed, removes flickering")
+#define MEANTHRESHOLD_TEXT     N_("Filter threshold")
+#define MEANTHRESHOLD_LONGTEXT N_("How much a color must changed, for an "\
+                                  "imediate color change")
+#define MEANPERCENTNEW_TEXT     N_("Filter Smoothness %")
+#define MEANPERCENTNEW_LONGTEXT N_("Filter Smoothness")
+
+#define FILTERMODE_TEXT        N_("Filtermode")
+#define FILTERMODE_LONGTEXT    N_("kind of filtering which should be use to "\
+                                  "calcuate the color output")
+static int pi_filtermode_values[] = {
+       (int)afmNoFilter,
+       (int)afmCombined,
+       (int)afmPercent
+};
+static const char *ppsz_filtermode_descriptions[] = {
+        N_("No Filtering"),
+        N_("Combined"),
+        N_("Percent")
+};
+
+#define FRAMEDELAY_TEXT       N_("Framedelay")
+#define FRAMEDELAY_LONGTEXT   N_("helps to get video out and light effects "\
+                             "insync values around 20ms should do the trick")
+
+
+#define CHANNEL_0_ASSIGN_TEXT N_("Channel summary")
+#define CHANNEL_1_ASSIGN_TEXT N_("Channel left")
+#define CHANNEL_2_ASSIGN_TEXT N_("Channel right")
+#define CHANNEL_3_ASSIGN_TEXT N_("Channel top")
+#define CHANNEL_4_ASSIGN_TEXT N_("Channel bottom")
+
+#define CHANNELASSIGN_LONGTEXT N_("maps the hardware channel X to logical "\
+                                  "channel Y to fix wrong wiring:-)")
+static int pi_channel_assignment_values[] = {
+    -1,
+     0,
+     1,
+     2,
+     3,
+     4
+};
+static const char *ppsz_channel_assignment_descriptions[] = {
+        N_("disabled"),
+        N_("summary"),
+        N_("left"),
+        N_("right"),
+        N_("top"),
+        N_("bottom")
+};
+
+#define ZONE_0_GRADIENT_TEXT N_("summary gradient")
+#define ZONE_1_GRADIENT_TEXT N_("left gradient")
+#define ZONE_2_GRADIENT_TEXT N_("right gradient")
+#define ZONE_3_GRADIENT_TEXT N_("top gradient")
+#define ZONE_4_GRADIENT_TEXT N_("bottom gradient")
+#define ZONE_X_GRADIENT_LONG_TEXT N_("defines a small bitmap with 64x48 "\
+                                     "pixels, containing a grayscale gradient")
+
+#if defined( WIN32 )
+#   define ATMOWINEXE_TEXT      N_("Filename of AtmoWinA.exe")
+#   define ATMOWINEXE_LONGTEXT  N_("if you wan't that the AtmoLight control "\
+                                   "software is launched by\nVLC enter the "\
+                                   "complete Filename of AtmoWinA.exe here")
+#   define USEBUILDIN_TEXT      N_("Use buildin AtmoLight")
+#   define USEBUILDIN_LONGTEXT N_("VideoLan will directly use your AtmoLight "\
+                                  "hardware without running the external "\
+                                  "AtmoWinA.exe Userspace driver.")
+#endif
+
+#define CFG_PREFIX "atmo-"
+
+/*****************************************************************************
+* Module descriptor
+*****************************************************************************/
+vlc_module_begin();
+set_description( _("AtmoLight Filter") );
+set_help( MODULE_DESCRIPTION );
+set_shortname( _( "AtmoLight" ));
+set_capability( "video filter2", 0 );
+
+set_category( CAT_VIDEO );
+set_subcategory( SUBCAT_VIDEO_VFILTER );
+
+#if defined(WIN32)
+set_section( N_("Choose between the buildin AtmoLight "\
+                 "driver or the external" ), 0 );
+
+/*
+    only on win32 exists the option to use the buildin driver or
+    the more flexible external driver application
+*/
+add_bool(CFG_PREFIX "usebuildin", VLC_TRUE, NULL,
+         USEBUILDIN_TEXT, USEBUILDIN_LONGTEXT, VLC_FALSE);
+add_string(CFG_PREFIX "serialdev", "COM1", NULL,
+           SERIALDEV_TEXT, SERIALDEV_LONGTEXT, VLC_FALSE );
+
+/*
+    on win32 the executeable external driver application
+    for automatic start if needed
+*/
+add_file(CFG_PREFIX "atmowinexe", NULL, NULL,
+         ATMOWINEXE_TEXT, ATMOWINEXE_LONGTEXT, VLC_FALSE );
+#else
+set_section( N_("Enter connection of your AtmoLight hardware" ), 0 );
+add_string(CFG_PREFIX "serialdev", "/dev/ttyS01", NULL,
+           SERIALDEV_TEXT, SERIALDEV_LONGTEXT, VLC_FALSE );
+#endif
+
+/*
+    color which is showed if you want durring pausing
+    your movie ... used for both buildin / external
+*/
+set_section( N_("Illuminate the room with this color on pause" ), 0 );
+add_bool(CFG_PREFIX "usepausecolor", VLC_FALSE, NULL,
+         PCOLOR_TEXT, PCOLOR_LONGTEXT, VLC_FALSE);
+add_integer_with_range(CFG_PREFIX "pcolor-red",   0, 0, 255, NULL,
+                       PCOLOR_RED_TEXT, PCOLOR_RED_LONGTEXT, VLC_FALSE);
+add_integer_with_range(CFG_PREFIX "pcolor-green", 0, 0, 255, NULL,
+                       PCOLOR_GREEN_TEXT, PCOLOR_GREEN_LONGTEXT, VLC_FALSE);
+add_integer_with_range(CFG_PREFIX "pcolor-blue",  192, 0, 255, NULL,
+                       PCOLOR_BLUE_TEXT, PCOLOR_BLUE_LONGTEXT, VLC_FALSE);
+add_integer_with_range(CFG_PREFIX "fadesteps", 50, 1, 250, NULL,
+                       FADESTEPS_TEXT, FADESTEPS_LONGTEXT, VLC_FALSE);
+
+/*
+    color which is showed if you finished watching your movie ...
+    used for both buildin / external
+*/
+set_section( N_("Illuminate the room with this color on shutdown" ), 0 );
+add_integer_with_range(CFG_PREFIX "ecolor-red",   192, 0, 255, NULL,
+                       ECOLOR_RED_TEXT,   ECOLOR_RED_LONGTEXT,   VLC_FALSE);
+add_integer_with_range(CFG_PREFIX "ecolor-green", 192, 0, 255, NULL,
+                       ECOLOR_GREEN_TEXT, ECOLOR_GREEN_LONGTEXT, VLC_FALSE);
+add_integer_with_range(CFG_PREFIX "ecolor-blue",  192, 0, 255, NULL,
+                       ECOLOR_BLUE_TEXT,  ECOLOR_BLUE_LONGTEXT,  VLC_FALSE);
+add_integer_with_range(CFG_PREFIX "efadesteps",    50, 1, 250, NULL,
+                       EFADESTEPS_TEXT,   EFADESTEPS_LONGTEXT,    VLC_FALSE);
+
+/*
+ settings only for the buildin driver (if external driver app is used
+ these parameters are ignored.)
+
+ definition of parameters for the buildin filter ...
+*/
+set_section( N_("Settings only for buildin Live Video Processor" ), 0 );
+
+add_integer_with_range(CFG_PREFIX "EdgeWeightning",   8, 1, 30, NULL,
+                       EDGE_TEXT, EDGE_LONGTEXT, VLC_FALSE);
+
+add_integer_with_range(CFG_PREFIX "Brightness",   100, 50, 300, NULL,
+                       BRIGHTNESS_TEXT, BRIGHTNESS_LONGTEXT, VLC_FALSE);
+
+add_integer_with_range(CFG_PREFIX "DarknessLimit",   5, 0, 10, NULL,
+                       DARKNESS_TEXT, DARKNESS_LONGTEXT, VLC_FALSE);
+
+add_integer_with_range(CFG_PREFIX "HueWinSize",   3, 0, 5, NULL,
+                       HUEWINSIZE_TEXT, HUEWINSIZE_LONGTEXT, VLC_FALSE);
+
+add_integer_with_range(CFG_PREFIX "SatWinSize",   3, 0, 5, NULL,
+                       SATWINSIZE_TEXT, SATWINSIZE_LONGTEXT, VLC_FALSE);
+
+add_integer(CFG_PREFIX "filtermode", (int)afmCombined, NULL,
+            FILTERMODE_TEXT, FILTERMODE_LONGTEXT, VLC_FALSE );
+
+change_integer_list(pi_filtermode_values, ppsz_filtermode_descriptions, 0 );
+
+add_integer_with_range(CFG_PREFIX "MeanLength",    300, 300, 5000, NULL,
+                       MEANLENGTH_TEXT, MEANLENGTH_LONGTEXT, VLC_FALSE);
+
+add_integer_with_range(CFG_PREFIX "MeanThreshold",  40, 1, 100, NULL,
+                       MEANTHRESHOLD_TEXT, MEANTHRESHOLD_LONGTEXT, VLC_FALSE);
+
+add_integer_with_range(CFG_PREFIX "PercentNew", 50, 1, 100, NULL,
+                      MEANPERCENTNEW_TEXT, MEANPERCENTNEW_LONGTEXT, VLC_FALSE);
+
+add_integer_with_range(CFG_PREFIX "FrameDelay", 18, 0, 35, NULL,
+                       FRAMEDELAY_TEXT, FRAMEDELAY_LONGTEXT, VLC_FALSE);
+
+/*
+  output channel reordering
+*/
+set_section( N_("Change channel assignment (fixes wrong wiring)" ), 0 );
+add_integer( CFG_PREFIX "channel_0", 0, NULL,
+            CHANNEL_0_ASSIGN_TEXT, CHANNELASSIGN_LONGTEXT, VLC_FALSE );
+change_integer_list( pi_channel_assignment_values,
+                     ppsz_channel_assignment_descriptions, 0 );
+
+add_integer( CFG_PREFIX "channel_1", 1, NULL,
+            CHANNEL_1_ASSIGN_TEXT, CHANNELASSIGN_LONGTEXT, VLC_FALSE );
+change_integer_list( pi_channel_assignment_values,
+                     ppsz_channel_assignment_descriptions, 0 );
+
+add_integer( CFG_PREFIX "channel_2", 2, NULL,
+            CHANNEL_2_ASSIGN_TEXT, CHANNELASSIGN_LONGTEXT, VLC_FALSE );
+change_integer_list( pi_channel_assignment_values,
+                     ppsz_channel_assignment_descriptions, 0 );
+
+add_integer( CFG_PREFIX "channel_3", 3, NULL,
+            CHANNEL_3_ASSIGN_TEXT, CHANNELASSIGN_LONGTEXT, VLC_FALSE );
+change_integer_list( pi_channel_assignment_values,
+                     ppsz_channel_assignment_descriptions, 0 );
+
+add_integer( CFG_PREFIX "channel_4", 4, NULL,
+            CHANNEL_4_ASSIGN_TEXT, CHANNELASSIGN_LONGTEXT, VLC_FALSE );
+change_integer_list( pi_channel_assignment_values,
+                     ppsz_channel_assignment_descriptions, 0 );
+
+/*
+  LED color white calibration
+*/
+set_section( N_("Adjust the white light to your LED stripes" ), 0 );
+add_bool(CFG_PREFIX "whiteadj", VLC_TRUE, NULL,
+         USEWHITEADJ_TEXT, USEWHITEADJ_LONGTEXT, VLC_FALSE);
+add_integer_with_range(CFG_PREFIX "white-red",   255, 0, 255, NULL,
+                       WHITE_RED_TEXT,   WHITE_RED_LONGTEXT,   VLC_FALSE);
+
+add_integer_with_range(CFG_PREFIX "white-green", 255, 0, 255, NULL,
+                       WHITE_GREEN_TEXT, WHITE_GREEN_LONGTEXT, VLC_FALSE);
+
+add_integer_with_range(CFG_PREFIX "white-blue",  255, 0, 255, NULL,
+                       WHITE_BLUE_TEXT,  WHITE_BLUE_LONGTEXT,  VLC_FALSE);
+/* end of definition of parameter for the buildin filter ... part 1 */
+
+
+/*
+only for buildin (external has own definition) per default the calucation
+used linear gradients for assigning a priority to the pixel - depending
+how near they are to the border ...for changing this you can create 64x48
+Pixel BMP files - which contain your own grayscale... (you can produce funny
+effects with this...) the images MUST not compressed, should have 24-bit per
+pixel, or a simple 256 color grayscale palette
+*/
+set_section( N_("Change gradients" ), 0 );
+add_file(CFG_PREFIX "gradient_zone_0", NULL, NULL,
+         ZONE_0_GRADIENT_TEXT, ZONE_X_GRADIENT_LONG_TEXT, VLC_TRUE );
+add_file(CFG_PREFIX "gradient_zone_1", NULL, NULL,
+         ZONE_1_GRADIENT_TEXT, ZONE_X_GRADIENT_LONG_TEXT, VLC_TRUE );
+add_file(CFG_PREFIX "gradient_zone_2", NULL, NULL,
+         ZONE_2_GRADIENT_TEXT, ZONE_X_GRADIENT_LONG_TEXT, VLC_TRUE );
+add_file(CFG_PREFIX "gradient_zone_3", NULL, NULL,
+         ZONE_3_GRADIENT_TEXT, ZONE_X_GRADIENT_LONG_TEXT, VLC_TRUE );
+add_file(CFG_PREFIX "gradient_zone_4", NULL, NULL,
+         ZONE_4_GRADIENT_TEXT, ZONE_X_GRADIENT_LONG_TEXT, VLC_TRUE );
+
+
+#if defined(__ATMO_DEBUG__)
+add_bool(CFG_PREFIX "saveframes", VLC_FALSE, NULL,
+         SAVEFRAMES_TEXT, SAVEFRAMES_LONGTEXT, VLC_FALSE);
+add_string(CFG_PREFIX "framepath", "", NULL,
+           FRAMEPATH_TEXT, FRAMEPATH_LONGTEXT, VLC_FALSE );
+#endif
+/*
+   may be later if computers gets more power ;-) than now we increase
+   the samplesize from which we do the stats for output color calculation
+*/
+add_integer_with_range(CFG_PREFIX "width",  64, 64, 512, NULL,
+                       WIDTH_TEXT,  WIDTH_LONGTEXT, VLC_TRUE);
+add_integer_with_range(CFG_PREFIX "height", 48, 48, 384, NULL,
+                       HEIGHT_TEXT,  HEIGHT_LONGTEXT, VLC_TRUE);
+
+add_shortcut( "atmo" );
+set_callbacks( CreateFilter, DestroyFilter  );
+vlc_module_end();
+
+
+static const char *ppsz_filter_options[] = {
+#if defined(WIN32)
+    "usebuildin",
+#endif
+        "serialdev",
+
+
+        "EdgeWeightning",
+        "Brightness",
+        "DarknessLimit",
+        "HueWinSize",
+        "SatWinSize",
+
+        "filtermode",
+
+        "MeanLength",
+        "MeanThreshold",
+        "PercentNew",
+        "FrameDelay",
+
+        "channel_0",
+        "channel_1",
+        "channel_2",
+        "channel_3",
+        "channel_4",
+
+        "whiteadj",
+        "white-red",
+        "white-green",
+        "white-blue",
+
+        "usepausecolor",
+        "pcolor-red",
+        "pcolor-green",
+        "pcolor-blue",
+        "fadesteps",
+
+        "ecolor-red",
+        "ecolor-green",
+        "ecolor-blue",
+        "efadesteps",
+
+
+#if defined(WIN32 )
+        "usebuildin",
+        "atmowinexe",
+#endif
+#if defined(__ATMO_DEBUG__)
+        "saveframes" ,
+        "framepath",
+#endif
+        "width",
+        "height",
+        "gradient_zone_0",
+        "gradient_zone_1",
+        "gradient_zone_2",
+        "gradient_zone_3",
+        "gradient_zone_4",
+        NULL
+};
+
+
+/*****************************************************************************
+* fadethread_t: Color Fading Thread
+*****************************************************************************
+* changes slowly the color of the output if videostream gets paused...
+*****************************************************************************
+*/
+typedef struct
+{
+    VLC_COMMON_MEMBERS
+        filter_t *p_filter;
+    /* tell the thread which color should be the target of fading */
+    uint8_t ui_red;
+    uint8_t ui_green;
+    uint8_t ui_blue;
+    /* how many steps should happen until this */
+    int i_steps;
+
+} fadethread_t;
+
+static void FadeToColorThread(fadethread_t *p_fadethread);
+
+
+/*****************************************************************************
+* filter_sys_t: AtmoLight filter method descriptor
+*****************************************************************************
+* It describes the AtmoLight specific properties of an video filter.
+*****************************************************************************/
+struct filter_sys_t
+{
+    /*
+    special for the access of the p_fadethread member all other members
+    need no special protection so far!
+    */
+    vlc_mutex_t filter_lock;
+
+    vlc_bool_t b_enabled;
+    int32_t i_AtmoOldEffect;
+    vlc_bool_t b_pause_live;
+
+    int32_t i_atmo_width;
+    int32_t i_atmo_height;
+
+#if defined(__ATMO_DEBUG__)
+    vlc_bool_t  b_saveframes;
+    int i_framecounter;
+    char sz_framepath[MAX_PATH];
+#endif
+
+    /* light color durring movie pause ... */
+    vlc_bool_t  b_usepausecolor;
+    uint8_t ui_pausecolor_red;
+    uint8_t ui_pausecolor_green;
+    uint8_t ui_pausecolor_blue;
+    int i_fadesteps;
+
+    /* light color on movie finish ... */
+    uint8_t ui_endcolor_red;
+    uint8_t ui_endcolor_green;
+    uint8_t ui_endcolor_blue;
+    int i_endfadesteps;
+
+    fadethread_t *p_fadethread;
+
+    /* Variables for buildin driver only... */
+
+    /* is only present and initialized if the internal driver is used*/
+    CAtmoConfig *p_atmo_config;
+    /* storage for temporal settings "volatile" */
+    CAtmoDynData *p_atmo_dyndata;
+    /* initialized for buildin driver with AtmoCreateTransferBuffers */
+    BITMAPINFOHEADER mini_image_format;
+    /* is only use buildin driver! */
+    uint8_t *p_atmo_transfer_buffer;
+    /* end buildin driver */
+
+    /*
+    contains the real output size of the video calculated on
+    change event of the variable "crop" from vout
+    */
+    int32_t i_crop_x_offset;
+    int32_t i_crop_y_offset;
+    int32_t i_crop_width;
+    int32_t i_crop_height;
+
+    void (*pf_extract_mini_image) (filter_sys_t *p_sys,
+        picture_t *p_inpic,
+        uint8_t *p_transfer_dest);
+
+#if defined( WIN32 )
+    /* External Library as wrapper arround COM Stuff */
+    HINSTANCE h_AtmoCtrl;
+    int32_t (*pf_ctrl_atmo_initialize) (void);
+    void (*pf_ctrl_atmo_finalize) (int32_t what);
+    int32_t (*pf_ctrl_atmo_switch_effect) (int32_t);
+    int32_t (*pf_ctrl_atmo_set_live_source) (int32_t);
+    void (*pf_ctrl_atmo_create_transfer_buffers) (int32_t, int32_t,
+                                                  int32_t , int32_t);
+    uint8_t* (*pf_ctrl_atmo_lock_transfer_buffer) (void);
+    void (*pf_ctrl_atmo_send_pixel_data) (void);
+#endif
+};
+
+/*
+initialize previously configured Atmo Light environment
+- if internal is enabled try to access the device on the serial port
+- if not internal is enabled and we are on win32 try to initialize
+the previously loaded DLL ...
+
+Return Values may be: -1 (failed for some reason - filter will be disabled)
+1 Ok. lets rock
+*/
+static int32_t AtmoInitialize(filter_t *p_filter, vlc_bool_t b_for_thread)
+{
+    filter_sys_t *p_sys = p_filter->p_sys;
+    if(p_sys->p_atmo_config)
+    {
+        if(b_for_thread == VLC_FALSE)
+        {
+            /* open com port */
+            /* setup Output Threads ... */
+            msg_Dbg( p_filter, "open serial connection %s",
+                p_sys->p_atmo_config->getSerialDevice());
+
+            if(CAtmoTools::RecreateConnection(p_sys->p_atmo_dyndata) == ATMO_TRUE)
+            {
+                msg_Dbg( p_filter, "start live view thread ...");
+                CAtmoTools::SwitchEffect(p_sys->p_atmo_dyndata, emLivePicture);
+                msg_Dbg( p_filter, "live view thread launched...");
+                return 1;
+
+            } else {
+                msg_Err( p_filter,"failed to open serial device? some other software/driver may use it?");
+            }
+        }
+#if defined(WIN32)
+    } else if(p_sys->pf_ctrl_atmo_initialize)
+    {
+        /* on win32 with active ctrl dll */
+        return p_sys->pf_ctrl_atmo_initialize();
+#endif
+    }
+    return -1;
+}
+
+/*
+prepare the shutdown of the effect threads,
+for build in filter - close the serialport after finishing the threads...
+cleanup possible loaded DLL...
+*/
+static void AtmoFinalize(filter_t *p_filter, int32_t what)
+{
+    filter_sys_t *p_sys = p_filter->p_sys;
+    if(p_sys->p_atmo_config)
+    {
+        if(what == 1)
+        {
+            CAtmoDynData *p_atmo_dyndata = p_sys->p_atmo_dyndata;
+            if(p_atmo_dyndata)
+            {
+                p_atmo_dyndata->LockCriticalSection();
+
+                CThread *p_effect_thread = p_atmo_dyndata->getEffectThread();
+                p_atmo_dyndata->setEffectThread(NULL);
+                if(p_effect_thread != NULL)
+                {
+                    /*
+                    forced the thread to die...
+                    and wait for termination of the thread
+                    */
+                    p_effect_thread->Terminate();
+                    delete p_effect_thread;
+                    msg_Dbg( p_filter, "effect thread died peacefully");
+                }
+
+                /*
+                close serial port if it is open (all OS specific is inside
+                CAtmoSerialConnection implemented / defined)
+                */
+                CAtmoConnection *p_atmo_connection =
+                                 p_atmo_dyndata->getAtmoConnection();
+                p_atmo_dyndata->setAtmoConnection(NULL);
+                if(p_atmo_connection) {
+                    p_atmo_connection->CloseConnection();
+                    delete p_atmo_connection;
+                }
+                p_atmo_dyndata->UnLockCriticalSection();
+            }
+        }
+#if defined(WIN32)
+    } else if(p_sys->pf_ctrl_atmo_finalize)
+    {
+        /* on win32 with active ctrl dll */
+        p_sys->pf_ctrl_atmo_finalize(what);
+#endif
+    }
+}
+
+/*
+switch the current light effect - does only something on win32, with the
+external  libraries - if the buildin effects are used nothing happens
+*/
+static int32_t AtmoSwitchEffect(filter_t *p_filter, int32_t newMode)
+{
+    filter_sys_t *p_sys = p_filter->p_sys;
+    if(p_sys->p_atmo_config)
+    {
+        /*
+        buildin driver
+
+        doesnt know different modes for effects so this
+        function call would just do nothing special
+        in this case
+        */
+
+#if defined(WIN32)
+    } else if(p_sys->pf_ctrl_atmo_switch_effect)
+    {
+        /* on win32 with active ctrl dll */
+        return p_sys->pf_ctrl_atmo_switch_effect(newMode);
+#endif
+    }
+    return emDisabled;
+}
+
+/*
+set the current live picture source, does only something on win32,
+with the external libraries - if the buildin effects are used nothing
+happens...
+*/
+static int32_t AtmoSetLiveSource(filter_t *p_filter, int32_t newSource)
+{
+    filter_sys_t *p_sys = p_filter->p_sys;
+    if(p_sys->p_atmo_config)
+    {
+        /*
+        buildin driver
+
+        doesnt know different sources so this
+        function call would just do nothing special
+        in this case
+        */
+#if defined(WIN32)
+    } else if(p_sys->pf_ctrl_atmo_set_live_source)
+    {
+        /* on win32 with active ctrl dll */
+        return p_sys->pf_ctrl_atmo_set_live_source(newSource);
+#endif
+    }
+    return lvsGDI;
+}
+
+/*
+setup the pixel transferbuffers which is used to transfer pixeldata from
+the filter to the effect thread, and possible accross the process
+boundaries on win32, with the external DLL
+*/
+static void AtmoCreateTransferBuffers(filter_t *p_filter,
+                                      int32_t FourCC,
+                                      int32_t bytePerPixel,
+                                      int32_t width,
+                                      int32_t height)
+{
+    filter_sys_t *p_sys = p_filter->p_sys;
+    if(p_sys->p_atmo_config)
+    {
+        /*
+        we need a buffer where the image is stored (only for transfer
+        to the processing thread)
+        */
+        if(p_sys->p_atmo_transfer_buffer)
+            free(p_sys->p_atmo_transfer_buffer);
+
+        p_sys->p_atmo_transfer_buffer = (uint8_t *)malloc(bytePerPixel *
+                                                          width *  height);
+
+        memset(&p_sys->mini_image_format,0,sizeof(BITMAPINFOHEADER));
+
+        p_sys->mini_image_format.biSize = sizeof(BITMAPINFOHEADER);
+        p_sys->mini_image_format.biWidth = width;
+        p_sys->mini_image_format.biHeight = height;
+        p_sys->mini_image_format.biBitCount = bytePerPixel*8;
+        p_sys->mini_image_format.biCompression = FourCC;
+
+#if defined(WIN32)
+    } else if(p_sys->pf_ctrl_atmo_create_transfer_buffers)
+    {
+        /* on win32 with active ctrl dll */
+        p_sys->pf_ctrl_atmo_create_transfer_buffers(FourCC,
+            bytePerPixel,
+            width,
+            height);
+#endif
+    }
+}
+
+/*
+acquire the transfer buffer pointer the buildin version only
+returns the pointer to the allocated buffer ... the
+external version on win32 has to do some COM stuff to lock the
+Variant Byte array which is behind the buffer
+*/
+static uint8_t* AtmoLockTransferBuffer(filter_t *p_filter)
+{
+    filter_sys_t *p_sys = p_filter->p_sys;
+    if(p_sys->p_atmo_config)
+    {
+        return p_sys->p_atmo_transfer_buffer;
+#if defined(WIN32)
+    } else if(p_sys->pf_ctrl_atmo_lock_transfer_buffer)
+    {
+        /* on win32 with active ctrl dll */
+        return p_sys->pf_ctrl_atmo_lock_transfer_buffer();
+#endif
+    }
+    return NULL;
+}
+
+/*
+send the content of current pixel buffer got with AtmoLockTransferBuffer
+to the processing threads
+- build in version - will forward the data to AtmoExternalCaptureInput Thread
+- win32 external - will do the same, but across the process boundaries via
+COM to the AtmoWinA.exe Process
+*/
+static void AtmoSendPixelData(filter_t *p_filter)
+{
+    filter_sys_t *p_sys = p_filter->p_sys;
+    if(p_sys->p_atmo_config && p_sys->p_atmo_transfer_buffer)
+    {
+        CAtmoDynData *p_atmo_dyndata = p_sys->p_atmo_dyndata;
+        if(p_atmo_dyndata)
+        {
+            /*
+            the cast will go Ok because we are inside videolan there is only
+            this kind of effect thread implemented!
+            */
+
+            CAtmoLiveView *p_atmo_live_view_thread =
+                (CAtmoLiveView *)p_atmo_dyndata->getEffectThread();
+            if(p_atmo_live_view_thread)
+            {
+                /*
+                the same as above inside videolan only this single kind of
+                input exists so we can cast without further tests!
+                */
+                CAtmoExternalCaptureInput *p_atmo_external_capture_input_thread =
+                    (CAtmoExternalCaptureInput *)p_atmo_live_view_thread->getAtmoInput();
+                if(p_atmo_external_capture_input_thread)
+                {
+                    /*
+                    this call will do a 1:1 copy of this buffer, and wakeup
+                    the thread from normal sleeping
+                    */
+                    p_atmo_external_capture_input_thread->
+                        DeliverNewSourceDataPaket(&p_sys->mini_image_format,
+                        p_sys->p_atmo_transfer_buffer);
+                }
+            }
+        }
+#if defined(WIN32)
+    } else if(p_sys->pf_ctrl_atmo_send_pixel_data)
+    {
+        /* on win32 with active ctrl dll */
+        p_sys->pf_ctrl_atmo_send_pixel_data();
+#endif
+    }
+}
+
+/*
+    Shutdown AtmoLight finally - is call from DestroyFilter
+    does the cleanup restores the effectmode on the external Software
+    (only win32) and possible setup the final light ...
+*/
+static void Atmo_Shutdown(filter_t *p_filter)
+{
+    filter_sys_t *p_sys = p_filter->p_sys;
+
+    if(p_sys->b_enabled == VLC_TRUE)
+    {
+        /*
+        if there is a still running show pause color thread kill him!
+        */
+        CheckAndStopFadeThread(p_filter);
+
+        if(p_sys->p_atmo_config || (p_sys->i_AtmoOldEffect == emStaticColor))
+        {
+            /*
+            fade to end color (in case of external AtmoWin Software
+            assume that the static color will equal to this
+            one to get a soft change and no flash!
+            */
+            p_sys->b_pause_live = VLC_TRUE;
+
+            // perpare spawn fadeing thread
+            vlc_mutex_lock( &p_sys->filter_lock );
+
+            p_sys->p_fadethread = (fadethread_t *)vlc_object_create( p_filter,
+                                                        sizeof(fadethread_t) );
+
+            p_sys->p_fadethread->p_filter = p_filter;
+            p_sys->p_fadethread->ui_red   = p_sys->ui_endcolor_red;
+            p_sys->p_fadethread->ui_green = p_sys->ui_endcolor_green;
+            p_sys->p_fadethread->ui_blue  = p_sys->ui_endcolor_blue;
+            p_sys->p_fadethread->i_steps  = p_sys->i_endfadesteps;
+
+            if( vlc_thread_create( p_sys->p_fadethread,
+                "AtmoLight fadeing",
+                FadeToColorThread,
+                VLC_THREAD_PRIORITY_LOW,
+                VLC_FALSE ) )
+            {
+                msg_Err( p_filter, "cannot create FadeToColorThread" );
+                vlc_object_destroy( p_sys->p_fadethread );
+                p_sys->p_fadethread = NULL;
+                vlc_mutex_unlock( &p_sys->filter_lock );
+
+            } else {
+
+                vlc_mutex_unlock( &p_sys->filter_lock );
+
+                /* wait for the thread... */
+                vlc_thread_join(p_sys->p_fadethread);
+
+                vlc_object_destroy(p_sys->p_fadethread);
+
+                p_sys->p_fadethread = NULL;
+            }
+        }
+
+        if(p_sys->i_AtmoOldEffect != emLivePicture)
+            AtmoSwitchEffect(p_filter, p_sys->i_AtmoOldEffect);
+        else
+            AtmoSetLiveSource(p_filter, lvsGDI);
+
+        AtmoFinalize(p_filter, 1);
+
+        /* disable filter method .. */
+        p_sys->b_enabled = VLC_FALSE;
+    }
+}
+
+/*
+initialize the filter_sys_t structure with the data from the settings
+variables - if the external filter on win32 is enabled try loading the DLL,
+if this fails fallback to the buildin software
+*/
+static void Atmo_SetupParameters(filter_t *p_filter)
+{
+    vlc_bool_t b_use_buildin_driver = VLC_TRUE;
+    char *psz_path;
+    filter_sys_t *p_sys =  p_filter->p_sys;
+
+
+    /* default filter disabled until DLL loaded and Init Success!*/
+    p_sys->b_enabled             = VLC_FALSE;
+
+    /* setup default mini image size (may be later a user option) */
+    p_sys->i_atmo_width          = 64;
+    p_sys->i_atmo_height         = 48;
+
+
+    vlc_mutex_init( p_filter, &p_sys->filter_lock );
+
+
+#if defined(WIN32)
+    /*
+    only on WIN32 the user has the choice between
+    internal driver and external
+    */
+    b_use_buildin_driver = var_CreateGetBoolCommand( p_filter,
+        CFG_PREFIX "usebuildin" );
+
+    if(b_use_buildin_driver == VLC_FALSE) {
+
+        /* Load the Com Wrapper Library (source available) */
+        p_sys->h_AtmoCtrl = LoadLibraryA("AtmoCtrlLib.dll");
+        if(p_sys->h_AtmoCtrl != NULL)
+        {
+            msg_Dbg( p_filter, "LoadLibrary('AtmoCtrlLib.dll'); Success");
+
+            /* importing all required functions I hope*/
+            p_sys->pf_ctrl_atmo_initialize =
+                (int32_t (*)(void))GetProcAddress(p_sys->h_AtmoCtrl,"AtmoInitialize");
+            if(!p_sys->pf_ctrl_atmo_initialize)
+                msg_Err( p_filter, "export AtmoInitialize missing.");
+
+            p_sys->pf_ctrl_atmo_finalize =
+                (void (*)(int32_t))GetProcAddress(p_sys->h_AtmoCtrl,"AtmoFinalize");
+            if(!p_sys->pf_ctrl_atmo_finalize)
+                msg_Err( p_filter, "export AtmoFinalize missing.");
+
+            p_sys->pf_ctrl_atmo_switch_effect =
+                (int32_t(*)(int32_t))GetProcAddress(p_sys->h_AtmoCtrl,"AtmoSwitchEffect");
+            if(!p_sys->pf_ctrl_atmo_switch_effect)
+                msg_Err( p_filter, "export AtmoSwitchEffect missing.");
+
+            p_sys->pf_ctrl_atmo_set_live_source =
+                (int32_t(*)(int32_t))GetProcAddress(p_sys->h_AtmoCtrl,"AtmoSetLiveSource");
+            if(!p_sys->pf_ctrl_atmo_set_live_source)
+                msg_Err( p_filter, "export AtmoSetLiveSource missing.");
+
+            p_sys->pf_ctrl_atmo_create_transfer_buffers =
+                (void (*)(int32_t, int32_t, int32_t , int32_t))GetProcAddress(p_sys->h_AtmoCtrl,"AtmoCreateTransferBuffers");
+            if(!p_sys->pf_ctrl_atmo_create_transfer_buffers)
+                msg_Err( p_filter, "export AtmoCreateTransferBuffers missing.");
+
+            p_sys->pf_ctrl_atmo_lock_transfer_buffer=
+                (uint8_t*(*) (void))GetProcAddress(p_sys->h_AtmoCtrl,"AtmoLockTransferBuffer");
+            if(!p_sys->pf_ctrl_atmo_lock_transfer_buffer)
+                msg_Err( p_filter, "export AtmoLockTransferBuffer missing.");
+
+            p_sys->pf_ctrl_atmo_send_pixel_data =
+                (void (*)(void))GetProcAddress(p_sys->h_AtmoCtrl,"AtmoSendPixelData");
+            if(!p_sys->pf_ctrl_atmo_send_pixel_data)
+                msg_Err( p_filter, "export AtmoSendPixelData missing.");
+        } else {
+            /* the DLL is missing try internal filter ...*/
+            msg_Warn( p_filter, "AtmoCtrlLib.dll missing fallback to internal driver");
+            b_use_buildin_driver = VLC_TRUE;
+        }
+    }
+#endif
+
+
+    if(b_use_buildin_driver == VLC_TRUE) {
+        msg_Dbg( p_filter, "use buildin driver");
+        /*
+        now we have to read a lof of options from the config dialog
+        most important the serial device if not set ... we can skip
+        the rest and disable the filter...
+        */
+        char *psz_serialdev = var_CreateGetStringCommand( p_filter,
+                                                      CFG_PREFIX "serialdev" );
+        if(psz_serialdev && (strlen(psz_serialdev)>0)) {
+            msg_Dbg( p_filter, "use buildin driver on port %s",psz_serialdev);
+
+            p_sys->p_atmo_config = new CAtmoConfig();
+
+            p_sys->p_atmo_config->setSerialDevice(psz_serialdev);
+
+            p_sys->p_atmo_config->setLiveViewFilterMode(
+                (AtmoFilterMode)var_CreateGetIntegerCommand( p_filter,
+                                                       CFG_PREFIX "filtermode")
+                );
+
+            p_sys->p_atmo_config->setLiveViewFilter_PercentNew(
+                var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "PercentNew")
+                );
+            p_sys->p_atmo_config->setLiveViewFilter_MeanLength(
+                var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "MeanLength")
+                );
+            p_sys->p_atmo_config->setLiveViewFilter_MeanThreshold(
+                var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "MeanThreshold")
+                );
+
+            p_sys->p_atmo_config->setLiveView_EdgeWeighting(
+                var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "EdgeWeightning")
+                );
+            p_sys->p_atmo_config->setLiveView_BrightCorrect(
+                var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "Brightness")
+                );
+            p_sys->p_atmo_config->setLiveView_DarknessLimit(
+                var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "DarknessLimit")
+                );
+            p_sys->p_atmo_config->setLiveView_HueWinSize(
+                var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "HueWinSize")
+                );
+            p_sys->p_atmo_config->setLiveView_SatWinSize(
+                var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "SatWinSize")
+                );
+
+            /* currently not required inside vlc */
+            p_sys->p_atmo_config->setLiveView_WidescreenMode( 0 );
+
+            p_sys->p_atmo_config->setLiveView_FrameDelay(
+                var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "FrameDelay")
+                );
+
+
+            p_sys->p_atmo_config->setUseSoftwareWhiteAdj(
+                var_CreateGetBoolCommand( p_filter, CFG_PREFIX "whiteadj")
+                );
+            p_sys->p_atmo_config->setWhiteAdjustment_Red(
+                var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "white-red")
+                );
+            p_sys->p_atmo_config->setWhiteAdjustment_Green(
+                var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "white-green")
+                );
+            p_sys->p_atmo_config->setWhiteAdjustment_Blue(
+                var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "white-blue")
+                );
+
+            tChannelAssignment *p_channel_assignment =
+                                 p_sys->p_atmo_config->getChannelAssignment(0);
+
+            p_channel_assignment->mappings[0] = var_CreateGetIntegerCommand(
+                                             p_filter, CFG_PREFIX "channel_0");
+
+            p_channel_assignment->mappings[1] = var_CreateGetIntegerCommand(
+                                             p_filter, CFG_PREFIX "channel_1");
+
+            p_channel_assignment->mappings[2] = var_CreateGetIntegerCommand(
+                                             p_filter, CFG_PREFIX "channel_2");
+
+            p_channel_assignment->mappings[3] = var_CreateGetIntegerCommand(
+                                             p_filter, CFG_PREFIX "channel_3");
+
+            p_channel_assignment->mappings[4] = var_CreateGetIntegerCommand(
+                                             p_filter, CFG_PREFIX "channel_4");
+
+            for(int i=0;i<ATMO_NUM_CHANNELS;i++)
+                msg_Dbg( p_filter, "map software channel %d to hardware channel %d",
+                p_channel_assignment->mappings[i],
+                i
+                );
+
+            // gradient_zone_0
+            char psz_gradient_var_name[30];
+            char *psz_gradient_file;
+            for(int i=0;i<ATMO_NUM_CHANNELS;i++)
+            {
+                sprintf(psz_gradient_var_name, CFG_PREFIX "gradient_zone_%d", i);
+                psz_gradient_file = var_CreateGetStringCommand(
+                    p_filter,
+                    psz_gradient_var_name
+                    );
+                if(psz_gradient_file && strlen(psz_gradient_file)>0)
+                {
+                    msg_Dbg( p_filter, "loading gradientfile %s for "\
+                                       "zone %d", psz_gradient_file, i);
+
+                    int i_res = p_sys->p_atmo_config->getZoneDefinition(i)->
+                                LoadGradientFromBitmap(psz_gradient_file);
+
+                    if(i_res != ATMO_LOAD_GRADIENT_OK)
+                    {
+                        msg_Err( p_filter,"failed to load gradient '%s' with "\
+                                          "error %d",psz_gradient_file,i_res);
+                    }
+                }
+                delete psz_gradient_file;
+            }
+
+            p_sys->p_atmo_dyndata = new CAtmoDynData((vlc_object_t *)p_filter,
+                p_sys->p_atmo_config
+                );
+
+            msg_Dbg( p_filter, "buildin driver initialized");
+
+            free(psz_serialdev);
+        } else {
+            msg_Err(p_filter,"no serial devicename set");
+        }
+    }
+
+    switch( p_filter->fmt_in.video.i_chroma )
+    {
+    case VLC_FOURCC('I','4','2','0'):
+    case VLC_FOURCC('I','Y','U','V'):
+    case VLC_FOURCC('Y','V','1','2'):
+    case VLC_FOURCC('Y','V','1','6'):
+    case VLC_FOURCC('Y','V','U','9'):
+        // simple enough? Dionoea?
+        p_sys->pf_extract_mini_image = ExtractMiniImage_YUV;
+        break;
+    default:
+        msg_Dbg( p_filter, "InitFilter-unsupported chroma: %4.4s",
+                            (char *)&p_filter->fmt_in.video.i_chroma);
+        p_sys->pf_extract_mini_image = NULL;
+    }
+
+    p_sys->i_crop_x_offset  = 0;
+    p_sys->i_crop_y_offset  = 0;
+    p_sys->i_crop_width     = p_filter->fmt_in.video.i_visible_width;
+    p_sys->i_crop_height    = p_filter->fmt_in.video.i_visible_height;
+
+    msg_Dbg( p_filter, "set default crop %d,%d %dx%d",p_sys->i_crop_x_offset,
+        p_sys->i_crop_y_offset,
+        p_sys->i_crop_width,
+        p_sys->i_crop_height );
+
+
+#if defined(__ATMO_DEBUG__)
+    /* save debug images to a folder as Bitmap files ? */
+    p_sys->b_saveframes  = var_CreateGetBoolCommand( p_filter,
+        CFG_PREFIX "saveframes"
+        );
+    msg_Dbg(p_filter,"saveframes = %d", (int)p_sys->b_saveframes);
+
+    /*
+    read debug image folder from config
+    */
+    psz_path = var_CreateGetStringCommand( p_filter, CFG_PREFIX "framepath" );
+    if(psz_path != NULL)
+    {
+        strcpy(p_sys->sz_framepath, psz_path);
+#if defined( WIN32 )
+        size_t i_strlen = strlen(p_sys->sz_framepath);
+        if((i_strlen>0) && (p_sys->sz_framepath[i_strlen-1] != '\\'))
+        {
+            p_sys->sz_framepath[i_strlen] = '\\';
+            p_sys->sz_framepath[i_strlen+1] = 0;
+        }
+#endif
+        free(psz_path);
+    }
+    msg_Dbg(p_filter,"saveframesfolder %s",p_sys->sz_framepath);
+#endif
+
+    /*
+       size of extracted image by default 64x48 (other imagesizes are
+       currently ignored by AtmoWin)
+    */
+    p_sys->i_atmo_width  = var_CreateGetIntegerCommand( p_filter,
+        CFG_PREFIX "width");
+    p_sys->i_atmo_height = var_CreateGetIntegerCommand( p_filter,
+        CFG_PREFIX "height");
+    msg_Dbg(p_filter,"mini image size %d * %d pixels", p_sys->i_atmo_width,
+        p_sys->i_atmo_height);
+
+    /*
+    because atmowin could also be used for lighten up the room - I think if you
+    pause the video it would be useful to get a little bit more light into to
+    your living room? - instead switching on a lamp?
+    */
+    p_sys->b_usepausecolor = var_CreateGetBoolCommand( p_filter,
+        CFG_PREFIX "usepausecolor" );
+    p_sys->ui_pausecolor_red = (uint8_t)var_CreateGetIntegerCommand( p_filter,
+        CFG_PREFIX "pcolor-red");
+    p_sys->ui_pausecolor_green = (uint8_t)var_CreateGetIntegerCommand( p_filter,
+        CFG_PREFIX "pcolor-green");
+    p_sys->ui_pausecolor_blue = (uint8_t)var_CreateGetIntegerCommand( p_filter,
+        CFG_PREFIX "pcolor-blue");
+    p_sys->i_fadesteps = var_CreateGetIntegerCommand( p_filter,
+        CFG_PREFIX "fadesteps");
+    if(p_sys->i_fadesteps < 1)
+        p_sys->i_fadesteps = 1;
+    msg_Dbg(p_filter,"use pause color %d, RGB: %d, %d, %d, Fadesteps: %d",
+        (int)p_sys->b_usepausecolor,
+        p_sys->ui_pausecolor_red,
+        p_sys->ui_pausecolor_green,
+        p_sys->ui_pausecolor_blue,
+        p_sys->i_fadesteps);
+
+    /*
+    this color is use on shutdown of the filter - the define the
+    final light after playback... may be used to dim up the light -
+    how it happens in the cinema...
+    */
+    p_sys->ui_endcolor_red = (uint8_t)var_CreateGetIntegerCommand( p_filter,
+        CFG_PREFIX "ecolor-red");
+    p_sys->ui_endcolor_green = (uint8_t)var_CreateGetIntegerCommand( p_filter,
+        CFG_PREFIX "ecolor-green");
+    p_sys->ui_endcolor_blue = (uint8_t)var_CreateGetIntegerCommand( p_filter,
+        CFG_PREFIX "ecolor-blue");
+    p_sys->i_endfadesteps = var_CreateGetIntegerCommand( p_filter,
+        CFG_PREFIX "efadesteps");
+    if(p_sys->i_endfadesteps < 1)
+        p_sys->i_endfadesteps = 1;
+    msg_Dbg(p_filter,"use ende color RGB: %d, %d, %d, Fadesteps: %d",
+        p_sys->ui_endcolor_red,
+        p_sys->ui_endcolor_green,
+        p_sys->ui_endcolor_blue,
+        p_sys->i_endfadesteps);
+
+    /* if the external DLL was loaded successfully call AtmoInitialize -
+    (must be done for each thread where you wan't to use AtmoLight!
+    */
+    int i = AtmoInitialize(p_filter, VLC_FALSE);
+#if defined( WIN32 )
+    if((i != 1) && !b_use_buildin_driver)
+    {
+        /* COM Server for AtmoLight not running ?
+        if the exe path is configured try to start the "userspace" driver
+        */
+        psz_path = var_CreateGetStringCommand( p_filter,
+                                               CFG_PREFIX "atmowinexe" );
+        if(psz_path != NULL)
+        {
+            STARTUPINFO startupinfo;
+            PROCESS_INFORMATION pinfo;
+            memset(&startupinfo, 0, sizeof(STARTUPINFO));
+            startupinfo.cb = sizeof(STARTUPINFO);
+            if(CreateProcess(psz_path, NULL, NULL, NULL,
+                FALSE, 0, NULL, NULL, &startupinfo, &pinfo) == TRUE)
+            {
+                msg_Dbg(p_filter,"launched AtmoWin from %s",psz_path);
+                WaitForInputIdle(pinfo.hProcess, 5000);
+                /*
+                retry to initialize the library COM ... functionality
+                after the server was launched
+                */
+                i = AtmoInitialize(p_filter, VLC_FALSE);
+            } else {
+                msg_Err(p_filter,"failed to launch AtmoWin from %s", psz_path);
+            }
+            free(psz_path);
+        }
+    }
+#endif
+
+    if(i == 1) /* Init Atmolight success... */
+    {
+        msg_Dbg( p_filter, "AtmoInitialize Ok!");
+
+        /* Setup Transferbuffers for 64 x 48 , RGB with 32bit Per Pixel */
+        AtmoCreateTransferBuffers(p_filter, BI_RGB, 4,
+            p_sys->i_atmo_width,
+            p_sys->i_atmo_height
+            );
+
+        /* say the userspace driver that a live mode should be activated
+        the functions returns the old mode for later restore!
+        */
+        p_sys->i_AtmoOldEffect = AtmoSwitchEffect(p_filter, emLivePicture);
+
+        /*
+        live view can have two differnt source the AtmoWinA
+        internal GDI Screencapture and the external one - which we
+        need here...
+        */
+        AtmoSetLiveSource(p_filter, lvsExternal);
+
+        /* enable other parts only if everything is fine */
+        p_sys->b_enabled = VLC_TRUE;
+    }
+
+}
+
+
+/*****************************************************************************
+* CreateFilter: allocates AtmoLight video thread output method
+*****************************************************************************
+* This function allocates and initializes a AtmoLight vout method.
+*****************************************************************************/
+static int CreateFilter( vlc_object_t *p_this )
+{
+    filter_t *p_filter = (filter_t *)p_this;
+    filter_sys_t *p_sys;
+
+    /* Allocate structure */
+    p_sys = (filter_sys_t *)malloc( sizeof( filter_sys_t ) );
+    p_filter->p_sys = p_sys;
+    if( p_filter->p_sys == NULL )
+    {
+        msg_Err( p_filter, "out of memory for p_sys structure" );
+        return VLC_ENOMEM;
+    }
+    /* set all entries to zero */
+    memset(p_sys, 0, sizeof( filter_sys_t ));
+
+    /* further Setup Function pointers for videolan for calling my filter */
+    p_filter->pf_video_filter = Filter;
+
+    config_ChainParse( p_filter, CFG_PREFIX, ppsz_filter_options,
+                       p_filter->p_cfg );
+
+    AddStateVariableCallback(p_filter);
+
+    AddCropVariableCallback(p_filter);
+
+    AddAtmoSettingsVariablesCallbacks(p_filter);
+
+    Atmo_SetupParameters(p_filter);
+
+
+    return VLC_SUCCESS;
+}
+
+
+
+/*****************************************************************************
+* DestroyFilter: destroy AtmoLight video thread output method
+*****************************************************************************
+* Terminate an output method created by CreateFilter
+*****************************************************************************/
+
+static void DestroyFilter( vlc_object_t *p_this )
+{
+    filter_t *p_filter = (filter_t *)p_this;
+    filter_sys_t *p_sys =  p_filter->p_sys;
+
+    DelStateVariableCallback(p_filter);
+    DelCropVariableCallback(p_filter);
+    DelAtmoSettingsVariablesCallbacks(p_filter);
+
+    Atmo_Shutdown(p_filter);
+
+#if defined( WIN32 )
+    if(p_sys->h_AtmoCtrl != NULL)
+    {
+        FreeLibrary(p_sys->h_AtmoCtrl);
+    }
+#endif
+
+    delete p_sys->p_atmo_dyndata;
+    delete p_sys->p_atmo_config;
+
+    vlc_mutex_destroy( &p_sys->filter_lock );
+
+    free( p_sys );
+}
+
+
+/*
+function stolen from some other videolan source filter ;-)
+for the moment RGB is OK... but better would be a direct transformation
+from YUV --> HSV
+*/
+static inline void yuv_to_rgb( uint8_t *r, uint8_t *g, uint8_t *b,
+                              uint8_t y1, uint8_t u1, uint8_t v1 )
+{
+    /* macros used for YUV pixel conversions */
+#   define SCALEBITS 10
+#   define ONE_HALF  (1 << (SCALEBITS - 1))
+#   define FIX(x)    ((int) ((x) * (1<<SCALEBITS) + 0.5))
+#   define CLAMP( x ) (((x) > 255) ? 255 : ((x) < 0) ? 0 : (x));
+
+    int y, cb, cr, r_add, g_add, b_add;
+
+    cb = u1 - 128;
+    cr = v1 - 128;
+    r_add = FIX(1.40200*255.0/224.0) * cr + ONE_HALF;
+    g_add = - FIX(0.34414*255.0/224.0) * cb
+        - FIX(0.71414*255.0/224.0) * cr + ONE_HALF;
+    b_add = FIX(1.77200*255.0/224.0) * cb + ONE_HALF;
+    y = (y1 - 16) * FIX(255.0/219.0);
+    *r = CLAMP((y + r_add) >> SCALEBITS);
+    *g = CLAMP((y + g_add) >> SCALEBITS);
+    *b = CLAMP((y + b_add) >> SCALEBITS);
+}
+/******************************************************************************
+* ExtractMiniImage_YUV: extract a small image from the picture as 24-bit RGB
+*******************************************************************************
+* p_sys is a pointer to
+* p_inpic is the source frame
+* p_transfer_dest is the target buffer for the picture must be big enough!
+* (in win32 enviroment this buffer comes from the external DLL where it is
+* create as "variant array" and returned through the AtmoLockTransferbuffer
+*/
+static void ExtractMiniImage_YUV(filter_sys_t *p_sys,
+                                 picture_t *p_inpic,
+                                 uint8_t *p_transfer_dest)
+{
+    int i_col;
+    int i_row;
+    uint8_t *p_src_y;
+    uint8_t *p_src_u;
+    uint8_t *p_src_v;
+    uint8_t *p_rgb_dst_line_red;
+    uint8_t *p_rgb_dst_line_green;
+    uint8_t *p_rgb_dst_line_blue;
+    int i_xpos_y;
+    int i_xpos_u;
+    int i_xpos_v;
+
+    /* calcute Pointers for Storage of B G R (A) */
+    p_rgb_dst_line_blue      = p_transfer_dest;
+    p_rgb_dst_line_green     = p_transfer_dest + 1;
+    p_rgb_dst_line_red       = p_transfer_dest + 2 ;
+
+    int i_row_count = p_sys->i_atmo_height + 1;
+    int i_col_count = p_sys->i_atmo_width + 1;
+    int i_y_row,i_u_row,i_v_row,i_pixel_row;
+    int i_pixel_col;
+
+
+    /*  these two ugly loops extract the small image - goes it faster? how?
+    the loops are so designed that there is a small border around the extracted
+    image so we wont get column and row - zero from the frame, and not the most
+    right and bottom pixels --- which may be clipped on computers useing TV out
+    - through overscan!
+
+    TODO: try to find out if the output is clipped through VLC - and try here
+    to ingore the clipped away area for a better result!
+
+    TODO: performance improvement in InitFilter percalculated the offsets of
+    the lines inside the planes so I can save (i_row_count * 3) 2xMUL and
+    one time DIV the same could be done for the inner loop I think...
+    */
+    for(i_row = 1; i_row < i_row_count; i_row++)
+    {
+        // calcute the current Lines in the source planes for this outputrow
+        /*  Adresscalcuation  pointer to plane  Length of one pixelrow in bytes
+        calculate row now number
+        */
+        /*
+           p_inpic->format? transform Pixel row into row of plane...
+           how? simple? fast? good?
+        */
+
+        /* compute the source pixel row and respect the active cropping */
+        i_pixel_row = (i_row * p_sys->i_crop_height) / i_row_count
+            + p_sys->i_crop_y_offset;
+
+        /*
+        trans for these Pixel row into the row of each plane ..
+        because planesize can differ from image size
+        */
+        i_y_row = (i_pixel_row * p_inpic->p[Y_PLANE].i_visible_lines) /
+            p_inpic->format.i_visible_height;
+
+        i_u_row = (i_pixel_row * p_inpic->p[U_PLANE].i_visible_lines) /
+            p_inpic->format.i_visible_height;
+
+        i_v_row = (i_pixel_row * p_inpic->p[V_PLANE].i_visible_lines) /
+            p_inpic->format.i_visible_height;
+
+        /* calculate  the pointers to the pixeldata for this row
+           in each plane
+        */
+        p_src_y = p_inpic->p[Y_PLANE].p_pixels +
+            p_inpic->p[Y_PLANE].i_pitch * i_y_row;
+        p_src_u = p_inpic->p[U_PLANE].p_pixels +
+            p_inpic->p[U_PLANE].i_pitch * i_u_row;
+        p_src_v = p_inpic->p[V_PLANE].p_pixels +
+            p_inpic->p[V_PLANE].i_pitch * i_v_row;
+
+        for(i_col = 1; i_col < i_col_count; i_col++)
+        {
+            i_pixel_col = (i_col * p_sys->i_crop_width) / i_col_count +
+                p_sys->i_crop_x_offset;
+            /*
+            trans for these Pixel row into the row of each plane ..
+            because planesize can differ from image size
+            */
+            i_xpos_y = (i_pixel_col * p_inpic->p[Y_PLANE].i_visible_pitch) /
+                p_inpic->format.i_visible_width;
+            i_xpos_u = (i_pixel_col * p_inpic->p[U_PLANE].i_visible_pitch) /
+                p_inpic->format.i_visible_width;
+            i_xpos_v = (i_pixel_col * p_inpic->p[V_PLANE].i_visible_pitch) /
+                p_inpic->format.i_visible_width;
+
+            yuv_to_rgb(p_rgb_dst_line_red,
+                p_rgb_dst_line_green,
+                p_rgb_dst_line_blue,
+
+                p_src_y[i_xpos_y],
+                p_src_u[i_xpos_u],
+                p_src_v[i_xpos_v]);
+
+            /* +4 because output image should be RGB32 with dword alignment! */
+            p_rgb_dst_line_red   += 4;
+            p_rgb_dst_line_green += 4;
+            p_rgb_dst_line_blue  += 4;
+        }
+    }
+}
+
+
+/******************************************************************************
+* SaveBitmap: Saves the content of a transferbuffer as Bitmap to disk
+*******************************************************************************
+* just for debugging
+* p_sys -> configuration if Atmo from there the function will get height and
+*          width
+* p_pixels -> should be the dword aligned BGR(A) image data
+* psz_filename -> filename where to store
+*/
+#if defined(__ATMO_DEBUG__)
+void SaveBitmap(filter_sys_t *p_sys, uint8_t *p_pixels, char *psz_filename)
+{
+    /* for debug out only used*/
+    BITMAPINFO bmp_info;
+    BITMAPFILEHEADER  bmp_fileheader;
+    FILE *fp_bitmap;
+
+    memset(&bmp_info, 0, sizeof(BITMAPINFO));
+    bmp_info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+    bmp_info.bmiHeader.biSizeImage   = p_sys->i_atmo_height *
+                                       p_sys->i_atmo_width * 4;
+    bmp_info.bmiHeader.biCompression = BI_RGB;
+    bmp_info.bmiHeader.biWidth        = p_sys->i_atmo_width;
+    bmp_info.bmiHeader.biHeight       = -p_sys->i_atmo_height;
+    bmp_info.bmiHeader.biBitCount     = 32;
+    bmp_info.bmiHeader.biPlanes       = 1;
+
+    bmp_fileheader.bfReserved1 = 0;
+    bmp_fileheader.bfReserved2 = 0;
+    bmp_fileheader.bfSize = sizeof(BITMAPFILEHEADER) +
+                            sizeof(BITMAPINFOHEADER) +
+                            bmp_info.bmiHeader.biSizeImage;
+    bmp_fileheader.bfType = 'MB';
+    bmp_fileheader.bfOffBits = sizeof(BITMAPFILEHEADER) +
+                               sizeof(BITMAPINFOHEADER);
+
+    fp_bitmap = fopen(psz_filename,"wb");
+    if( fp_bitmap != NULL)
+    {
+        fwrite(&bmp_fileheader, sizeof(BITMAPFILEHEADER), 1, fp_bitmap);
+        fwrite(&bmp_info.bmiHeader, sizeof(BITMAPINFOHEADER), 1, fp_bitmap);
+        fwrite(p_pixels, bmp_info.bmiHeader.biSizeImage, 1, fp_bitmap);
+        fclose(fp_bitmap);
+    }
+}
+#endif
+
+
+/****************************************************************************
+* CreateMiniImage: extracts a 64x48 pixel image from the frame
+* (there is a small border arround thats why the loops starts with one
+* instead zero) without any interpolation
+*****************************************************************************/
+static void CreateMiniImage( filter_t *p_filter, picture_t *p_inpic)
+{
+    filter_sys_t *p_sys = p_filter->p_sys;
+    /*
+    pointer to RGB Buffer created in external libary as safe array which
+    is locked inside AtmoLockTransferBuffer
+    */
+    uint8_t *p_transfer = NULL;
+#if defined( __ATMO_DEBUG__ )
+    /* for debug out only used*/
+    char sz_filename[MAX_PATH];
+#endif
+
+    /*
+    Lock the before created VarArray (AtmoCreateTransferBuffers)
+    inside my wrapper library and give me a pointer to the buffer!
+    below linux a global buffer may be used and protected with a mutex?
+    */
+    p_transfer = AtmoLockTransferBuffer(p_filter);
+    if(p_transfer == NULL)
+    {
+        msg_Err( p_filter, "AtmoLight no transferbuffer available. "\
+                           "AtmoLight will be disabled!");
+        p_sys->b_enabled = VLC_FALSE;
+        return;
+    }
+
+    /*
+    do the call via pointer to function instead of having a
+    case structure here
+    */
+    p_sys->pf_extract_mini_image(p_sys, p_inpic, p_transfer);
+
+
+#if defined( __ATMO_DEBUG__ )
+    /*
+    if debugging enabled save every 128th image to disk
+    */
+    if((p_sys->b_saveframes == VLC_TRUE) && (p_sys->sz_framepath[0] != 0 ))
+    {
+
+        if((p_sys->i_framecounter & 127) == 0)
+        {
+            sprintf(sz_filename,"%satmo_dbg_%06d.bmp",p_sys->sz_framepath,
+                p_sys->i_framecounter);
+            msg_Dbg(p_filter, "SaveFrame %s",sz_filename);
+
+            SaveBitmap(p_sys, p_transfer, sz_filename);
+        }
+        p_sys->i_framecounter++;
+    }
+#endif
+
+    /* show the colors on the wall */
+    AtmoSendPixelData(p_filter);
+}
+
+
+
+
+/*****************************************************************************
+* Filter: calls the extract method and forwards the incomming picture 1:1
+*****************************************************************************
+*
+*****************************************************************************/
+
+static picture_t * Filter( filter_t *p_filter, picture_t *p_pic )
+{
+    filter_sys_t *p_sys = p_filter->p_sys;
+    if( !p_pic ) return NULL;
+
+    if((p_sys->b_enabled == VLC_TRUE) &&
+        (p_sys->pf_extract_mini_image != NULL) &&
+        (p_sys->b_pause_live == VLC_FALSE))
+    {
+        CreateMiniImage(p_filter, p_pic);
+    }
+
+    return p_pic;
+}
+
+
+/*****************************************************************************
+* FadeToColorThread: Threadmethod which changes slowly the color
+* to a target color defined in p_fadethread struct
+* use for: Fade to Pause Color,  and Fade to End Color
+*****************************************************************************/
+static void FadeToColorThread(fadethread_t *p_fadethread)
+{
+    filter_sys_t *p_sys = (filter_sys_t *)p_fadethread->p_filter->p_sys;
+    int i_steps_done = 0;
+    int i_index;
+    int i_pause_red;
+    int i_pause_green;
+    int i_pause_blue;
+
+    int i_src_red;
+    int i_src_green;
+    int i_src_blue;
+
+    vlc_thread_ready( p_fadethread );
+
+    uint8_t *p_source = NULL;
+
+    /* initialize AtmoWin for this thread! */
+    AtmoInitialize(p_fadethread->p_filter , VLC_TRUE);
+
+    uint8_t *p_transfer = AtmoLockTransferBuffer( p_fadethread->p_filter );
+    if(p_transfer != NULL) {
+        /* safe colors as "32bit" Integers to avoid overflows*/
+        i_pause_red   = p_fadethread->ui_red;
+        i_pause_blue  = p_fadethread->ui_blue;
+        i_pause_green = p_fadethread->ui_green;
+
+        /*
+        allocate a temporary buffer for the last send
+        image size less then 15kb
+        */
+        int i_size = 4 * p_sys->i_atmo_width * p_sys->i_atmo_height;
+        p_source = (uint8_t *)malloc( i_size );
+        if(p_source != NULL)
+        {
+            /*
+            get a copy of the last transfered image as orign for the
+            fading steps...
+            */
+            memcpy(p_source, p_transfer, i_size);
+            /* send the same pixel data again... to unlock the buffer! */
+            AtmoSendPixelData( p_fadethread->p_filter );
+
+            while( (!p_fadethread->b_die) &&
+                (i_steps_done < p_fadethread->i_steps))
+            {
+                p_transfer = AtmoLockTransferBuffer( p_fadethread->p_filter );
+                if(!p_transfer) break; /* should not happen if it worked
+                                       one time in the code above! */
+                i_steps_done++;
+                /*
+                move all pixels in the mini image (64x48) one step closer to
+                the desired color these loop takes the most time of this
+                thread improvements wellcome!
+                */
+                for(i_index = 0;
+                    (i_index < i_size) && (!p_fadethread->b_die);
+                    i_index+=4)
+                {
+                    i_src_blue  = p_source[i_index+0];
+                    i_src_green = p_source[i_index+1];
+                    i_src_red   = p_source[i_index+2];
+                    p_transfer[i_index+0] = (uint8_t) (((
+                        (i_pause_blue  - i_src_blue)
+                        * i_steps_done)/p_fadethread->i_steps)
+                        + i_src_blue);
+
+                    p_transfer[i_index+1] = (uint8_t) (((
+                        (i_pause_green - i_src_green)
+                        * i_steps_done)/p_fadethread->i_steps)
+                        + i_src_green);
+
+                    p_transfer[i_index+2] = (uint8_t) (((
+                        (i_pause_red   - i_src_red)
+                        * i_steps_done)/p_fadethread->i_steps)
+                        + i_src_red);
+                }
+
+                /* send image to lightcontroller */
+                AtmoSendPixelData( p_fadethread->p_filter );
+                /* is there something like and interruptable sleep inside
+                the VLC libaries? inside native win32 I would use an Event
+                (CreateEvent) and here an WaitForSingleObject?
+                */
+                if(p_fadethread->b_die) break;
+                msleep(10000);
+                if(p_fadethread->b_die) break;
+                msleep(10000);
+                if(p_fadethread->b_die) break;
+                msleep(10000);
+                if(p_fadethread->b_die) break;
+                msleep(10000);
+            }
+            free(p_source);
+        } else {
+            /* in failure of malloc also unlock buffer  */
+            AtmoSendPixelData(p_fadethread->p_filter);
+        }
+    }
+    /* call indirect to OleUnitialize() for this thread */
+    AtmoFinalize(p_fadethread->p_filter, 0);
+}
+
+/*****************************************************************************
+* CheckAndStopFadeThread: if there is a fadethread structure left, or running.
+******************************************************************************
+* this function will stop the thread ... and waits for its termination
+* before removeing the objects from vout_sys_t ...
+******************************************************************************/
+static void CheckAndStopFadeThread(filter_t *p_filter)
+{
+    filter_sys_t *p_sys = (filter_sys_t *)p_filter->p_sys;
+    vlc_mutex_lock( &p_sys->filter_lock );
+    if(p_sys->p_fadethread != NULL)
+    {
+        msg_Dbg(p_filter, "kill still running fadeing thread...");
+
+        p_sys->p_fadethread->b_die = VLC_TRUE;
+
+        vlc_thread_join(p_sys->p_fadethread);
+
+        vlc_object_destroy(p_sys->p_fadethread);
+        p_sys->p_fadethread = NULL;
+    }
+    vlc_mutex_unlock( &p_sys->filter_lock );
+}
+
+/*****************************************************************************
+* StateCallback: Callback for the inputs variable "State" to get notified
+* about Pause and Continue Playback events.
+*****************************************************************************/
+static int StateCallback( vlc_object_t *p_this, char const *psz_cmd,
+                         vlc_value_t oldval, vlc_value_t newval,
+                         void *p_data )
+{
+    filter_t *p_filter = (filter_t *)p_data;
+    filter_sys_t *p_sys = (filter_sys_t *)p_filter->p_sys;
+
+    if((p_sys->b_usepausecolor == VLC_TRUE) && (p_sys->b_enabled == VLC_TRUE))
+    {
+        msg_Dbg(p_filter, "state change from: %d to %d", oldval.i_int,
+            newval.i_int);
+
+        if((newval.i_int == PAUSE_S) && (oldval.i_int == PLAYING_S))
+        {
+            /* tell the other thread to stop sending images to light
+               controller */
+            p_sys->b_pause_live = VLC_TRUE;
+
+            // ggf. alten Thread abräumen should not happen....
+            CheckAndStopFadeThread(p_filter);
+
+            // perpare spawn fadeing thread
+            vlc_mutex_lock( &p_sys->filter_lock );
+            /*
+            launch only a new thread if there is none active!
+            or waiting for cleanup
+            */
+            if(p_sys->p_fadethread == NULL)
+            {
+                p_sys->p_fadethread = (fadethread_t *)vlc_object_create(
+                     p_filter,
+                     sizeof(fadethread_t) );
+
+                p_sys->p_fadethread->p_filter = p_filter;
+                p_sys->p_fadethread->ui_red   = p_sys->ui_pausecolor_red;
+                p_sys->p_fadethread->ui_green = p_sys->ui_pausecolor_green;
+                p_sys->p_fadethread->ui_blue  = p_sys->ui_pausecolor_blue;
+                p_sys->p_fadethread->i_steps  = p_sys->i_fadesteps;
+
+                if( vlc_thread_create( p_sys->p_fadethread,
+                    "AtmoLight fadeing",
+                    FadeToColorThread,
+                    VLC_THREAD_PRIORITY_LOW,
+                    VLC_FALSE) )
+                {
+                    msg_Err( p_filter, "cannot create FadeToColorThread" );
+                    vlc_object_destroy( p_sys->p_fadethread );
+                    p_sys->p_fadethread = NULL;
+                }
+            }
+            vlc_mutex_unlock( &p_sys->filter_lock );
+        }
+
+        if((newval.i_int == PLAYING_S) && (oldval.i_int == PAUSE_S))
+        {
+            /* playback continues check thread state */
+            CheckAndStopFadeThread(p_filter);
+            /* reactivate the Render function... to do its normal work */
+            p_sys->b_pause_live = VLC_FALSE;
+        }
+    }
+
+    return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+* AddPlaylistInputThreadStateCallback: Setup call back on "State" Variable
+*****************************************************************************
+* Add Callback function to the "state" variable of the input thread..
+* first find the PlayList and get the input thread from there to attach
+* my callback? is vlc_object_find the right way for this??
+*****************************************************************************/
+static void AddStateVariableCallback(filter_t *p_filter)
+{
+    playlist_t *p_playlist = (playlist_t *)vlc_object_find( p_filter,
+        VLC_OBJECT_PLAYLIST,
+        FIND_ANYWHERE );
+    if( p_playlist )
+    {
+        input_thread_t *p_input = p_playlist->p_input;
+        if(p_input)
+        {
+            var_AddCallback( p_input, "state", StateCallback, p_filter );
+        }
+        vlc_object_release( p_playlist );
+    }
+}
+
+/*****************************************************************************
+* DelPlaylistInputThreadStateCallback: Remove call back on "State" Variable
+*****************************************************************************
+* Delete the callback function to the "state" variable of the input thread...
+* first find the PlayList and get the input thread from there to attach
+* my callback? is vlc_object_find the right way for this??
+*****************************************************************************/
+static void DelStateVariableCallback( filter_t *p_filter )
+{
+    playlist_t *p_playlist = (playlist_t *)vlc_object_find( p_filter,
+        VLC_OBJECT_PLAYLIST,
+        FIND_ANYWHERE );
+    if( p_playlist )
+    {
+        input_thread_t *p_input = p_playlist->p_input;
+        if(p_input)
+        {
+            var_DelCallback( p_input, "state", StateCallback, p_filter );
+        }
+        vlc_object_release( p_playlist );
+    }
+}
+
+
+static int CropCallback(vlc_object_t *p_this, char const *psz_cmd,
+                        vlc_value_t oldval, vlc_value_t newval,
+                        void *p_data)
+{
+    vout_thread_t *p_vout = (vout_thread_t *)p_this;
+    filter_t *p_filter = (filter_t *)p_data;
+    filter_sys_t *p_sys = (filter_sys_t *)p_filter->p_sys;
+
+    /*
+    //if the handler is attache to crop variable directly!
+    int i_visible_width, i_visible_height, i_x_offset, i_y_offset;
+    atmo_parse_crop(newval.psz_string, p_vout->fmt_render,
+    p_vout->fmt_render,
+    i_visible_width, i_visible_height,
+    i_x_offset, i_y_offset);
+    p_sys->i_crop_x_offset  = i_x_offset;
+    p_sys->i_crop_y_offset  = i_y_offset;
+    p_sys->i_crop_width     = i_visible_width;
+    p_sys->i_crop_height    = i_visible_height;
+    */
+
+    p_sys->i_crop_x_offset  = p_vout->fmt_in.i_x_offset;
+    p_sys->i_crop_y_offset  = p_vout->fmt_in.i_y_offset;
+    p_sys->i_crop_width     = p_vout->fmt_in.i_visible_width;
+    p_sys->i_crop_height    = p_vout->fmt_in.i_visible_height;
+
+    msg_Dbg(p_filter, "cropping picture %ix%i to %i,%i,%ix%i",
+        p_vout->fmt_in.i_width,
+        p_vout->fmt_in.i_height,
+        p_sys->i_crop_x_offset,
+        p_sys->i_crop_y_offset,
+        p_sys->i_crop_width,
+        p_sys->i_crop_height
+        );
+
+    return VLC_SUCCESS;
+}
+
+
+static void AddCropVariableCallback( filter_t *p_filter)
+{
+    vout_thread_t *p_vout = (vout_thread_t *)vlc_object_find( p_filter,
+        VLC_OBJECT_VOUT,
+        FIND_ANYWHERE );
+    if( p_vout )
+    {
+        var_AddCallback( p_vout, "crop-update", CropCallback, p_filter );
+        vlc_object_release( p_vout );
+    }
+}
+
+static void DelCropVariableCallback( filter_t *p_filter)
+{
+    vout_thread_t *p_vout = (vout_thread_t *)vlc_object_find( p_filter,
+        VLC_OBJECT_VOUT,
+        FIND_ANYWHERE );
+    if( p_vout )
+    {
+        var_DelCallback( p_vout, "crop-update", CropCallback, p_filter );
+        vlc_object_release( p_vout );
+    }
+}
+
+
+/****************************************************************************
+* StateCallback: Callback for the inputs variable "State" to get notified
+* about Pause and Continue Playback events.
+*****************************************************************************/
+static int AtmoSettingsCallback( vlc_object_t *p_this, char const *psz_var,
+                                 vlc_value_t oldval, vlc_value_t newval,
+                                 void *p_data )
+{
+    filter_t *p_filter = (filter_t *)p_data;
+    filter_sys_t *p_sys = (filter_sys_t *)p_filter->p_sys;
+
+    CAtmoConfig *p_atmo_config = p_sys->p_atmo_config;
+    if(p_atmo_config)
+    {
+
+       msg_Dbg(p_filter, "apply AtmoSettingsCallback %s (int: %d -> %d)",
+             psz_var,
+             oldval.i_int,
+             newval.i_int
+       );
+
+        if( !strcmp( psz_var, CFG_PREFIX "filtermode" ))
+            p_atmo_config->setLiveViewFilterMode( (AtmoFilterMode)newval.i_int);
+
+        else if( !strcmp( psz_var, CFG_PREFIX "PercentNew" ))
+                 p_atmo_config->setLiveViewFilter_PercentNew( newval.i_int );
+
+        else if( !strcmp( psz_var, CFG_PREFIX "MeanLength" ))
+                 p_atmo_config->setLiveViewFilter_MeanLength( newval.i_int );
+
+        else if( !strcmp( psz_var, CFG_PREFIX "MeanThreshold" ))
+                 p_atmo_config->setLiveViewFilter_MeanThreshold( newval.i_int );
+
+        else if( !strcmp( psz_var, CFG_PREFIX "EdgeWeightning" ))
+                 p_atmo_config->setLiveView_EdgeWeighting( newval.i_int );
+
+        else if( !strcmp( psz_var, CFG_PREFIX "Brightness" ))
+                 p_atmo_config->setLiveView_BrightCorrect( newval.i_int );
+
+        else if( !strcmp( psz_var, CFG_PREFIX "DarknessLimit" ))
+                 p_atmo_config->setLiveView_DarknessLimit( newval.i_int );
+
+        else if( !strcmp( psz_var, CFG_PREFIX "HueWinSize" ))
+                 p_atmo_config->setLiveView_HueWinSize( newval.i_int );
+
+        else if( !strcmp( psz_var, CFG_PREFIX "SatWinSize" ))
+                 p_atmo_config->setLiveView_SatWinSize( newval.i_int );
+
+        else if( !strcmp( psz_var, CFG_PREFIX "FrameDelay" ))
+                 p_atmo_config->setLiveView_FrameDelay( newval.i_int );
+
+        else if( !strcmp( psz_var, CFG_PREFIX "whiteadj" ))
+                 p_atmo_config->setUseSoftwareWhiteAdj( newval.b_bool );
+
+        else if( !strcmp( psz_var, CFG_PREFIX "white-red" ))
+                 p_atmo_config->setWhiteAdjustment_Red( newval.i_int );
+
+        else if( !strcmp( psz_var, CFG_PREFIX "white-green" ))
+                 p_atmo_config->setWhiteAdjustment_Green( newval.i_int );
+
+        else if( !strcmp( psz_var, CFG_PREFIX "white-blue" ))
+                 p_atmo_config->setWhiteAdjustment_Blue( newval.i_int );
+
+    }
+    return VLC_SUCCESS;
+}
+
+static void AddAtmoSettingsVariablesCallbacks(filter_t *p_filter)
+{
+   var_AddCallback( p_filter, CFG_PREFIX "filtermode",
+                    AtmoSettingsCallback, p_filter );
+   var_AddCallback( p_filter, CFG_PREFIX "PercentNew",
+                    AtmoSettingsCallback, p_filter );
+
+
+   var_AddCallback( p_filter, CFG_PREFIX "MeanLength",
+                    AtmoSettingsCallback, p_filter );
+   var_AddCallback( p_filter, CFG_PREFIX "MeanThreshold",
+                    AtmoSettingsCallback, p_filter );
+
+   var_AddCallback( p_filter, CFG_PREFIX "EdgeWeightning",
+                    AtmoSettingsCallback, p_filter );
+   var_AddCallback( p_filter, CFG_PREFIX "Brightness",
+                    AtmoSettingsCallback, p_filter );
+   var_AddCallback( p_filter, CFG_PREFIX "DarknessLimit",
+                    AtmoSettingsCallback, p_filter );
+
+   var_AddCallback( p_filter, CFG_PREFIX "HueWinSize",
+                    AtmoSettingsCallback, p_filter );
+   var_AddCallback( p_filter, CFG_PREFIX "SatWinSize",
+                    AtmoSettingsCallback, p_filter );
+   var_AddCallback( p_filter, CFG_PREFIX "FrameDelay",
+                    AtmoSettingsCallback, p_filter );
+
+
+   var_AddCallback( p_filter, CFG_PREFIX "whiteadj",
+                    AtmoSettingsCallback, p_filter );
+   var_AddCallback( p_filter, CFG_PREFIX "white-red",
+                    AtmoSettingsCallback, p_filter );
+   var_AddCallback( p_filter, CFG_PREFIX "white-green",
+                    AtmoSettingsCallback, p_filter );
+   var_AddCallback( p_filter, CFG_PREFIX "white-blue",
+                    AtmoSettingsCallback, p_filter );
+}
+
+static void DelAtmoSettingsVariablesCallbacks( filter_t *p_filter )
+{
+
+   var_DelCallback( p_filter, CFG_PREFIX "filtermode",
+                    AtmoSettingsCallback, p_filter );
+
+   var_DelCallback( p_filter, CFG_PREFIX "PercentNew",
+                    AtmoSettingsCallback, p_filter );
+   var_DelCallback( p_filter, CFG_PREFIX "MeanLength",
+                    AtmoSettingsCallback, p_filter );
+   var_DelCallback( p_filter, CFG_PREFIX "MeanThreshold",
+                    AtmoSettingsCallback, p_filter );
+
+   var_DelCallback( p_filter, CFG_PREFIX "EdgeWeightning",
+                    AtmoSettingsCallback, p_filter );
+   var_DelCallback( p_filter, CFG_PREFIX "Brightness",
+                    AtmoSettingsCallback, p_filter );
+   var_DelCallback( p_filter, CFG_PREFIX "DarknessLimit",
+                    AtmoSettingsCallback, p_filter );
+
+   var_DelCallback( p_filter, CFG_PREFIX "HueWinSize",
+                    AtmoSettingsCallback, p_filter );
+   var_DelCallback( p_filter, CFG_PREFIX "SatWinSize",
+                    AtmoSettingsCallback, p_filter );
+   var_DelCallback( p_filter, CFG_PREFIX "FrameDelay",
+                    AtmoSettingsCallback, p_filter );
+
+
+   var_DelCallback( p_filter, CFG_PREFIX "whiteadj",
+                    AtmoSettingsCallback, p_filter );
+   var_DelCallback( p_filter, CFG_PREFIX "white-red",
+                    AtmoSettingsCallback, p_filter );
+   var_DelCallback( p_filter, CFG_PREFIX "white-green",
+                    AtmoSettingsCallback, p_filter );
+   var_DelCallback( p_filter, CFG_PREFIX "white-blue",
+                    AtmoSettingsCallback, p_filter );
+
+}
+
+
+#if defined(__ATMO_DEBUG__)
+static void atmo_parse_crop(char *psz_cropconfig,
+                            video_format_t fmt_in,
+                            video_format_t fmt_render,
+                            int &i_visible_width, int &i_visible_height,
+                            int &i_x_offset, int &i_y_offset )
+{
+    int64_t i_aspect_num, i_aspect_den;
+    unsigned int i_width, i_height;
+
+    i_visible_width  = fmt_in.i_visible_width;
+    i_visible_height = fmt_in.i_visible_height;
+    i_x_offset       = fmt_in.i_x_offset;
+    i_y_offset       = fmt_in.i_y_offset;
+
+    char *psz_end = NULL, *psz_parser = strchr( psz_cropconfig, ':' );
+    if( psz_parser )
+    {
+        /* We're using the 3:4 syntax */
+        i_aspect_num = strtol( psz_cropconfig, &psz_end, 10 );
+        if( psz_end == psz_cropconfig || !i_aspect_num ) return;
+
+        i_aspect_den = strtol( ++psz_parser, &psz_end, 10 );
+        if( psz_end == psz_parser || !i_aspect_den ) return;
+
+        i_width = fmt_in.i_sar_den * fmt_render.i_visible_height *
+            i_aspect_num / i_aspect_den / fmt_in.i_sar_num;
+
+        i_height = fmt_render.i_visible_width*fmt_in.i_sar_num *
+            i_aspect_den / i_aspect_num / fmt_in.i_sar_den;
+
+        if( i_width < fmt_render.i_visible_width )
+        {
+            i_x_offset = fmt_render.i_x_offset +
+                (fmt_render.i_visible_width - i_width) / 2;
+            i_visible_width = i_width;
+        }
+        else
+        {
+            i_y_offset = fmt_render.i_y_offset +
+                (fmt_render.i_visible_height - i_height) / 2;
+            i_visible_height = i_height;
+        }
+    }
+    else
+    {
+        psz_parser = strchr( psz_cropconfig, 'x' );
+        if( psz_parser )
+        {
+            /* Maybe we're using the <width>x<height>+<left>+<top> syntax */
+            unsigned int i_crop_width, i_crop_height, i_crop_top, i_crop_left;
+
+            i_crop_width = strtol( psz_cropconfig, &psz_end, 10 );
+            if( psz_end != psz_parser ) return;
+
+            psz_parser = strchr( ++psz_end, '+' );
+            i_crop_height = strtol( psz_end, &psz_end, 10 );
+            if( psz_end != psz_parser ) return;
+
+            psz_parser = strchr( ++psz_end, '+' );
+            i_crop_left = strtol( psz_end, &psz_end, 10 );
+            if( psz_end != psz_parser ) return;
+
+            psz_end++;
+            i_crop_top = strtol( psz_end, &psz_end, 10 );
+            if( *psz_end != '\0' ) return;
+
+            i_width = i_crop_width;
+            i_visible_width = i_width;
+
+            i_height = i_crop_height;
+            i_visible_height = i_height;
+
+            i_x_offset = i_crop_left;
+            i_y_offset = i_crop_top;
+        }
+        else
+        {
+            /* Maybe we're using the <left>+<top>+<right>+<bottom> syntax */
+            unsigned int i_crop_top, i_crop_left, i_crop_bottom, i_crop_right;
+
+            psz_parser = strchr( psz_cropconfig, '+' );
+            i_crop_left = strtol( psz_cropconfig, &psz_end, 10 );
+            if( psz_end != psz_parser ) return;
+
+            psz_parser = strchr( ++psz_end, '+' );
+            i_crop_top = strtol( psz_end, &psz_end, 10 );
+            if( psz_end != psz_parser ) return;
+
+            psz_parser = strchr( ++psz_end, '+' );
+            i_crop_right = strtol( psz_end, &psz_end, 10 );
+            if( psz_end != psz_parser ) return;
+
+            psz_end++;
+            i_crop_bottom = strtol( psz_end, &psz_end, 10 );
+            if( *psz_end != '\0' ) return;
+
+            i_width = fmt_render.i_visible_width - i_crop_left - i_crop_right;
+            i_visible_width = i_width;
+
+            i_height = fmt_render.i_visible_height - i_crop_top - i_crop_bottom;
+            i_visible_height = i_height;
+
+            i_x_offset = i_crop_left;
+            i_y_offset = i_crop_top;
+        }
+    }
+}
+#endif