]> git.sesse.net Git - vlc/commitdiff
enhanced & corrected AtmoLight filter module
authorAndré Weber <atmo@videolan.org>
Tue, 26 Jan 2010 18:37:37 +0000 (19:37 +0100)
committerAndré Weber <atmo@videolan.org>
Tue, 26 Jan 2010 18:37:37 +0000 (19:37 +0100)
- added more thread locking/synchronization, to avoid potential risk of race conditions
- changed the option to choose the output device
- added support for MoMoLight (http://www.ambilight4pc.com/momolight/momolight.html)
- added support for a simple serial DMX (255 channel) controller
- added support for Quattro Atmo Light (allows to use four separated classic AtmoLights, as one virtual AtmoLight)
- changed the way color packets are passed from AtmoExternalCaptureInput to AtmoLiveView useing a queue object (instead of a unsynchronized global variable)
- renamed some options inside atmo.cpp to meet the requirements from the video effect dialog widget (later commit)
- changed the way to define the zones for image color extraction (because the number of zones isn't longer fixed to 4 or 5)
- removed the need to copy some .dll as bridge for the external AtmoWin into the VideoLAN folder, try to load the dll from the same folder like AtmoWinX.exe
- do not a complete fade out, if the filter processed a low number of frames and gets stopped (keeps VideoLAN quick responding, if switching through deinterlacing modes)
- added a debug option to see which pixels are used for color computation (just for fun)
- added more infos to README.txt inside the source folder

39 files changed:
modules/video_filter/Modules.am
modules/video_filter/atmo/AtmoCalculations.cpp
modules/video_filter/atmo/AtmoCalculations.h
modules/video_filter/atmo/AtmoChannelAssignment.cpp [new file with mode: 0644]
modules/video_filter/atmo/AtmoChannelAssignment.h [new file with mode: 0644]
modules/video_filter/atmo/AtmoClassicConnection.cpp [moved from modules/video_filter/atmo/AtmoSerialConnection.cpp with 66% similarity]
modules/video_filter/atmo/AtmoClassicConnection.h [moved from modules/video_filter/atmo/AtmoSerialConnection.h with 66% similarity]
modules/video_filter/atmo/AtmoConfig.cpp
modules/video_filter/atmo/AtmoConfig.h
modules/video_filter/atmo/AtmoConnection.cpp
modules/video_filter/atmo/AtmoConnection.h
modules/video_filter/atmo/AtmoDefs.h
modules/video_filter/atmo/AtmoDmxSerialConnection.cpp [new file with mode: 0644]
modules/video_filter/atmo/AtmoDmxSerialConnection.h [new file with mode: 0644]
modules/video_filter/atmo/AtmoDynData.cpp
modules/video_filter/atmo/AtmoDynData.h
modules/video_filter/atmo/AtmoExternalCaptureInput.cpp
modules/video_filter/atmo/AtmoExternalCaptureInput.h
modules/video_filter/atmo/AtmoInput.cpp
modules/video_filter/atmo/AtmoInput.h
modules/video_filter/atmo/AtmoLiveView.cpp
modules/video_filter/atmo/AtmoLiveView.h
modules/video_filter/atmo/AtmoMultiConnection.cpp [new file with mode: 0644]
modules/video_filter/atmo/AtmoMultiConnection.h [new file with mode: 0644]
modules/video_filter/atmo/AtmoOutputFilter.cpp
modules/video_filter/atmo/AtmoOutputFilter.h
modules/video_filter/atmo/AtmoPacketQueue.cpp [new file with mode: 0644]
modules/video_filter/atmo/AtmoPacketQueue.h [new file with mode: 0644]
modules/video_filter/atmo/AtmoThread.cpp
modules/video_filter/atmo/AtmoTools.cpp
modules/video_filter/atmo/AtmoTools.h
modules/video_filter/atmo/AtmoZoneDefinition.cpp
modules/video_filter/atmo/AtmoZoneDefinition.h
modules/video_filter/atmo/DmxTools.cpp [new file with mode: 0644]
modules/video_filter/atmo/DmxTools.h [new file with mode: 0644]
modules/video_filter/atmo/MoMoConnection.cpp [new file with mode: 0644]
modules/video_filter/atmo/MoMoConnection.h [new file with mode: 0644]
modules/video_filter/atmo/README.txt
modules/video_filter/atmo/atmo.cpp

index b2c9ec20db169026f67105b493db1e81ef8af91b..660c03f17db2ea6bb66ec40a9b975322db4281d7 100644 (file)
@@ -62,10 +62,16 @@ SOURCES_atmo = atmo/atmo.cpp \
        atmo/AtmoInput.cpp atmo/AtmoInput.h \
        atmo/AtmoLiveView.cpp atmo/AtmoLiveView.h \
        atmo/AtmoOutputFilter.cpp atmo/AtmoOutputFilter.h \
-       atmo/AtmoSerialConnection.cpp atmo/AtmoSerialConnection.h \
        atmo/AtmoThread.cpp atmo/AtmoThread.h \
        atmo/AtmoTools.cpp atmo/AtmoTools.h \
-       atmo/AtmoZoneDefinition.cpp atmo/AtmoZoneDefinition.h
+       atmo/AtmoZoneDefinition.cpp atmo/AtmoZoneDefinition.h \
+       atmo/AtmoChannelAssignment.cpp atmo/AtmoChannelAssignment.h \
+       atmo/AtmoClassicConnection.cpp atmo/AtmoClassicConnection.h \
+       atmo/AtmoDmxSerialConnection.cpp atmo/AtmoDmxSerialConnection.h \
+       atmo/DmxTools.cpp atmo/DmxTools.h \
+       atmo/AtmoMultiConnection.cpp atmo/AtmoMultiConnection.h \
+       atmo/MoMoConnection.cpp atmo/MoMoConnection.h \
+       atmo/AtmoPacketQueue.cpp atmo/AtmoPacketQueue.h
 SOURCES_video_filter_wrapper = wrapper.c
 noinst_HEADERS = filter_common.h filter_picture.h
 
index b8d4443b42e01a3be04810c934561a99b260bba1..23f5fc6ef833792af23e40454ce034c0c2cc6c59 100644 (file)
@@ -7,9 +7,14 @@
  */
 #include <stdlib.h>
 #include <string.h>
-
+#include <stdio.h>
 
 #include "AtmoDefs.h"
+
+#if defined(WIN32)
+#   include <windows.h>
+#endif
+
 #include "AtmoCalculations.h"
 #include "AtmoConfig.h"
 #include "AtmoZoneDefinition.h"
 #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))
+// macro
 #define POS_DIV(a, b)  ( (a)/(b) + ( ((a)%(b) >= (b)/2 ) ? 1 : 0) )
 
-tColorPacket CalcColorsAnalyzeHSV(CAtmoConfig *pAtmoConfig, tHSVColor *HSV_Img)
+
+CAtmoColorCalculator::CAtmoColorCalculator(CAtmoConfig *pAtmoConfig)
 {
-  int i; // counter
+  m_pAtmoConfig = pAtmoConfig;
+  m_Weight                = NULL;
+  m_hue_hist              = NULL;
+  m_windowed_hue_hist     = NULL;
+  m_most_used_hue_last    = NULL;
+  m_most_used_hue         = NULL;
+  m_sat_hist              = NULL;
+  m_windowed_sat_hist     = NULL;
+  m_most_used_sat         = NULL;
+  m_Zone_Weights          = NULL;
+  m_average_v             = NULL;
+  m_average_counter       = NULL;
+
+  m_LastEdgeWeighting      = -1;
+  m_LastWidescreenMode     = -1;
+  m_LastLayout_TopCount    = -1;
+  m_LastLayout_BottomCount = -1;
+  m_LastLayout_LRCount     = -1;
+  m_LastNumZones           = -1;
+}
 
-  // 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];
+CAtmoColorCalculator::~CAtmoColorCalculator(void)
+{
+  delete m_Weight;
+  delete m_hue_hist;
+  delete m_windowed_hue_hist;
+  delete m_most_used_hue_last;
+  delete m_most_used_hue;
+  delete m_sat_hist;
+  delete m_windowed_sat_hist;
+  delete m_most_used_sat;
+  delete m_Zone_Weights;
+  delete m_average_v;
+  delete m_average_counter;
+}
 
-  /***************************************************************************/
-  /* Weight                                                                  */
-  /***************************************************************************/
-  static int LastEdgeWeighting = -1;
-  static int LastWidescreenMode = -1;
+void CAtmoColorCalculator::UpdateParameters()
+{
+  // Zonen Definition neu laden
+  // diverse Vorberechnungen neu ausführen
+  // Speicherbuffer neu allokieren!
+}
 
-  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();
+void CAtmoColorCalculator::FindMostUsed(int AtmoSetup_NumZones,int *most_used,long int *windowed_hist)
+{
+  memset(most_used, 0, sizeof(int) * AtmoSetup_NumZones);
 
 
-  // calculate only if setup has changed
-  if ((AtmoSetup_EdgeWeighting != LastEdgeWeighting) ||
-      (AtmoSetup_WidescreenMode != LastWidescreenMode))
+  for (int zone = 0; zone < AtmoSetup_NumZones; zone++)
   {
-     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++)
+    int value = 0;
+    // walk trough histogram
+    for (int i = 0; i < s_MAX+1; i++) // assume s_MAX = h_MAX = v_Max
     {
-         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 new value bigger then old one
+      int tmp = *windowed_hist;  // windowed_hist[zone * (s_MAX+1) + i];
+      // if (w_sat_hist[channel][i] > value)
+      if (tmp > value)
       {
-        // 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++;
+        // remember index
+        most_used[zone] = i;
+        // and value
+        value = tmp;
       }
+      windowed_hist++;
     }
-    */
-       LastEdgeWeighting = AtmoSetup_EdgeWeighting;
-    LastWidescreenMode = AtmoSetup_WidescreenMode;
+  }
+}
+
+pColorPacket CAtmoColorCalculator::AnalyzeHSV(tHSVColor *HSV_Img)
+{
+  int i; // counter
+
+  int AtmoSetup_EdgeWeighting  = m_pAtmoConfig->getLiveView_EdgeWeighting();
+  int AtmoSetup_WidescreenMode = m_pAtmoConfig->getLiveView_WidescreenMode();
+  int AtmoSetup_DarknessLimit  = m_pAtmoConfig->getLiveView_DarknessLimit();
+  int AtmoSetup_BrightCorrect  = m_pAtmoConfig->getLiveView_BrightCorrect();
+  int AtmoSetup_SatWinSize     = m_pAtmoConfig->getLiveView_SatWinSize();
+  int AtmoSetup_NumZones       = m_pAtmoConfig->getZoneCount();
+  tHSVColor *temp_Img;
+
+  if(AtmoSetup_NumZones != m_LastNumZones)
+  {
+     delete m_Weight;
+     delete m_hue_hist;
+     delete m_windowed_hue_hist;
+     delete m_most_used_hue_last;
+     delete m_most_used_hue;
+     delete m_sat_hist;
+     delete m_windowed_sat_hist;
+     delete m_most_used_sat;
+     delete m_Zone_Weights;
+     delete m_average_v;
+     delete m_average_counter;
+
+     m_Weight              = new int[AtmoSetup_NumZones * IMAGE_SIZE];
+     m_Zone_Weights        = new int*[AtmoSetup_NumZones];
+     for(int i = 0; i < AtmoSetup_NumZones; i++)
+         m_Zone_Weights[i] = &m_Weight[i * IMAGE_SIZE];
+
+     m_hue_hist            = new long int[(h_MAX+1) * AtmoSetup_NumZones];
+     m_windowed_hue_hist   = new long int[(h_MAX+1) * AtmoSetup_NumZones];
+
+     m_most_used_hue_last  = new int[AtmoSetup_NumZones];
+     m_most_used_hue       = new int[AtmoSetup_NumZones];
+     memset( m_most_used_hue_last, 0, sizeof(int) * AtmoSetup_NumZones);
+
+     m_sat_hist           = new long int[(s_MAX+1) * AtmoSetup_NumZones];
+     m_windowed_sat_hist  = new long int[(s_MAX+1) * AtmoSetup_NumZones];
+     m_most_used_sat      = new int[AtmoSetup_NumZones];
+
+     m_average_v         = new long int[AtmoSetup_NumZones];
+     m_average_counter   = new int[AtmoSetup_NumZones];
+
+     m_LastNumZones = AtmoSetup_NumZones;
+  }
+
+
+  // calculate only if setup has changed
+  if ((AtmoSetup_EdgeWeighting != m_LastEdgeWeighting) ||
+      (AtmoSetup_WidescreenMode != m_LastWidescreenMode) ||
+      (m_pAtmoConfig->getZonesTopCount() != m_LastLayout_TopCount) ||
+      (m_pAtmoConfig->getZonesBottomCount() != m_LastLayout_BottomCount) ||
+      (m_pAtmoConfig->getZonesLRCount() !=  m_LastLayout_LRCount) ||
+      (m_pAtmoConfig->m_UpdateEdgeWeightningFlag != 0)
+     )
+  {
+
+      for(i = 0 ;i < AtmoSetup_NumZones; i++) {
+          CAtmoZoneDefinition *pZoneDef = m_pAtmoConfig->getZoneDefinition(i);
+          if(pZoneDef)
+          {
+             pZoneDef->UpdateWeighting(m_Zone_Weights[i],
+                                                              AtmoSetup_WidescreenMode,
+                                                              AtmoSetup_EdgeWeighting);
+#ifdef _debug_zone_weight_
+             char filename[128];
+             sprintf(filename, "zone_%d_gradient_debug.bmp",i);
+             pZoneDef->SaveZoneBitmap( filename );
+             sprintf(filename, "zone_%d_weight_%d_debug.bmp",i,AtmoSetup_EdgeWeighting);
+             pZoneDef->SaveWeightBitmap(filename, m_Zone_Weights[i] );
+#endif
+          }
+
+     }
+     m_pAtmoConfig->m_UpdateEdgeWeightningFlag = 0;
+
+     m_LastEdgeWeighting      = AtmoSetup_EdgeWeighting;
+     m_LastWidescreenMode     = AtmoSetup_WidescreenMode;
+     m_LastLayout_TopCount    = m_pAtmoConfig->getZonesTopCount();
+     m_LastLayout_BottomCount = m_pAtmoConfig->getZonesBottomCount();
+     m_LastLayout_LRCount     = m_pAtmoConfig->getZonesLRCount();
   }
 
+  AtmoSetup_DarknessLimit = AtmoSetup_DarknessLimit * 10;
+
+
   /***************************************************************************/
   /* 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));
+  // long int hue_hist[CAP_MAX_NUM_ZONES][h_MAX+1];
+
+  // average brightness (value)
+  // m_average_v m_average_counter
+
+  // clean histogram --> calloc
+  memset(m_hue_hist, 0, sizeof(long int) * (h_MAX+1) * AtmoSetup_NumZones);
+  memset(m_average_v, 0, sizeof(long int) * AtmoSetup_NumZones);
+  memset(m_average_counter, 0, sizeof(int) * AtmoSetup_NumZones);
 
+  temp_Img = HSV_Img;
   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)
+         if ((*temp_Img).v > AtmoSetup_DarknessLimit)
       {
-        // builtup histogram for the 5 channels
-        for (int channel = 0; channel < ATMO_NUM_CHANNELS; channel++)
+        // builtup histogram for the x Zones of the Display
+        for (int zone = 0; zone < AtmoSetup_NumZones; zone++)
         {
           // Add weight to channel
-          hue_hist[channel][HSV_Img[i].h] += Weight[channel][i] * HSV_Img[i].v;
+         // Weight(zone, pixel_nummer) m_Weight[((zone) * (IMAGE_SIZE)) + (pixel_nummer)]
+         // m_hue_hist[zone*(h_MAX+1) + HSV_Img[i].h] += m_Zone_Weights[zone][i] * HSV_Img[i].v;
+            m_hue_hist[zone*(h_MAX+1) + (*temp_Img).h] += m_Zone_Weights[zone][i] * temp_Img->v;
+
+            if(m_Zone_Weights[zone][i] > 0) {
+               m_average_v[zone] += temp_Img->v;
+               m_average_counter[zone]++;
+            }
+
         }
+        // calculate brightness average
       }
+      temp_Img++;
       i++;
     }
   }
@@ -126,11 +239,11 @@ tColorPacket CalcColorsAnalyzeHSV(CAtmoConfig *pAtmoConfig, tHSVColor *HSV_Img)
   /* hue histogram windowing    */
   /*----------------------------*/
   // windowed HSV histogram
-  long int w_hue_hist[ATMO_NUM_CHANNELS][h_MAX+1];
+  // long int w_hue_hist[CAP_MAX_NUM_ZONES][h_MAX+1]; -> m_windowed_hue_hist
   // clean windowed histogram
-  memset(&w_hue_hist, 0, sizeof(w_hue_hist));
+  memset(m_windowed_hue_hist, 0, sizeof(long int) * (h_MAX+1) * AtmoSetup_NumZones);
   // steps in each direction; eg. 2 => -2 -1 0 1 2 windowing
-  int hue_windowsize = pAtmoConfig->getLiveView_HueWinSize();
+  int hue_windowsize = m_pAtmoConfig->getLiveView_HueWinSize();
 
   for (i = 0; i < h_MAX+1; i++) // walk through histogram [0;h_MAX]
   {
@@ -146,11 +259,11 @@ tColorPacket CalcColorsAnalyzeHSV(CAtmoConfig *pAtmoConfig, tHSVColor *HSV_Img)
       // 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 windowing to all x zones
+      for (int zone = 0; zone < AtmoSetup_NumZones; zone++)
       {
         // 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
+        m_windowed_hue_hist[(zone * (h_MAX+1)) + i] += m_hue_hist[(zone * (h_MAX+1)) + myidx] * ((hue_windowsize+1)-abs(mywin)); // apply window
       }
     }
   }
@@ -159,71 +272,89 @@ tColorPacket CalcColorsAnalyzeHSV(CAtmoConfig *pAtmoConfig, tHSVColor *HSV_Img)
   /* analyze histogram for most used hue  */
   /*--------------------------------------*/
   // index of last maximum
-  static int most_used_hue_last[ATMO_NUM_CHANNELS] = {0, 0, 0, 0, 0};
+  // static int most_used_hue_last[CAP_MAX_NUM_ZONES] = {0, 0, 0, 0, 0}; --> m_most_used_hue_last
 
   // resulting hue for each channel
-  int most_used_hue[ATMO_NUM_CHANNELS];
-  memset(&most_used_hue, 0, sizeof(most_used_hue));
+  //int most_used_hue[CAP_MAX_NUM_ZONES]; --> m_most_used_hue
 
-  for (int channel = 0; channel < ATMO_NUM_CHANNELS; channel++)
+  FindMostUsed(AtmoSetup_NumZones, m_most_used_hue, m_windowed_hue_hist);
+  for (int zone = 0; zone < AtmoSetup_NumZones; zone++)
   {
-    int value = 0;
+    float percent = (float)m_windowed_hue_hist[zone * (h_MAX+1) + m_most_used_hue_last[zone]] / (float)m_windowed_hue_hist[zone * (h_MAX+1) + m_most_used_hue[zone]];
+    if (percent > 0.93f) // less than 7% difference?
+        m_most_used_hue[zone] = m_most_used_hue_last[zone]; // use last index
+     else
+        m_most_used_hue_last[zone] = m_most_used_hue[zone];
+  }
+
+  /*
+  memset(m_most_used_hue, 0, sizeof(int) * AtmoSetup_NumZones);
+
+  for (int zone = 0; zone < AtmoSetup_NumZones; zone++)
+  {
+    long 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
+      long int tmp = m_windowed_hue_hist[ (zone * (h_MAX+1)) + i ];
+      if (tmp > value) // if new value bigger then old one
       {
-        most_used_hue[channel] = i;     // remember index
-        value = w_hue_hist[channel][i]; // and value
+        m_most_used_hue[zone] = i;     // remember index
+        value = tmp; // w_hue_hist[zone][i]; // and value
       }
     }
 
-    float percent = (float)w_hue_hist[channel][most_used_hue_last[channel]] / (float)value;
+    float percent = (float)m_windowed_hue_hist[zone * (h_MAX+1) + m_most_used_hue_last[zone]] / (float)value;
     if (percent > 0.93f) // less than 7% difference?
     {
-      most_used_hue[channel] = most_used_hue_last[channel]; // use last index
+      m_most_used_hue[zone] = m_most_used_hue_last[zone]; // use last index
     }
-    most_used_hue_last[channel] = most_used_hue[channel]; // save current index of most used hue
+
+    m_most_used_hue_last[zone] = m_most_used_hue[zone]; // save current index of most used hue
   }
+  */
 
   /***************************************************************************/
   /* saturation                                                              */
   /***************************************************************************/
   // sat histogram
-  long int sat_hist[ATMO_NUM_CHANNELS][s_MAX+1];
+  // long int sat_hist[CAP_MAX_NUM_ZONES][s_MAX+1];  -> m_sat_hist
   // hue of the pixel we are working at
   int pixel_hue = 0;
   // clean histogram
-  memset(&sat_hist, 0, sizeof(sat_hist));
+  memset(m_sat_hist, 0, sizeof(long int) * (s_MAX+1) * AtmoSetup_NumZones);
 
   /*--------------------------------------*/
   /* saturation histogram builtup         */
   /*--------------------------------------*/
   i = 0;
+  temp_Img = HSV_Img;
   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)
+         if ((*temp_Img).v > AtmoSetup_DarknessLimit)
       {
         // find histogram position for pixel
-        pixel_hue = HSV_Img[i].h;
+        pixel_hue = (*temp_Img).h;
 
         // TODO:   brightness calculation(if we require it some time)
 
-        for (int channel = 0; channel < ATMO_NUM_CHANNELS; channel++)
+        for (int zone = 0; zone < AtmoSetup_NumZones; zone++)
         {
           // 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))
+          if ((pixel_hue > m_most_used_hue[zone] - hue_windowsize) &&
+              (pixel_hue < m_most_used_hue[zone] + 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;
+            m_sat_hist[zone * (s_MAX+1) + (*temp_Img).s ] += m_Zone_Weights[zone][i] * (*temp_Img).v;
+
           }
         }
       }
       i++;
+      temp_Img++;
     }
   }
 
@@ -231,9 +362,9 @@ tColorPacket CalcColorsAnalyzeHSV(CAtmoConfig *pAtmoConfig, tHSVColor *HSV_Img)
   /* saturation histogram windowing       */
   /*--------------------------------------*/
    // windowed HSV histogram
-   long int w_sat_hist[ATMO_NUM_CHANNELS][s_MAX+1];
+   // long int w_sat_hist[CAP_MAX_NUM_ZONES][s_MAX+1]; --> m_windowed_sat_hist
    // clean windowed histogram
-   memset(&w_sat_hist, 0, sizeof(w_sat_hist));
+   memset(m_windowed_sat_hist, 0, sizeof(long int) * (s_MAX+1) * AtmoSetup_NumZones);
    // steps in each direction; eg. 2 => -2 -1 0 1 2 windowing
    int sat_windowsize = AtmoSetup_SatWinSize;
 
@@ -252,14 +383,18 @@ tColorPacket CalcColorsAnalyzeHSV(CAtmoConfig *pAtmoConfig, tHSVColor *HSV_Img)
        // handle end of windowing -> roll forward
        if (myidx > h_MAX) { myidx = myidx - s_MAX - 1; }
 
-       for (int channel = 0; channel < ATMO_NUM_CHANNELS; channel++)
+       for (int zone = 0; zone < AtmoSetup_NumZones; zone++)
        {
          /*
             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
+         */
+         m_windowed_sat_hist[zone * (s_MAX+1) + i] += m_sat_hist[zone* (h_MAX+1) + myidx] *
+                                  ((sat_windowsize+1)-abs(mywin)); // apply window
        }
      }
    }
@@ -268,43 +403,48 @@ tColorPacket CalcColorsAnalyzeHSV(CAtmoConfig *pAtmoConfig, tHSVColor *HSV_Img)
   /* 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));
+  // int most_used_sat[CAP_MAX_NUM_ZONES];->m_most_used_sat
 
-  for (int channel = 0; channel < ATMO_NUM_CHANNELS; channel++)
+  FindMostUsed(AtmoSetup_NumZones, m_most_used_sat, m_windowed_sat_hist);
+  /*
+  memset(m_most_used_sat, 0, sizeof(int) * AtmoSetup_NumZones);
+
+  for (int zone = 0; zone < AtmoSetup_NumZones; zone++)
   {
     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)
+      int tmp = m_windowed_sat_hist[zone * (s_MAX+1) + i];
+      // if (w_sat_hist[channel][i] > value)
+      if (tmp > value)
       {
         // remember index
-        most_used_sat[channel] = i;
+        m_most_used_sat[zone] = i;
         // and value
-        value = w_sat_hist[channel][i];
+        value = tmp;
       }
     }
   }
+  */
+
 
   /*----------------------------------------------------------*/
   /* calculate average brightness within HSV image            */
   /* uniform Brightness for all channels is calculated        */
   /*----------------------------------------------------------*/
+  /* code integrated into "hue histogram builtup" to save some looping time!
   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)
+         if (HSV_Img[i].v > AtmoSetup_DarknessLimit)
       {
         // build brightness average
         value_avg += HSV_Img[i].v;
@@ -313,33 +453,56 @@ tColorPacket CalcColorsAnalyzeHSV(CAtmoConfig *pAtmoConfig, tHSVColor *HSV_Img)
       i++;
     }
   }
-
   // calculate brightness average
   if (l_counter > 0) { value_avg = value_avg / l_counter; }
-    else { value_avg = 10 * AtmoSetup_DarknessLimit; }
+    else { value_avg = AtmoSetup_DarknessLimit; }
+
+  */
+
 
   /*----------------------------*/
   /* adjust and copy results    */
   /*----------------------------*/
   tHSVColor hsv_pixel;
   // storage container for resulting RGB values
-  tColorPacket ColorChannels;
+  pColorPacket output_colors;
+  AllocColorPacket(output_colors, AtmoSetup_NumZones);
+
+  // 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;
+
+  /*
+  // calculate brightness average
+  for(int zone = 0; zone < AtmoSetup_NumZones; zone++) {
+      if(m_average_counter[zone] > 0)
+          m_average_v[zone] = m_average_v[zone] / m_average_counter[zone]
+      else
+          m_average_v[zone] = AtmoSetup_DarknessLimit;
+  }
+
+  */
 
-  for (int channel = 0; channel < ATMO_NUM_CHANNELS; channel++)
+  for (int zone = 0; zone < AtmoSetup_NumZones; zone++)
   {
-    // copy values
-    hsv_pixel.h = most_used_hue[channel];
-    hsv_pixel.s = most_used_sat[channel];
+    if(m_average_counter[zone] > 0)
+       m_average_v[zone] = m_average_v[zone] / m_average_counter[zone];
+    else
+       m_average_v[zone] = AtmoSetup_DarknessLimit;
+
+    m_average_v[zone] = (int)((float)m_average_v[zone] * ((float)AtmoSetup_BrightCorrect / 100.0));
 
-    // 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;
+    hsv_pixel.v = (unsigned char)ATMO_MAX(ATMO_MIN(m_average_v[zone],255),0);
+    hsv_pixel.h = m_most_used_hue[zone];
+    hsv_pixel.s = m_most_used_sat[zone];
 
     // convert back to rgb
-    ColorChannels.channel[channel] = HSV2RGB(hsv_pixel);
+    output_colors->zone[zone] = HSV2RGB(hsv_pixel);
   }
-  return ColorChannels;
+
+
+  return output_colors;
 }
 
 tHSVColor RGB2HSV(tRGBColor color)
@@ -353,8 +516,8 @@ tHSVColor RGB2HSV(tRGBColor color)
  g = color.g;
  b = color.b;
 
- min = MIN(MIN(r, g), b);
- max = MAX(MAX(r, g), b);
+ min = ATMO_MIN(ATMO_MIN(r, g), b);
+ max = ATMO_MAX(ATMO_MAX(r, g), b);
 
  delta = max - min;
 
index e82580331b30215eea0a3e2da11431f73f0f602a..a8b97f05503025908219552ee5648b04913e1992 100644 (file)
 #include "AtmoDefs.h"
 #include "AtmoConfig.h"
 
+#define Weight(zone, pixel_nummer) m_Weight[((zone) * (IMAGE_SIZE)) + (pixel_nummer)]
+
+class CAtmoColorCalculator
+{
+protected:
+   CAtmoConfig *m_pAtmoConfig;
+
+  // 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)
+  int *m_Weight;
+  int **m_Zone_Weights;
+
+  long int *m_hue_hist;
+  long int *m_windowed_hue_hist;
+  int *m_most_used_hue_last;
+  int *m_most_used_hue;
+
+  long int *m_sat_hist;
+  long int *m_windowed_sat_hist;
+  int *m_most_used_sat;
+
+  long int *m_average_v;
+  int *m_average_counter;
+
+protected:
+  int m_LastEdgeWeighting;
+  int m_LastWidescreenMode;
+  int m_LastLayout_TopCount;
+  int m_LastLayout_BottomCount;
+  int m_LastLayout_LRCount;
+  int m_LastNumZones;
+
+
+protected:
+    void FindMostUsed(int AtmoSetup_NumZones,int *most_used,long int *windowed_hist);
+
+public:
+    CAtmoColorCalculator(CAtmoConfig *pAtmoConfig);
+       ~CAtmoColorCalculator(void);
+
+    pColorPacket AnalyzeHSV(tHSVColor *HSV_Img);
+
+    void UpdateParameters();
+};
 
-tColorPacket CalcColorsAnalyzeHSV(CAtmoConfig *pAtmoConfig, tHSVColor *HSV_Img);
 
 tHSVColor RGB2HSV(tRGBColor color);
 tRGBColor HSV2RGB(tHSVColor color);
diff --git a/modules/video_filter/atmo/AtmoChannelAssignment.cpp b/modules/video_filter/atmo/AtmoChannelAssignment.cpp
new file mode 100644 (file)
index 0000000..7acb133
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * AtmoChannelAssignment.cpp: Class for storing a hardware channel to zone mapping
+ * List
+ *
+ * See the README.txt file for copyright information and how to reach the author(s).
+ *
+ * $Id$
+ */
+#include <string.h>
+#include <stdlib.h>
+#include <malloc.h>
+#include "AtmoChannelAssignment.h"
+
+
+CAtmoChannelAssignment::CAtmoChannelAssignment(void)
+{
+  m_psz_name = strdup("");
+  m_mappings = NULL;
+  m_num_channels = 0;
+  system = ATMO_FALSE;
+}
+
+CAtmoChannelAssignment::CAtmoChannelAssignment(CAtmoChannelAssignment &source)
+{
+  m_num_channels = 0; m_psz_name = NULL;
+  m_mappings = source.getMapArrayClone(m_num_channels);
+  setName( source.getName() );
+  system = source.system;
+}
+
+CAtmoChannelAssignment::~CAtmoChannelAssignment(void)
+{
+  free(m_psz_name);
+}
+
+void CAtmoChannelAssignment::setName(const char *pszNewName)
+{
+  free(m_psz_name);
+  m_psz_name = pszNewName ? strdup(pszNewName) : strdup("");
+}
+
+void CAtmoChannelAssignment::setSize(int numChannels)
+{
+  if(numChannels != m_num_channels)
+  {
+     delete []m_mappings;
+     m_mappings = NULL;
+     m_num_channels = numChannels;
+     if(m_num_channels > 0)
+     {
+       m_mappings = new int[m_num_channels];
+       memset(m_mappings, 0, sizeof(int) * m_num_channels);
+     }
+  }
+}
+
+int *CAtmoChannelAssignment::getMapArrayClone(int &count)
+{
+  count = m_num_channels;
+  if(count == 0) return NULL;
+  int *temp = new int[m_num_channels];
+  memcpy(temp, m_mappings, sizeof(int) * m_num_channels);
+  return(temp);
+}
+
+int CAtmoChannelAssignment::getZoneIndex(int channel)
+{
+   if(m_mappings && (channel>=0) && (channel<m_num_channels))
+     return m_mappings[channel] ;
+   else
+     return -1;
+}
+
+void CAtmoChannelAssignment::setZoneIndex(int channel, int zone)
+{
+ if(m_mappings && (channel>=0) && (channel<m_num_channels))
+    m_mappings[channel] = zone;
+}
+
+
diff --git a/modules/video_filter/atmo/AtmoChannelAssignment.h b/modules/video_filter/atmo/AtmoChannelAssignment.h
new file mode 100644 (file)
index 0000000..5996763
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef _AtmoChannelAssignment_
+#define _AtmoChannelAssignment_
+
+#include "AtmoDefs.h"
+
+class CAtmoChannelAssignment
+{
+protected:
+    // name of the mapping (for menus and lists)
+    char *m_psz_name;
+    // count of channels starting with 0 ... X for which a mapping exists!
+    int m_num_channels;
+    // array were each destination channel - has an index to the source zone to use
+    // or -1 to show black output on this channel
+    int *m_mappings;
+
+public:
+    CAtmoChannelAssignment(void);
+    CAtmoChannelAssignment(CAtmoChannelAssignment &source);
+    ~CAtmoChannelAssignment(void);
+
+public:
+    // internal used to mark a not modifyable definition
+    // with a default assignment!
+    ATMO_BOOL system;
+    char *getName() { return(m_psz_name); }
+    void setName(const char *pszNewName);
+
+    void setSize(int numChannels);
+    int getSize() { return m_num_channels; }
+    int *getMapArrayClone(int &count);
+    int getZoneIndex(int channel);
+    void setZoneIndex(int channel, int zone);
+};
+
+#endif
similarity index 66%
rename from modules/video_filter/atmo/AtmoSerialConnection.cpp
rename to modules/video_filter/atmo/AtmoClassicConnection.cpp
index 73c1a4c097b6db4094157bde00dbead5839a108f..74f1f67b7a94f3f24ebf4bd44c423b785f0280c6 100644 (file)
@@ -9,8 +9,11 @@
 
 
 #include "AtmoDefs.h"
-#include "AtmoSerialConnection.h"
+#include "AtmoClassicConnection.h"
 
+#if !defined(_ATMO_VLC_PLUGIN_)
+# include "AtmoClassicConfigDialog.h"
+#endif
 
 #include <stdio.h>
 #include <fcntl.h>
 #include <unistd.h>
 #endif
 
-/*
-#include <sys/types.h>
-#include <fcntl.h>
-#include <string.h>
-#include <termios.h>
-#include <unistd.h>
-#include <vdr/tools.h>
-*/
 
-
-CAtmoSerialConnection::CAtmoSerialConnection(CAtmoConfig *cfg) : CAtmoConnection(cfg) {
+CAtmoClassicConnection::CAtmoClassicConnection(CAtmoConfig *cfg) : CAtmoConnection(cfg) {
     m_hComport = INVALID_HANDLE_VALUE;
 }
 
-CAtmoSerialConnection::~CAtmoSerialConnection() {
-   CloseConnection();
+CAtmoClassicConnection::~CAtmoClassicConnection() {
 }
 
-ATMO_BOOL CAtmoSerialConnection::OpenConnection() {
+ATMO_BOOL CAtmoClassicConnection::OpenConnection() {
 #if defined(_ATMO_VLC_PLUGIN_)
      char *serdevice = m_pAtmoConfig->getSerialDevice();
      if(!serdevice)
@@ -52,24 +45,20 @@ ATMO_BOOL CAtmoSerialConnection::OpenConnection() {
         CloseConnection();
 
 #if !defined(_ATMO_VLC_PLUGIN_)
-     char comport[16];  // com4294967295
-     sprintf(comport,"com%d",portNummer);
+     char serdevice[16];  // com4294967295
+     sprintf(serdevice,"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 dcb; // für comport-parameter
      dcb.DCBlength = sizeof(DCB);
      GetCommState (m_hComport, &dcb); // ger current serialport settings
      dcb.BaudRate  = 38400;        // set speed
@@ -81,11 +70,7 @@ ATMO_BOOL CAtmoSerialConnection::OpenConnection() {
 #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;
      }
@@ -110,7 +95,7 @@ ATMO_BOOL CAtmoSerialConnection::OpenConnection() {
      return true;
 }
 
-void CAtmoSerialConnection::CloseConnection() {
+void CAtmoClassicConnection::CloseConnection() {
   if(m_hComport!=INVALID_HANDLE_VALUE) {
 #if defined(WIN32)
      CloseHandle(m_hComport);
@@ -121,11 +106,11 @@ void CAtmoSerialConnection::CloseConnection() {
   }
 }
 
-ATMO_BOOL CAtmoSerialConnection::isOpen(void) {
+ATMO_BOOL CAtmoClassicConnection::isOpen(void) {
         return (m_hComport != INVALID_HANDLE_VALUE);
 }
 
-ATMO_BOOL CAtmoSerialConnection::HardwareWhiteAdjust(int global_gamma,
+ATMO_BOOL CAtmoClassicConnection::HardwareWhiteAdjust(int global_gamma,
                                                      int global_contrast,
                                                      int contrast_red,
                                                      int contrast_green,
@@ -193,7 +178,7 @@ ATMO_BOOL CAtmoSerialConnection::HardwareWhiteAdjust(int global_gamma,
 }
 
 
-ATMO_BOOL CAtmoSerialConnection::SendData(tColorPacket data) {
+ATMO_BOOL CAtmoClassicConnection::SendData(pColorPacket data) {
    if(m_hComport == INVALID_HANDLE_VALUE)
          return ATMO_FALSE;
 
@@ -205,11 +190,19 @@ ATMO_BOOL CAtmoSerialConnection::SendData(tColorPacket data) {
    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;
+   int idx;
+
+   Lock();
+
+   for(int i=0; i < 5 ; i++) {
+       if(m_ChannelAssignment && (i < m_NumAssignedChannels))
+          idx = m_ChannelAssignment[i];
+       else
+          idx = -1;
+       if((idx>=0) && (idx<data->numColors)) {
+          buffer[iBuffer++] = data->zone[idx].r;
+          buffer[iBuffer++] = data->zone[idx].g;
+          buffer[iBuffer++] = data->zone[idx].b;
        } else {
           buffer[iBuffer++] = 0;
           buffer[iBuffer++] = 0;
@@ -224,47 +217,67 @@ ATMO_BOOL CAtmoSerialConnection::SendData(tColorPacket data) {
    tcdrain(m_hComport);
 #endif
 
+   Unlock();
+
    return (iBytesWritten == 19) ? ATMO_TRUE : ATMO_FALSE;
 }
 
-ATMO_BOOL CAtmoSerialConnection::SendData(unsigned char numChannels,
-                                          int red[],
-                                          int green[],
-                                          int blue[])
+
+ATMO_BOOL CAtmoClassicConnection::CreateDefaultMapping(CAtmoChannelAssignment *ca)
 {
-   if(m_hComport == INVALID_HANDLE_VALUE)
-         return ATMO_FALSE;
+   if(!ca) return ATMO_FALSE;
+   ca->setSize(5);
+   ca->setZoneIndex(0, 4); // Zone 5
+   ca->setZoneIndex(1, 3);
+   ca->setZoneIndex(2, 1);
+   ca->setZoneIndex(3, 0);
+   ca->setZoneIndex(4, 2);
+   return ATMO_TRUE;
+}
 
-   DWORD bufSize = 4 + numChannels*3;
-   unsigned char *buffer = new unsigned char[bufSize];
-   DWORD iBytesWritten;
+#if !defined(_ATMO_VLC_PLUGIN_)
 
-   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;
-       }
-   }
+char *CAtmoClassicConnection::getChannelName(int ch)
+{
+  if(ch < 0) return NULL;
+  char buf[30];
+
+  switch(ch) {
+      case 0:
+          sprintf(buf,"Summen Kanal [%d]",ch);
+          break;
+      case 1:
+          sprintf(buf,"Linker Kanal [%d]",ch);
+          break;
+      case 2:
+          sprintf(buf,"Rechter Kanal [%d]",ch);
+          break;
+      case 3:
+          sprintf(buf,"Oberer Kanal [%d]",ch);
+          break;
+      case 4:
+          sprintf(buf,"Unterer Kanal [%d]",ch);
+          break;
+      default:
+          sprintf(buf,"Kanal [%d]",ch);
+          break;
+  }
 
-#if defined(WIN32)
-   WriteFile(m_hComport, buffer, bufSize, &iBytesWritten, NULL);
-#else
-   iBytesWritten = write(m_hComport, buffer, bufSize);
-   tcdrain(m_hComport);
-#endif
+  return strdup(buf);
+}
 
-   delete[] buffer;
+ATMO_BOOL CAtmoClassicConnection::ShowConfigDialog(HINSTANCE hInst, HWND parent, CAtmoConfig *cfg)
+{
+    CAtmoClassicConfigDialog *dlg = new CAtmoClassicConfigDialog(hInst, parent, cfg);
+
+    INT_PTR result = dlg->ShowModal();
 
-   return (iBytesWritten == bufSize) ? ATMO_TRUE : ATMO_FALSE;
+    delete dlg;
+
+    if(result == IDOK)
+      return ATMO_TRUE;
+    else
+      return ATMO_FALSE;
 }
 
+#endif
similarity index 66%
rename from modules/video_filter/atmo/AtmoSerialConnection.h
rename to modules/video_filter/atmo/AtmoClassicConnection.h
index 22ddb72facc17b9c712e6fc6ea0a48a4c113eb2d..7d0c56abf5249105a54bbbec9dff09876c1e18b1 100644 (file)
@@ -6,8 +6,8 @@
  *
  * $Id$
  */
-#ifndef _AtmoSerialConnection_h_
-#define _AtmoSerialConnection_h_
+#ifndef _AtmoClassicConnection_h_
+#define _AtmoClassicConnection_h_
 
 #include "AtmoDefs.h"
 #include "AtmoConnection.h"
@@ -18,7 +18,7 @@
 #endif
 
 
-class CAtmoSerialConnection : public CAtmoConnection {
+class CAtmoClassicConnection : public CAtmoConnection {
     private:
         HANDLE m_hComport;
 
@@ -29,8 +29,8 @@ class CAtmoSerialConnection : public CAtmoConnection {
 #endif
 
     public:
-       CAtmoSerialConnection(CAtmoConfig *cfg);
-       virtual ~CAtmoSerialConnection(void);
+       CAtmoClassicConnection(CAtmoConfig *cfg);
+       virtual ~CAtmoClassicConnection(void);
 
           virtual ATMO_BOOL OpenConnection();
 
@@ -38,12 +38,7 @@ class CAtmoSerialConnection : public CAtmoConnection {
 
        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 SendData(pColorPacket data);
 
        virtual ATMO_BOOL HardwareWhiteAdjust(int global_gamma,
                                              int global_contrast,
@@ -54,6 +49,18 @@ class CAtmoSerialConnection : public CAtmoConnection {
                                              int gamma_green,
                                              int gamma_blue,
                                              ATMO_BOOL storeToEeprom);
+
+       virtual int getNumChannels() { return 5; }
+
+
+       virtual const char *getDevicePath() { return "atmo"; }
+
+#if !defined(_ATMO_VLC_PLUGIN_)
+       virtual char *getChannelName(int ch);
+       virtual ATMO_BOOL ShowConfigDialog(HINSTANCE hInst, HWND parent, CAtmoConfig *cfg);
+#endif
+
+       virtual ATMO_BOOL CreateDefaultMapping(CAtmoChannelAssignment *ca);
 };
 
 #endif
index 48d4fb86abd0955214c4512f1bface01fa7249d2..ec6c519587c0c5c6057f6e0493cd65079a4d7195 100644 (file)
@@ -29,54 +29,84 @@ CAtmoConfig::CAtmoConfig()
 {
   // setup basic configruation structures...
   m_IsShowConfigDialog = 0;
-  m_eAtmoConnectionType = actSerialPort;
+  m_eAtmoConnectionType = actClassicAtmo;
   for(int i=0;i<10;i++)
       m_ChannelAssignments[i] = NULL;
+
 #if defined (_ATMO_VLC_PLUGIN_)
   m_devicename = NULL;
+  m_devicenames[0] = NULL;
+  m_devicenames[1] = NULL;
+  m_devicenames[2] = NULL;
 #endif
   // load all config values with there defaults
-  LoadDefaults();
+  m_ZoneDefinitions  = NULL;
+  m_AtmoZoneDefCount = -1;
+  m_DMX_BaseChannels = NULL;
 
-  //   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;
-      }
-  }
+  LoadDefaults();
 }
 
 CAtmoConfig::~CAtmoConfig() {
-    // and finally cleanup...
-    clearAllChannelMappings();
-#if !defined (WIN32)
+   // and finally cleanup...
+   clearAllChannelMappings();
+
+   if(m_ZoneDefinitions)
+   {
+     for(int zone=0; zone<m_AtmoZoneDefCount; zone++)
+         delete m_ZoneDefinitions[zone];
+     delete m_ZoneDefinitions;
+     m_ZoneDefinitions = NULL;
+   }
+
+   free( m_DMX_BaseChannels );
+
+#if defined (_ATMO_VLC_PLUGIN_)
     free( m_devicename );
+    free( m_devicenames[0] );
+    free( m_devicenames[1] );
+    free( m_devicenames[2] );
 #endif
 }
 
 void CAtmoConfig::LoadDefaults() {
     //    m_eAtmoConnectionType = actSerialPort;
     //    m_Comport
+#if defined (_ATMO_VLC_PLUGIN_)
+
+    free( m_devicename );
+    free( m_devicenames[0] );
+    free( m_devicenames[1] );
+    free( m_devicenames[2] );
+
+    m_devicename = NULL;
+    m_devicenames[0] = NULL;
+    m_devicenames[1] = NULL;
+    m_devicenames[2] = NULL;
+
+#else
+
+    m_Comport     = -1;
+    m_Comports[0] = -1;
+    m_Comports[1] = -1;
+    m_Comports[2] = -1;
+
+#endif
 
     m_eEffectMode = emDisabled;
 
+    m_IgnoreConnectionErrorOnStartup = ATMO_FALSE;
+
+    m_UpdateEdgeWeightningFlag = 0;
+
+
+
+    m_Software_gamma_mode = agcNone;
+    m_Software_gamma_red    = 10;
+    m_Software_gamma_green  = 10;
+    m_Software_gamma_blue   = 10;
+    m_Software_gamma_global = 10;
+
     m_WhiteAdjustment_Red    = 255;
     m_WhiteAdjustment_Green  = 255;
     m_WhiteAdjustment_Blue   = 255;
@@ -101,6 +131,7 @@ void CAtmoConfig::LoadDefaults() {
     m_LiveViewFilter_PercentNew  = 50;
     m_LiveViewFilter_MeanLength  = 300;
     m_LiveViewFilter_MeanThreshold   = 40;
+    m_show_statistics = ATMO_FALSE;
 
     m_LiveView_EdgeWeighting  = 8;
     m_LiveView_BrightCorrect  = 100;
@@ -112,7 +143,8 @@ void CAtmoConfig::LoadDefaults() {
     m_LiveView_HOverscanBorder  = 0;
     m_LiveView_VOverscanBorder  = 0;
     m_LiveView_DisplayNr        = 0;
-    m_LiveView_FrameDelay       = 0;
+    m_LiveView_FrameDelay       = 30;
+    m_LiveView_GDI_FrameRate    = 25;
 
 
     m_Hardware_global_gamma    = 128;
@@ -125,22 +157,40 @@ void CAtmoConfig::LoadDefaults() {
     m_Hardware_gamma_green     = 22;
     m_Hardware_gamma_blue      = 22;
 
+    m_DMX_BaseChannels         = strdup("0");
+    m_DMX_RGB_Channels        = 5; // so wie atmolight
+
+    m_MoMo_Channels           = 3; // default momo, there exists also a 4 ch version!
+
+    m_ZonesTopCount            = 1;
+    m_ZonesBottomCount         = 1;
+    m_ZonesLRCount             = 1;
+    m_ZoneSummary              = ATMO_FALSE;
+    UpdateZoneCount();
+
+
     clearAllChannelMappings();
     m_CurrentChannelAssignment = 0;
-    tChannelAssignment* temp = new tChannelAssignment;
+    CAtmoChannelAssignment *temp = new CAtmoChannelAssignment();
     temp->system = true;
-    for(int i=0;i<ATMO_NUM_CHANNELS;i++)
-        temp->mappings[i] = i;
-    strcpy(temp->name,"Standard");
+    temp->setName( "Standard" );
     this->m_ChannelAssignments[0] =  temp;
+
+    UpdateZoneDefinitionCount();
 }
 
 void CAtmoConfig::Assign(CAtmoConfig *pAtmoConfigSrc) {
 
 #if defined(_ATMO_VLC_PLUGIN_)
-    this->setSerialDevice(pAtmoConfigSrc->getSerialDevice());
+    this->setSerialDevice(0, pAtmoConfigSrc->getSerialDevice(0));
+    this->setSerialDevice(1, pAtmoConfigSrc->getSerialDevice(1));
+    this->setSerialDevice(2, pAtmoConfigSrc->getSerialDevice(2));
+    this->setSerialDevice(3, pAtmoConfigSrc->getSerialDevice(3));
 #else
     this->m_Comport                  = pAtmoConfigSrc->m_Comport;
+    this->m_Comports[0]              = pAtmoConfigSrc->m_Comports[0];
+    this->m_Comports[1]              = pAtmoConfigSrc->m_Comports[1];
+    this->m_Comports[2]              = pAtmoConfigSrc->m_Comports[2];
 #endif
 
     this->m_eAtmoConnectionType      = pAtmoConfigSrc->m_eAtmoConnectionType;
@@ -171,6 +221,8 @@ void CAtmoConfig::Assign(CAtmoConfig *pAtmoConfigSrc) {
     this->m_LiveViewFilter_MeanLength      = pAtmoConfigSrc->m_LiveViewFilter_MeanLength;
     this->m_LiveViewFilter_MeanThreshold   = pAtmoConfigSrc->m_LiveViewFilter_MeanThreshold;
 
+    this->m_show_statistics               = pAtmoConfigSrc->m_show_statistics;
+
 
     this->m_LiveView_EdgeWeighting  =  pAtmoConfigSrc->m_LiveView_EdgeWeighting;
     this->m_LiveView_BrightCorrect  =  pAtmoConfigSrc->m_LiveView_BrightCorrect;
@@ -183,19 +235,47 @@ void CAtmoConfig::Assign(CAtmoConfig *pAtmoConfigSrc) {
     this->m_LiveView_VOverscanBorder  = pAtmoConfigSrc->m_LiveView_VOverscanBorder;
     this->m_LiveView_DisplayNr        = pAtmoConfigSrc->m_LiveView_DisplayNr;
     this->m_LiveView_FrameDelay       = pAtmoConfigSrc->m_LiveView_FrameDelay;
+    this->m_LiveView_GDI_FrameRate    = pAtmoConfigSrc->m_LiveView_GDI_FrameRate;
+
+    this->m_ZonesTopCount             = pAtmoConfigSrc->m_ZonesTopCount;
+    this->m_ZonesBottomCount          = pAtmoConfigSrc->m_ZonesBottomCount;
+    this->m_ZonesLRCount              = pAtmoConfigSrc->m_ZonesLRCount;
+    this->m_ZoneSummary               = pAtmoConfigSrc->m_ZoneSummary;
+    UpdateZoneCount();
+
+    this->m_Software_gamma_mode      =  pAtmoConfigSrc->m_Software_gamma_mode;
+    this->m_Software_gamma_red       =  pAtmoConfigSrc->m_Software_gamma_red;
+    this->m_Software_gamma_green     =  pAtmoConfigSrc->m_Software_gamma_green;
+    this->m_Software_gamma_blue      =  pAtmoConfigSrc->m_Software_gamma_blue;
+    this->m_Software_gamma_global    =  pAtmoConfigSrc->m_Software_gamma_global;
+
+    this->setDMX_BaseChannels( pAtmoConfigSrc->getDMX_BaseChannels() );
+
+    this->m_DMX_RGB_Channels         = pAtmoConfigSrc->m_DMX_RGB_Channels;
+
+    this->m_MoMo_Channels            = pAtmoConfigSrc->m_MoMo_Channels;
+
+    this->m_CurrentChannelAssignment = pAtmoConfigSrc->m_CurrentChannelAssignment;
 
     clearChannelMappings();
     for(int i=1;i<pAtmoConfigSrc->getNumChannelAssignments();i++) {
-        tChannelAssignment *ta = pAtmoConfigSrc->m_ChannelAssignments[i];
+        CAtmoChannelAssignment *ta = pAtmoConfigSrc->m_ChannelAssignments[i];
         if(ta!=NULL) {
-            tChannelAssignment *dest = this->m_ChannelAssignments[i];
+            CAtmoChannelAssignment *dest = this->m_ChannelAssignments[i];
             if(dest == NULL) {
-               dest = new tChannelAssignment;
+               dest = new CAtmoChannelAssignment();
                this->m_ChannelAssignments[i] = dest;
             }
-            memcpy(dest, ta, sizeof(tChannelAssignment));
+            // memcpy(dest, ta, sizeof(tChannelAssignment));
+            dest->setSize(ta->getSize());
+            dest->setName(ta->getName());
+            dest->system = ta->system;
+            for(int c=0;c<dest->getSize();c++)
+                dest->setZoneIndex(c, ta->getZoneIndex(c));
         }
     }
+
+    UpdateZoneDefinitionCount();
 }
 
 
@@ -209,21 +289,23 @@ int CAtmoConfig::getNumChannelAssignments() {
 
 void CAtmoConfig::clearChannelMappings() {
     for(int i=1;i<10;i++) {
-        tChannelAssignment *ca = m_ChannelAssignments[i];
-        delete ca;
+        CAtmoChannelAssignment *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];
-        delete ca;
+        CAtmoChannelAssignment *ca = m_ChannelAssignments[i];
+        if(ca!=NULL)
+           delete ca;
         m_ChannelAssignments[i] = NULL;
     }
 }
 
-void CAtmoConfig::AddChannelAssignment(tChannelAssignment *ta) {
+void CAtmoConfig::AddChannelAssignment(CAtmoChannelAssignment *ta) {
     for(int i=0;i<10;i++) {
         if(m_ChannelAssignments[i] == NULL) {
            m_ChannelAssignments[i] = ta;
@@ -232,17 +314,112 @@ void CAtmoConfig::AddChannelAssignment(tChannelAssignment *ta) {
     }
 }
 
-void CAtmoConfig::SetChannelAssignment(int index, tChannelAssignment *ta) {
-    delete m_ChannelAssignments[index];
-    m_ChannelAssignments[index] = ta;
+void CAtmoConfig::SetChannelAssignment(int index, CAtmoChannelAssignment *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)
+    if(zoneIndex >= m_AtmoZoneDefCount)
        return NULL;
     return m_ZoneDefinitions[zoneIndex];
 
 }
 
+void CAtmoConfig::UpdateZoneCount()
+{
+  m_computed_zones_count = m_ZonesTopCount + m_ZonesBottomCount + 2 * m_ZonesLRCount;
+  if(m_ZoneSummary)
+     m_computed_zones_count++;
+}
+
+
+
+int CAtmoConfig::getZoneCount()
+{
+    return(m_computed_zones_count);
+}
+
+void CAtmoConfig::UpdateZoneDefinitionCount()
+{
+   if( getZoneCount() != m_AtmoZoneDefCount)
+   {
+      // okay zonen anzahl hat sich geändert - wir müssen neu rechnen
+      // und allokieren!
+      if(m_ZoneDefinitions)
+      {
+        for(int zone=0; zone<m_AtmoZoneDefCount; zone++)
+            delete m_ZoneDefinitions[zone];
+        delete m_ZoneDefinitions;
+        m_ZoneDefinitions = NULL;
+      }
+      m_AtmoZoneDefCount = getZoneCount();
+      if(m_AtmoZoneDefCount > 0)
+      {
+         m_ZoneDefinitions = new CAtmoZoneDefinition*[m_AtmoZoneDefCount];
+         for(int zone=0; zone< m_AtmoZoneDefCount; zone++) {
+             m_ZoneDefinitions[zone] = new CAtmoZoneDefinition();
+             m_ZoneDefinitions[zone]->Fill(255);
+         }
+      }
+   }
+}
+
+#if defined(_ATMO_VLC_PLUGIN_)
+
+char *CAtmoConfig::getSerialDevice(int i)
+{
+   if(i == 0)
+      return m_devicename;
+   else  {
+       i--;
+       return m_devicenames[i];
+   }
+}
+
+void CAtmoConfig::setSerialDevice(int i,const char *pszNewDevice)
+{
+    if(i == 0)
+       setSerialDevice(pszNewDevice);
+    else {
+       i--;
+       free( m_devicenames[i] );
+       if(pszNewDevice)
+          m_devicenames[i] = strdup(pszNewDevice);
+       else
+          m_devicenames[i] = NULL;
+    }
+}
+
+#else
+
+int CAtmoConfig::getComport(int i)
+{
+  if(i == 0)
+     return this->m_Comport;
+  else {
+     i--;
+     return this->m_Comports[i];
+  }
+}
+
+void CAtmoConfig::setComport(int i, int nr)
+{
+  if(i == 0)
+      this->m_Comport = nr;
+  else {
+    this->m_Comports[i-1] = nr;
+  }
+}
+
+#endif
+
+void CAtmoConfig::setDMX_BaseChannels(char *channels)
+{
+     free(m_DMX_BaseChannels);
+     m_DMX_BaseChannels = strdup(channels);
+}
+
index 52c57f3fd9e346cb5917e9b8c3f8e53f1aed05ff..656c20ed72135e350d9b6c1973dee29fb036dc03 100644 (file)
@@ -9,11 +9,13 @@
 #ifndef _AtmoConfig_h_
 #define _AtmoConfig_h_
 
+#include <stdlib.h>
+
 #include "AtmoDefs.h"
 #include "AtmoZoneDefinition.h"
+#include "AtmoChannelAssignment.h"
 
 #if defined(_ATMO_VLC_PLUGIN_)
-#   include <stdlib.h>
 #   include <string.h>
 #endif
 
@@ -24,12 +26,16 @@ class CAtmoConfig {
           int m_IsShowConfigDialog;    
 #if defined(_ATMO_VLC_PLUGIN_)
        char *m_devicename;
+       char *m_devicenames[3]; // additional Devices ?
 #else
           int m_Comport;
+       int m_Comports[3]; // additional Comports
 #endif
        enum AtmoConnectionType m_eAtmoConnectionType;
        enum EffectMode m_eEffectMode;
 
+       ATMO_BOOL m_IgnoreConnectionErrorOnStartup;
+
     protected:
        ATMO_BOOL m_UseSoftwareWhiteAdj;
        int m_WhiteAdjustment_Red;
@@ -63,11 +69,30 @@ class CAtmoConfig {
            one for System + 9 for userdefined channel
            assignments (will it be enough?)
         */
-        tChannelAssignment *m_ChannelAssignments[10];
+        CAtmoChannelAssignment *m_ChannelAssignments[10];
         int m_CurrentChannelAssignment;
 
     protected:
-        CAtmoZoneDefinition *m_ZoneDefinitions[ATMO_NUM_CHANNELS];
+        CAtmoZoneDefinition **m_ZoneDefinitions;
+        int m_AtmoZoneDefCount;
+
+
+        /*
+          zone layout description for generating the default Zone weightning
+        */
+        // count of zone on the top of the screen
+        int m_ZonesTopCount;
+        // count of zone on the bottom of the screen
+        int m_ZonesBottomCount;
+        // count of zones on left and right (the same count)
+        int m_ZonesLRCount;
+
+        // does a summary Zone exists (Fullscreen)
+        int m_computed_zones_count;
+        ATMO_BOOL m_ZoneSummary;
+
+    public:
+        int getZoneCount();
 
 
     protected:
@@ -77,6 +102,8 @@ class CAtmoConfig {
         int m_LiveViewFilter_MeanLength;
         int m_LiveViewFilter_MeanThreshold;
 
+        ATMO_BOOL m_show_statistics;
+
         // weighting of distance to edge
         int m_LiveView_EdgeWeighting; //  = 8;
         // brightness correction
@@ -107,6 +134,8 @@ class CAtmoConfig {
         */
         int m_LiveView_FrameDelay;
 
+        int m_LiveView_GDI_FrameRate;
+
     protected:
          /* values of the last hardware white adjustment (only for hardware with new firmware) */
          int m_Hardware_global_gamma;
@@ -118,6 +147,25 @@ class CAtmoConfig {
          int m_Hardware_gamma_green;
          int m_Hardware_gamma_blue;
 
+    protected:
+         char *m_DMX_BaseChannels;
+         int m_DMX_RGB_Channels;
+
+    protected:
+         int m_MoMo_Channels;
+
+    protected:
+         AtmoGammaCorrect m_Software_gamma_mode;
+
+         int m_Software_gamma_red;
+         int m_Software_gamma_green;
+         int m_Software_gamma_blue;
+
+         int m_Software_gamma_global;
+    public:
+        volatile int m_UpdateEdgeWeightningFlag;
+
+
     public:
        CAtmoConfig();
        virtual ~CAtmoConfig();
@@ -132,18 +180,27 @@ class CAtmoConfig {
        */
        void Assign(CAtmoConfig *pAtmoConfigSrc);
 
+       void UpdateZoneDefinitionCount();
+
     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) { free( m_devicename ); if(newdevice) m_devicename = strdup(newdevice); else m_devicename = NULL; }
+        void setSerialDevice(const char *newdevice) { free(m_devicename); if(newdevice) m_devicename = strdup(newdevice); else m_devicename = NULL; }
+        char *getSerialDevice(int i);
+        void setSerialDevice(int i,const char *pszNewDevice);
 #else
         int getComport()                    { return m_Comport; }
         void setComport(int value)          { m_Comport = value; }
+        int getComport(int i);
+        void setComport(int i, int nr);
 #endif
 
+        ATMO_BOOL getIgnoreConnectionErrorOnStartup() { return m_IgnoreConnectionErrorOnStartup; }
+        void setIgnoreConnectionErrorOnStartup(ATMO_BOOL ignore) { m_IgnoreConnectionErrorOnStartup = ignore; }
+
         int getWhiteAdjustment_Red() { return m_WhiteAdjustment_Red;  }
         void setWhiteAdjustment_Red(int value) { m_WhiteAdjustment_Red = value; }
         int getWhiteAdjustment_Green() { return m_WhiteAdjustment_Green;  }
@@ -186,6 +243,8 @@ class CAtmoConfig {
         EffectMode getEffectMode() { return m_eEffectMode; }
         void setEffectMode(EffectMode value) { m_eEffectMode = value; }
 
+        ATMO_BOOL getShow_statistics() { return m_show_statistics; }
+
         AtmoFilterMode getLiveViewFilterMode() { return m_LiveViewFilterMode; }
         void setLiveViewFilterMode(AtmoFilterMode value) { m_LiveViewFilterMode = value; }
 
@@ -226,6 +285,9 @@ class CAtmoConfig {
         int getLiveView_FrameDelay() { return m_LiveView_FrameDelay; }
         void setLiveView_FrameDelay(int delay) { m_LiveView_FrameDelay = delay; }
 
+        int getLiveView_GDI_FrameRate() { return m_LiveView_GDI_FrameRate; }
+        void setLiveView_GDI_FrameRate(int value) { m_LiveView_GDI_FrameRate=value; }
+
         int getHardware_global_gamma() { return m_Hardware_global_gamma ; }
         void setHardware_global_gamma(int value) { m_Hardware_global_gamma=value; }
 
@@ -250,7 +312,20 @@ class CAtmoConfig {
         int getHardware_gamma_blue() { return m_Hardware_gamma_blue; }
         void setHardware_gamma_blue(int value) { m_Hardware_gamma_blue=value; }
 
-        tChannelAssignment *getChannelAssignment(int nummer) {
+
+        AtmoGammaCorrect getSoftware_gamma_mode() { return m_Software_gamma_mode; }
+        int getSoftware_gamma_red() { return m_Software_gamma_red; }
+        int getSoftware_gamma_green() { return m_Software_gamma_green; }
+        int getSoftware_gamma_blue() { return m_Software_gamma_blue; }
+        int getSoftware_gamma_global() { return m_Software_gamma_global; }
+
+        void setSoftware_gamma_mode(AtmoGammaCorrect value) { m_Software_gamma_mode = value; }
+        void setSoftware_gamma_red(int value)    { m_Software_gamma_red = value; }
+        void setSoftware_gamma_green(int value)  { m_Software_gamma_green = value; }
+        void setSoftware_gamma_blue(int value)   { m_Software_gamma_blue = value; }
+        void setSoftware_gamma_global(int value) { m_Software_gamma_global = value; }
+
+        CAtmoChannelAssignment *getChannelAssignment(int nummer) {
             return this->m_ChannelAssignments[nummer];
         }
         int getCurrentChannelAssignment() { return m_CurrentChannelAssignment; }
@@ -259,11 +334,31 @@ class CAtmoConfig {
         int getNumChannelAssignments();
         void clearChannelMappings();
         void clearAllChannelMappings();
-        void AddChannelAssignment(tChannelAssignment *ta);
-        void SetChannelAssignment(int index, tChannelAssignment *ta);
+        void AddChannelAssignment(CAtmoChannelAssignment *ta);
+        void SetChannelAssignment(int index, CAtmoChannelAssignment *ta);
 
         CAtmoZoneDefinition *getZoneDefinition(int zoneIndex);
 
+        void UpdateZoneCount();
+
+        void setZonesTopCount(int zones) { m_ZonesTopCount = zones; UpdateZoneCount(); };
+        int getZonesTopCount() { return m_ZonesTopCount; }
+        void setZonesBottomCount(int zones) { m_ZonesBottomCount = zones; UpdateZoneCount(); };
+        int getZonesBottomCount() { return m_ZonesBottomCount; }
+        void setZonesLRCount(int zones) { m_ZonesLRCount = zones; UpdateZoneCount(); };
+        int getZonesLRCount() { return m_ZonesLRCount; }
+        ATMO_BOOL getZoneSummary() { return m_ZoneSummary; }
+        void setZoneSummary(ATMO_BOOL summary) { m_ZoneSummary = summary; UpdateZoneCount(); }
+
+        char *getDMX_BaseChannels() { return m_DMX_BaseChannels; }
+        void setDMX_BaseChannels(char *channels);
+
+        int getDMX_RGB_Channels() { return m_DMX_RGB_Channels; }
+        void setDMX_RGB_Channels(int ch) { m_DMX_RGB_Channels = ch; }
+
+        int getMoMo_Channels() { return m_MoMo_Channels; }
+        void setMoMo_Channels(int chCount) { m_MoMo_Channels = chCount; }
+
 };
 
 #endif
index f8878456c3f8f90e740e01c639efa9f68c86f227..f61c98223039a58b1e188311d1d090431bb7c62f 100644 (file)
@@ -6,31 +6,68 @@
  *
  * $Id$
  */
+#include <string.h>
 #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;
-        }
-    }
-}
+        this->m_pAtmoConfig = cfg;     
+     m_ChannelAssignment = NULL;
+     m_NumAssignedChannels = 0;
 
-void CAtmoConnection::SetChannelAssignment(tChannelAssignment *ca) {
-     for(int i=0;i<ATMO_NUM_CHANNELS;i++) {
-         m_ChannelAssignment[i] = ca->mappings[i];
-     }
+#if defined(_ATMO_VLC_PLUGIN_)
+     vlc_mutex_init( &m_AccessConnection );
+#else
+     InitializeCriticalSection( &m_AccessConnection );
+#endif
 }
 
 CAtmoConnection::~CAtmoConnection(void)
 {
   if(isOpen())
      CloseConnection();
+
+#if defined(_ATMO_VLC_PLUGIN_)
+     vlc_mutex_destroy( &m_AccessConnection );
+#else
+     DeleteCriticalSection( &m_AccessConnection );
+#endif
+}
+
+void CAtmoConnection::SetChannelAssignment(CAtmoChannelAssignment *ca)
+{
+  if(ca)
+  {
+      Lock();
+      delete m_ChannelAssignment;
+      m_ChannelAssignment = ca->getMapArrayClone(m_NumAssignedChannels);
+      Unlock();
+  }
+}
+
+#if !defined(_ATMO_VLC_PLUGIN_)
+ATMO_BOOL CAtmoConnection::ShowConfigDialog(HINSTANCE hInst, HWND parent, CAtmoConfig *cfg)
+{
+    MessageBox(parent, "This device doesn't have a special config dialog", "Info", 0);
+    return ATMO_FALSE;
+}
+#endif
+
+
+void CAtmoConnection::Lock()
+{
+#if defined(_ATMO_VLC_PLUGIN_)
+    vlc_mutex_lock( &m_AccessConnection );
+#else
+    EnterCriticalSection( &m_AccessConnection );
+#endif
+}
+void CAtmoConnection::Unlock()
+{
+#if defined(_ATMO_VLC_PLUGIN_)
+    vlc_mutex_unlock( &m_AccessConnection );
+#else
+    LeaveCriticalSection( &m_AccessConnection );
+#endif
 }
index a7e6e97c99970138b17023b32f68c96ab60170bb..6f788008652182bd89a9aec9b93a1a2b3e61701e 100644 (file)
@@ -9,14 +9,36 @@
 #ifndef _AtmoConnection_h_
 #define _AtmoConnection_h_
 
+#include <stdlib.h>
+
 #include "AtmoDefs.h"
 #include "AtmoConfig.h"
+#include "AtmoChannelAssignment.h"
+
+#if defined(_ATMO_VLC_PLUGIN_)
+#   include <vlc_common.h>
+#   include <vlc_threads.h>
+#else
+#   include <windows.h>
+#endif
 
 class CAtmoConnection
 {
 protected:
        CAtmoConfig *m_pAtmoConfig;
-    int m_ChannelAssignment[ATMO_NUM_CHANNELS];
+
+#if defined(_ATMO_VLC_PLUGIN_)
+    vlc_mutex_t m_AccessConnection;
+#else
+    CRITICAL_SECTION m_AccessConnection;
+#endif
+
+    int *m_ChannelAssignment;
+    int m_NumAssignedChannels;
+
+protected:
+    void Lock();
+    void Unlock();
 
 public:
        CAtmoConnection(CAtmoConfig *cfg);
@@ -25,12 +47,7 @@ public:
        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 SendData(pColorPacket 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; }
@@ -45,7 +62,18 @@ public:
                                           int gamma_blue,
                                           ATMO_BOOL storeToEeprom) { return false; }
 
-    virtual void SetChannelAssignment(tChannelAssignment *ca);
+#if !defined(_ATMO_VLC_PLUGIN_)
+    virtual ATMO_BOOL ShowConfigDialog(HINSTANCE hInst, HWND parent, CAtmoConfig *cfg);
+#endif
+
+    virtual void SetChannelAssignment(CAtmoChannelAssignment *ca);
+
+    virtual int getNumChannels() { return 0; }
+    virtual char *getChannelName(int ch) { return NULL; }
+
+    virtual const char *getDevicePath() { return "none"; }
+
+    virtual ATMO_BOOL CreateDefaultMapping(CAtmoChannelAssignment *ca) { return false; }
 
 };
 
index 7ee1c4ed1237e7468ba1fe53e37a2e7b579cbefa..f9195971bf7f017f15fd4bd298a43828d326ad45 100644 (file)
 #ifndef _AtmoDefs_h_
 #define _AtmoDefs_h_
 
-#if defined(__LIBVLC__)
-#   include "config.h"
 
-#   define __STDC_CONSTANT_MACROS 1
-#   include <inttypes.h>
+#if defined(__LIBVLC__)
 
-#   include <vlc_common.h>
+#   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 bool
-#   define ATMO_TRUE true
-#   define ATMO_FALSE false
+#   define get_time mdate()
+#   define do_sleep(a) msleep(a)
 
 #else
 
-    typedef int ATMO_BOOL;
-#   define ATMO_TRUE   1
-#   define ATMO_FALSE  0
-#   define MakeWord(ch1,ch2)  ((((int)(ch1)&255)<<8) | \
-                           ((int)(ch2)&255))
-
 #   define MakeDword(ch1,ch2,ch3,ch4) ((((DWORD)(ch1)&255) << 24) | \
                                    (((DWORD)(ch2)&255) << 16) | \
                                    (((DWORD)(ch3)&255) << 8) | \
                                    (((DWORD)(ch4)&255)))
 
+#  define get_time GetTickCount()
+#  define do_sleep(a) Sleep(a)
 
 #endif
 
+#define ATMO_BOOL   bool
+#define ATMO_TRUE   true
+#define ATMO_FALSE  false
+
+
+/*
+  can't use the VLC_TWOCC macro because the byte order there is CPU dependent
+  but for the use in Atmo I need for this single purpose Intel Byte Order
+  every time!
+*/
+
+#define MakeIntelWord(ch1,ch2)  ((((int)(ch1)&255)<<8) | \
+                           ((int)(ch2)&255))
+
+// my own min max macros
+#define ATMO_MIN(X, Y)  ((X) < (Y) ? (X) : (Y))
+#define ATMO_MAX(X, Y)  ((X) > (Y) ? (X) : (Y))
+
 
 #if !defined(WIN32)
 
@@ -68,33 +79,54 @@ typedef struct
 
 
 
+// maximal Anzahl Kanäle... original 5!
+#define CAP_MAX_NUM_ZONES  64
+// only for classic to avoid changing too much code!
+// #define ATMO_MAX_NUM_CHANNELS 5
 
+// capture width/height
 
+// #define CAP_WIDTH    88
 
-
-// maximal Anzahl Kanäle...
-#define ATMO_NUM_CHANNELS   5
-
-// capture width/height
-#define CAP_WIDTH    64
-#define CAP_HEIGHT   48
+#ifdef CAP_16x9
+# define CAP_WIDTH    88
+# define CAP_HEIGHT   48
+#else
+# define CAP_WIDTH    64
+# define CAP_HEIGHT   48
+#endif
 
 // imagesize
 #define IMAGE_SIZE   (CAP_WIDTH * CAP_HEIGHT)
 
+/*
+  number of pixel the atmo zones should overlap - based on CAP_WIDTH and CAP_HEIGHT
+*/
+#define CAP_ZONE_OVERLAP  2
+
+
 
 enum AtmoConnectionType
 {
-      actSerialPort = 0,
+      actClassicAtmo = 0,
       actDummy = 1,
-      actDMX = 2
+      actDMX = 2,
+      actNUL = 3,
+      actMultiAtmo = 4,
+      actMondolight = 5,
+      actMoMoLight  = 6
 };
 static const char *AtmoDeviceTypes[] = {
-      "Atmo",
+      "Atmo-Classic",
       "Dummy",
-      "DMX"
+      "DMX",
+      "Nul-Device",
+      "Multi-Atmo",
+      "Mondolight",
+      "MoMoLight"
+
   };
-#define ATMO_DEVICE_COUNT 3
+#define ATMO_DEVICE_COUNT 7
 
 #if defined(_ATMO_VLC_PLUGIN_)
 enum EffectMode {
@@ -103,7 +135,14 @@ enum EffectMode {
       emStaticColor = 1,
       emLivePicture = 2
    };
+
+enum LivePictureSource {
+       lpsDisabled = 0,
+       lpsExtern = 2
+     };
+
 #else
+
 enum EffectMode {
       emUndefined = -1,
       emDisabled = 0,
@@ -112,10 +151,20 @@ enum EffectMode {
       emColorChange = 3,
       emLrColorChange = 4
    };
-#endif
 
+enum LivePictureSource {
+       lpsDisabled = 0,
+       lpsScreenCapture = 1,
+       lpsExtern = 2
+     };
 
+#endif
 
+enum AtmoGammaCorrect {
+     agcNone = 0,
+     agcPerColor = 1,
+     agcGlobal = 2
+};
 
 enum AtmoFilterMode {
      afmNoFilter,
@@ -123,12 +172,6 @@ enum AtmoFilterMode {
      afmPercent
 };
 
-typedef struct {
-    ATMO_BOOL system;
-    char name[64];
-    int mappings[ATMO_NUM_CHANNELS];
-} tChannelAssignment;
-
 
 // --- tRGBColor --------------------------------------------------------------
 typedef struct
@@ -139,8 +182,23 @@ typedef struct
 // --- tColorPacket -----------------------------------------------------------
 typedef struct
 {
-  tRGBColor channel[ATMO_NUM_CHANNELS];
-} tColorPacket;
+   int numColors;
+   tRGBColor zone[1];
+} xColorPacket;
+typedef xColorPacket* pColorPacket;
+#define AllocColorPacket(packet, numColors_) packet = (pColorPacket)new char[sizeof(xColorPacket) + (numColors_)*sizeof(tRGBColor)]; \
+                                             packet->numColors = numColors_;
+
+#define DupColorPacket(dest, source) dest = NULL; \
+                                     if(source) { \
+                                         dest = (pColorPacket)new char[sizeof(xColorPacket) + (source->numColors)*sizeof(tRGBColor)]; \
+                                         memcpy(dest, source, sizeof(xColorPacket) + (source->numColors)*sizeof(tRGBColor)); \
+                                     }
+
+#define CopyColorPacket( source, dest)  memcpy(dest, source, sizeof(xColorPacket) + (source->numColors)*sizeof(tRGBColor) );
+
+
+#define ZeroColorPacket( packet ) memset( &((packet)->zone[0]), 0, (packet->numColors)*sizeof(tRGBColor));
 
 // --- tRGBColorLongInt -------------------------------------------------------
 typedef struct
@@ -151,14 +209,28 @@ typedef struct
 // --- tColorPacketLongInt ----------------------------------------------------
 typedef struct
 {
-  tRGBColorLongInt channel[ATMO_NUM_CHANNELS];
-} tColorPacketLongInt;
+  int numColors;
+  tRGBColorLongInt longZone[1];
+} xColorPacketLongInt;
+typedef xColorPacketLongInt* pColorPacketLongInt;
+#define AllocLongColorPacket(packet, numColors_) packet = (pColorPacketLongInt)new char[sizeof(xColorPacketLongInt) + (numColors_)*sizeof(tRGBColorLongInt)]; \
+                                             packet->numColors = numColors_;
+
+#define DupLongColorPacket(dest, source) dest = NULL; \
+                                     if(source) { \
+                                         dest = (pColorPacketLongInt)new char[sizeof(xColorPacketLongInt) + (source->numColors)*sizeof(tRGBColorLongInt)]; \
+                                         memcpy(dest, source, sizeof(xColorPacketLongInt) + (source->numColors)*sizeof(tRGBColorLongInt)); \
+                                     }
+#define ZeroLongColorPacket( packet ) memset( &((packet)->longZone[0]), 0, (packet->numColors)*sizeof(tRGBColorLongInt));
+
 
 // --- tWeightPacket ----------------------------------------------------------
+/*
 typedef struct
 {
-  int channel[ATMO_NUM_CHANNELS];
+  int channel[CAP_MAX_NUM_ZONES];
 } tWeightPacket;
+*/
 
 // --- tHSVColor --------------------------------------------------------------
 typedef struct
diff --git a/modules/video_filter/atmo/AtmoDmxSerialConnection.cpp b/modules/video_filter/atmo/AtmoDmxSerialConnection.cpp
new file mode 100644 (file)
index 0000000..bc47035
--- /dev/null
@@ -0,0 +1,297 @@
+/*
+ * AtmoDmxSerialConnection.cpp: Class for communication with a Simple DMX Dongle/Controller
+ * for hardware see also:
+ * http://www.dzionsko.de/elektronic/index.htm
+ * http://www.ulrichradig.de/ (search for dmx on his page)
+ *
+ * See the README.txt file for copyright information and how to reach the author(s).
+ *
+ * $Id$
+ */
+#include "AtmoDefs.h"
+#include "AtmoDmxSerialConnection.h"
+#include "DmxTools.h"
+
+#if !defined(_ATMO_VLC_PLUGIN_)
+#include "DmxConfigDialog.h"
+#endif
+
+#include <stdio.h>
+#include <fcntl.h>
+
+#if !defined(WIN32)
+#include <termios.h>
+#include <unistd.h>
+#endif
+
+
+CAtmoDmxSerialConnection::CAtmoDmxSerialConnection(CAtmoConfig *cfg) : CAtmoConnection(cfg) {
+    m_hComport = INVALID_HANDLE_VALUE;
+
+    memset(&DMXout, 0, sizeof(DMXout));
+    DMXout[0] = 0x5A;     // DMX Command Start Byte
+    DMXout[1] = 0xA1;     // DMX Controlcommand for 256 channels
+    DMXout[258] = 0xA5;   // end of block
+
+    m_dmx_channels_base = ConvertDmxStartChannelsToInt( cfg->getDMX_RGB_Channels(), cfg->getDMX_BaseChannels());
+}
+
+
+CAtmoDmxSerialConnection::~CAtmoDmxSerialConnection() {
+    delete m_dmx_channels_base;
+}
+
+ATMO_BOOL CAtmoDmxSerialConnection::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
+
+     if(!m_dmx_channels_base)
+        return ATMO_FALSE;
+
+        CloseConnection();
+
+#if !defined(_ATMO_VLC_PLUGIN_)
+     char serdevice[16];  // com4294967295
+     sprintf(serdevice,"com%d",portNummer);
+#endif
+
+#if defined(WIN32)
+
+     m_hComport = CreateFile(serdevice, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
+     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  = 115200;        // 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 = B115200;
+     m_hComport = open(serdevice, O_RDWR |O_NOCTTY);
+     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 CAtmoDmxSerialConnection::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 CAtmoDmxSerialConnection::isOpen(void) {
+        return (m_hComport != INVALID_HANDLE_VALUE);
+}
+
+ATMO_BOOL CAtmoDmxSerialConnection::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 ATMO_FALSE;
+}
+
+
+ATMO_BOOL CAtmoDmxSerialConnection::SendData(pColorPacket data) {
+   if(m_hComport == INVALID_HANDLE_VALUE)
+         return ATMO_FALSE;
+
+   int iBuffer = 2;
+   DWORD iBytesWritten;
+
+   Lock();
+
+   int idx, z = 0;
+
+   for(int i=0;i<getNumChannels();i++) {
+       if(m_ChannelAssignment && (i < m_NumAssignedChannels))
+         idx = m_ChannelAssignment[i];
+       else
+         idx = -1;
+
+       if((idx>=0) && (idx<data->numColors)) {
+          if( m_dmx_channels_base[z] >= 0 )
+              iBuffer = m_dmx_channels_base[z] + 2;
+          else
+              iBuffer += 3;
+
+          DMXout[iBuffer]   = data->zone[ idx ].r;
+          DMXout[iBuffer+1] = data->zone[ idx ].g;
+          DMXout[iBuffer+2] = data->zone[ idx ].b;
+       }
+
+       if( m_dmx_channels_base[z] >= 0 )
+          z++;
+   }
+
+#if defined(WIN32)
+   WriteFile(m_hComport, DMXout, 259, &iBytesWritten, NULL); // send to COM-Port
+#else
+   iBytesWritten = write(m_hComport, DMXout, 259);
+   tcdrain(m_hComport);
+#endif
+   Unlock();
+
+   return (iBytesWritten == 259) ? ATMO_TRUE : ATMO_FALSE;
+}
+
+
+ATMO_BOOL CAtmoDmxSerialConnection::setChannelValues(int numValues,unsigned char *channel_values)
+{
+       DWORD iBytesWritten;
+    if((numValues & 1) || !channel_values)
+       return ATMO_FALSE; // numValues must be even!
+
+    /*
+       the array shall contain
+    */
+
+       Lock();
+    int dmxIndex = 0;
+
+    for (int i = 0; i < numValues; i+=2) {
+         dmxIndex = ((int)channel_values[i]) + 2;
+         DMXout[dmxIndex] = channel_values[i+1];
+    }
+#if defined(WIN32)
+       WriteFile(m_hComport, DMXout, 259, &iBytesWritten, NULL);
+#else
+    iBytesWritten = write(m_hComport, DMXout, 259);
+    tcdrain(m_hComport);
+#endif
+
+    Unlock();
+
+       return (iBytesWritten == 259) ? ATMO_TRUE : ATMO_FALSE;
+}
+
+
+ATMO_BOOL CAtmoDmxSerialConnection::setChannelColor(int channel, tRGBColor color)
+{
+       DWORD iBytesWritten;
+       
+    Lock();
+
+    DMXout[channel+0+2]=color.r;
+       DMXout[channel+1+2]=color.g;
+       DMXout[channel+2+2]=color.b;
+
+#if defined(WIN32)
+       WriteFile(m_hComport, DMXout, 259, &iBytesWritten, NULL);
+#else
+    iBytesWritten = write(m_hComport, DMXout, 259);
+    tcdrain(m_hComport);
+#endif
+
+
+    Unlock();
+
+       return (iBytesWritten == 259) ? ATMO_TRUE : ATMO_FALSE;
+}
+
+ATMO_BOOL CAtmoDmxSerialConnection::CreateDefaultMapping(CAtmoChannelAssignment *ca)
+{
+    if(!ca) return ATMO_FALSE;
+    ca->setSize( getNumChannels() );
+    for(int i = 0; i < getNumChannels(); i++)
+        ca->setZoneIndex(i , i);
+    return ATMO_TRUE;
+}
+
+#if !defined(_ATMO_VLC_PLUGIN_)
+
+char *CAtmoDmxSerialConnection::getChannelName(int ch)
+{
+  if(ch < 0) return NULL;
+  char buf[30];
+
+  switch(ch) {
+      case 0:
+          sprintf(buf,"Summenkanal [%d]",ch);
+          break;
+      case 1:
+          sprintf(buf,"Linker Kanal [%d]",ch);
+          break;
+      case 2:
+          sprintf(buf,"Rechter Kanal [%d]",ch);
+          break;
+      case 3:
+          sprintf(buf,"Oberer Kanal [%d]",ch);
+          break;
+      case 4:
+          sprintf(buf,"Unterer Kanal [%d]",ch);
+          break;
+      default:
+          sprintf(buf,"Kanal [%d]",ch);
+          break;
+  }
+
+  return strdup(buf);
+}
+
+ATMO_BOOL CAtmoDmxSerialConnection::ShowConfigDialog(HINSTANCE hInst, HWND parent, CAtmoConfig *cfg)
+{
+    CDmxConfigDialog *dlg = new CDmxConfigDialog(hInst, parent, cfg);
+
+    INT_PTR result = dlg->ShowModal();
+
+    delete dlg;
+
+    if(result == IDOK)
+      return ATMO_TRUE;
+    else
+      return ATMO_FALSE;
+}
+
+#endif
+
+
+int CAtmoDmxSerialConnection::getNumChannels()
+{
+    return m_pAtmoConfig->getDMX_RGB_Channels();
+}
+
diff --git a/modules/video_filter/atmo/AtmoDmxSerialConnection.h b/modules/video_filter/atmo/AtmoDmxSerialConnection.h
new file mode 100644 (file)
index 0000000..53ef12a
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * AtmoDmxSerialConnection.h: Class for communication with the serial DMX Interface of dzionsko,
+ * opens and configures the serial port
+ *
+ * See the README.txt file for copyright information and how to reach the author(s).
+ *
+ * $Id$
+ */
+#ifndef _AtmoDmxSerialConnection_h_
+#define _AtmoDmxSerialConnection_h_
+
+
+#include "AtmoDefs.h"
+#include "AtmoConnection.h"
+#include "AtmoConfig.h"
+
+#if defined(WIN32)
+#   include <windows.h>
+#endif
+
+class CAtmoDmxSerialConnection : public CAtmoConnection {
+    private:
+        HANDLE m_hComport;
+        // DMX Channel Buffer including some Control Bytes for up to 256 DMX Channels
+               unsigned char DMXout[259];
+        // contains the DMX Start Adress of each Atmo-Dmx-Channel
+        int *m_dmx_channels_base;
+
+#if defined(WIN32)
+        DWORD  m_dwLastWin32Error;
+    public:
+        DWORD getLastError() { return m_dwLastWin32Error; }
+#endif
+
+    public:
+       CAtmoDmxSerialConnection(CAtmoConfig *cfg);
+       virtual ~CAtmoDmxSerialConnection(void);
+
+          virtual ATMO_BOOL OpenConnection();
+
+       virtual void CloseConnection();
+
+       virtual ATMO_BOOL isOpen(void);
+
+       virtual ATMO_BOOL SendData(pColorPacket 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);
+
+          virtual ATMO_BOOL setChannelColor(int channel, tRGBColor color);
+
+       virtual ATMO_BOOL setChannelValues(int numValues,unsigned char *channel_values);
+
+       virtual int getNumChannels();
+
+#if !defined(_ATMO_VLC_PLUGIN_)
+       virtual char *getChannelName(int ch);
+       virtual ATMO_BOOL ShowConfigDialog(HINSTANCE hInst, HWND parent, CAtmoConfig *cfg);
+#endif
+
+       virtual const char *getDevicePath() { return "dmx"; }
+
+       virtual ATMO_BOOL CreateDefaultMapping(CAtmoChannelAssignment *ca);
+};
+
+#endif
index 701e80757d85ab975ed216802e59dddbeecf15bb..b15eac22ae14612b233b3c66cb33dfd69e8d7194 100644 (file)
@@ -17,8 +17,10 @@ CAtmoDynData::CAtmoDynData(vlc_object_t *p_atmo_filter, CAtmoConfig *pAtmoConfig
     this->m_pAtmoConnection = NULL;
     this->m_pCurrentEffectThread = NULL;
 
+    this->m_pLivePacketQueue = NULL;
+    this->m_pLiveInput = NULL;
+    this->m_LivePictureSource = lpsExtern;
     vlc_mutex_init( &m_lock );
-
 }
 #else
 CAtmoDynData::CAtmoDynData(HINSTANCE hInst, CAtmoConfig *pAtmoConfig, CAtmoDisplays *pAtmoDisplays) {
@@ -27,7 +29,11 @@ CAtmoDynData::CAtmoDynData(HINSTANCE hInst, CAtmoConfig *pAtmoConfig, CAtmoDispl
     this->m_pAtmoConnection = NULL;
     this->m_pCurrentEffectThread = NULL;
     this->m_hInst = hInst;
-    InitializeCriticalSection(&m_RemoteCallCriticalSection);
+
+    this->m_pLivePacketQueue = NULL;
+    this->m_pLiveInput = NULL;
+    this->m_LivePictureSource = lpsScreenCapture;
+    InitializeCriticalSection( &m_RemoteCallCriticalSection );
 }
 #endif
 
@@ -55,3 +61,187 @@ void CAtmoDynData::UnLockCriticalSection() {
     LeaveCriticalSection(&m_RemoteCallCriticalSection);
 #endif
 }
+
+void CAtmoDynData::CalculateDefaultZones()
+{
+  int i;
+  int num_cols_top;
+  int num_cols_bottom;
+  int num_rows;
+  CAtmoZoneDefinition *zoneDef;
+
+  if(!m_pAtmoConfig)
+     return;
+
+  m_pAtmoConfig->UpdateZoneDefinitionCount();
+
+
+  num_cols_top    = m_pAtmoConfig->getZonesTopCount();
+  num_cols_bottom = m_pAtmoConfig->getZonesBottomCount();
+  num_rows        = m_pAtmoConfig->getZonesLRCount();
+
+  for(int zone=0; zone < m_pAtmoConfig->getZoneCount(); zone++)
+  {
+     zoneDef = m_pAtmoConfig->getZoneDefinition(zone);
+     if(zoneDef)
+        zoneDef->Fill(0);
+  }
+
+
+  // the zones will be counted starting from top left - in clockwise order around the display
+  // the summary channel will be the last one (in the center)
+  i = 0;
+  // top zones from left to right
+  for(int c=0;c<num_cols_top;c++)
+  {
+       zoneDef = m_pAtmoConfig->getZoneDefinition(i); i++;
+       if(zoneDef) {
+          int l = (c * CAP_WIDTH)/num_cols_top;
+          int r = ((c+1) * CAP_WIDTH)/num_cols_top;
+          zoneDef->FillGradientFromTop( ATMO_MAX( l - CAP_ZONE_OVERLAP, 0) , ATMO_MIN( r + CAP_ZONE_OVERLAP, CAP_WIDTH ) );
+       }
+  }
+  // right zones from top to bottom
+  for(int r=0;r<num_rows;r++)
+  {
+       zoneDef = m_pAtmoConfig->getZoneDefinition(i); i++;
+       if(zoneDef) {
+          int t = (r * CAP_HEIGHT)/num_rows;
+          int b = ((r+1) * CAP_HEIGHT)/num_rows;
+          zoneDef->FillGradientFromRight( ATMO_MAX( t - CAP_ZONE_OVERLAP, 0) , ATMO_MIN( b + CAP_ZONE_OVERLAP, CAP_HEIGHT) );
+       }
+  }
+  //  bottom zones from  RIGHT to LEFT!
+  for(int c=(num_cols_bottom-1);c>=0;c--)
+  {
+       zoneDef = m_pAtmoConfig->getZoneDefinition(i); i++;
+       if(zoneDef) {
+          int l = (c * CAP_WIDTH)/num_cols_bottom;
+          int r = ((c+1) * CAP_WIDTH)/num_cols_bottom;
+          zoneDef->FillGradientFromBottom( ATMO_MAX( l - CAP_ZONE_OVERLAP, 0 ), ATMO_MIN( r + CAP_ZONE_OVERLAP, CAP_WIDTH ) );
+       }
+  }
+  // left zones from bottom to top!
+  for(int r=(num_rows-1);r>=0;r--)
+  {
+       zoneDef = m_pAtmoConfig->getZoneDefinition(i); i++;
+       if(zoneDef)
+       {
+          int t = (r * CAP_HEIGHT)/num_rows;
+          int b = ((r+1) * CAP_HEIGHT)/num_rows;
+          zoneDef->FillGradientFromLeft( ATMO_MAX( t - CAP_ZONE_OVERLAP, 0 ), ATMO_MIN( b + CAP_ZONE_OVERLAP, CAP_HEIGHT ) );
+       }
+  }
+  if(m_pAtmoConfig->getZoneSummary())
+  {
+     // and last the summary zone if requested!
+     zoneDef = m_pAtmoConfig->getZoneDefinition(i++);
+     if(zoneDef)
+        zoneDef->Fill(255);
+  }
+}
+
+
+#if defined(_ATMO_VLC_PLUGIN_)
+void CAtmoDynData::ReloadZoneDefinitionBitmaps()
+{
+ // only as dummy for VLC Module - to avoid to if def out all calls to this function
+}
+#endif
+
+
+#if !defined(_ATMO_VLC_PLUGIN_)
+
+void CAtmoDynData::setWorkDir(const char *dir)
+{
+    strcpy( m_WorkDir, dir );
+}
+
+char *CAtmoDynData::getWorkDir()
+{
+    return m_WorkDir;
+}
+
+void CAtmoDynData::ReloadZoneDefinitionBitmaps()
+{
+  int i;
+  // suchlogik für die Bitmaps ...
+  // <WorkDir>\hardware\numchannels\zone..0..n.bmp
+  // <WorkDir>\hardware\zone..0..n.bmp
+  // <WorkDir>\zone..0..n.bmp
+  // Automatik Berechnung...
+  LockCriticalSection();
+  if(!m_pAtmoConnection || !m_pAtmoConfig) {
+      UnLockCriticalSection();
+      return;
+  }
+
+  m_pAtmoConfig->UpdateZoneDefinitionCount();
+
+  CalculateDefaultZones();
+
+
+  char psz_filename[MAX_PATH];
+  CAtmoZoneDefinition *zoneDef;
+
+  sprintf(psz_filename,"%s%s",
+                        m_WorkDir,
+                        m_pAtmoConnection->getDevicePath()
+                );
+  CreateDirectory( psz_filename, NULL );
+
+  sprintf(psz_filename,"%s%s\\%dx%dx%d",
+                        m_WorkDir,
+                        m_pAtmoConnection->getDevicePath(),
+                        m_pAtmoConfig->getZonesTopCount(),
+                        m_pAtmoConfig->getZonesLRCount(),
+                        m_pAtmoConfig->getZonesBottomCount()
+
+               );
+  CreateDirectory(psz_filename, NULL );
+
+  // try to load device depended zone definition bitmaps
+  for(int zone=0; zone < m_pAtmoConfig->getZoneCount(); zone++)  {
+      zoneDef = m_pAtmoConfig->getZoneDefinition(zone);
+      if(!zoneDef) continue;
+
+      sprintf(psz_filename,"%s%s\\%dx%dx%d\\zone_%d.bmp",
+                        m_WorkDir,
+                        m_pAtmoConnection->getDevicePath(),
+                        m_pAtmoConfig->getZonesTopCount(),
+                        m_pAtmoConfig->getZonesLRCount(),
+                        m_pAtmoConfig->getZonesBottomCount(),
+                        zone
+                );
+      i = zoneDef->LoadGradientFromBitmap( psz_filename );
+      if(i == ATMO_LOAD_GRADIENT_OK) continue;
+      if((i == ATMO_LOAD_GRADIENT_FAILED_SIZE) || (i == ATMO_LOAD_GRADIENT_FAILED_HEADER))
+         MessageBox(0,psz_filename,"Failed to load, Check Format, Check Size.",MB_ICONERROR);
+
+      sprintf(psz_filename,"%s%s\\zone_%d.bmp",
+                        m_WorkDir,
+                        m_pAtmoConnection->getDevicePath(),
+                        zone
+                );
+      i = zoneDef->LoadGradientFromBitmap( psz_filename );
+      if(i == ATMO_LOAD_GRADIENT_OK) continue;
+      if((i == ATMO_LOAD_GRADIENT_FAILED_SIZE) || (i == ATMO_LOAD_GRADIENT_FAILED_HEADER))
+         MessageBox(0,psz_filename,"Failed to load, Check Format, Check Size.",MB_ICONERROR);
+
+      sprintf(psz_filename,"%szone_%d.bmp",
+                        m_WorkDir,
+                        zone
+                );
+      i = zoneDef->LoadGradientFromBitmap( psz_filename );
+      if(i == ATMO_LOAD_GRADIENT_OK) continue;
+      if((i == ATMO_LOAD_GRADIENT_FAILED_SIZE) || (i == ATMO_LOAD_GRADIENT_FAILED_HEADER))
+         MessageBox(0,psz_filename,"Failed to load, Check Format, Check Size.",MB_ICONERROR);
+  }
+
+  UnLockCriticalSection();
+}
+
+#endif
+
+
+
index d03d4dc9b3bc02fa3bae48923c794d9596f3d2e5..f33fa812f68b45dc81189aefb47a2cf0610fe7a9 100644 (file)
@@ -9,19 +9,25 @@
 #ifndef _AtmoDynData_h_
 #define _AtmoDynData_h_
 
+#include <stdio.h>
+
 #include "AtmoDefs.h"
 
 #include "AtmoThread.h"
 #include "AtmoConfig.h"
 #include "AtmoConnection.h"
+#include "AtmoPacketQueue.h"
+#include "AtmoInput.h"
 
 #if !defined(_ATMO_VLC_PLUGIN_)
 #    include "AtmoDisplays.h"
 #else
-#    include <vlc_common.h>
-#    include <vlc_threads.h>
+#   include <vlc_common.h>
+#   include <vlc_threads.h>
 #endif
 
+class CAtmoInput;
+
 /*
   the idea behind this class is to avoid a mix of persistent value and
   volatile values in CAtmoConfig class because some parameters and variables
 
   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:
+    /*
+      thread creating the current output (depends on active effect)
+    */
     CThread *m_pCurrentEffectThread;
+
+    /*
+      in Modus Live View the packetQueue is the connection
+      between the output processing and the pixelsource
+    */
+    CAtmoPacketQueue *m_pLivePacketQueue;
+
+    /*
+      thread for getting and preparing the pixeldata in color
+      packets for each zone
+    */
+    CAtmoInput *m_pLiveInput;
+    LivePictureSource m_LivePictureSource;
+
+    /*
+    connection to the current configure hardware device
+    */
     CAtmoConnection *m_pAtmoConnection;
+
+    /*
+     all global persistent parameters
+    */
     CAtmoConfig *m_pAtmoConfig;
 
 #if !defined(_ATMO_VLC_PLUGIN_)
     CAtmoDisplays *m_pAtmoDisplays;
     HINSTANCE m_hInst;
     CRITICAL_SECTION m_RemoteCallCriticalSection;
+    char m_WorkDir[MAX_PATH];
 #else
     vlc_object_t *p_atmo_filter;
     vlc_mutex_t  m_lock;
@@ -67,14 +96,29 @@ public:
     CThread *getEffectThread()           { return m_pCurrentEffectThread; }
     void setEffectThread(CThread *value) { m_pCurrentEffectThread = value; }
 
+
+    CAtmoPacketQueue *getLivePacketQueue() { return m_pLivePacketQueue; }
+    void setLivePacketQueue(CAtmoPacketQueue *pQueue) { m_pLivePacketQueue = pQueue; }
+
+    CAtmoInput *getLiveInput() { return m_pLiveInput; }
+    void setLiveInput(CAtmoInput *value) {  m_pLiveInput = value; }
+
+    LivePictureSource getLivePictureSource() { return m_LivePictureSource; }
+    void setLivePictureSource(LivePictureSource lps) { m_LivePictureSource = lps; }
+
     CAtmoConnection *getAtmoConnection() { return m_pAtmoConnection; }
     void setAtmoConnection(CAtmoConnection *value) { m_pAtmoConnection = value; }
 
     CAtmoConfig *getAtmoConfig() { return m_pAtmoConfig; }
 
+    void ReloadZoneDefinitionBitmaps();
+    void CalculateDefaultZones();
+
 #if !defined(_ATMO_VLC_PLUGIN_)
     CAtmoDisplays *getAtmoDisplays() { return m_pAtmoDisplays; }
     HINSTANCE getHinstance() { return m_hInst; }
+    void setWorkDir(const char *dir);
+    char *getWorkDir();
 #else
     vlc_object_t *getAtmoFilter() { return p_atmo_filter; }
 #endif
index 2df7ab7e443b9094e600e9f122792192a92d48ef..fceda92a69a4cf0a3255a86b423dd2bfdd22818b 100644 (file)
 #include "AtmoExternalCaptureInput.h"
 #include "AtmoTools.h"
 
+
+#if defined(_ATMO_VLC_PLUGIN_)
+
+
 #ifndef INT64_C
 #define INT64_C(c)  c ## LL
 #endif
 
-#if defined(_ATMO_VLC_PLUGIN_)
-
 CAtmoExternalCaptureInput::CAtmoExternalCaptureInput(CAtmoDynData *pAtmoDynData) :
-                           CAtmoInput(pAtmoDynData),
-                           CThread(pAtmoDynData->getAtmoFilter())
+                           CAtmoInput(pAtmoDynData)
 {
-    m_pCurrentFramePixels = NULL;
     vlc_cond_init( &m_WakeupCond );
     vlc_mutex_init( &m_WakeupLock );
-    msg_Dbg( m_pAtmoThread, "CAtmoExternalCaptureInput created.");
-
+    m_pCurrentFramePixels = NULL;
 }
 
 #else
@@ -33,7 +32,8 @@ CAtmoExternalCaptureInput::CAtmoExternalCaptureInput(CAtmoDynData *pAtmoDynData)
 CAtmoExternalCaptureInput::CAtmoExternalCaptureInput(CAtmoDynData *pAtmoDynData) :
                            CAtmoInput(pAtmoDynData)
 {
-    m_hWakeupEvent = CreateEvent(NULL,ATMO_FALSE,ATMO_FALSE,NULL);
+    m_hWakeupEvent = CreateEvent(NULL,0,0,NULL);
+    InitializeCriticalSection( &m_BufferLock );
     m_pCurrentFramePixels = NULL;
 }
 
@@ -41,15 +41,20 @@ CAtmoExternalCaptureInput::CAtmoExternalCaptureInput(CAtmoDynData *pAtmoDynData)
 
 CAtmoExternalCaptureInput::~CAtmoExternalCaptureInput(void)
 {
-    /* if there is still an unprocessed bufferpicture do kill it */
-    free( m_pCurrentFramePixels );
-
+   /* if there is still an unprocessed bufferpicture do kill it */
 #if defined(_ATMO_VLC_PLUGIN_)
-    vlc_cond_destroy( &m_WakeupCond );
-    vlc_mutex_destroy(&m_WakeupLock);
-    msg_Dbg( m_pAtmoThread, "CAtmoExternalCaptureInput destroyed.");
+   vlc_mutex_lock( &m_WakeupLock );
+   free( m_pCurrentFramePixels );
+   vlc_mutex_unlock( &m_WakeupLock );
+
+   vlc_cond_destroy( &m_WakeupCond );
+   vlc_mutex_destroy( &m_WakeupLock );
 #else
-    CloseHandle(m_hWakeupEvent);
+   EnterCriticalSection( &m_BufferLock );
+   free( m_pCurrentFramePixels );
+   LeaveCriticalSection( &m_BufferLock );
+   CloseHandle(m_hWakeupEvent);
+   DeleteCriticalSection( &m_BufferLock );
 #endif
 }
 
@@ -67,10 +72,6 @@ ATMO_BOOL CAtmoExternalCaptureInput::Close(void)
     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
@@ -91,6 +92,12 @@ void CAtmoExternalCaptureInput::DeliverNewSourceDataPaket(BITMAPINFOHEADER *bmpI
        so it's nearly impossible that two frames are delivert in the same time
        the test needs and malloc needs...
     */
+#if defined(_ATMO_VLC_PLUGIN_)
+//    msg_Dbg( m_pAtmoThread, "DeliverNewSourceDataPaket start...");
+    vlc_mutex_lock( &m_WakeupLock );
+#else
+    EnterCriticalSection( &m_BufferLock );
+#endif
     if( !m_pCurrentFramePixels )
     {
         // Last Frame was processed... take this one...
@@ -106,12 +113,12 @@ void CAtmoExternalCaptureInput::DeliverNewSourceDataPaket(BITMAPINFOHEADER *bmpI
         memcpy(m_pCurrentFramePixels,pixelData,PixelDataSize);
     }
 #if defined(_ATMO_VLC_PLUGIN_)
-#error This makes no sense!
-   vlc_mutex_lock( &m_WakeupLock );
-   vlc_cond_signal( &m_WakeupCond );
-   vlc_mutex_unlock( &m_WakeupLock );
+    vlc_cond_signal( &m_WakeupCond );
+    vlc_mutex_unlock( &m_WakeupLock );
+    // msg_Dbg( m_pAtmoThread, "DeliverNewSourceDataPaket done.");
 #else
     SetEvent(m_hWakeupEvent);
+    LeaveCriticalSection( &m_BufferLock );
 #endif
 }
 
@@ -125,24 +132,17 @@ void CAtmoExternalCaptureInput::DeliverNewSourceDataPaket(BITMAPINFOHEADER *bmpI
 
 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 == false)) {
+          vlc_mutex_lock( &m_WakeupLock );
+          vlc_cond_timedwait(&m_WakeupCond, &m_WakeupLock, mdate() + 75000 );
 
-    while ((this->m_bTerminated == ATMO_FALSE) && (!vlc_object_alive (this->m_pAtmoThread) == false)) {
-          int value = vlc_cond_timedwait(&m_WakeupCond, &m_WakeupLock, mdate() + INT64_C(75000));
-          if(!value) {
-             /* DeliverNewSourceDataPaket delivered new work for me... get it! */
+          /* DeliverNewSourceDataPaket delivered new work for me... get it! */
+          if(m_pCurrentFramePixels)
              CalcColors(); // read picture and calculate colors
-             this->m_FrameArrived = ATMO_TRUE;
-          }
-          i++;
-          if(i == 100) {
-             i = 0;
-          }
+          vlc_mutex_unlock( &m_WakeupLock );
     }
-    vlc_mutex_unlock( &m_WakeupLock );
+
+    msg_Dbg( m_pAtmoThread, "DWORD CAtmoExternalCaptureInput::Execute(void) bailed out?");
 
     return 0;
 }
@@ -155,14 +155,16 @@ DWORD CAtmoExternalCaptureInput::Execute(void) {
     handles[1] = m_hWakeupEvent;
 
     while (this->m_bTerminated == ATMO_FALSE) {
-           DWORD event = WaitForMultipleObjects(2,handles,ATMO_FALSE,INFINITE);
+           DWORD event = WaitForMultipleObjects(2, &handles[0], 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;
+              EnterCriticalSection( &m_BufferLock );
+              if(m_pCurrentFramePixels)
+                 CalcColors(); // read picture and calculate colors
+              LeaveCriticalSection( &m_BufferLock );
            }
     }
     return 0;
@@ -171,134 +173,102 @@ DWORD CAtmoExternalCaptureInput::Execute(void) {
 #endif
 
 
-void CAtmoExternalCaptureInput::WaitForNextFrame(DWORD timeout)
+void CAtmoExternalCaptureInput::CalcColors()
 {
-    this->m_FrameArrived = ATMO_FALSE;
-#error m_FrameArrived is not protected (no, volatile does not work)
-    for(DWORD i=0;(i<timeout) && !m_FrameArrived;i++)
-#if defined (_ATMO_VLC_PLUGIN_)
-#error A condition variable or a semaphore is needed.
-        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)
+    // msg_Dbg( m_pAtmoThread, "CalcColors start...");
+
+    if((m_CurrentFrameHeader.biWidth == CAP_WIDTH) && (m_CurrentFrameHeader.biHeight == CAP_HEIGHT))
     {
-        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
+        // HSVI = HSV Image allready in right format just copy the easiest task
+        // und weiterverarbeiten lassen
 #ifdef _ATMO_VLC_PLUGIN_
-          if(m_CurrentFrameHeader.biCompression ==  VLC_FOURCC('H','S','V','I'))
+        if(m_CurrentFrameHeader.biCompression ==  VLC_FOURCC('H','S','V','I'))
 #else
-          if(m_CurrentFrameHeader.biCompression ==  MakeDword('H','S','V','I'))
+        if(m_CurrentFrameHeader.biCompression ==  MakeDword('H','S','V','I'))
 #endif
-          {
-              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;
+        {
+            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);
+                    }
+                }
+            }
+        }
     }
+    /*
+      else {
+        if the image color format wasn't recognized - the output
+        will be black (memset)
+        }
+    */
+
+    /* remove the source buffer */
+    free( m_pCurrentFramePixels );
+    m_pCurrentFramePixels = NULL;
+
+    /*
+        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 formulas
+        are done by some one else...)
+    */
+    //msg_Dbg( m_pAtmoThread, "CalcColors ende AddPacket...");
+    m_pAtmoDynData->getLivePacketQueue()->AddPacket( m_pAtmoColorCalculator->AnalyzeHSV( HSV_Img ) );
+    //msg_Dbg( m_pAtmoThread, "CalcColors ende AddPacket...done.");
 }
 
index 354033c5a7321a1898dd622d18f338507a416262..2ec00cd17f9537064494797a5b9f4a233de2260b 100644 (file)
@@ -12,9 +12,9 @@
 #   endif
 #endif
 
-#if !defined(_ATMO_VLC_PLUGIN_)
-#  include <comdef.h>          
-#  include "AtmoWin_h.h"
+#if defined(_ATMO_VLC_PLUGIN_)
+#  include <vlc_common.h>
+#  include <vlc_threads.h>
 #endif
 
 #include "AtmoInput.h"
@@ -24,9 +24,7 @@
 #include "AtmoCalculations.h"
 
 
-class CAtmoExternalCaptureInput :
-      public CAtmoInput,
-      public CThread
+class CAtmoExternalCaptureInput :  public CAtmoInput
 {
 protected:
 #if defined(_ATMO_VLC_PLUGIN_)
@@ -34,6 +32,7 @@ protected:
     vlc_mutex_t  m_WakeupLock;
 #else
     HANDLE m_hWakeupEvent;
+    CRITICAL_SECTION m_BufferLock;
 #endif
 
     BITMAPINFOHEADER m_CurrentFrameHeader;
@@ -67,17 +66,6 @@ public:
     */
     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
index 3cf6ef1c0fe36f5a37bdaf3f198732bf0c9e328c..fc0ba660bd13f81cbdb7fd288ae31f014faf4765 100644 (file)
@@ -7,20 +7,25 @@
  *
  * $Id$
  */
-
+#include "AtmoDefs.h"
 #include "AtmoInput.h"
 
-CAtmoInput::CAtmoInput(CAtmoDynData *pAtmoDynData)
+#if defined(_ATMO_VLC_PLUGIN_)
+CAtmoInput::CAtmoInput(CAtmoDynData *pAtmoDynData) : CThread(pAtmoDynData->getAtmoFilter())
 {
-  this->m_pAtmoDynData = pAtmoDynData;
+  m_pAtmoDynData         = pAtmoDynData;
+  m_pAtmoColorCalculator = new CAtmoColorCalculator(pAtmoDynData->getAtmoConfig());
 }
-
-CAtmoInput::~CAtmoInput(void)
+#else
+CAtmoInput::CAtmoInput(CAtmoDynData *pAtmoDynData)
 {
+  m_pAtmoDynData = pAtmoDynData;
+  m_pAtmoColorCalculator = new CAtmoColorCalculator(pAtmoDynData->getAtmoConfig());
 }
+#endif
 
-void CAtmoInput::WaitForNextFrame(DWORD timeout)
+CAtmoInput::~CAtmoInput(void)
 {
-    return;
+  delete m_pAtmoColorCalculator;
 }
 
index aecbd0638c0688b19554d04829d09e0519e11a7a..0425eb1bbc4ee267415a744cc67abef151314a5b 100644 (file)
 #define _AtmoInput_h_
 
 #include "AtmoDefs.h"
+#include "AtmoCalculations.h"
+#include "AtmoPacketQueue.h"
+#include "AtmoThread.h"
 #include "AtmoDynData.h"
 
+class CAtmoDynData;
+
 /*
   basic definition of an AtmoLight data/image source ...
 */
-class CAtmoInput {
+class CAtmoInput : public CThread {
 
 protected:
-    tColorPacket m_ColorPacket;
-    volatile ATMO_BOOL m_FrameArrived;
-    CAtmoDynData *m_pAtmoDynData;
+    CAtmoDynData         *m_pAtmoDynData;
+    CAtmoColorCalculator *m_pAtmoColorCalculator;
 
 public:
     CAtmoInput(CAtmoDynData *pAtmoDynData);
@@ -35,11 +39,6 @@ public:
     // 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
index 4ce5ba02e59bad3e257bd7dc04e29b994d196905..cda99a424460758fe34e5eb4de6b070708a68b33 100644 (file)
@@ -13,7 +13,7 @@
 #include "AtmoTools.h"
 
 #if defined(_ATMO_VLC_PLUGIN_)
-# include <vlc_common.h>
+#  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
@@ -35,11 +35,6 @@ CAtmoLiveView::CAtmoLiveView(CAtmoDynData *pAtmoDynData) :
 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
@@ -47,215 +42,157 @@ CAtmoLiveView::CAtmoLiveView(CAtmoDynData *pAtmoDynData)
 
 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;
+    mtime_t ticks;
+    mtime_t t;
+    mtime_t packet_time;
 #else
-      DWORD ticks;
+    DWORD ticks;
+    DWORD t;
+    DWORD packet_time;
 #endif
-      int i_frame_counter = 0;
-      CAtmoInput *newInput,*oldInput;
-      tColorPacket ColorPacket;
+    int i_frame_counter = -1;
 
-      CAtmoConnection *pAtmoConnection = this->m_pAtmoDynData->getAtmoConnection();
-      if((pAtmoConnection == NULL) || (pAtmoConnection->isOpen() == ATMO_FALSE)) return 0;
+    pColorPacket ColorPacket;
+    pColorPacket PreviousPacket = NULL;
 
-      CAtmoConfig *pAtmoConfig = this->m_pAtmoDynData->getAtmoConfig();
+    CAtmoConnection *pAtmoConnection = this->m_pAtmoDynData->getAtmoConnection();
+    if((pAtmoConnection == NULL) || (pAtmoConnection->isOpen() == ATMO_FALSE)) return 0;
 
-      /*
-         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());
+    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() );
+    CAtmoPacketQueue *pPacketQueue = this->m_pAtmoDynData->getLivePacketQueue();
 
+    int frameDelay = pAtmoConfig->getLiveView_FrameDelay();
 
 #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);
+    /*
+     because time function of vlc are working with us values instead of ms
+    */
+    frameDelay = frameDelay * 1000;
 #endif
 
-      if(m_pAtmoInput->Open() == ATMO_TRUE)
-      {
-          /*
-            wait for the first frame to go in sync with the other thread
-          */
+    /*
+      wait for the first frame to go in sync with the other thread
+    */
+    t = get_time;
+
+    if( pPacketQueue->WaitForNextPacket(3000) )
+    {
+        if( frameDelay > 0 )
+            do_sleep( frameDelay );
 #if defined(_ATMO_VLC_PLUGIN_)
-          msg_Dbg( m_pAtmoThread, "CAtmoLiveView::Execute(void)");
+        msg_Dbg( m_pAtmoThread, "First Packet got %d ms", (get_time - t) / 1000  );
 #endif
-          m_pAtmoInput->WaitForNextFrame(500);
+    }
 
-          while(this->m_bTerminated == ATMO_FALSE)
-          {
-              /*  atmoInput - capture Thread Running... */
+    while(this->m_bTerminated == ATMO_FALSE)
+    {
+        i_frame_counter++;
+        if(i_frame_counter == 50) i_frame_counter = 0;
+
+        /* grab current Packet from InputQueue (working as FIFO)! */
 #if defined(_ATMO_VLC_PLUGIN_)
-                ticks = mdate();
+        ColorPacket = pPacketQueue->GetNextPacket(get_time - frameDelay, (i_frame_counter == 0), m_pAtmoThread, packet_time);
 #else
-                ticks = GetTickCount();
+        ColorPacket = pPacketQueue->GetNextPacket(get_time - frameDelay, (i_frame_counter == 0), packet_time);
 #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_TerminateCond );
-                   vlc_mutex_unlock( &m_TerminateLock );
+        if(ColorPacket)
+        {
+            /*
+              create a packet copy - for later reuse if the input is slower than 25fps
+            */
+            if(PreviousPacket && (PreviousPacket->numColors == ColorPacket->numColors))
+                CopyColorPacket(ColorPacket, PreviousPacket)
+            else {
+                delete (char *)PreviousPacket;
+                DupColorPacket(PreviousPacket, ColorPacket )
+            }
+        } else {
+            /*
+              packet queue was empty for the given point of time
+            */
+            if(i_frame_counter == 0)
+            {
+#if defined(_ATMO_VLC_PLUGIN_)
+                msg_Dbg( m_pAtmoThread, "wait for delayed packet..." );
 #endif
+                t = get_time;
+                if( pPacketQueue->WaitForNextPacket(200) )
+                {
+                    if( frameDelay > 0 )
+                        do_sleep( frameDelay );
+#if defined(_ATMO_VLC_PLUGIN_)
+                    msg_Dbg( m_pAtmoThread, "got delayed packet %d ms", (mdate() - t) / 1000  );
 #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;
+                    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
-               */
+            }
+            /*
+              reuse previous color packet
+            */
+            DupColorPacket(ColorPacket, PreviousPacket)
+        }
+
+        ticks = get_time;
+
+        if(ColorPacket)
+        {
+            /* pass it through the outputfilters! */
+            // Info Filtering will possible free the colorpacket and alloc a new one!
+            ColorPacket = filter->Filtering(ColorPacket);
+
+            /* apply gamma correction - only if the hardware isnt capable doing this */
+            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);
+
+            delete (char *)ColorPacket;
+        }
+
+        /*
+            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;
+        ticks = ((mdate() - ticks) + 999)/1000;
 #else
-                ticks = GetTickCount() - ticks;
+        ticks = GetTickCount() - ticks;
 #endif
-                if(ticks < 40)
-                {
-                    // ThreadSleep -> AtmoThread.cpp
-                    if(this->ThreadSleep(40 - ticks)==ATMO_FALSE)
-                      break;
-                }
-          }
+        if(ticks < 40)
+        {
+            if( ThreadSleep( 40 - ticks ) == ATMO_FALSE )
+                break;
+        }
+    }
 
-          /* shutdown the input processor thread */
-          m_pAtmoInput->Close();
-      }
+#if defined(_ATMO_VLC_PLUGIN_)
+    msg_Dbg( m_pAtmoThread, "DWORD CAtmoLiveView::Execute(void) terminates");
+    pPacketQueue->ShowQueueStatus( m_pAtmoThread );
+#endif
 
-      delete m_pAtmoInput;
-      m_pAtmoInput = NULL;
+    delete (char *)PreviousPacket;
 
-#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;
+    delete filter;
+    return 0;
 }
 
index 20da086d23e2ddadd65daeef805d683cb1abffe1..9d7f57b4b635e4f3a5c552f2dd480685e70ff8df 100644 (file)
@@ -13,8 +13,6 @@
 #include "AtmoDefs.h"
 
 #if !defined(_ATMO_VLC_PLUGIN_)
-#   include <comdef.h>         
-#   include "AtmoWin_h.h"
 #   include <windows.h>
 #endif
 
@@ -28,32 +26,12 @@ 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/AtmoMultiConnection.cpp b/modules/video_filter/atmo/AtmoMultiConnection.cpp
new file mode 100644 (file)
index 0000000..71f70f9
--- /dev/null
@@ -0,0 +1,437 @@
+/*
+ * AtmoMultiConnection.cpp: Class for communication with up to 4 - 4 channel classic atmolight controllers
+ * so you can built a cheap solution for having up to 16 channels
+ *
+ * See the README.txt file for copyright information and how to reach the author(s).
+ *
+ * $Id$
+ */
+
+#include "AtmoDefs.h"
+#include "AtmoMultiConnection.h"
+
+#if !defined(_ATMO_VLC_PLUGIN_)
+#include "AtmoMultiConfigDialog.h"
+#endif
+
+#include <stdio.h>
+#include <fcntl.h>
+
+#if !defined(WIN32)
+#include <termios.h>
+#include <unistd.h>
+#endif
+
+
+
+CAtmoMultiConnection::CAtmoMultiConnection(CAtmoConfig *cfg) : CAtmoConnection(cfg)
+{
+   m_hComports[0] = INVALID_HANDLE_VALUE;
+   m_hComports[1] = INVALID_HANDLE_VALUE;
+   m_hComports[2] = INVALID_HANDLE_VALUE;
+   m_hComports[3] = INVALID_HANDLE_VALUE;
+   memset(&m_output, 0, sizeof(m_output));
+}
+
+CAtmoMultiConnection::~CAtmoMultiConnection(void)
+{
+}
+
+HANDLE CAtmoMultiConnection::OpenDevice(char *devName)
+{
+     HANDLE hComport;
+
+#if !defined(_ATMO_VLC_PLUGIN_)
+     m_dwLastWin32Error = 0;
+#endif
+
+#if defined(WIN32)
+     hComport = CreateFile(devName, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
+     if(hComport == INVALID_HANDLE_VALUE) {
+#if !defined(_ATMO_VLC_PLUGIN_)
+           m_dwLastWin32Error = GetLastError();
+#endif
+           return INVALID_HANDLE_VALUE;
+     }
+     /* change serial settings (Speed, stopbits etc.) */
+     DCB dcb; // für comport-parameter
+     dcb.DCBlength = sizeof(DCB);
+     GetCommState (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 (hComport, &dcb);    // apply settings
+
+#else
+
+     int bconst = B38400;
+     hComport = open(devName,O_RDWR |O_NOCTTY);
+     if(hComport < 0) {
+           return INVALID_HANDLE_VALUE;;
+     }
+     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(hComport, TCSANOW, &tio)) {
+         tcflush(hComport, TCIOFLUSH);
+     } else {
+         // can't change parms
+        close(hComport);
+        return INVALID_HANDLE_VALUE;
+     }
+#endif
+
+     return hComport;
+}
+
+ATMO_BOOL CAtmoMultiConnection::OpenConnection()
+{
+    int z = 0;
+#if defined(_ATMO_VLC_PLUGIN_)
+
+    for(int c = 0; c < 4; c++ ) {
+        char *devName = m_pAtmoConfig->getSerialDevice( c );
+        if( devName && strlen(devName) > 0 )
+        {
+            m_hComports[z] = OpenDevice( devName );
+            if(m_hComports[z] == INVALID_HANDLE_VALUE) {
+                while(z) {
+                      z--;
+#if defined(WIN32)
+                      CloseHandle( m_hComports[z] );
+#else
+                      close( m_hComports[z] );
+#endif
+                      m_hComports[z] = INVALID_HANDLE_VALUE;
+                }
+                return ATMO_FALSE;
+            }
+            z++;
+        }
+    }
+
+
+#else
+
+    char devName[16];
+
+    for(int c = 0; c < 4; c++ ) {
+        int comportnr = m_pAtmoConfig->getComport(c);
+        if(comportnr > 0)
+        {
+            sprintf(devName,"com%d",comportnr);
+            m_hComports[z] = OpenDevice(devName);
+            if(m_hComports[z] == INVALID_HANDLE_VALUE) {
+                while(z) {
+                      z--;
+                      CloseHandle( m_hComports[z] );
+                      m_hComports[z] = INVALID_HANDLE_VALUE;
+                }
+                return ATMO_FALSE;
+            }
+            z++;
+        }
+    }
+#endif
+    return ATMO_TRUE;
+}
+
+void CAtmoMultiConnection::CloseConnection() {
+    for(int i = 0; i < 4; i++ ) {
+        if(m_hComports[i] != INVALID_HANDLE_VALUE) {
+#if defined(WIN32)
+           CloseHandle( m_hComports[i] );
+#else
+           close( m_hComports[i] );
+#endif
+              m_hComports[i] = INVALID_HANDLE_VALUE;
+        }
+    }
+}
+
+ATMO_BOOL CAtmoMultiConnection::isOpen(void) {
+     int z = 0;
+     for(int i = 0; i < 4; i++ )
+         if(m_hComports[i] != INVALID_HANDLE_VALUE) z++;
+
+        return (z > 0);
+}
+
+int CAtmoMultiConnection::getNumChannels()
+{
+    int z = 0;
+#if defined(_ATMO_VLC_PLUGIN_)
+    char *psz_dev;
+    for(int i=0;i<4;i++) {
+        psz_dev = m_pAtmoConfig->getSerialDevice( i );
+        if( psz_dev && strlen( psz_dev ) > 0 )
+            z+=4;
+    }
+#else
+    for(int i=0;i<4;i++)
+        if(m_pAtmoConfig->getComport(i)>0)
+           z+=4;
+#endif
+    return z;
+}
+
+ATMO_BOOL CAtmoMultiConnection::CreateDefaultMapping(CAtmoChannelAssignment *ca)
+{
+  if(!ca) return ATMO_FALSE;
+  int z = getNumChannels();
+  ca->setSize( z );
+  // 1 : 1 mapping vorschlagen...
+  for(int i = 0; i < z ; i++ ) {
+      ca->setZoneIndex( i, i );
+  }
+  return ATMO_TRUE;
+}
+
+
+ATMO_BOOL CAtmoMultiConnection::internal_HardwareWhiteAdjust(HANDLE hComport,
+                                                     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(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(hComport, sendBuffer, 13, &iBytesWritten, NULL); // send to COM-Port
+#else
+     iBytesWritten = write(hComport, sendBuffer, 13);
+     tcdrain(hComport);
+#endif
+
+     return (iBytesWritten == 13) ? ATMO_TRUE : ATMO_FALSE;
+}
+
+
+ATMO_BOOL CAtmoMultiConnection::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)
+{
+    for(int z = 0 ; z < 4; z++ ) {
+        if(m_hComports[z]!= INVALID_HANDLE_VALUE)
+           if(internal_HardwareWhiteAdjust(m_hComports[z], global_gamma, global_contrast,
+                                           contrast_red, contrast_green, contrast_blue,
+                                           gamma_red, gamma_green, gamma_blue,
+                                           storeToEeprom) == ATMO_FALSE)
+                                                return ATMO_FALSE;
+    }
+    return ATMO_TRUE;
+}
+
+ATMO_BOOL CAtmoMultiConnection::internal_SendData(HANDLE hComport, unsigned char *colorData)
+{
+ if(m_hComports[0] == 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; //
+  buffer[4] = 0; // Summe Red
+  buffer[5] = 0; // Summe Green
+  buffer[6] = 0; // Summe Blue
+  memcpy(&buffer[7], colorData, 4 * 3);
+
+#if defined(WIN32)
+   WriteFile(hComport, buffer, 19, &iBytesWritten, NULL); // send to COM-Port
+#else
+   iBytesWritten = write(hComport, buffer, 19);
+   tcdrain(hComport);
+#endif
+
+ return (iBytesWritten == 19) ? ATMO_TRUE : ATMO_FALSE;
+}
+
+ATMO_BOOL CAtmoMultiConnection::SendData(pColorPacket data)
+{
+   if(m_hComports[0] == INVALID_HANDLE_VALUE)
+         return ATMO_FALSE;
+
+   int numChannels = this->getNumChannels();
+
+   int idx;
+   int iBuffer = 0;
+   ATMO_BOOL result = ATMO_TRUE;
+
+   Lock();
+
+   for(int i = 0; i < numChannels ; i++) {
+       if(m_ChannelAssignment && (i < m_NumAssignedChannels))
+          idx = m_ChannelAssignment[i];
+       else
+          idx = -1;
+       if((idx>=0) && (idx<data->numColors)) {
+          m_output[iBuffer] = data->zone[idx].r;
+          m_output[iBuffer+1] = data->zone[idx].g;
+          m_output[iBuffer+2] = data->zone[idx].b;
+       }
+       iBuffer+=3;
+   }
+   for(int i = 0;i < 4; i++)
+       if(m_hComports[i] != INVALID_HANDLE_VALUE)
+          result = result & internal_SendData(m_hComports[i], &m_output[i*4*3]);
+
+   Unlock();
+
+   return result;
+}
+
+ATMO_BOOL CAtmoMultiConnection::setChannelColor(int channel, tRGBColor color)
+{
+   if(m_hComports[0] == INVALID_HANDLE_VALUE)
+         return ATMO_FALSE;
+   if((channel < 0) || (channel >= getNumChannels()))
+      return ATMO_FALSE;
+
+   ATMO_BOOL result = ATMO_TRUE;
+
+   Lock();
+   channel*=3;
+   m_output[channel++] = color.r;
+   m_output[channel++] = color.g;
+   m_output[channel]   = color.b;
+   for(int i = 0; i < 4; i++)
+       if(m_hComports[i] != INVALID_HANDLE_VALUE)
+          result = result & internal_SendData(m_hComports[i], &m_output[i*4*3]);
+   Unlock();
+
+   return result;
+}
+
+ATMO_BOOL CAtmoMultiConnection::setChannelValues(int numValues,unsigned char *channel_values)
+{
+  if(m_hComports[0] == INVALID_HANDLE_VALUE)
+     return ATMO_FALSE;
+
+  if((numValues & 1) || !channel_values)
+     return ATMO_FALSE; // numValues must be even!
+
+  ATMO_BOOL result = ATMO_TRUE;
+
+
+  Lock();
+  int Index = 0;
+  for (int i = 0; i < numValues; i+=2) {
+       Index = (int)channel_values[i];
+       if(Index < sizeof(m_output))
+          m_output[Index] = channel_values[i + 1];
+  }
+  for(int i = 0; i < 4; i++)
+      if(m_hComports[i] != INVALID_HANDLE_VALUE)
+         result = result & internal_SendData(m_hComports[i], &m_output[i*4*3]);
+
+  Unlock();
+  return result;
+}
+
+#if !defined(_ATMO_VLC_PLUGIN_)
+
+char *CAtmoMultiConnection::getChannelName(int ch)
+{
+  int devnum = ch / 4;
+  int kanal  = ch % 4;
+  char buf[60];
+  switch(kanal) {
+         case 0: {
+                   sprintf(buf,"Atmo[%d.%d] Links (%d)", devnum, kanal, ch);
+                   break;
+                 }
+         case 1: {
+                   sprintf(buf,"Atmo[%d.%d] Rechts (%d)", devnum, kanal, ch);
+                   break;
+                 }
+         case 2: {
+                   sprintf(buf,"Atmo[%d.%d] Oben (%d)", devnum, kanal, ch);
+                   break;
+                 }
+         case 3: {
+                   sprintf(buf,"Atmo[%d.%d] Unten (%d)", devnum, kanal, ch);
+                   break;
+                 }
+  }
+  return strdup(buf);
+}
+
+ATMO_BOOL CAtmoMultiConnection::ShowConfigDialog(HINSTANCE hInst, HWND parent, CAtmoConfig *cfg)
+{
+    CAtmoMultiConfigDialog *dlg = new CAtmoMultiConfigDialog(hInst, parent, cfg);
+
+    INT_PTR result = dlg->ShowModal();
+
+    delete dlg;
+
+    if(result == IDOK)
+      return ATMO_TRUE;
+    else
+      return ATMO_FALSE;
+}
+
+#endif
+
diff --git a/modules/video_filter/atmo/AtmoMultiConnection.h b/modules/video_filter/atmo/AtmoMultiConnection.h
new file mode 100644 (file)
index 0000000..0ffd754
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * AtmoMultiConnection.h: Class for communication with up to 4 - 4 channel classic atmolight controllers
+ * so you can built a cheap solution for having up to 16 channels, but you need four comports or
+ * USB Adapters
+ *
+ * See the README.txt file for copyright information and how to reach the author(s).
+ *
+ * $Id$
+ */
+
+#ifndef _AtmoMultiConnection_h_
+#define _AtmoMultiConnection_h_
+
+#include "AtmoDefs.h"
+#include "AtmoConnection.h"
+#include "AtmoConfig.h"
+
+#if defined(WIN32)
+#   include <windows.h>
+#endif
+
+
+class CAtmoMultiConnection :  public CAtmoConnection
+{
+    private:
+        HANDLE m_hComports[4];
+        unsigned char m_output[4 * 4 * 3];
+
+#if defined(WIN32)
+        DWORD  m_dwLastWin32Error;
+    public:
+        DWORD getLastError() { return m_dwLastWin32Error; }
+#endif
+
+        /*
+          on windows devName is COM1 COM2 etc.
+          on linux devname my be /dev/ttyS0 or /dev/ttyUSB0
+        */
+       HANDLE OpenDevice(char *devName);
+       ATMO_BOOL internal_HardwareWhiteAdjust(HANDLE hComport,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);
+
+       ATMO_BOOL internal_SendData(HANDLE hComport, unsigned char *colorData);
+
+    public:
+       CAtmoMultiConnection(CAtmoConfig *cfg);
+       virtual ~CAtmoMultiConnection(void);
+
+          virtual ATMO_BOOL OpenConnection();
+
+       virtual void CloseConnection();
+
+       virtual ATMO_BOOL isOpen(void);
+
+       virtual ATMO_BOOL SendData(pColorPacket data);
+
+       virtual ATMO_BOOL setChannelColor(int channel, tRGBColor color);
+       virtual ATMO_BOOL setChannelValues(int numValues,unsigned char *channel_values);
+
+       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);
+
+       virtual int getNumChannels();
+       virtual const char *getDevicePath() { return "multiatmo"; }
+
+#if !defined(_ATMO_VLC_PLUGIN_)
+       virtual char *getChannelName(int ch);
+       virtual ATMO_BOOL ShowConfigDialog(HINSTANCE hInst, HWND parent, CAtmoConfig *cfg);
+#endif
+
+       virtual ATMO_BOOL CreateDefaultMapping(CAtmoChannelAssignment *ca);
+};
+
+#endif
index 3cefa0033c5aee8bf19329c1fc064368c7f50c6c..8d8030c01820cedc9e4724a17ac36b23b384d60b 100644 (file)
 
 
 
-CAtmoOutputFilter::CAtmoOutputFilter(CAtmoConfig *atmoConfig)
+CAtmoOutputFilter::CAtmoOutputFilter(CAtmoConfig *atmoConfig )
 {
    this->m_pAtmoConfig = atmoConfig;
+   this->m_percent_filter_output_old = NULL;
+   this->m_mean_filter_output_old = NULL;
+   this->m_mean_values = NULL;
+   this->m_mean_sums = NULL;
    ResetFilter();
 }
 
 CAtmoOutputFilter::~CAtmoOutputFilter(void)
 {
+  if(m_percent_filter_output_old)
+     delete (char *)m_percent_filter_output_old;
+
+  if(m_mean_filter_output_old)
+     delete (char *)m_mean_filter_output_old;
+
+  if(m_mean_values)
+     delete (char *)m_mean_values;
+
+  if(m_mean_sums)
+     delete (char *)m_mean_sums;
 }
 
 void CAtmoOutputFilter::ResetFilter(void)
 {
   // reset filter values
-  MeanFilter(true);
-  PercentFilter(true);
+  MeanFilter(NULL, true);
+  PercentFilter(NULL, true);
 }
 
-tColorPacket CAtmoOutputFilter::Filtering(tColorPacket ColorPacket)
+pColorPacket CAtmoOutputFilter::Filtering(pColorPacket ColorPacket)
 {
-  filter_input = ColorPacket;
-
   switch (m_pAtmoConfig->getLiveViewFilterMode())
   {
     case afmNoFilter:
-         filter_output = filter_input;
+         return ColorPacket;
     break;
 
     case afmCombined:
-         MeanFilter(false);
+         return MeanFilter(ColorPacket, false);
     break;
 
     case afmPercent:
-         PercentFilter(false);
-    break;
-
-    default:
-         filter_output = filter_input;
+         return PercentFilter(ColorPacket, false);
     break;
   }
 
-  return filter_output;
+  return ColorPacket;
 }
 
-void CAtmoOutputFilter::PercentFilter(ATMO_BOOL init)
+pColorPacket CAtmoOutputFilter::PercentFilter(pColorPacket filter_input, 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;
+    if(m_percent_filter_output_old)
+       delete (char *)m_percent_filter_output_old;
+    m_percent_filter_output_old = NULL;
+    return(NULL);
+  }
+
+  if(!m_percent_filter_output_old || (m_percent_filter_output_old->numColors!=filter_input->numColors)) {
+     delete m_percent_filter_output_old;
+     AllocColorPacket(m_percent_filter_output_old, filter_input->numColors);
+     ZeroColorPacket(m_percent_filter_output_old);
   }
 
   int percentNew = this->m_pAtmoConfig->getLiveViewFilter_PercentNew();
 
-  for (int ch = 0; ch < ATMO_NUM_CHANNELS; ch++)
+  pColorPacket filter_output;
+  AllocColorPacket(filter_output, filter_input->numColors);
+
+  for (int zone = 0; zone < filter_input->numColors; zone++)
   {
-       filter_output.channel[ch].r = (filter_input.channel[ch].r *
-         (100-percentNew) + filter_output_old.channel[ch].r * percentNew) / 100;
+       filter_output->zone[zone].r = (filter_input->zone[zone].r *
+         (100-percentNew) + m_percent_filter_output_old->zone[zone].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->zone[zone].g = (filter_input->zone[zone].g *
+         (100-percentNew) + m_percent_filter_output_old->zone[zone].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->zone[zone].b = (filter_input->zone[zone].b *
+         (100-percentNew) + m_percent_filter_output_old->zone[zone].b * percentNew) / 100;
   }
 
-  filter_output_old = filter_output;
+  CopyColorPacket( filter_output, m_percent_filter_output_old );
+
+  delete (char *)filter_input;
+
+  return filter_output;
 }
 
-void CAtmoOutputFilter::MeanFilter(ATMO_BOOL init)
+pColorPacket CAtmoOutputFilter::MeanFilter(pColorPacket filter_input, 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;
   long int tmp;
+  pColorPacket filter_output;
 
   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;
+    if(m_mean_filter_output_old)
+       delete (char *)m_mean_filter_output_old;
+    m_mean_filter_output_old = NULL;
+
+    if(m_mean_values)
+       delete (char *)m_mean_values;
+    m_mean_values = NULL;
+
+    if(m_mean_sums)
+       delete (char *)m_mean_sums;
+    m_mean_sums = NULL;
+    return (NULL);
+  }
+
+  if(!m_mean_filter_output_old || (m_mean_filter_output_old->numColors!=filter_input->numColors)) {
+        delete m_mean_filter_output_old;
+        AllocColorPacket(m_mean_filter_output_old, filter_input->numColors);
+        ZeroColorPacket(m_mean_filter_output_old);
+  }
+
+  if(!m_mean_values || (m_mean_values->numColors!=filter_input->numColors)) {
+        delete m_mean_values;
+        AllocColorPacket(m_mean_values, filter_input->numColors);
+        ZeroColorPacket(m_mean_values);
+  }
+
+  if(!m_mean_sums || (m_mean_sums->numColors!=filter_input->numColors)) {
+        delete m_mean_sums;
+        AllocLongColorPacket(m_mean_sums, filter_input->numColors);
+        ZeroLongColorPacket(m_mean_sums);
   }
+
+  AllocColorPacket(filter_output, filter_input->numColors);
+
+
   int AtmoSetup_Filter_MeanLength = m_pAtmoConfig->getLiveViewFilter_MeanLength();
   int AtmoSetup_Filter_PercentNew = m_pAtmoConfig->getLiveViewFilter_PercentNew();
   int AtmoSetup_Filter_MeanThreshold = m_pAtmoConfig->getLiveViewFilter_MeanThreshold();
@@ -117,36 +168,36 @@ void CAtmoOutputFilter::MeanFilter(ATMO_BOOL init)
 
   if (filter_length_old < 20) filter_length_old = 20; // avoid division by 0
 
-  for (int ch = 0; ch < ATMO_NUM_CHANNELS; ch++)
+  for (int zone = 0; zone < filter_input->numColors; zone++)
   {
     // calculate the mean-value filters
-    mean_sums.channel[ch].r +=
-         (long int)(filter_input.channel[ch].r - mean_values.channel[ch].r); // red
-    tmp = mean_sums.channel[ch].r / ((long int)filter_length_old / 20);
+      m_mean_sums->longZone[zone].r +=
+        (long int)(filter_input->zone[zone].r - m_mean_values->zone[zone].r); // red
+    tmp = m_mean_sums->longZone[zone].r / ((long int)filter_length_old / 20);
     if(tmp<0) tmp = 0; else { if(tmp>255) tmp = 255; }
-    mean_values.channel[ch].r = (unsigned char)tmp;
+    m_mean_values->zone[zone].r = (unsigned char)tmp;
 
-    mean_sums.channel[ch].g +=
-        (long int)(filter_input.channel[ch].g - mean_values.channel[ch].g); // green
-    tmp = mean_sums.channel[ch].g / ((long int)filter_length_old / 20);
+    m_mean_sums->longZone[zone].g +=
+        (long int)(filter_input->zone[zone].g - m_mean_values->zone[zone].g); // green
+    tmp = m_mean_sums->longZone[zone].g / ((long int)filter_length_old / 20);
     if(tmp<0) tmp = 0; else { if(tmp>255) tmp = 255; }
-    mean_values.channel[ch].g = (unsigned char)tmp;
+    m_mean_values->zone[zone].g = (unsigned char)tmp;
 
-    mean_sums.channel[ch].b +=
-        (long int)(filter_input.channel[ch].b - mean_values.channel[ch].b); // blue
-    tmp = mean_sums.channel[ch].b / ((long int)filter_length_old / 20);
+    m_mean_sums->longZone[zone].b +=
+        (long int)(filter_input->zone[zone].b - m_mean_values->zone[zone].b); // blue
+    tmp = m_mean_sums->longZone[zone].b / ((long int)filter_length_old / 20);
     if(tmp<0) tmp = 0; else { if(tmp>255) tmp = 255; }
-    mean_values.channel[ch].b = (unsigned char)tmp;
+    m_mean_values->zone[zone].b = (unsigned char)tmp;
 
     // 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);
+    dist = (m_mean_values->zone[zone].r - filter_input->zone[zone].r) *
+           (m_mean_values->zone[zone].r - filter_input->zone[zone].r) +
+           (m_mean_values->zone[zone].g - filter_input->zone[zone].g) *
+           (m_mean_values->zone[zone].g - filter_input->zone[zone].g) +
+           (m_mean_values->zone[zone].b - filter_input->zone[zone].b) *
+           (m_mean_values->zone[zone].b - filter_input->zone[zone].b);
 
     /*
        if (dist > 0) { dist = (long int)sqrt((double)dist); }
@@ -164,31 +215,36 @@ void CAtmoOutputFilter::MeanFilter(ATMO_BOOL init)
        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];
+      filter_output->zone[zone] = m_mean_values->zone[zone] = filter_input->zone[zone];
 
-      mean_sums.channel[ch].r = filter_input.channel[ch].r *
+      m_mean_sums->longZone[zone].r = filter_input->zone[zone].r *
                                 (filter_length_old / 20);
-      mean_sums.channel[ch].g = filter_input.channel[ch].g *
+      m_mean_sums->longZone[zone].g = filter_input->zone[zone].g *
                                 (filter_length_old / 20);
-      mean_sums.channel[ch].b = filter_input.channel[ch].b *
+      m_mean_sums->longZone[zone].b = filter_input->zone[zone].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 *
+         filter_output->zone[zone].r = (m_mean_values->zone[zone].r *
           (100-AtmoSetup_Filter_PercentNew) +
-          filter_output_old.channel[ch].r * AtmoSetup_Filter_PercentNew) / 100;
+          m_mean_filter_output_old->zone[zone].r * AtmoSetup_Filter_PercentNew) / 100;
 
-         filter_output.channel[ch].g = (mean_values.channel[ch].g *
+         filter_output->zone[zone].g = (m_mean_values->zone[zone].g *
           (100-AtmoSetup_Filter_PercentNew) +
-          filter_output_old.channel[ch].g * AtmoSetup_Filter_PercentNew) / 100;
+          m_mean_filter_output_old->zone[zone].g * AtmoSetup_Filter_PercentNew) / 100;
 
-         filter_output.channel[ch].b = (mean_values.channel[ch].b *
+         filter_output->zone[zone].b = (m_mean_values->zone[zone].b *
           (100-AtmoSetup_Filter_PercentNew) +
-          filter_output_old.channel[ch].b * AtmoSetup_Filter_PercentNew) / 100;
+          m_mean_filter_output_old->zone[zone].b * AtmoSetup_Filter_PercentNew) / 100;
     }
   }
-  filter_output_old = filter_output;
+
+  CopyColorPacket(filter_output, m_mean_filter_output_old);
+
+  delete (char *)filter_input;
+
+  return(filter_output);
 }
index e6397ac2b346dbab829c03dc63ed37162180cd86..80ad1561b381f1608fda89f51103e8c017b9222a 100644 (file)
 class CAtmoOutputFilter
 {
 private:
-  tColorPacket filter_input;  // input of the filter
-  tColorPacket filter_output; // output of the filter
+  //tColorPacket filter_input;  // input of the filter wozu?
+  //tColorPacket filter_output; // output of the filter
+  pColorPacket  m_percent_filter_output_old;
 
-  void PercentFilter(ATMO_BOOL init);
-  void MeanFilter(ATMO_BOOL init);
+  pColorPacket  m_mean_filter_output_old;
+  pColorPacket  m_mean_values;
+  pColorPacketLongInt m_mean_sums;
+
+  pColorPacket PercentFilter(pColorPacket filter_input, ATMO_BOOL init);
+  pColorPacket MeanFilter(pColorPacket filter_input, ATMO_BOOL init);
 
   CAtmoConfig *m_pAtmoConfig;
 public:
@@ -30,7 +35,7 @@ public:
     CAtmoOutputFilter(CAtmoConfig *atmoConfig);
     virtual ~CAtmoOutputFilter(void);
     void ResetFilter(void);
-    tColorPacket Filtering(tColorPacket ColorPacket);
+    pColorPacket Filtering(pColorPacket ColorPacket);
 };
 
 #endif
diff --git a/modules/video_filter/atmo/AtmoPacketQueue.cpp b/modules/video_filter/atmo/AtmoPacketQueue.cpp
new file mode 100644 (file)
index 0000000..776c8e1
--- /dev/null
@@ -0,0 +1,332 @@
+/*
+ * AtmoPacketQueue.cpp:  works as connection between the framegrabber (color-preprocessor)
+ * and the live output thread. It works as a FIFO for the colorpackets - helps also
+ * to synchronize between grabber and liveview threads.
+ * especially if the grabber has another framerate as the liveview (25fps)
+ *
+ * See the README.txt file for copyright information and how to reach the author(s).
+ *
+ * $Id$
+ */
+
+#include "AtmoDefs.h"
+#include "AtmoPacketQueue.h"
+
+#if defined(_ATMO_VLC_PLUGIN_)
+# include <vlc/vlc.h>
+#define MAX_PACKET_TOO_LATE  -30000
+#define MAX_PACKET_TOO_EARLY  30000
+#define MIN_SLEEP_TIME        15000
+#else
+#define MAX_PACKET_TOO_LATE  -30
+#define MAX_PACKET_TOO_EARLY  30
+#define MIN_SLEEP_TIME        15
+#endif
+
+
+#if defined(_ATMO_VLC_PLUGIN_)
+
+CAtmoPacketQueue::CAtmoPacketQueue()
+{
+  m_first = NULL;
+  m_last = NULL;
+  m_waitcounter   = 0;
+  m_skipcounter   = 0;
+  m_framecounter  = 0;
+  m_nullpackets   = 0;
+
+  m_avgWait  = 0;
+  m_avgDelay = 0;
+
+  vlc_cond_init( &m_PacketArrivedCond );
+  vlc_mutex_init( &m_PacketArrivedLock );
+  vlc_mutex_init( &m_Lock );
+  m_PacketArrived = ATMO_FALSE;
+}
+
+#else
+
+CAtmoPacketQueue::CAtmoPacketQueue(CAtmoPacketQueueStatus *statusMonitor)
+{
+  m_first = NULL;
+  m_last = NULL;
+  m_waitcounter   = 0;
+  m_skipcounter   = 0;
+  m_framecounter  = 0;
+  m_nullpackets   = 0;
+
+  m_avgWait  = 0;
+  m_avgDelay = 0;
+
+  m_StatusMonitor = statusMonitor;
+
+  InitializeCriticalSection(&m_lock);
+  m_hPacketArrivedEvent = CreateEvent(NULL,ATMO_FALSE,ATMO_FALSE,NULL);
+}
+
+#endif
+
+
+CAtmoPacketQueue::~CAtmoPacketQueue(void)
+{
+  ClearQueue();
+
+#if defined(_ATMO_VLC_PLUGIN_)
+
+  vlc_cond_destroy( &m_PacketArrivedCond );
+  vlc_mutex_destroy( &m_Lock );
+
+#else
+
+  DeleteCriticalSection( &m_lock );
+  CloseHandle(m_hPacketArrivedEvent);
+  if(m_StatusMonitor)
+     m_StatusMonitor->destroyWindow();
+
+#endif
+}
+
+void CAtmoPacketQueue::Lock()
+{
+#if defined(_ATMO_VLC_PLUGIN_)
+    vlc_mutex_lock( &m_Lock );
+#else
+    EnterCriticalSection( &m_lock );
+#endif
+}
+
+void CAtmoPacketQueue::Unlock()
+{
+#if defined(_ATMO_VLC_PLUGIN_)
+    vlc_mutex_unlock( &m_Lock );
+#else
+    LeaveCriticalSection( &m_lock );
+#endif
+}
+
+void CAtmoPacketQueue::SignalEvent()
+{
+#if defined(_ATMO_VLC_PLUGIN_)
+   vlc_mutex_lock( &m_PacketArrivedLock );
+   m_PacketArrived = ATMO_TRUE;
+   vlc_cond_signal( &m_PacketArrivedCond );
+   vlc_mutex_unlock( &m_PacketArrivedLock );
+#else
+   SetEvent( m_hPacketArrivedEvent );
+#endif
+}
+
+void CAtmoPacketQueue::UnSignalEvent()
+{
+#if defined(_ATMO_VLC_PLUGIN_)
+
+#else
+   ResetEvent( m_hPacketArrivedEvent );
+#endif
+}
+
+void CAtmoPacketQueue::AddPacket(pColorPacket newPacket)
+{
+  pColorPacketItem temp = new ColorPacketItem;
+  temp->packet = newPacket;
+  temp->next = NULL;
+#if defined(_ATMO_VLC_PLUGIN_)
+  temp->tickcount = mdate();
+#else
+  temp->tickcount = GetTickCount();
+#endif
+
+  Lock();
+  if(m_last) {
+     m_last->next = temp;
+     m_last = temp;
+  } else {
+     m_last = temp;
+     m_first = temp;
+  }
+  Unlock();
+  SignalEvent();
+}
+
+pColorPacketItem CAtmoPacketQueue::GetNextPacketContainer()
+{
+  pColorPacketItem temp = NULL;
+
+  Lock();
+  if(m_first) {
+     temp      = m_first;
+     m_first   = m_first->next;
+     if(!m_first)
+        m_last = NULL;
+     temp->next = NULL;
+  }
+  Unlock();
+
+  return temp;
+}
+
+pColorPacket CAtmoPacketQueue::GetNextPacket()
+{
+  pColorPacketItem item = GetNextPacketContainer();
+  if(item) {
+     pColorPacket temp = item->packet;
+     delete item;
+     return(temp);
+  } else
+     return(NULL);
+}
+
+#if defined(_ATMO_VLC_PLUGIN_)
+void CAtmoPacketQueue::ShowQueueStatus(atmo_thread_t *p_this)
+{
+    /*
+     show some statistics for the whole time...
+    */
+    msg_Dbg( p_this, "Skipped Packets: %d", m_skipcounter );
+    if( m_skipcounter > 0 )
+        msg_Dbg( p_this, "Average Delay: %d ms", (int)(m_avgDelay/m_skipcounter)/1000 );
+    msg_Dbg( p_this, "Waited Packets: %d", m_waitcounter );
+    if( m_waitcounter > 0 )
+        msg_Dbg( p_this, "Average Wait: %d ms", (int)(m_avgWait/m_waitcounter)/1000 );
+    msg_Dbg( p_this, "Used Packets: %d", m_framecounter );
+    msg_Dbg( p_this, "Null Packets: %d", m_nullpackets );
+}
+#endif
+
+#if defined(_ATMO_VLC_PLUGIN_)
+pColorPacket CAtmoPacketQueue::GetNextPacket(mtime_t timecode, ATMO_BOOL withWait, atmo_thread_t *p_this, mtime_t &packet_time)
+#else
+pColorPacket CAtmoPacketQueue::GetNextPacket(DWORD timecode, ATMO_BOOL withWait, DWORD &packet_time)
+#endif
+{
+#if !defined(_ATMO_VLC_PLUGIN_)
+    if(timecode & 0x80000000) // GetTickCount - delay < 0 ;-)
+      return NULL;
+#endif
+
+   int timeDiff;
+
+   while(1)
+   {
+     Lock();
+     if(!m_first) {
+        Unlock();
+        break;
+     }
+     timeDiff    = m_first->tickcount - timecode;
+     packet_time = m_first->tickcount;
+     Unlock();
+
+     if(timeDiff >= MAX_PACKET_TOO_EARLY) // packet should be process in 35ms or later (usually we are to early for it)
+     {
+       if( !withWait )
+            break;
+     }
+     else
+     {
+         if(timeDiff <= MAX_PACKET_TOO_LATE) {
+            // we are more than -35ms too late for this packet, skip it and throw it away!
+#if defined(_ATMO_VLC_PLUGIN_)
+            msg_Dbg( p_this, "getNextPacket skip late %d ms", timeDiff / 1000 );
+#endif
+            pColorPacket skip = GetNextPacket();
+            delete (char *)skip;
+
+            m_skipcounter++;
+            m_avgDelay += abs(timeDiff);
+
+            continue;
+         }
+     }
+
+     if(withWait && timeDiff > MIN_SLEEP_TIME)
+     {
+          // if this is a sync call, to get in sync with frame source again we wait untils its time!
+#if defined(_ATMO_VLC_PLUGIN_)
+         msg_Dbg( p_this, "getNextPacket Sleep %d ms", timeDiff / 1000 );
+#endif
+         do_sleep( timeDiff );
+
+         m_avgWait += timeDiff;
+         m_waitcounter++;
+     }
+
+     m_framecounter++;
+#if !defined(_ATMO_VLC_PLUGIN_)
+     if(m_StatusMonitor)
+     {
+        if(withWait)
+           m_StatusMonitor->UpdateValues(m_waitcounter, m_skipcounter, m_framecounter, m_nullpackets, m_avgWait, m_avgDelay);
+     }
+#endif
+
+     return GetNextPacket();
+   }
+
+   m_nullpackets++;
+#if !defined(_ATMO_VLC_PLUGIN_)
+   if(m_StatusMonitor)
+   {
+      if(withWait)
+         m_StatusMonitor->UpdateValues(m_waitcounter, m_skipcounter, m_framecounter, m_nullpackets, m_avgWait, m_avgDelay);
+   }
+#endif
+   return NULL;
+}
+
+ATMO_BOOL CAtmoPacketQueue::WaitForNextPacket(DWORD timeout)
+{
+    UnSignalEvent();
+
+#if !defined(_ATMO_VLC_PLUGIN_)
+
+    return ( WaitForSingleObject( m_hPacketArrivedEvent, timeout ) == WAIT_OBJECT_0 );
+
+#else
+
+    mtime_t maxWait = mdate() + timeout * 1000;
+
+    vlc_mutex_lock( &m_PacketArrivedLock );
+    m_PacketArrived = ATMO_FALSE;
+    while(vlc_cond_timedwait( &m_PacketArrivedCond, &m_PacketArrivedLock, maxWait) == 0)
+    {
+      /*
+        condition was set -> but may be an old signal from previous AddPacket
+        which is still left - so if m_PacketArrived is still false, wait again
+      */
+      if(mdate() >= maxWait)
+         break;
+      if( m_PacketArrived )
+         break;
+    }
+    vlc_mutex_unlock( &m_PacketArrivedLock );
+    return m_PacketArrived;
+
+#endif
+}
+
+void CAtmoPacketQueue::ClearQueue()
+{
+  pColorPacketItem next;
+
+  Lock();
+
+  while(m_first)
+  {
+      next = m_first->next;
+      delete (char *)(m_first->packet);
+      delete m_first;
+      m_first = next;
+  }
+  m_last = NULL;
+
+  m_waitcounter   = 0;
+  m_skipcounter   = 0;
+  m_framecounter  = 0;
+
+  m_avgWait  = 0;
+  m_avgDelay = 0;
+  m_nullpackets = 0;
+
+  Unlock();
+}
diff --git a/modules/video_filter/atmo/AtmoPacketQueue.h b/modules/video_filter/atmo/AtmoPacketQueue.h
new file mode 100644 (file)
index 0000000..31ad98d
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * AtmoPacketQueue.h:  works as connection between the framegrabber (color-preprocessor)
+ * and the live output thread. It works as a FIFO for the colorpackets - helps also
+ * to synchronize between grabber and liveview threads.
+ * especially if the grabber has another framerate as the liveview (25fps)
+ *
+ * See the README.txt file for copyright information and how to reach the author(s).
+ *
+ * $Id$
+ */
+
+#ifndef _AtmoPacketQueue_
+#define _AtmoPacketQueue_
+
+#include "AtmoDefs.h"
+#include "AtmoThread.h"
+
+#if defined(_ATMO_VLC_PLUGIN_)
+#  include <vlc_common.h>
+#  include <vlc_threads.h>
+#else
+# include "AtmoPacketQueueStatus.h"
+#endif
+
+
+struct ColorPacketItem {
+    pColorPacket packet;
+#if defined(_ATMO_VLC_PLUGIN_)
+    mtime_t tickcount;
+#else
+    DWORD tickcount;
+#endif
+    ColorPacketItem *next;
+};
+typedef ColorPacketItem* pColorPacketItem;
+
+
+
+class CAtmoPacketQueue
+{
+public:
+#if defined(_ATMO_VLC_PLUGIN_)
+    CAtmoPacketQueue();
+#else
+    CAtmoPacketQueue(CAtmoPacketQueueStatus *statusMonitor);
+#endif
+    ~CAtmoPacketQueue(void);
+
+protected:
+    int m_waitcounter;
+    int m_skipcounter;
+    int m_framecounter;
+    int m_nullpackets;
+    DWORD m_avgWait;
+    DWORD m_avgDelay;
+
+#if !defined(_ATMO_VLC_PLUGIN_)
+    CAtmoPacketQueueStatus *m_StatusMonitor;
+#endif
+
+private:
+    volatile pColorPacketItem m_first;
+    volatile pColorPacketItem m_last;
+
+#if defined(_ATMO_VLC_PLUGIN_)
+    vlc_cond_t   m_PacketArrivedCond;
+    vlc_mutex_t  m_PacketArrivedLock;
+    volatile ATMO_BOOL m_PacketArrived;
+    vlc_mutex_t  m_Lock;
+#else
+    CRITICAL_SECTION m_lock;
+    HANDLE m_hPacketArrivedEvent;
+#endif
+
+private:
+    void Lock();
+    void Unlock();
+    void SignalEvent();
+    void UnSignalEvent();
+
+private:
+    pColorPacket GetNextPacket();
+    pColorPacketItem GetNextPacketContainer();
+
+public:
+    void AddPacket(pColorPacket newPacket);
+
+    // timecode = GetTickCount() - framedelay;
+#if defined(_ATMO_VLC_PLUGIN_)
+    void ShowQueueStatus(atmo_thread_t *p_this);
+    pColorPacket GetNextPacket(mtime_t timecode, ATMO_BOOL withWait, atmo_thread_t *p_this, mtime_t &packet_time );
+#else
+    pColorPacket GetNextPacket(DWORD timecode, ATMO_BOOL withWait, DWORD &packet_time );
+#endif
+
+    void ClearQueue();
+
+    ATMO_BOOL WaitForNextPacket(DWORD timeout);
+
+};
+
+#endif
index 34d8b3f10e24e8a9950c5bacebf219eea62a134c..25209ab64890996d00a5912edf02c8f3f6a0ee6f 100644 (file)
@@ -11,6 +11,7 @@
 
 CThread::CThread(vlc_object_t *pOwner)
 {
+    m_bTerminated  = ATMO_FALSE;
     m_pAtmoThread = (atmo_thread_t *)vlc_object_create( pOwner,
                                                         sizeof(atmo_thread_t) );
     if(m_pAtmoThread)
@@ -29,9 +30,12 @@ CThread::CThread(vlc_object_t *pOwner)
 
 CThread::CThread(void)
 {
+  m_bTerminated  = ATMO_FALSE;
+
   m_hThread = CreateThread(NULL, 0, CThread::ThreadProc ,
                            this, CREATE_SUSPENDED, &m_dwThreadID);
-  m_hTerminateEvent = CreateEvent(NULL,ATMO_FALSE,ATMO_FALSE,NULL);
+
+  m_hTerminateEvent = CreateEvent(NULL,0,0,NULL);
 }
 
 #endif
@@ -81,9 +85,9 @@ void *CThread::ThreadProc(vlc_object_t *obj)
 
 DWORD WINAPI CThread::ThreadProc(LPVOID lpParameter)
 {
-          CThread *aThread = (CThread *)lpParameter;
-          if(aThread)
-             return aThread->Execute();
+          CThread *pThread = (CThread *)lpParameter;
+          if(pThread)
+             return pThread->Execute();
           else
                  return (DWORD)-1;
 }
@@ -107,19 +111,20 @@ 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 );
+      m_bTerminated = ATMO_TRUE;
       vlc_cond_signal( &m_TerminateCond  );
       vlc_mutex_unlock( &m_TerminateLock );
-      vlc_object_kill( m_pAtmoThread );
 
+      vlc_object_kill( m_pAtmoThread );
       vlc_thread_join( m_pAtmoThread );
    }
 #else
+   m_bTerminated = ATMO_TRUE;
    SetEvent(m_hTerminateEvent);
    WaitForSingleObject(m_hThread,INFINITE);
 #endif
@@ -154,12 +159,14 @@ void CThread::Run()
 ATMO_BOOL CThread::ThreadSleep(DWORD millisekunden)
 {
 #if defined(_ATMO_VLC_PLUGIN_)
+     ATMO_BOOL temp;
      vlc_mutex_lock( &m_TerminateLock );
-     int value = vlc_cond_timedwait(&m_TerminateCond,
-                                    &m_TerminateLock,
-                                    mdate() + (mtime_t)(millisekunden * 1000));
+     vlc_cond_timedwait(&m_TerminateCond,
+                        &m_TerminateLock,
+                        mdate() + (mtime_t)(millisekunden * 1000));
+     temp = m_bTerminated;
      vlc_mutex_unlock( &m_TerminateLock );
-     return (value != 0);
+     return !temp;
 
 #else
      DWORD res = WaitForSingleObject(m_hTerminateEvent,millisekunden);
index 91e41c7a11b939d64b3b4677349178a8c8404ce1..69e07739ccd2e6a66394e24684b53c4457cff89e 100644 (file)
@@ -7,14 +7,24 @@
  */
 
 #include "AtmoTools.h"
+#include "AtmoDynData.h"
 #include "AtmoLiveView.h"
-#include "AtmoSerialConnection.h"
+#include "AtmoClassicConnection.h"
+#include "AtmoDmxSerialConnection.h"
+#include "AtmoMultiConnection.h"
+#include "MoMoConnection.h"
+#include "AtmoExternalCaptureInput.h"
+#include <math.h>
 
 #if !defined(_ATMO_VLC_PLUGIN_)
 #   include "AtmoColorChanger.h"
 #   include "AtmoLeftRightColorChanger.h"
+
 #   include "AtmoDummyConnection.h"
-#   include "AtmoDmxSerialConnection.h"
+#   include "AtmoNulConnection.h"
+#   include "MondolightConnection.h"
+
+#   include "AtmoGdiDisplayCaptureInput.h"
 #endif
 
 
@@ -30,22 +40,31 @@ 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;
+    if((atmoConnection != NULL) && (atmoConfig!=NULL) && atmoConfig->isSetShutdownColor()) {
+       int i;
+       pColorPacket packet;
+       AllocColorPacket(packet, atmoConfig->getZoneCount());
+
        // 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);
-               }
+       for(i = 0; i < packet->numColors; i++) {
+           packet->zone[i].r = atmoConfig->getShutdownColor_Red();
+           packet->zone[i].g = atmoConfig->getShutdownColor_Green();
+           packet->zone[i].b = atmoConfig->getShutdownColor_Blue();
        }
+
+       packet = CAtmoTools::ApplyGamma(atmoConfig, packet);
+
+       if(atmoConfig->isUseSoftwareWhiteAdj())
+          packet = CAtmoTools::WhiteCalibration(atmoConfig, packet);
+
+       atmoConnection->SendData(packet);
+
+       delete (char *)packet;
+
        }
 
     pDynData->UnLockCriticalSection();
@@ -68,15 +87,40 @@ EffectMode CAtmoTools::SwitchEffect(CAtmoDynData *pDynData, EffectMode newEffect
 
     EffectMode oldEffectMode = atmoConfig->getEffectMode();
     CThread *currentEffect = pDynData->getEffectThread();
+    CAtmoInput *currentInput = pDynData->getLiveInput();
+    CAtmoPacketQueue *currentPacketQueue = pDynData->getLivePacketQueue();
+
+
+    if(oldEffectMode == emLivePicture) {
+        /* in case of disabling the live mode
+           first we have to stop the input
+           then the effect thread!
+        */
+        if(currentInput != NULL) {
+           pDynData->setLiveInput( NULL );
+           currentInput->Close();
+           delete currentInput;
+           currentInput = NULL;
+        }
+    }
 
     // stop and delete/cleanup current Effect Thread...
-    pDynData->setEffectThread(NULL);
-    if(currentEffect!=NULL) {
+    pDynData->setEffectThread( NULL );
+    if(currentEffect != NULL) {
        currentEffect->Terminate();
        delete currentEffect;
        currentEffect = NULL;
     }
 
+    if(oldEffectMode == emLivePicture) {
+       /*
+         and last we kill the PacketQueue used for communication between the threads
+       */
+       pDynData->setLivePacketQueue( NULL );
+       delete currentPacketQueue;
+       currentPacketQueue = NULL;
+    }
+
     if((atmoConnection!=NULL) && (atmoConnection->isOpen()==ATMO_TRUE)) {
         // neuen EffectThread nur mit aktiver Connection starten...
 
@@ -84,28 +128,54 @@ EffectMode CAtmoTools::SwitchEffect(CAtmoDynData *pDynData, EffectMode newEffect
             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 emStaticColor: {
+                 // get values from config - and put them to all channels?
+                 pColorPacket packet;
+                 AllocColorPacket(packet, atmoConfig->getZoneCount());
+                 for(int i=0; i < packet->numColors; i++){
+                     packet->zone[i].r = atmoConfig->getStaticColor_Red();
+                     packet->zone[i].g = atmoConfig->getStaticColor_Green();
+                     packet->zone[i].b = atmoConfig->getStaticColor_Blue();
+                 }
+
+                 packet = CAtmoTools::ApplyGamma( atmoConfig, packet );
+
+                 if(atmoConfig->isUseSoftwareWhiteAdj())
+                    packet = CAtmoTools::WhiteCalibration(atmoConfig, packet);
+
+                 atmoConnection->SendData( packet );
 
-            case emLivePicture:
+                 delete (char *)packet;
+
+                 break;
+             }
+
+            case emLivePicture: {
                 currentEffect = new CAtmoLiveView(pDynData);
+
+#if !defined(_ATMO_VLC_PLUGIN_)
+                CAtmoPacketQueueStatus *packetMon = NULL;
+                if(atmoConfig->getShow_statistics()) {
+                   packetMon = new CAtmoPacketQueueStatus(pDynData->getHinstance(), (HWND)NULL);
+                   packetMon->createWindow();
+                   packetMon->showWindow(SW_SHOW);
+                }
+                currentPacketQueue = new CAtmoPacketQueue(packetMon);
+                pDynData->setLivePictureSource(lpsScreenCapture);
+                currentInput = new CAtmoGdiDisplayCaptureInput( pDynData );
+#else
+                currentPacketQueue = new CAtmoPacketQueue();
+                pDynData->setLivePictureSource(lpsExtern);
+                currentInput = new CAtmoExternalCaptureInput( pDynData );
+#endif
                 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;
@@ -114,23 +184,68 @@ EffectMode CAtmoTools::SwitchEffect(CAtmoDynData *pDynData, EffectMode newEffect
 
     }
 
-    atmoConfig->setEffectMode(newEffectMode);
+    atmoConfig->setEffectMode( newEffectMode );
 
-    pDynData->setEffectThread(currentEffect);
+    pDynData->setLivePacketQueue( currentPacketQueue );
+    pDynData->setEffectThread( currentEffect );
+    pDynData->setLiveInput( currentInput );
 
-    if(currentEffect!=NULL)
+    if(currentEffect != NULL)
        currentEffect->Run();
+    if(currentInput != NULL)
+       currentInput->Open();
 
     pDynData->UnLockCriticalSection();
     return oldEffectMode;
 }
 
+LivePictureSource CAtmoTools::SwitchLiveSource(CAtmoDynData *pDynData, LivePictureSource newLiveSource)
+{
+    LivePictureSource oldSource;
+    pDynData->LockCriticalSection();
+
+    oldSource = pDynData->getLivePictureSource();
+    pDynData->setLivePictureSource( newLiveSource );
+
+    if ((pDynData->getAtmoConfig()->getEffectMode() == emLivePicture) &&
+        (pDynData->getEffectThread() != NULL) &&
+        (pDynData->getLivePacketQueue() != NULL))
+    {
+        CAtmoInput *input = pDynData->getLiveInput();
+        pDynData->setLiveInput( NULL );
+        if(input != NULL) {
+            input->Close();
+            delete input;
+            input = NULL;
+        }
+
+        switch(pDynData->getLivePictureSource()) {
+#if !defined(_ATMO_VLC_PLUGIN_)
+               case lpsScreenCapture:
+                    input = new CAtmoGdiDisplayCaptureInput( pDynData );
+               break;
+#endif
+               case lpsExtern:
+                    input = new CAtmoExternalCaptureInput( pDynData );
+               break;
+        }
+
+        pDynData->setLiveInput( input );
+        if(input != NULL)
+           input->Open();
+    }
+
+    pDynData->UnLockCriticalSection();
+    return oldSource;
+}
+
 ATMO_BOOL CAtmoTools::RecreateConnection(CAtmoDynData *pDynData)
 {
     pDynData->LockCriticalSection();
 
     CAtmoConnection *current = pDynData->getAtmoConnection();
-    AtmoConnectionType act = pDynData->getAtmoConfig()->getConnectionType();
+    CAtmoConfig *atmoConfig = pDynData->getAtmoConfig();
+    AtmoConnectionType act = atmoConfig->getConnectionType();
     pDynData->setAtmoConnection(NULL);
     if(current != NULL) {
        current->CloseConnection();
@@ -138,67 +253,155 @@ ATMO_BOOL CAtmoTools::RecreateConnection(CAtmoDynData *pDynData)
     }
 
     switch(act) {
-           case actSerialPort: {
-               CAtmoSerialConnection *tempConnection = new CAtmoSerialConnection(pDynData->getAtmoConfig());
+           case actClassicAtmo: {
+               CAtmoClassicConnection *tempConnection = new CAtmoClassicConnection( atmoConfig );
                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);
+                  if(atmoConfig->getIgnoreConnectionErrorOnStartup() == ATMO_FALSE)
+                  {
+                        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->setAtmoConnection(tempConnection);
 
                   pDynData->UnLockCriticalSection();
                   return ATMO_FALSE;
                }
                pDynData->setAtmoConnection(tempConnection);
+               pDynData->ReloadZoneDefinitionBitmaps();
+
+               tempConnection->CreateDefaultMapping(atmoConfig->getChannelAssignment(0));
 
                CAtmoTools::SetChannelAssignment(pDynData,
-                           pDynData->getAtmoConfig()->getCurrentChannelAssignment());
+                                                atmoConfig->getCurrentChannelAssignment());
 
                pDynData->UnLockCriticalSection();
                return ATMO_TRUE;
            }
 
 #if !defined(_ATMO_VLC_PLUGIN_)
-           case actDummy: {
+           case actDummy:
+           {
+               // actDummy8,actDummy12,actDummy16
                CAtmoDummyConnection *tempConnection = new CAtmoDummyConnection(pDynData->getHinstance(),
-                                                                               pDynData->getAtmoConfig());
+                                                                               atmoConfig);
                if(tempConnection->OpenConnection() == ATMO_FALSE) {
-                  delete tempConnection;
-
+                  pDynData->setAtmoConnection(tempConnection);
                   pDynData->UnLockCriticalSection();
                   return ATMO_FALSE;
                }
                pDynData->setAtmoConnection(tempConnection);
+               pDynData->ReloadZoneDefinitionBitmaps();
+
+               tempConnection->CreateDefaultMapping(atmoConfig->getChannelAssignment(0));
 
                CAtmoTools::SetChannelAssignment(pDynData, pDynData->getAtmoConfig()->getCurrentChannelAssignment());
 
                pDynData->UnLockCriticalSection();
                return ATMO_TRUE;
            }
+#endif
 
            case actDMX: {
                // create here your DMX connections... instead of the dummy....
-               CAtmoDmxSerialConnection *tempConnection = new CAtmoDmxSerialConnection(pDynData->getAtmoConfig());
+               CAtmoDmxSerialConnection *tempConnection = new CAtmoDmxSerialConnection( atmoConfig );
                if(tempConnection->OpenConnection() == ATMO_FALSE) {
-                  delete tempConnection;
+                  pDynData->setAtmoConnection(tempConnection);
 
                   pDynData->UnLockCriticalSection();
                   return ATMO_FALSE;
                }
                pDynData->setAtmoConnection(tempConnection);
+               pDynData->ReloadZoneDefinitionBitmaps();
 
-               CAtmoTools::SetChannelAssignment(pDynData, pDynData->getAtmoConfig()->getCurrentChannelAssignment());
+               tempConnection->CreateDefaultMapping(atmoConfig->getChannelAssignment(0));
+
+               CAtmoTools::SetChannelAssignment(pDynData, atmoConfig->getCurrentChannelAssignment());
+
+               pDynData->UnLockCriticalSection();
+               return ATMO_TRUE;
+           }
+
+#if !defined(_ATMO_VLC_PLUGIN_)
+           case actNUL: {
+               CAtmoNulConnection *tempConnection = new CAtmoNulConnection( atmoConfig );
+               if(tempConnection->OpenConnection() == ATMO_FALSE) {
+                  pDynData->setAtmoConnection(tempConnection);
+                  pDynData->UnLockCriticalSection();
+                  return ATMO_FALSE;
+               }
+               pDynData->setAtmoConnection(tempConnection);
+               pDynData->ReloadZoneDefinitionBitmaps();
+
+               tempConnection->CreateDefaultMapping(atmoConfig->getChannelAssignment(0));
+
+               CAtmoTools::SetChannelAssignment(pDynData, atmoConfig->getCurrentChannelAssignment());
+
+               pDynData->UnLockCriticalSection();
+               return ATMO_TRUE;
+           }
+#endif
+
+           case actMultiAtmo: {
+               CAtmoMultiConnection *tempConnection = new CAtmoMultiConnection( atmoConfig );
+               if(tempConnection->OpenConnection() == ATMO_FALSE) {
+                  pDynData->setAtmoConnection(tempConnection);
+                  pDynData->UnLockCriticalSection();
+                  return ATMO_FALSE;
+               }
+               pDynData->setAtmoConnection(tempConnection);
+               pDynData->ReloadZoneDefinitionBitmaps();
+
+               tempConnection->CreateDefaultMapping(atmoConfig->getChannelAssignment(0));
+
+               CAtmoTools::SetChannelAssignment(pDynData, atmoConfig->getCurrentChannelAssignment());
+
+               pDynData->UnLockCriticalSection();
+               return ATMO_TRUE;
+           }
+
+#if !defined(_ATMO_VLC_PLUGIN_)
+           case actMondolight: {
+               CMondolightConnection *tempConnection = new CMondolightConnection( atmoConfig );
+               if(tempConnection->OpenConnection() == ATMO_FALSE) {
+                  pDynData->setAtmoConnection(tempConnection);
+                  pDynData->UnLockCriticalSection();
+                  return ATMO_FALSE;
+               }
+               pDynData->setAtmoConnection(tempConnection);
+               pDynData->ReloadZoneDefinitionBitmaps();
+
+               tempConnection->CreateDefaultMapping(atmoConfig->getChannelAssignment(0));
+
+               CAtmoTools::SetChannelAssignment(pDynData, atmoConfig->getCurrentChannelAssignment());
 
                pDynData->UnLockCriticalSection();
                return ATMO_TRUE;
            }
 #endif
+           case actMoMoLight: {
+               CMoMoConnection *tempConnection = new CMoMoConnection( atmoConfig );
+               if(tempConnection->OpenConnection() == ATMO_FALSE) {
+                  pDynData->setAtmoConnection(tempConnection);
+                  pDynData->UnLockCriticalSection();
+                  return ATMO_FALSE;
+               }
+               pDynData->setAtmoConnection(tempConnection);
+               pDynData->ReloadZoneDefinitionBitmaps();
+
+               tempConnection->CreateDefaultMapping( atmoConfig->getChannelAssignment(0) );
+
+               CAtmoTools::SetChannelAssignment(pDynData, atmoConfig->getCurrentChannelAssignment() );
+
+               pDynData->UnLockCriticalSection();
+               return ATMO_TRUE;
+           }
 
            default: {
                pDynData->UnLockCriticalSection();
@@ -207,22 +410,64 @@ ATMO_BOOL CAtmoTools::RecreateConnection(CAtmoDynData *pDynData)
     }
 }
 
-tColorPacket CAtmoTools::WhiteCalibration(CAtmoConfig *pAtmoConfig, tColorPacket ColorPacket)
+pColorPacket CAtmoTools::WhiteCalibration(CAtmoConfig *pAtmoConfig, pColorPacket 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);
+    for (int i = 0; i < ColorPacket->numColors; i++)  {
+        ColorPacket->zone[i].r = (unsigned char)(((int)w_adj_red   * (int)ColorPacket->zone[i].r) / 255);
+        ColorPacket->zone[i].g = (unsigned char)(((int)w_adj_green * (int)ColorPacket->zone[i].g) / 255);
+        ColorPacket->zone[i].b = (unsigned char)(((int)w_adj_blue  * (int)ColorPacket->zone[i].b) / 255);
     }
     return ColorPacket;
 }
 
-tColorPacket CAtmoTools::ApplyGamma(CAtmoConfig *pAtmoConfig, tColorPacket ColorPacket)
+pColorPacket CAtmoTools::ApplyGamma(CAtmoConfig *pAtmoConfig, pColorPacket ColorPacket)
 {
+  double v;
+  switch(pAtmoConfig->getSoftware_gamma_mode()) {
+    case agcNone: break;
+    case agcPerColor: {
+        double GammaRed   = 10.0 / ((double)pAtmoConfig->getSoftware_gamma_red());
+        double GammaGreen = 10.0 / ((double)pAtmoConfig->getSoftware_gamma_green());
+        double GammaBlue  = 10.0 / ((double)pAtmoConfig->getSoftware_gamma_blue());
+        for (int i = 0; i < ColorPacket->numColors; i++)
+        {
+          v = ColorPacket->zone[i].r;
+          v = (pow( v / 255.0f, GammaRed ) * 255.0f);
+          ColorPacket->zone[i].r = ATMO_MIN((int)v, 255);
+
+          v = ColorPacket->zone[i].g;
+          v = (pow( v / 255.0f, GammaGreen ) * 255.0f);
+          ColorPacket->zone[i].g = ATMO_MIN((int)v, 255);
+
+          v = ColorPacket->zone[i].b;
+          v = (pow( v / 255.0f, GammaBlue ) * 255.0f);
+          ColorPacket->zone[i].b = ATMO_MIN((int)v, 255);
+        }
+        break;
+    }
+    case agcGlobal:   {
+        double Gamma   = 10.0 / ((double)pAtmoConfig->getSoftware_gamma_global());
+        for (int i = 0; i < ColorPacket->numColors; i++)
+        {
+          v = ColorPacket->zone[i].r;
+          v = (pow( v / 255.0f, Gamma ) * 255.0f);
+          ColorPacket->zone[i].r = ATMO_MIN((int)v, 255);
+
+          v = ColorPacket->zone[i].g;
+          v = (pow( v / 255.0f, Gamma ) * 255.0f);
+          ColorPacket->zone[i].g = ATMO_MIN((int)v, 255);
+
+          v = ColorPacket->zone[i].b;
+          v = (pow( v / 255.0f, Gamma ) * 255.0f);
+          ColorPacket->zone[i].b = ATMO_MIN((int)v, 255);
+        }
+        break;
+    }
+  }
   return ColorPacket;
 }
 
@@ -232,7 +477,7 @@ int CAtmoTools::SetChannelAssignment(CAtmoDynData *pDynData, int index)
     CAtmoConnection *pAtmoConnection = pDynData->getAtmoConnection();
     int oldIndex = pAtmoConfig->getCurrentChannelAssignment();
 
-    tChannelAssignment *ca = pAtmoConfig->getChannelAssignment(index);
+    CAtmoChannelAssignment *ca = pAtmoConfig->getChannelAssignment(index);
     if((ca!=NULL) && (pAtmoConnection!=NULL)) {
         pAtmoConnection->SetChannelAssignment(ca);
         pAtmoConfig->setCurrentChannelAssignment(index);
@@ -261,11 +506,7 @@ void CAtmoTools::SaveBitmap(HDC hdc,HBITMAP hBmp,char *fileName) {
      bmpFileHeader.bfReserved1=0;
      bmpFileHeader.bfReserved2=0;
      bmpFileHeader.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+bmpInfo.bmiHeader.biSizeImage;
-#ifdef _ATMO_VLC_PLUGIN_
-     bmpFileHeader.bfType = VLC_TWOCC('M','B');
-#else
-     bmpFileHeader.bfType = MakeWord('M','B');
-#endif
+     bmpFileHeader.bfType = MakeIntelWord('M','B');
      bmpFileHeader.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
 
 
@@ -277,5 +518,7 @@ void CAtmoTools::SaveBitmap(HDC hdc,HBITMAP hBmp,char *fileName) {
      fclose(fp);
 }
 
+
+
 #endif
 
index d80ea0760bdf70ac2dfbf41aa72803e411b7e842..106201adb95b5a4c387489394959e2b6ffdeac0b 100644 (file)
@@ -26,11 +26,13 @@ private:
     ~CAtmoTools(void);
 public:
     static EffectMode SwitchEffect(CAtmoDynData *pDynData, EffectMode newEffectMode);
+    static LivePictureSource SwitchLiveSource(CAtmoDynData *pDynData, LivePictureSource newLiveSource);
+
     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 pColorPacket WhiteCalibration(CAtmoConfig *pAtmoConfig, pColorPacket ColorPacket);
+    static pColorPacket ApplyGamma(CAtmoConfig *pAtmoConfig, pColorPacket ColorPacket);
 
     static int SetChannelAssignment(CAtmoDynData *pDynData, int index);
 
index d2dc1625c3a46be41154bfb3fc0086d0231215db..df3964279e627108b7bffdbaaa7e814d602582a8 100644 (file)
@@ -25,12 +25,14 @@ void CAtmoZoneDefinition::Fill(unsigned char value)
       m_BasicWeight[i] = value;
 }
 
+
 // max weight to left
-void CAtmoZoneDefinition::FillGradientFromLeft()
+void CAtmoZoneDefinition::FillGradientFromLeft(int start_row,int end_row)
 {
-   int index = 0;
+   int index;
    unsigned char col_norm;
-   for(int row=0; row < CAP_HEIGHT; row++) {
+   index = start_row * CAP_WIDTH;
+   for(int row=start_row; row < end_row; 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);
@@ -40,11 +42,12 @@ void CAtmoZoneDefinition::FillGradientFromLeft()
 }
 
 // max weight to right
-void CAtmoZoneDefinition::FillGradientFromRight()
+void CAtmoZoneDefinition::FillGradientFromRight(int start_row,int end_row)
 {
-   int index = 0;
+   int index;
    unsigned char col_norm;
-   for(int row=0; row < CAP_HEIGHT; row++) {
+   index = start_row * CAP_WIDTH;
+   for(int row=start_row; row < end_row; 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;
@@ -53,31 +56,131 @@ void CAtmoZoneDefinition::FillGradientFromRight()
 }
 
 // max weight from top
-void CAtmoZoneDefinition::FillGradientFromTop()
+void CAtmoZoneDefinition::FillGradientFromTop(int start_col,int end_col)
 {
-   int index = 0;
+   int index;
    unsigned char row_norm;
+
    for(int row=0; row < CAP_HEIGHT; row++) {
+       index = row * CAP_WIDTH + start_col;
+
        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++) {
+       for(int col=start_col; col < end_col; col++) {
            m_BasicWeight[index++] = row_norm;
        }
    }
 }
 
 // max weight from bottom
-void CAtmoZoneDefinition::FillGradientFromBottom()
+void CAtmoZoneDefinition::FillGradientFromBottom(int start_col,int end_col)
 {
-   int index = 0;
+   int index;
    unsigned char row_norm;
    for(int row=0; row < CAP_HEIGHT; row++) {
+       index = row * CAP_WIDTH + start_col;
        row_norm = (255 * row) / (CAP_HEIGHT-1); // should be a value between 0 .. 255?
-       for(int col=0; col < CAP_WIDTH; col++) {
+       for(int col=start_col; col < end_col; col++) {
            m_BasicWeight[index++] = row_norm;
        }
    }
 }
 
+#if !defined(_ATMO_VLC_PLUGIN_)
+
+void CAtmoZoneDefinition::SaveZoneBitmap(char *fileName)
+{
+     if(!fileName) return;
+
+     BITMAPINFO bmpInfo;
+     // BITMAPINFOHEADER
+     BITMAPFILEHEADER  bmpFileHeader;
+     ZeroMemory(&bmpInfo, sizeof(BITMAPINFO));
+     bmpInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
+
+
+     bmpInfo.bmiHeader.biHeight = -CAP_HEIGHT;
+     bmpInfo.bmiHeader.biWidth  = CAP_WIDTH;
+     bmpInfo.bmiHeader.biSizeImage = abs(bmpInfo.bmiHeader.biHeight) * bmpInfo.bmiHeader.biWidth * 3;
+
+     unsigned char *pBuf = (unsigned char *)malloc(bmpInfo.bmiHeader.biSizeImage);
+     for(int y=0; y < CAP_HEIGHT; y++ )
+     {
+         for(int x=0; x < CAP_WIDTH; x++)
+         {
+             pBuf[y * CAP_WIDTH * 3 + x * 3 ] = 0;
+             pBuf[y * CAP_WIDTH * 3 + x * 3 + 1 ] = m_BasicWeight[y * CAP_WIDTH + x];
+             pBuf[y * CAP_WIDTH * 3 + x * 3 + 2] = 0;
+         }
+     }
+
+     bmpInfo.bmiHeader.biCompression = BI_RGB;
+     bmpInfo.bmiHeader.biPlanes = 1;
+     bmpInfo.bmiHeader.biBitCount = 24;
+
+     bmpFileHeader.bfReserved1=0;
+     bmpFileHeader.bfReserved2=0;
+     bmpFileHeader.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+bmpInfo.bmiHeader.biSizeImage;
+     bmpFileHeader.bfType = MakeIntelWord('M','B');
+     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);
+}
+
+void CAtmoZoneDefinition::SaveWeightBitmap(char *fileName,int *weight)
+{
+     if(!fileName || !weight) return;
+
+     BITMAPINFO bmpInfo;
+     // BITMAPINFOHEADER
+     BITMAPFILEHEADER  bmpFileHeader;
+     ZeroMemory(&bmpInfo, sizeof(BITMAPINFO));
+     bmpInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
+
+
+     bmpInfo.bmiHeader.biHeight = -CAP_HEIGHT;
+     bmpInfo.bmiHeader.biWidth  = CAP_WIDTH;
+     bmpInfo.bmiHeader.biSizeImage = abs(bmpInfo.bmiHeader.biHeight) * bmpInfo.bmiHeader.biWidth * 3;
+
+     unsigned char *pBuf = (unsigned char *)malloc(bmpInfo.bmiHeader.biSizeImage);
+     for(int y=0; y < CAP_HEIGHT; y++ )
+     {
+         for(int x=0; x < CAP_WIDTH; x++)
+         {
+             pBuf[y * CAP_WIDTH * 3 + x * 3 ] = 0;
+             pBuf[y * CAP_WIDTH * 3 + x * 3 + 1 ] = (unsigned char)weight[y * CAP_WIDTH + x];
+             pBuf[y * CAP_WIDTH * 3 + x * 3 + 2] = 0;
+         }
+     }
+
+     bmpInfo.bmiHeader.biCompression = BI_RGB;
+     bmpInfo.bmiHeader.biPlanes = 1;
+     bmpInfo.bmiHeader.biBitCount = 24;
+
+     bmpFileHeader.bfReserved1=0;
+     bmpFileHeader.bfReserved2=0;
+     bmpFileHeader.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+bmpInfo.bmiHeader.biSizeImage;
+     bmpFileHeader.bfType = MakeIntelWord('M','B');
+     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
+
+
 
 int CAtmoZoneDefinition::LoadGradientFromBitmap(char *pszBitmap)
 {
@@ -88,6 +191,7 @@ int CAtmoZoneDefinition::LoadGradientFromBitmap(char *pszBitmap)
   BITMAPFILEHEADER  bmpFileHeader;
 
   /*
+  ATMO_LOAD_GRADIENT_FILENOTFOND
 #define ATMO_LOAD_GRADIENT_OK  0
 #define ATMO_LOAD_GRADIENT_FAILED_SIZE    1
 #define ATMO_LOAD_GRADIENT_FAILED_HEADER  2
@@ -96,18 +200,15 @@ int CAtmoZoneDefinition::LoadGradientFromBitmap(char *pszBitmap)
 
    FILE *bmp = fopen(pszBitmap, "rb");
    if(!bmp)
-     return ATMO_LOAD_GRADIENT_FILENOTFOND;
+    return ATMO_LOAD_GRADIENT_FILENOTFOND;
 
     if(fread(&bmpFileHeader, sizeof(BITMAPFILEHEADER), 1, bmp) != 1)
     {
         fclose(bmp);
         return ATMO_LOAD_GRADIENT_FAILED_SIZE;
     }
-#ifdef _ATMO_VLC_PLUGIN_
-    if(bmpFileHeader.bfType != VLC_TWOCC('M','B'))
-#else
-    if(bmpFileHeader.bfType != MakeWord('M','B'))
-#endif
+
+    if(bmpFileHeader.bfType != MakeIntelWord('M','B'))
     {
         fclose(bmp);
         return ATMO_LOAD_GRADIENT_FAILED_HEADER;
index 96c798f39cee7d5f91401cae6b6e6bffa77e65fb..99cadc5f1c21aaa98d3094abd6dac4f765adaa63 100644 (file)
@@ -21,12 +21,16 @@ public:
     ~CAtmoZoneDefinition(void);
 
     void Fill(unsigned char value);
-    void FillGradientFromLeft();
-    void FillGradientFromRight();
-    void FillGradientFromTop();
-    void FillGradientFromBottom();
+    void FillGradientFromLeft(int start_row,int end_row);
+    void FillGradientFromRight(int start_row,int end_row);
+    void FillGradientFromTop(int start_col,int end_col);
+    void FillGradientFromBottom(int start_col,int end_col);
 
     int LoadGradientFromBitmap(char *pszBitmap);
+#if !defined(_ATMO_VLC_PLUGIN_)
+    void SaveZoneBitmap(char *);
+    void SaveWeightBitmap(char *fileName,int *weight);
+#endif
 
     void UpdateWeighting(int *destWeight,
                          int WidescreenMode,
diff --git a/modules/video_filter/atmo/DmxTools.cpp b/modules/video_filter/atmo/DmxTools.cpp
new file mode 100644 (file)
index 0000000..9854ceb
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * DmxTools.cpp: functions to convert , or ; seperatered numbers into an integer array
+ *
+ * See the README.txt file for copyright information and how to reach the author(s).
+ *
+ * $Id$
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "DmxTools.h"
+
+int IsValidDmxStartString(char *startChannels)
+{
+  if(!startChannels) return -1;
+
+  char channel[16];
+  int tmp;
+  int ch = 0;
+  int i = 0;
+
+  while(*startChannels) {
+      if(*startChannels == ',' || *startChannels == ';') {
+         if(i > 0) {
+            channel[i] = 0;
+            // atoi ?
+            tmp = atoi(channel);
+            if((tmp >= 0) && (tmp<=253))
+                ch++;
+            else
+                return -2; // invalid channel number!
+            i = 0;
+         }
+      }
+      else
+      {
+        if((*startChannels >= '0') && (*startChannels <= '9')) {
+            if(i < 3)
+                channel[i++] = *startChannels;
+            else
+                return -3; // invalid index length!
+        } else {
+            if(*startChannels != ' ') {
+                return -4; // invalid character found!
+            }
+        }
+      }
+      startChannels++;
+  }
+
+  // process the rest (or last channel)
+  if(!*startChannels && (i>0)) {
+      channel[i] = 0;
+      tmp = atoi(channel);
+      if((tmp >= 0) && (tmp<=253)) {
+         ch++;
+      } else
+         return -2;
+  }
+
+  return ch;
+}
+
+int *ConvertDmxStartChannelsToInt(int numChannels, char *startChannels)
+{
+  if(!numChannels || !startChannels) return NULL;
+  int *channels = new int[numChannels + 1];
+  // tmp buffer to store channel number!
+  char channel[16];
+  int next_dmx_ch = 0;
+  int tmp;
+  int ch = 0;
+  int i = 0;
+
+  while(*startChannels) {
+      if(*startChannels == ',' || *startChannels == ';') {
+         if(i > 0) {
+            channel[i] = 0;
+            // atoi ?
+            tmp = atoi(channel);
+            if((tmp >= 0) && (tmp<=253)) {
+                next_dmx_ch = tmp + 3;
+                channels[ch++] = tmp;
+                if(ch == numChannels)
+                   break;
+            } else
+                break;
+            i = 0;
+         }
+      }
+      if((*startChannels >= '0') && (*startChannels <= '9')) {
+         if(i < 3)
+            channel[i++] = *startChannels;
+         else
+            break;
+      }
+      startChannels++;
+  }
+
+  if(!*startChannels && (i>0)) {
+      channel[i] = 0;
+      tmp = atoi(channel);
+      if((tmp >= 0) && (tmp<=253)) {
+         next_dmx_ch = tmp + 3;
+         channels[ch++] = tmp;
+      }
+  }
+  //
+  // fillup the array with the logical next dmx channels - for simple devices that should work!
+  //
+  while(ch < numChannels) {
+        if(next_dmx_ch>253) next_dmx_ch=0; // wrap arround :) better than indexing memory out of range
+        channels[ch++] = next_dmx_ch;
+        next_dmx_ch += 3;
+  }
+  channels[ch++] = -1; // last Entry :)
+
+  return channels;
+}
+
+char *ConvertDmxStartChannelsToString(int numChannels, int *startChannels)
+{
+  // maxBufSize worst case having numChannels 256 each 3 digits Adress and one colon 256*4 bytes + zero byte
+  char tmp[1025];
+  // fuck up! (should not happen)
+  if(numChannels > 256) return NULL;
+
+
+  char *psz_tmp = tmp;
+  for(int i = 0; i < numChannels; i++) {
+      if(startChannels[i] == -1) break;
+      if(i > 0) {
+         *psz_tmp = ',';
+         psz_tmp++;
+         *psz_tmp = 0;
+      }
+      int n = sprintf(psz_tmp, "%d", startChannels[i] );
+      if(n > 0)
+         psz_tmp += n;
+  }
+
+  return strdup(tmp);
+}
+
diff --git a/modules/video_filter/atmo/DmxTools.h b/modules/video_filter/atmo/DmxTools.h
new file mode 100644 (file)
index 0000000..a714bc9
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+* DmxTools.h: functions to convert , or ; seperatered numbers into an integer array
+ *
+ * See the README.txt file for copyright information and how to reach the author(s).
+ *
+ * $Id$
+ */
+
+#ifndef _dmxtools_h_
+#define _dmxtools_h_
+
+int *ConvertDmxStartChannelsToInt(int numChannels, char *startChannels);
+char *ConvertDmxStartChannelsToString(int numChannels, int *startChannels);
+int IsValidDmxStartString(char *startChannels);
+
+#endif
diff --git a/modules/video_filter/atmo/MoMoConnection.cpp b/modules/video_filter/atmo/MoMoConnection.cpp
new file mode 100644 (file)
index 0000000..97c21c5
--- /dev/null
@@ -0,0 +1,236 @@
+/*
+ * 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 "MoMoConnection.h"
+
+#if !defined(_ATMO_VLC_PLUGIN_)
+# include "MoMoConfigDialog.h"
+#endif
+
+#include <stdio.h>
+#include <fcntl.h>
+
+#if !defined(WIN32)
+#include <termios.h>
+#include <unistd.h>
+#endif
+
+
+CMoMoConnection::CMoMoConnection(CAtmoConfig *cfg) : CAtmoConnection(cfg) {
+    m_hComport = INVALID_HANDLE_VALUE;
+}
+
+CMoMoConnection::~CMoMoConnection() {
+}
+
+ATMO_BOOL CMoMoConnection::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 serdevice[16];  // com4294967295
+     sprintf(serdevice,"com%d",portNummer);
+#endif
+
+#if defined(WIN32)
+
+     m_hComport = CreateFile(serdevice, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
+     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  = 9600;        // 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 = B9600;
+     m_hComport = open(serdevice,O_RDWR |O_NOCTTY);
+     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 CMoMoConnection::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 CMoMoConnection::isOpen(void) {
+        return (m_hComport != INVALID_HANDLE_VALUE);
+}
+
+ATMO_BOOL CMoMoConnection::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 ATMO_FALSE;
+}
+
+
+ATMO_BOOL CMoMoConnection::SendData(pColorPacket data) {
+   if(m_hComport == INVALID_HANDLE_VALUE)
+         return ATMO_FALSE;
+
+   int channels = getNumChannels();
+   DWORD bufSize = channels * 3;
+   unsigned char *buffer = new unsigned char[ bufSize ];
+   DWORD iBytesWritten;
+
+   Lock();
+   int i_red   = 0;
+   int i_green = channels;
+   int i_blue  = channels * 2;
+   int idx;
+   /*
+     3 ch
+     i_red = 0, i_green = 3, i_blue = 6
+     4 ch
+     i_red = 0, i_green = 4, i_blue = 8
+   */
+
+   for(int i=0; i < channels ; i++) {
+       if(m_ChannelAssignment && (i < m_NumAssignedChannels))
+          idx = m_ChannelAssignment[i];
+       else
+          idx = -1;
+       if((idx>=0) && (idx<data->numColors)) {
+          buffer[i_red++]   = data->zone[idx].r;
+          buffer[i_green++] = data->zone[idx].g;
+          buffer[i_blue++]  = data->zone[idx].b;
+       } else {
+          buffer[i_red++]   = 0;
+          buffer[i_green++] = 0;
+          buffer[i_blue++]  = 0;
+       }
+   }
+
+#if defined(WIN32)
+   WriteFile(m_hComport, buffer, bufSize, &iBytesWritten, NULL); // send to COM-Port
+#else
+   iBytesWritten = write(m_hComport, buffer, bufSize);
+   tcdrain(m_hComport);
+#endif
+   delete []buffer;
+
+   Unlock();
+
+   return (iBytesWritten == bufSize) ? ATMO_TRUE : ATMO_FALSE;
+}
+
+
+ATMO_BOOL CMoMoConnection::CreateDefaultMapping(CAtmoChannelAssignment *ca)
+{
+   if(!ca) return ATMO_FALSE;
+   ca->setSize( getNumChannels() );  // oder 4 ? depending on config!
+   ca->setZoneIndex(0, 0); // Zone 5
+   ca->setZoneIndex(1, 1);
+   ca->setZoneIndex(2, 2);
+   ca->setZoneIndex(3, 3);
+   return ATMO_TRUE;
+}
+
+int CMoMoConnection::getNumChannels()
+{
+   return m_pAtmoConfig->getMoMo_Channels();
+}
+
+
+#if !defined(_ATMO_VLC_PLUGIN_)
+
+char *CMoMoConnection::getChannelName(int ch)
+{
+  if(ch < 0) return NULL;
+  char buf[30];
+
+  switch(ch) {
+      case 0:
+          sprintf(buf,"Channel [%d]",ch);
+          break;
+      case 1:
+          sprintf(buf,"Channel [%d]",ch);
+          break;
+      case 2:
+          sprintf(buf,"Channel [%d]",ch);
+          break;
+      case 3:
+          sprintf(buf,"Channel [%d]",ch);
+          break;
+      default:
+          sprintf(buf,"Channel [%d]",ch);
+          break;
+  }
+
+  return strdup(buf);
+}
+
+ATMO_BOOL CMoMoConnection::ShowConfigDialog(HINSTANCE hInst, HWND parent, CAtmoConfig *cfg)
+{
+    CMoMoConfigDialog *dlg = new CMoMoConfigDialog(hInst, parent, cfg);
+
+    INT_PTR result = dlg->ShowModal();
+
+    delete dlg;
+
+    if(result == IDOK)
+      return ATMO_TRUE;
+    else
+      return ATMO_FALSE;
+}
+
+#endif
diff --git a/modules/video_filter/atmo/MoMoConnection.h b/modules/video_filter/atmo/MoMoConnection.h
new file mode 100644 (file)
index 0000000..2a0315b
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * MoMoConnection.h: class to access a MoMoLight Hardware - the description could be found
+ * here: http://lx.divxstation.com/article.asp?aId=151
+ *
+ * See the README.txt file for copyright information and how to reach the author(s).
+ *
+ * $Id$
+ */
+#ifndef _MoMoConnection_h_
+#define _MoMoConnection_h_
+
+#include "AtmoDefs.h"
+#include "AtmoConnection.h"
+#include "AtmoConfig.h"
+
+#if defined(WIN32)
+#   include <windows.h>
+#endif
+
+
+class CMoMoConnection : public CAtmoConnection {
+    private:
+        HANDLE m_hComport;
+
+#if defined(WIN32)
+        DWORD  m_dwLastWin32Error;
+    public:
+        DWORD getLastError() { return m_dwLastWin32Error; }
+#endif
+
+    public:
+       CMoMoConnection (CAtmoConfig *cfg);
+       virtual ~CMoMoConnection (void);
+
+       virtual ATMO_BOOL OpenConnection();
+
+       virtual void CloseConnection();
+
+       virtual ATMO_BOOL isOpen(void);
+
+       virtual ATMO_BOOL SendData(pColorPacket 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);
+
+       virtual int getNumChannels();
+
+
+       virtual const char *getDevicePath() { return "momo"; }
+
+#if !defined(_ATMO_VLC_PLUGIN_)
+       virtual char *getChannelName(int ch);
+       virtual ATMO_BOOL ShowConfigDialog(HINSTANCE hInst, HWND parent, CAtmoConfig *cfg);
+#endif
+
+       virtual ATMO_BOOL CreateDefaultMapping(CAtmoChannelAssignment *ca);
+};
+
+#endif
index a48353ae934aa57ececc9cb2d39bbafcb5afaf8a..4cf6595960c74119d02e0b73d06bf9aa8f865772 100644 (file)
-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).
+This piece of software is based on the software and descriptions mentioned below -\r
+\r
+\r
+(re)Written by:              Igor / Atmo (aka André Weber)  - WeberAndre@gmx.de\r
+                             Matthiaz    \r
+                             MacGyver2k\r
+\r
+if you need to contact one of us - come to www.vdr-portal.de \r
+\r
+http://www.vdr-portal.de/board/thread.php?threadid=59294 -- Description and Development of the Windows Software\r
+http://www.vdr-portal.de/board/thread.php?threadid=48574 -- Description and Development of the Hardware part\r
+\r
+=====================================================\r
+Info for Users on Vista or Windows 7 with active UAC!\r
+=====================================================\r
+for the first launch do it as Administrator with the following command line \r
+\r
+AtmoWinA.exe /register \r
+\r
+to create the required registry entries for the COM Objects, without\r
+these registry entries - the DirectShow Filter and also the VLC Plugin\r
+will not work.\r
+If anything went fine you should see the message "COM Server registered Ok!".\r
+\r
+See the file COPYING.txt for license information.\r
+\r
+\r
+VideoLAN / VLC\r
+---------------\r
+\r
+In order to use this Programm with the VLC-Media-Player properly copy the "AtmoCtrlLib.dll" into the same Location where the vlc.exe is. E.G.: "D:\Programme\VLC". \r
+\r
+NEWER Versions of VideoLAN 1.1.x and higher, don't need a own copy of the "AtmoCtrlLib.dll" in the vlc.exe folder,\r
+if the complete filename of the AtmoWin*.exe is given. (Atmo Filter will try to load the DLL from there)\r
+\r
+Then open VLC and navigate to "Extras" / "Settings" or Press "Ctrl" + "p".\r
+Check that the radiobutton in the lower part of the dialogbox called "Show settings" -> "all" is checked.\r
+Now open the Register "Video" and click on "Filter". There you have to select the checkbox "AtmoLight-Filter".\r
+Afterwards you expand the Tree "Filter" in the Listbox on the left side. By selecting the entry "AtmoLight" you gain more settings.\r
+The most important are right these one at the beginning:\r
+\r
+VideoLAN 1.0.x \r
+==============\r
+"Use build in AtmoLight driver": \r
+Using this Property means VLC will control the Hardware with its built in driver. \r
+(no need for the extra AtmoWin software driver) \r
+\r
+VideoLAN 1.1.x \r
+==============\r
+You have the following choices for "Devicetype" instead of the old settings\r
+"AtmoWin Software" - is only available on Windows and works like the old way useing the external AtmoWin*.exe Software package, with the AtmoCtrlLib.dll.\r
+"Classic AtmoLight" - is the same as the former "use build in AtmoLight driver" \r
+"Quattro AtmoLight" - allows to use up to four serial connected class AtmoLight devices, as one logical device\r
+"DMX" - allows to control a simple serial DMX devices for AtmoLight effects\r
+"MoMoLight" - is a another kind of hardware supporting 2 oder 3 channels.\r
+(see bottom of this file - for more infos about the devices.)\r
+\r
+VideonLAN 1.0.x\r
+===============\r
+"Serial Device / Port":\r
+The COM-Port you are using for the hardware. E.G.: COM6 (This setting must be done if you are using the Property \r
+"use build in AtmoLight driver" )\r
+\r
+VideonLAN 1.1.x\r
+===============\r
+"Serial Device / Port":\r
+The COM-Port you are using for the hardware. E.G.: COM6 (This setting must be done if you are using a device\r
+other than "AtmoWin Software") \r
+in the case of the device "Quattro AtmoLight" you may specify up to four ports/devices seperated by\r
+, or ; for example if you are useing two physical devices write\r
+COM6;COM7 or on linux /dev/ttyUSB1;/dev/ttyUSB2\r
+\r
+VideoLAN 1.0.x\r
+==============\r
+"Filename of AtmoWinA.exe":\r
+The Path and the Name of the executable. E.G.:\r
+'D:\atmoWin_0.45\AtmoWinA.exe' (Using this setting expects that you have copied "AtmoCtrlLib.dll" to the Path where VLC.exe is like described before)\r
+\r
+VideoLAN 1.1.x\r
+==============\r
+"Filename of AtmoWinA.exe":\r
+The Path and the Name of the executable. E.G.:\r
+'D:\atmoWin_0.45\AtmoWinA.exe' \r
+in the same path where the .exe resides the "AtmoCtrlLib.dll" should be there. or you may need to place\r
+a copy of this ".dll" into the vlc.exe folder - like in VideoLAN 1.0.x\r
+\r
+Afterwards you should apply those settings by pressing the button "Save".\r
+\r
+\r
+\r
+\r
+VideoLAN 1.1.x - new options and settings\r
+=========================================\r
+Zone Layout for the build-in Atmo\r
+=================================\r
+This is the most important change I think - because the number of analyzed zones isn't\r
+longer fixed to 4 or 5 - it allows to define the physical layout of your lights arround\r
+the screen.\r
+"Number of zones on top"     -- how many light sources are place on top of the screen\r
+                               (number of columns in which the screen should be tiled)\r
+\r
+"Number of zones on bottom"  -- how many light sources are place on bottom of the screen\r
+                               (number of columns in which the screen should be tiled)\r
+\r
+"Zones on left / right side" -- how many light sources are place on right/left of the screen\r
+                               (number of rows in which the screen should be tiled)\r
+                               its assumed that the number on right and left is equal.\r
+\r
+"[] Calculate a average zone" -- define a color pair depending on the complete screen content\r
+\r
+This settings tiles the screen into a number of zones - which get analyzed by atmoLight to\r
+determine a most used color for these areas - each zone has a number starting from zero.\r
+The zones are usualy numbered in clock-wise order starting at the top/left of the screen.\r
+\r
+Example 1: classic Atmo with 4 channels\r
+---------------------------------------\r
+"Number of zones on top" = 1\r
+"Number of zones on bottom" = 1\r
+"Zones on left / right side" = 1\r
+"[] Calculate a average zone" = false/0 not checked.\r
+\r
+will produce this zone layout\r
+     ----------- \r
+     | Zone 0  | \r
+---------------------\r
+|   |           |   |  \r
+| Z |           | Z | \r
+| o |           | o |\r
+| n |           | n |\r
+| e |           | e |  \r
+|   |           |   | \r
+| 3 |           | 1 |   \r
+---------------- ----\r
+     | Zone 2  |\r
+     -----------\r
+\r
+\r
+Example 2: classic Atmo with 4 channels\r
+---------------------------------------\r
+"Number of zones on top" = 2\r
+"Number of zones on bottom" = 0\r
+"Zones on left / right side" = 1\r
+"[] Calculate a average zone" = false/0 not checked.\r
+\r
+     ----------- -----------\r
+     | Zone 0  | | Zone 1  |\r
+---------------------------------\r
+|   |                       |   |  \r
+| Z |                       | Z | \r
+| o |                       | o |\r
+| n |                       | n |\r
+| e |                       | e |  \r
+|   |                       |   | \r
+| 3 |                       | 2 |   \r
+-----                       -----\r
+\r
+Example 3: classic Atmo with 4 channels\r
+---------------------------------------\r
+"Number of zones on top" = 1\r
+"Number of zones on bottom" = 0\r
+"Zones on left / right side" = 1\r
+"[X] Calculate a average zone" = true/1 checked.\r
\r
+     ----------- \r
+     | Zone 0  | \r
+---------------------\r
+|   | --------  |   |  \r
+| Z | |  Z    | | Z | \r
+| o | |  o    | | o |\r
+| n | |  n    | | n |\r
+| e | |  e    | | e |  \r
+|   | |  3    | |   | \r
+| 2 | --------  | 1 |   \r
+-----           -----\r
+Zone 3 - usualy calcuates the most used color of the full screen / picture / frame\r
+not only at the border of the picture.\r
+\r
+"The average zone" is allways the last in the sequence of numbers.\r
+\r
+\r
+     \r
+the weightning gradients for these zones are auto calculated\r
+from 100% .. 0% starting from the edge.\r
+\r
+thats also the cause why the parameters  Channel assignment changed,\r
+the classic comboboxes are still there for devices with 4 channels ot less,\r
+but for newer devices the "Channel / Zone assignment" should be used which\r
+is defined by a , or ; separated list of "AtmoLight channel numbers" if you\r
+want to hide a calcuated zone from output - you can assign channel -1 to\r
+do this. \r
+for classic AtmoLight with "Example 1" you may write this:\r
+-1;3;2;1;0 \r
+AtmoLight Channel 0: gets no zone assigned (-1)\r
+AtmoLight Channel 1: gets zone 3 (left)\r
+AtmoLight Channel 2: gets zone 2 (bottom)\r
+AtmoLight Channel 3: gets zone 1 (right)\r
+AtmoLight Channel 4: gets zone 0 (top)\r
+\r
+\r
+Also the settings for Gradient images change for the new devices, its no longer\r
+sufficient to speficy only 5 image name - because the number of zones is no longer\r
+fixed to five.\r
+So its prefered to set a path ("Gradient Bitmap searchpath"), where files \r
+like "zone_0.bmp" "zone_1.bmp" etc. exists. (with the same rules as defined for \r
+the old zone bitmaps.)\r
+--> I think in most cases its no longer required to use this option,\r
+to change the zone layout - for most cases its sufficient to change \r
+"Zone Layout for the build-in Atmo" to get the same effect?\r
+\r
+Live Set of parameters for Buildin AtmoLight\r
+============================================\r
+durring playback with the buildin driver you can now change some settings\r
+of the filter without stopping / starting your movie - just open the\r
+"extras" --> "Effects and Filters"  --> [Video effects] --> [AtmoLight]\r
+- move the sliders or change the calcuation mode, or enable/disable\r
+the debug grid - just in time.\r
+\r
+\r
+new Debugging Option\r
+====================\r
+[] Mark analyzed pixels - puts a grid of the used pixels on each frame\r
+to see from which locations/positions the colors are extracted.\r
+\r
+DMX Options\r
+-----------\r
+like the group says only for the DMX device\r
+"Count of AtmoLight Channels" - defines how many RGB Channels should be simulated\r
+with this DMX device (each RGB channel needs three DMX channels!)\r
+\r
+"DMX adress for each channel" - defines the DMX Startadress for each AtmoLight\r
+channel as "," or ";" separated list. (starting with 0 up to 252) it is assumed\r
+that the f.e. of the DMX-AtmoLight channel starts at DMX-Channel 5 - that\r
+DMX-Channel 5: is red\r
+DMX-Channel 6: is green\r
+DMX-Channel 7: is blue!\r
+\r
+MoMoLight options\r
+-----------------\r
+"Count of channels" - defines the devicetype and serial protocol \r
+3: - means 3 channels hardware\r
+4: - means 4 channels hardware\r
+(its required to set the correct number of channels to get this device working,\r
+ because the serial protocol isn't the same!)\r
+\r
+\r
+\r
+VideoLan Options and Devices - the buildin version of AtmoLight supports a subset of the\r
+devices that AtmoWin supports.\r
+\r
+- AtmoWin Software - means do not use the VLC buildin video processing - just forward\r
+  the basic preprocessed data to the launched AtmoWinA.exe controlling your hardware.\r
+\r
+- Classic AtmoLight - means the classic hardware from www.vdr-portal.de - with up to 5 channels. \r
+\r
+- Quattro AtmoLight - is nothing else as that you have connected up to 4 "classic AtmoLight" devices\r
+  to your computer creating a up 16 channel Atmo Light - each devices needs its own serial port.\r
+  you have to write the ports seperated by , or ; to [Serial Port/device] f.e. COM3,COM4,COM5 or on \r
+  Linux /dev/ttyUSB01,/dev/ttyUSB02,/dev/ttyUSB03\r
+\r
+- DMX - stands for a simple DMX controller which can control up to 255 DMX devices (lights)\r
+  - f.e. you may have a look here: \r
+     * http://www.dzionsko.de/elektronic/index.htm\r
+     * http://www.ulrichradig.de/ (search for dmx on his page)\r
\r
+- MoMoLight - is a serial device, with 3 or 4 channels - doing nearly the same like\r
+  Classic AtmoLight - just another protocol to control the hardware.\r
+   http://lx.divxstation.com/article.asp?aId=151\r
+   http://www.the-boss.dk/pages/momolight.htm\r
+\r
+\r
+\r
+\r
+\r
+Original Readme - of the Linux Version - from where some code was used\r
+to do the color calculations ...\r
+\r
+######################################################################\r
+Original Readme and Authors of the Linux VDR Plugin!\r
+######################################################################\r
+\r
+Written by:                  Eike Edener   <vdr@edener.de>\r
+Project's homepage:          www.edener.de\r
+Latest version available at: www.edener.de\r
+See the file COPYING for license information.\r
+----------------------------------------------------------------------\r
+\r
+for detailed informations visit the VDR-Wiki:\r
+http://www.vdr-wiki.de/wiki/index.php/Atmo-plugin\r
+\r
+Development:\r
+http://www.vdr-portal.de/board/thread.php?threadid=48574\r
+\r
+Known bugs:\r
+n/a\r
+\r
+----------------------------------------------------------------------\r
index 9cb0edef2119b92bc2f7801c2872834a9056b23a..07d5f6018f1150edf58367bfeb3679f7429503fb 100644 (file)
 #include <stdlib.h>                                      /* malloc(), free() */
 #include <string.h>
 #include <math.h>                                            /* sin(), cos() */
+#include <assert.h>
 
 #ifdef HAVE_CONFIG_H
 # include "config.h"
 #endif
 
 // #define __ATMO_DEBUG__
+
 // [:Zs]+$
 #include <vlc_common.h>
 #include <vlc_plugin.h>
@@ -48,7 +50,7 @@
 #include "AtmoExternalCaptureInput.h"
 #include "AtmoConfig.h"
 #include "AtmoConnection.h"
-#include "AtmoSerialConnection.h"
+#include "AtmoClassicConnection.h"
 
 
 /*****************************************************************************
@@ -112,6 +114,8 @@ void SaveBitmap(filter_sys_t *p_sys, uint8_t *p_pixels, char *psz_filename);
 #define lvsGDI           0
 #define lvsExternal      1
 
+#define CLASSIC_ATMO_NUM_ZONES  5
+
 
 /*
 strings for settings menus and hints
@@ -121,14 +125,54 @@ strings for settings menus and hints
  "connected to your computer.\n"\
  "AtmoLight is the homegrown version of what Philips calls AmbiLight.\n"\
  "If you need further information 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/Atmo-plugin\n"\
  "http://www.vdr-wiki.de/wiki/index.php/AtmoWin\n\n"\
  "You can find there detailed descriptions on how to build it for yourself "\
  "and where to get the required parts.\n" \
  "You can also have a look at pictures and some movies showing such a device " \
  "in live action.")
 
+#define DRIVER_TEXT            N_("Devicetype")
+#define DRIVER_LONGTEXT        N_("Choose your prefered hardware from " \
+                                  "the list, or choose AtmoWin Software " \
+                                  "to delegate processing to the external " \
+                                  "process - with more options")
+
+static const int pi_device_type_values[] = {
+#if defined( WIN32 )
+     0, /* use AtmoWinA.exe userspace driver */
+#endif
+     1, /* AtmoLight classic */
+     2, /* Quattro AtmoLight */
+     3, /* DMX Device */
+     4  /* MoMoLight device */
+};
+static const char *const ppsz_device_type_descriptions[] = {
+#if defined( WIN32 )
+        N_("AtmoWin Software"),
+#endif
+        N_("Classic AtmoLight"),
+        N_("Quattro AtmoLight"),
+        N_("DMX"),
+        N_("MoMoLight")
+};
+
+#define DMX_CHANNELS_TEXT      N_("Count of AtmoLight channels")
+#define DMX_CHANNELS_LONGTEXT  N_("How many AtmoLight channels, should be " \
+                                  "emulated with that DMX device")
+#define DMX_CHBASE_TEXT        N_("DMX address for each channel")
+#define DMX_CHBASE_LONGTEXT    N_("Define here the DMX base address for each " \
+                                  "channel use , or ; to seperate the values")
 
+#define MOMO_CHANNELS_TEXT      N_("Count of channels")
+#define MOMO_CHANNELS_LONGTEXT  N_("Depending on your MoMoLight hardware " \
+                                   "choose 3 or 4 channels")
+
+#if defined( WIN32 )
+#  define DEFAULT_DEVICE   0
+#else
+#  define DEFAULT_DEVICE   1
+#endif
 
 #if defined( __ATMO_DEBUG__ )
 #   define SAVEFRAMES_TEXT     N_("Save Debug Frames")
@@ -146,6 +190,10 @@ strings for settings menus and hints
 #define HEIGHT_LONGTEXT        N_("The height of the mini image for " \
                                   "further processing (48 is default)")
 
+#define SHOW_DOTS_TEXT         N_("Mark analyzed pixels")
+#define SHOW_DOTS_LONGTEXT     N_("makes the sample grid visible on screen as "\
+                                  "white pixels")
+
 #define PCOLOR_TEXT            N_("Color when paused")
 #define PCOLOR_LONGTEXT        N_("Set the color to show if the user " \
                                   "pauses the video. (Have light to get " \
@@ -171,6 +219,19 @@ strings for settings menus and hints
                              "end color for dimming up the light in cinema " \
                              "style... (each step takes 40ms)")
 
+#define ZONE_TOP_TEXT          N_("Number of zones on top")
+#define ZONE_TOP_LONGTEXT      N_("Number of zones on the top of the screen")
+#define ZONE_BOTTOM_TEXT       N_("Number of zones on bottom")
+#define ZONE_BOTTOM_LONGTEXT   N_("Number of zones on the bottom of the screen")
+#define ZONE_LR_TEXT           N_("Zones on left / right side")
+#define ZONE_LR_LONGTEXT       N_("left and right side having allways the " \
+                                  "same number of zones")
+#define ZONE_SUMMARY_TEXT      N_("Calculate a average zone")
+#define ZONE_SUMMARY_LONGTEXT  N_("it contains the average of all pixels " \
+                                  "in the sample image (only useful for " \
+                                  "single channel AtmoLight)")
+
+
 #define USEWHITEADJ_TEXT       N_("Use Software White adjust")
 #define USEWHITEADJ_LONGTEXT   N_("Should the buildin driver do a white " \
                                   "adjust or your LED stripes? recommend.")
@@ -213,10 +274,10 @@ strings for settings menus and hints
 #define MEANPERCENTNEW_TEXT     N_("Filter Smoothness (in %)")
 #define MEANPERCENTNEW_LONGTEXT N_("Filter Smoothness")
 
-/* FIXME: WTF?!! feepk, July 6 '08 */
-#define FILTERMODE_TEXT        N_("Filter mode")
-#define FILTERMODE_LONGTEXT    N_("kind of filtering which should be use to "\
-                                  "calcuate the color output")
+#define FILTERMODE_TEXT        N_("Output Color filter mode")
+#define FILTERMODE_LONGTEXT    N_("defines the how the output color should " \
+                                  "be calculated based on previous color")
+
 static const int pi_filtermode_values[] = {
        (int)afmNoFilter,
        (int)afmCombined,
@@ -228,54 +289,65 @@ static const char *const ppsz_filtermode_descriptions[] = {
         N_("Percent")
 };
 
-#define FRAMEDELAY_TEXT       N_("Frame delay")
+#define FRAMEDELAY_TEXT       N_("Frame delay (ms)")
 #define FRAMEDELAY_LONGTEXT   N_("Helps to get the video output and the light "\
                                  "effects in sync. 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 CHANNEL_0_ASSIGN_TEXT N_("Channel 0: summary")
+#define CHANNEL_1_ASSIGN_TEXT N_("Channel 1: left")
+#define CHANNEL_2_ASSIGN_TEXT N_("Channel 2: right")
+#define CHANNEL_3_ASSIGN_TEXT N_("Channel 3: top")
+#define CHANNEL_4_ASSIGN_TEXT N_("Channel 4: bottom")
 
 #define CHANNELASSIGN_LONGTEXT N_("Maps the hardware channel X to logical "\
-                                  "channel Y to fix wrong wiring :-)")
-static const int pi_channel_assignment_values[] = {
+                                  "zone Y to fix wrong wiring :-)")
+static const int pi_zone_assignment_values[] = {
     -1,
-     0,
-     1,
-     2,
+     4,
      3,
-     4
+     1,
+     0,
+     2
 };
-static const char *const ppsz_channel_assignment_descriptions[] = {
+static const char *const ppsz_zone_assignment_descriptions[] = {
         N_("disabled"),
-        N_("summary"),
-        N_("left"),
-        N_("right"),
-        N_("top"),
-        N_("bottom")
+        N_("Zone 4:summary"),
+        N_("Zone 3:left"),
+        N_("Zone 1:right"),
+        N_("Zone 0:top"),
+        N_("Zone 2: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 CHANNELS_ASSIGN_TEXT        N_("Channel / Zone Assignment")
+#define CHANNELS_ASSIGN_LONGTEXT N_("for devices with more than five " \
+                  "channels / zones write down here for each channel " \
+                  "the zone number to show and seperate the values with " \
+                  ", or ; and use -1 to not use some channels. For the " \
+                  "classic AtmoLight the sequence 4,3,1,0,2 would set the " \
+                  "default channel/zone mapping. " \
+                  "Having only two zones on top, and one zone on left and " \
+                  "right and no summary zone the mapping for classic " \
+                  "AtmoLight would be -1,3,2,1,0")
+
+#define ZONE_0_GRADIENT_TEXT N_("Zone 0: Top gradient")
+#define ZONE_1_GRADIENT_TEXT N_("Zone 1: Right gradient")
+#define ZONE_2_GRADIENT_TEXT N_("Zone 2: Bottom gradient")
+#define ZONE_3_GRADIENT_TEXT N_("Zone 3: Left gradient")
+#define ZONE_4_GRADIENT_TEXT N_("Zone 4: Summary gradient")
 #define ZONE_X_GRADIENT_LONG_TEXT N_("Defines a small bitmap with 64x48 "\
                                      "pixels, containing a grayscale gradient")
 
+#define GRADIENT_PATH_TEXT      N_("Gradient bitmap searchpath")
+#define GRADIENT_PATH_LONGTEXT  N_("Now prefered option to assign gradient "\
+    "bitmaps, put them as zone_0.bmp, zone_1.bmp etc. into one folder and "\
+    "set the foldername here")
+
 #if defined( WIN32 )
-#   define ATMOWINEXE_TEXT      N_("Filename of AtmoWinA.exe")
+#   define ATMOWINEXE_TEXT      N_("Filename of AtmoWin*.exe")
 #   define ATMOWINEXE_LONGTEXT  N_("if you want the AtmoLight control "\
                                    "software to be launched by VLC, enter the "\
                                    "complete path of AtmoWinA.exe here.")
-#   define USEBUILDIN_TEXT      N_("Use built-in AtmoLight")
-#   define USEBUILDIN_LONGTEXT N_("VLC will directly use your AtmoLight "\
-                                  "hardware without running the external "\
-                                  "AtmoWinA.exe Userspace driver.")
 #endif
 
 #define CFG_PREFIX "atmo-"
@@ -287,24 +359,22 @@ vlc_module_begin ()
 set_description( N_("AtmoLight Filter") )
 set_help( MODULE_DESCRIPTION )
 set_shortname( N_( "AtmoLight" ))
-set_capability( "video filter2", 0 )
-
 set_category( CAT_VIDEO )
 set_subcategory( SUBCAT_VIDEO_VFILTER )
 
-#if defined(WIN32)
-set_section( N_("Choose between the built-in AtmoLight "\
-                 "driver or the external" ), 0 )
+set_capability( "video filter2", 0 )
 
-/*
-    only on win32 exists the option to use the buildin driver or
-    the more flexible external driver application
-*/
-add_bool(CFG_PREFIX "usebuildin", true, NULL,
-         USEBUILDIN_TEXT, USEBUILDIN_LONGTEXT, false)
+
+set_section( N_("Choose Devicetype and Connection" ), 0 )
+
+add_integer( CFG_PREFIX "device", DEFAULT_DEVICE, NULL,
+            DRIVER_TEXT, DRIVER_LONGTEXT, false )
+change_integer_list( pi_device_type_values,
+                     ppsz_device_type_descriptions, 0 )
+
+#if defined(WIN32)
 add_string(CFG_PREFIX "serialdev", "COM1", NULL,
            SERIALDEV_TEXT, SERIALDEV_LONGTEXT, false )
-
 /*
     on win32 the executeable external driver application
     for automatic start if needed
@@ -312,7 +382,6 @@ add_string(CFG_PREFIX "serialdev", "COM1", NULL,
 add_file(CFG_PREFIX "atmowinexe", NULL, NULL,
          ATMOWINEXE_TEXT, ATMOWINEXE_LONGTEXT, false )
 #else
-set_section( N_("Enter the connection of your AtmoLight hardware" ), 0 )
 add_string(CFG_PREFIX "serialdev", "/dev/ttyS01", NULL,
            SERIALDEV_TEXT, SERIALDEV_LONGTEXT, false )
 #endif
@@ -347,6 +416,65 @@ add_integer_with_range(CFG_PREFIX "ecolor-blue",  192, 0, 255, NULL,
 add_integer_with_range(CFG_PREFIX "efadesteps",    50, 1, 250, NULL,
                        EFADESTEPS_TEXT,   EFADESTEPS_LONGTEXT,    false)
 
+
+set_section( N_("DMX options" ), 0 )
+add_integer_with_range(CFG_PREFIX "dmx-channels",   5, 1, 64, NULL,
+                       DMX_CHANNELS_TEXT, DMX_CHANNELS_LONGTEXT, false)
+add_string(CFG_PREFIX "dmx-chbase", "0,3,6,9,12", NULL,
+                       DMX_CHBASE_TEXT, DMX_CHBASE_LONGTEXT, false )
+
+set_section( N_("MoMoLight options" ), 0 )
+add_integer_with_range(CFG_PREFIX "momo-channels",   3, 3, 4, NULL,
+                       MOMO_CHANNELS_TEXT, MOMO_CHANNELS_LONGTEXT, false)
+
+
+
+/*
+  instead of redefining the original AtmoLight zones with gradient
+  bitmaps, we can now define the layout of the zones useing these
+  parameters - the function with the gradient bitmaps would still
+  work (but for most cases its no longer required)
+
+  short description whats this means - f.e. the classic atmo would
+  have this layout
+  zones-top    = 1  - zone 0
+  zones-lr     = 1  - zone 1 und zone 3
+  zones-bottom = 1  - zone 2
+  zone-summary = true - zone 4
+         Z0
+   ,------------,
+   |            |
+ Z3|     Z4     | Z1
+   |____________|
+         Z2
+
+  the zone numbers will be counted clockwise starting at top / left
+  if you want to split the light at the top, without having a bottom zone
+  (which is my private config)
+
+  zones-top    = 2  - zone 0, zone 1
+  zones-lr     = 1  - zone 2 und zone 3
+  zones-bottom = 0
+  zone-summary = false
+
+      Z0    Z1
+   ,------------,
+   |            |
+ Z3|            | Z2
+   |____________|
+
+*/
+
+set_section( N_("Zone Layout for the build-in Atmo" ), 0 )
+add_integer_with_range(CFG_PREFIX "zones-top",   1, 0, 16, NULL,
+                       ZONE_TOP_TEXT, ZONE_TOP_LONGTEXT, false)
+add_integer_with_range(CFG_PREFIX "zones-bottom",   1, 0, 16, NULL,
+                       ZONE_BOTTOM_TEXT, ZONE_BOTTOM_LONGTEXT, false)
+add_integer_with_range(CFG_PREFIX "zones-lr",   1, 0, 16, NULL,
+                       ZONE_LR_TEXT, ZONE_LR_LONGTEXT, false)
+add_bool(CFG_PREFIX "zone-summary", false, NULL,
+         ZONE_SUMMARY_TEXT, ZONE_SUMMARY_LONGTEXT, false)
+
 /*
  settings only for the buildin driver (if external driver app is used
  these parameters are ignored.)
@@ -355,19 +483,19 @@ add_integer_with_range(CFG_PREFIX "efadesteps",    50, 1, 250, NULL,
 */
 set_section( N_("Settings for the built-in Live Video Processor only" ), 0 )
 
-add_integer_with_range(CFG_PREFIX "EdgeWeightning",   8, 1, 30, NULL,
+add_integer_with_range(CFG_PREFIX "edgeweightning",   3, 1, 30, NULL,
                        EDGE_TEXT, EDGE_LONGTEXT, false)
 
-add_integer_with_range(CFG_PREFIX "Brightness",   100, 50, 300, NULL,
+add_integer_with_range(CFG_PREFIX "brightness",   100, 50, 300, NULL,
                        BRIGHTNESS_TEXT, BRIGHTNESS_LONGTEXT, false)
 
-add_integer_with_range(CFG_PREFIX "DarknessLimit",   5, 0, 10, NULL,
+add_integer_with_range(CFG_PREFIX "darknesslimit",   3, 0, 10, NULL,
                        DARKNESS_TEXT, DARKNESS_LONGTEXT, false)
 
-add_integer_with_range(CFG_PREFIX "HueWinSize",   3, 0, 5, NULL,
+add_integer_with_range(CFG_PREFIX "huewinsize",   3, 0, 5, NULL,
                        HUEWINSIZE_TEXT, HUEWINSIZE_LONGTEXT, false)
 
-add_integer_with_range(CFG_PREFIX "SatWinSize",   3, 0, 5, NULL,
+add_integer_with_range(CFG_PREFIX "satwinsize",   3, 0, 5, NULL,
                        SATWINSIZE_TEXT, SATWINSIZE_LONGTEXT, false)
 
 add_integer(CFG_PREFIX "filtermode", (int)afmCombined, NULL,
@@ -375,46 +503,50 @@ add_integer(CFG_PREFIX "filtermode", (int)afmCombined, NULL,
 
 change_integer_list(pi_filtermode_values, ppsz_filtermode_descriptions, NULL )
 
-add_integer_with_range(CFG_PREFIX "MeanLength",    300, 300, 5000, NULL,
+add_integer_with_range(CFG_PREFIX "meanlength",    300, 300, 5000, NULL,
                        MEANLENGTH_TEXT, MEANLENGTH_LONGTEXT, false)
 
-add_integer_with_range(CFG_PREFIX "MeanThreshold",  40, 1, 100, NULL,
+add_integer_with_range(CFG_PREFIX "meanthreshold",  40, 1, 100, NULL,
                        MEANTHRESHOLD_TEXT, MEANTHRESHOLD_LONGTEXT, false)
 
-add_integer_with_range(CFG_PREFIX "PercentNew", 50, 1, 100, NULL,
+add_integer_with_range(CFG_PREFIX "percentnew", 50, 1, 100, NULL,
                       MEANPERCENTNEW_TEXT, MEANPERCENTNEW_LONGTEXT, false)
 
-add_integer_with_range(CFG_PREFIX "FrameDelay", 18, 0, 35, NULL,
+add_integer_with_range(CFG_PREFIX "framedelay", 18, 0, 200, NULL,
                        FRAMEDELAY_TEXT, FRAMEDELAY_LONGTEXT, false)
 
 /*
   output channel reordering
 */
 set_section( N_("Change channel assignment (fixes wrong wiring)" ), 0 )
-add_integer( CFG_PREFIX "channel_0", 0, NULL,
+add_integer( CFG_PREFIX "channel_0", 4, NULL,
             CHANNEL_0_ASSIGN_TEXT, CHANNELASSIGN_LONGTEXT, false )
-change_integer_list( pi_channel_assignment_values,
-                     ppsz_channel_assignment_descriptions, 0 )
+change_integer_list( pi_zone_assignment_values,
+                     ppsz_zone_assignment_descriptions, 0 )
 
-add_integer( CFG_PREFIX "channel_1", 1, NULL,
+add_integer( CFG_PREFIX "channel_1", 3, NULL,
             CHANNEL_1_ASSIGN_TEXT, CHANNELASSIGN_LONGTEXT, false )
-change_integer_list( pi_channel_assignment_values,
-                     ppsz_channel_assignment_descriptions, 0 )
+change_integer_list( pi_zone_assignment_values,
+                     ppsz_zone_assignment_descriptions, 0 )
 
-add_integer( CFG_PREFIX "channel_2", 2, NULL,
+add_integer( CFG_PREFIX "channel_2", 1, NULL,
             CHANNEL_2_ASSIGN_TEXT, CHANNELASSIGN_LONGTEXT, false )
-change_integer_list( pi_channel_assignment_values,
-                     ppsz_channel_assignment_descriptions, 0 )
+change_integer_list( pi_zone_assignment_values,
+                     ppsz_zone_assignment_descriptions, 0 )
 
-add_integer( CFG_PREFIX "channel_3", 3, NULL,
+add_integer( CFG_PREFIX "channel_3", 0, NULL,
             CHANNEL_3_ASSIGN_TEXT, CHANNELASSIGN_LONGTEXT, false )
-change_integer_list( pi_channel_assignment_values,
-                     ppsz_channel_assignment_descriptions, 0 )
+change_integer_list( pi_zone_assignment_values,
+                     ppsz_zone_assignment_descriptions, 0 )
 
-add_integer( CFG_PREFIX "channel_4", 4, NULL,
+add_integer( CFG_PREFIX "channel_4", 2, NULL,
             CHANNEL_4_ASSIGN_TEXT, CHANNELASSIGN_LONGTEXT, false )
-change_integer_list( pi_channel_assignment_values,
-                     ppsz_channel_assignment_descriptions, 0 )
+change_integer_list( pi_zone_assignment_values,
+                     ppsz_zone_assignment_descriptions, 0 )
+
+add_string(CFG_PREFIX "channels", NULL, NULL,
+           CHANNELS_ASSIGN_TEXT, CHANNELS_ASSIGN_LONGTEXT, false )
+
 
 /*
   LED color white calibration
@@ -452,7 +584,8 @@ add_file(CFG_PREFIX "gradient_zone_3", NULL, NULL,
          ZONE_3_GRADIENT_TEXT, ZONE_X_GRADIENT_LONG_TEXT, true )
 add_file(CFG_PREFIX "gradient_zone_4", NULL, NULL,
          ZONE_4_GRADIENT_TEXT, ZONE_X_GRADIENT_LONG_TEXT, true )
-
+add_directory(CFG_PREFIX "gradient_path", NULL, NULL,
+           GRADIENT_PATH_TEXT, GRADIENT_PATH_LONGTEXT, false )
 
 #if defined(__ATMO_DEBUG__)
 add_bool(CFG_PREFIX "saveframes", false, NULL,
@@ -468,37 +601,43 @@ add_integer_with_range(CFG_PREFIX "width",  64, 64, 512, NULL,
                        WIDTH_TEXT,  WIDTH_LONGTEXT, true)
 add_integer_with_range(CFG_PREFIX "height", 48, 48, 384, NULL,
                        HEIGHT_TEXT,  HEIGHT_LONGTEXT, true)
-
+add_bool(CFG_PREFIX "showdots", false, NULL,
+                   SHOW_DOTS_TEXT, SHOW_DOTS_LONGTEXT, false)
 add_shortcut( "atmo" )
 set_callbacks( CreateFilter, DestroyFilter  )
 vlc_module_end ()
 
 
 static const char *const ppsz_filter_options[] = {
-#if defined(WIN32)
-        "usebuildin",
-#endif
+        "device",
+
         "serialdev",
 
 
-        "EdgeWeightning",
-        "Brightness",
-        "DarknessLimit",
-        "HueWinSize",
-        "SatWinSize",
+        "edgeweightning",
+        "brightness",
+        "darknesslimit",
+        "huewinsize",
+        "satwinsize",
 
         "filtermode",
 
-        "MeanLength",
-        "MeanThreshold",
-        "PercentNew",
-        "FrameDelay",
+        "meanlength",
+        "meanthreshold",
+        "percentnew",
+        "framedelay",
+
+        "zones-top",
+        "zones-bottom",
+        "zones-lr",
+        "zone-summary",
 
         "channel_0",
         "channel_1",
         "channel_2",
         "channel_3",
         "channel_4",
+        "channels",
 
         "whiteadj",
         "white-red",
@@ -516,9 +655,11 @@ static const char *const ppsz_filter_options[] = {
         "ecolor-blue",
         "efadesteps",
 
+        "dmx-channels",
+        "dmx-chbase",
+        "momo-channels",
 
 #if defined(WIN32 )
-        "usebuildin",
         "atmowinexe",
 #endif
 #if defined(__ATMO_DEBUG__)
@@ -527,11 +668,13 @@ static const char *const ppsz_filter_options[] = {
 #endif
         "width",
         "height",
+        "showdots",
         "gradient_zone_0",
         "gradient_zone_1",
         "gradient_zone_2",
         "gradient_zone_3",
         "gradient_zone_4",
+        "gradient_path",
         NULL
 };
 
@@ -574,13 +717,21 @@ struct filter_sys_t
     bool b_enabled;
     int32_t i_AtmoOldEffect;
     bool b_pause_live;
+    bool b_show_dots;
+    int32_t i_device_type;
 
     int32_t i_atmo_width;
     int32_t i_atmo_height;
+    /* used to disable fadeout if less than 50 frames are processed
+       used to avoid long time waiting when switch quickly between
+       deinterlaceing modes, where the output filter chains is rebuild
+       on each switch
+    */
+    int32_t i_frames_processed;
 
 #if defined(__ATMO_DEBUG__)
     bool  b_saveframes;
-    int i_framecounter;
+    uint32_t ui_frame_counter;
     char sz_framepath[MAX_PATH];
 #endif
 
@@ -635,6 +786,7 @@ struct filter_sys_t
                                                   int32_t , int32_t);
     uint8_t* (*pf_ctrl_atmo_lock_transfer_buffer) (void);
     void (*pf_ctrl_atmo_send_pixel_data) (void);
+    void (*pf_ctrl_atmo_get_image_size)(int32_t *,int32_t *);
 #endif
 };
 
@@ -656,18 +808,14 @@ static int32_t AtmoInitialize(filter_t *p_filter, bool b_for_thread)
         {
             /* 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, "open atmo device...");
+            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?");
+                msg_Err( p_filter,"failed to open atmo device, "\
+                                  "some other software/driver may use it?");
             }
         }
 #if defined(WIN32)
@@ -697,6 +845,15 @@ static void AtmoFinalize(filter_t *p_filter, int32_t what)
             {
                 p_atmo_dyndata->LockCriticalSection();
 
+                CAtmoInput *p_input = p_atmo_dyndata->getLiveInput();
+                p_atmo_dyndata->setLiveInput( NULL );
+                if(p_input != NULL)
+                {
+                    p_input->Terminate();
+                    delete p_input;
+                    msg_Dbg( p_filter, "input thread died peacefully");
+                }
+
                 CThread *p_effect_thread = p_atmo_dyndata->getEffectThread();
                 p_atmo_dyndata->setEffectThread(NULL);
                 if(p_effect_thread != NULL)
@@ -710,6 +867,15 @@ static void AtmoFinalize(filter_t *p_filter, int32_t what)
                     msg_Dbg( p_filter, "effect thread died peacefully");
                 }
 
+                CAtmoPacketQueue *p_queue =
+                                           p_atmo_dyndata->getLivePacketQueue();
+                p_atmo_dyndata->setLivePacketQueue( NULL );
+                if(p_queue != NULL)
+                {
+                   delete p_queue;
+                   msg_Dbg( p_filter, "packetqueue removed");
+                }
+
                 /*
                 close serial port if it is open (all OS specific is inside
                 CAtmoSerialConnection implemented / defined)
@@ -734,27 +900,22 @@ static void AtmoFinalize(filter_t *p_filter, int32_t what)
 }
 
 /*
-switch the current light effect - does only something on win32, with the
-external  libraries - if the buildin effects are used nothing happens
+  switch the current light effect to LiveView
 */
 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
-        */
+    msg_Dbg( p_filter, "AtmoSwitchEffect %d", newMode );
 
+    if(p_sys->p_atmo_config)
+    {
+       return CAtmoTools::SwitchEffect(p_sys->p_atmo_dyndata, emLivePicture);
 #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);
+        return p_sys->pf_ctrl_atmo_switch_effect( newMode );
 #endif
     }
     return emDisabled;
@@ -768,6 +929,9 @@ happens...
 static int32_t AtmoSetLiveSource(filter_t *p_filter, int32_t newSource)
 {
     filter_sys_t *p_sys = p_filter->p_sys;
+
+    msg_Dbg( p_filter, "AtmoSetLiveSource %d", newSource );
+
     if(p_sys->p_atmo_config)
     {
         /*
@@ -865,33 +1029,28 @@ static void AtmoSendPixelData(filter_t *p_filter)
     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)
+        if(p_atmo_dyndata &&
+          (p_atmo_dyndata->getLivePictureSource() == lpsExtern))
         {
             /*
             the cast will go Ok because we are inside videolan there is only
             this kind of effect thread implemented!
             */
+            CAtmoExternalCaptureInput *p_atmo_external_capture_input_thread =
+                (CAtmoExternalCaptureInput *)p_atmo_dyndata->getLiveInput();
 
-            CAtmoLiveView *p_atmo_live_view_thread =
-                (CAtmoLiveView *)p_atmo_dyndata->getEffectThread();
-            if(p_atmo_live_view_thread)
+            if(p_atmo_external_capture_input_thread)
             {
                 /*
                 the same as above inside videolan only this single kind of
                 input exists so we can cast without further tests!
+
+                this call will do a 1:1 copy of this buffer, and wakeup
+                the thread from normal sleeping
                 */
-                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);
-                }
+                p_atmo_external_capture_input_thread->
+                     DeliverNewSourceDataPaket(&p_sys->mini_image_format,
+                                               p_sys->p_atmo_transfer_buffer);
             }
         }
 #if defined(WIN32)
@@ -900,6 +1059,9 @@ static void AtmoSendPixelData(filter_t *p_filter)
         /* on win32 with active ctrl dll */
         p_sys->pf_ctrl_atmo_send_pixel_data();
 #endif
+    } else
+    {
+       msg_Warn( p_filter, "AtmoSendPixelData no method");
     }
 }
 
@@ -914,67 +1076,462 @@ static void Atmo_Shutdown(filter_t *p_filter)
 
     if(p_sys->b_enabled == true)
     {
+        msg_Dbg( p_filter, "shut down atmo!");
         /*
         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))
+        // perpare spawn fadeing thread
+        vlc_mutex_lock( &p_sys->filter_lock );
+
+        /*
+        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 = true;
+
+
+        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;
+        if(p_sys->i_frames_processed < 50)
+          p_sys->p_fadethread->i_steps  = 1;
+        else
+          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 ) )
         {
-            /*
-            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 = true;
+            msg_Err( p_filter, "cannot create FadeToColorThread" );
+            vlc_object_release( p_sys->p_fadethread );
+            p_sys->p_fadethread = NULL;
+            vlc_mutex_unlock( &p_sys->filter_lock );
 
-            // perpare spawn fadeing thread
-            vlc_mutex_lock( &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_release(p_sys->p_fadethread);
+
+            p_sys->p_fadethread = NULL;
+        }
+
+        /*
+           the following happens only useing the
+           external AtmoWin Device Software
+        */
+        if( !p_sys->p_atmo_config )
+        {
+           if(p_sys->i_AtmoOldEffect != emLivePicture)
+              AtmoSwitchEffect( p_filter, p_sys->i_AtmoOldEffect);
+           else
+              AtmoSetLiveSource( p_filter, lvsGDI );
+        }
+
+        /* close device connection etc. */
+        AtmoFinalize(p_filter, 1);
+
+        /* disable filter method .. */
+        p_sys->b_enabled = false;
+    }
+}
+
+/*
+depending on mode setup imagesize to 64x48(classic), or defined
+resolution of external atmowin.exe on windows
+*/
+static void Atmo_SetupImageSize(filter_t *p_filter)
+{
+    filter_sys_t *p_sys = p_filter->p_sys;
+    /*
+       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");
+
+    if(p_sys->p_atmo_config)
+    {
+#if defined(WIN32)
+    } else if(p_sys->pf_ctrl_atmo_get_image_size)
+    {
+        /* on win32 with active ctrl dll */
+        p_sys->pf_ctrl_atmo_get_image_size( &p_sys->i_atmo_width,
+                                            &p_sys->i_atmo_height );
+#endif
+    }
+
+    msg_Dbg(p_filter,"sample image size %d * %d pixels", p_sys->i_atmo_width,
+        p_sys->i_atmo_height);
+}
+
+/*
+initialize the zone and channel mapping for the buildin atmolight adapter
+*/
+static void Atmo_SetupBuildZones(filter_t *p_filter)
+{
+    filter_sys_t *p_sys = p_filter->p_sys;
+
+    p_sys->p_atmo_dyndata->LockCriticalSection();
+
+    CAtmoConfig *p_atmo_config = p_sys->p_atmo_config;
 
-            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;
+    CAtmoChannelAssignment *p_channel_assignment =
+                            p_atmo_config->getChannelAssignment(0);
 
-            if( vlc_thread_create( p_sys->p_fadethread,
-                "AtmoLight fadeing",
-                FadeToColorThread,
-                VLC_THREAD_PRIORITY_LOW ) )
+    // channel 0 - zone 4
+    p_channel_assignment->setZoneIndex( 0, var_CreateGetIntegerCommand(
+                                        p_filter, CFG_PREFIX "channel_0")
+                                        );
+
+    // channel 1 - zone 3
+    p_channel_assignment->setZoneIndex( 1, var_CreateGetIntegerCommand(
+                                        p_filter, CFG_PREFIX "channel_1")
+                                        );
+
+    // channel 2 - zone 1
+    p_channel_assignment->setZoneIndex( 2, var_CreateGetIntegerCommand(
+                                        p_filter, CFG_PREFIX "channel_2")
+                                        );
+
+    // channel 3 - zone 0
+    p_channel_assignment->setZoneIndex( 3, var_CreateGetIntegerCommand(
+                                        p_filter, CFG_PREFIX "channel_3")
+                                        );
+
+    // channel 4 - zone 2
+    p_channel_assignment->setZoneIndex( 4, var_CreateGetIntegerCommand(
+                                        p_filter, CFG_PREFIX "channel_4")
+                                        );
+
+    char *psz_channels = var_CreateGetStringCommand(
+              p_filter,
+              CFG_PREFIX "channels"
+            );
+    if( psz_channels && strlen(psz_channels) > 0 )
+    {
+        msg_Dbg( p_filter, "deal with new zone mapping %s", psz_channels );
+        int channel = 0;
+        char *psz_temp = psz_channels;
+        char *psz_start = psz_temp;
+        while( *psz_temp )
+        {
+            if(*psz_temp == ',' || *psz_temp == ';')
             {
-                msg_Err( p_filter, "cannot create FadeToColorThread" );
-                vlc_object_release( p_sys->p_fadethread );
-                p_sys->p_fadethread = NULL;
-                vlc_mutex_unlock( &p_sys->filter_lock );
+                *psz_temp = 0;
+                if(*psz_start)
+                {
+                    int zone = atoi( psz_start );
+                    if( zone < -1 ||
+                        zone >= p_channel_assignment->getSize()) {
+                         msg_Warn( p_filter, "Zone %d out of range -1..%d",
+                                zone, p_channel_assignment->getSize()-1 );
+                    } else {
+                        p_channel_assignment->setZoneIndex( channel, zone );
+                        channel++;
+                    }
+                }
+                psz_start = psz_temp;
+                psz_start++;
+            }
 
+            psz_temp++;
+        }
+
+        /*
+          process the rest of the string
+        */
+        if( *psz_start && !*psz_temp )
+        {
+            int zone = atoi( psz_start );
+            if( zone < -1 ||
+                zone >= p_channel_assignment->getSize()) {
+                msg_Warn( p_filter, "Zone %d out of range -1..%d",
+                            zone, p_channel_assignment->getSize()-1 );
             } else {
+                p_channel_assignment->setZoneIndex( channel, zone );
+            }
+        }
+    }
+    free( psz_channels );
+
+    for(int i=0;i< p_channel_assignment->getSize() ;i++)
+        msg_Info( p_filter, "map zone %d to hardware channel %d",
+        p_channel_assignment->getZoneIndex( i ),
+        i
+        );
+    p_sys->p_atmo_dyndata->getAtmoConnection()
+         ->SetChannelAssignment( p_channel_assignment );
+
 
-                vlc_mutex_unlock( &p_sys->filter_lock );
 
-                /* wait for the thread... */
-                vlc_thread_join(p_sys->p_fadethread);
 
-                vlc_object_release(p_sys->p_fadethread);
 
-                p_sys->p_fadethread = NULL;
+    /*
+      calculate the default gradients for each zone!
+      depending on the zone layout set before, this now
+      supports also multiple gradients on each side
+      (older versions could do this only with external
+      gradient bitmaps)
+    */
+    p_sys->p_atmo_dyndata->CalculateDefaultZones();
+
+
+    /*
+      first try to load the old style defined gradient bitmaps
+      this could only be done for the first five zones
+      - should be deprecated -
+    */
+    CAtmoZoneDefinition *p_zone;
+    char psz_gradient_var_name[30];
+    char *psz_gradient_file;
+    for(int i=0;i<CLASSIC_ATMO_NUM_ZONES;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);
+
+            p_zone = p_atmo_config->getZoneDefinition(i);
+            if( p_zone )
+            {
+                int i_res = p_zone->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);
+                }
             }
         }
+        free( psz_gradient_file );
+    }
 
-        if(p_sys->i_AtmoOldEffect != emLivePicture)
-            AtmoSwitchEffect(p_filter, p_sys->i_AtmoOldEffect);
-        else
-            AtmoSetLiveSource(p_filter, lvsGDI);
 
-        AtmoFinalize(p_filter, 1);
+    /*
+      the new approach try to load a gradient bitmap for each zone
+      from a previously defined folder containing
+      zone_0.bmp
+      zone_1.bmp
+      zone_2.bmp etc.
+    */
+    char *psz_gradient_path = var_CreateGetStringCommand(
+              p_filter,
+              CFG_PREFIX "gradient_path"
+            );
+    if( psz_gradient_path && strlen(psz_gradient_path) > 0 )
+    {
+        char *psz_file_name = (char *)malloc( strlen(psz_gradient_path) + 16 );
+        assert( psz_file_name );
 
-        /* disable filter method .. */
-        p_sys->b_enabled = false;
+        for(int i=0; i < p_atmo_config->getZoneCount(); i++ )
+        {
+            p_zone = p_atmo_config->getZoneDefinition(i);
+
+            if( p_zone )
+            {
+                sprintf(psz_file_name, "%s%szone_%d.bmp",
+                                            psz_gradient_path, DIR_SEP, i );
+
+                int i_res = p_zone->LoadGradientFromBitmap( psz_file_name );
+
+                if( i_res == ATMO_LOAD_GRADIENT_OK )
+                {
+                msg_Dbg( p_filter, "loaded gradientfile %s for "\
+                                   "zone %d", psz_file_name, i);
+                }
+
+                if( (i_res != ATMO_LOAD_GRADIENT_OK) &&
+                    (i_res != ATMO_LOAD_GRADIENT_FILENOTFOND) )
+                {
+                    msg_Err( p_filter,"failed to load gradient '%s' with "\
+                                    "error %d",psz_file_name,i_res);
+                }
+            }
+        }
+
+        free( psz_file_name );
+    }
+    free( psz_gradient_path );
+
+
+    p_sys->p_atmo_dyndata->UnLockCriticalSection();
+
+}
+
+static void Atmo_SetupConfig(filter_t *p_filter, CAtmoConfig *p_atmo_config)
+{
+    /*
+       figuring out the device ports (com-ports, ttys)
+    */
+    char *psz_serialdev = var_CreateGetStringCommand( p_filter,
+                                                      CFG_PREFIX "serialdev" );
+    char *psz_temp = psz_serialdev;
+
+    if( psz_temp && strlen(psz_temp) > 0 )
+    {
+        char *psz_token;
+        int i_port = 0;
+        int i;
+        int j;
+
+        msg_Dbg( p_filter, "use port(s) %s",psz_serialdev);
+
+        /*
+          psz_serialdev - may contain up to 4 COM ports for the quattro device
+          the quattro device is just hack of useing 4 classic devices as one
+          logical device - thanks that usb-com-ports exists :)
+          as Seperator I defined , or ; with the hope that these
+          characters are never part of a device name
+        */
+        while( (psz_token = strsep(&psz_temp, ",;")) != NULL && i_port < 4 )
+        {
+            /*
+              psz_token may contain spaces we have to trim away
+            */
+            i = 0;
+            j = 0;
+            /*
+              find first none space in string
+            */
+            while( psz_token[i] == 32 ) i++;
+            /*
+              contains string only spaces or is empty? skip it
+            */
+            if( !psz_token[i] )
+                continue;
+
+            /*
+              trim
+            */
+            while( psz_token[i] && psz_token[i] != 32 )
+                psz_token[ j++ ] = psz_token[ i++ ];
+            psz_token[j++] = 0;
+
+            msg_Dbg( p_filter, "Serial Device [%d]: %s", i_port, psz_token );
+
+            p_atmo_config->setSerialDevice( i_port, psz_token );
+
+            i_port++;
+        }
+    }
+    else
+    {
+       msg_Err(p_filter,"no serial devicename(s) set");
     }
+    free( psz_serialdev );
+
+    /*
+      configuration of light source layout arround the display
+    */
+    p_atmo_config->setZonesTopCount(
+        var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "zones-top")
+        );
+    p_atmo_config->setZonesBottomCount(
+        var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "zones-bottom")
+        );
+    p_atmo_config->setZonesLRCount(
+        var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "zones-lr")
+        );
+    p_atmo_config->setZoneSummary(
+        var_CreateGetBoolCommand( p_filter, CFG_PREFIX "zone-summary")
+        );
+
+
+    p_atmo_config->setLiveViewFilterMode(
+        (AtmoFilterMode)var_CreateGetIntegerCommand( p_filter,
+                                                CFG_PREFIX "filtermode")
+        );
+
+    p_atmo_config->setLiveViewFilter_PercentNew(
+        var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "percentnew")
+        );
+    p_atmo_config->setLiveViewFilter_MeanLength(
+        var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "meanlength")
+        );
+    p_atmo_config->setLiveViewFilter_MeanThreshold(
+        var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "meanthreshold")
+        );
+
+    p_atmo_config->setLiveView_EdgeWeighting(
+        var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "edgeweightning")
+        );
+    p_atmo_config->setLiveView_BrightCorrect(
+        var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "brightness")
+        );
+    p_atmo_config->setLiveView_DarknessLimit(
+        var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "darknesslimit")
+        );
+    p_atmo_config->setLiveView_HueWinSize(
+        var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "huewinsize")
+        );
+    p_atmo_config->setLiveView_SatWinSize(
+        var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "satwinsize")
+        );
+
+    /* currently not required inside vlc */
+    p_atmo_config->setLiveView_WidescreenMode( 0 );
+
+    p_atmo_config->setLiveView_FrameDelay(
+        var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "framedelay")
+        );
+
+
+    p_atmo_config->setUseSoftwareWhiteAdj(
+        var_CreateGetBoolCommand( p_filter, CFG_PREFIX "whiteadj")
+        );
+    p_atmo_config->setWhiteAdjustment_Red(
+        var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "white-red")
+        );
+    p_atmo_config->setWhiteAdjustment_Green(
+        var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "white-green")
+        );
+    p_atmo_config->setWhiteAdjustment_Blue(
+        var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "white-blue")
+        );
+
+    /*
+      settings for DMX device only
+    */
+    p_atmo_config->setDMX_RGB_Channels(
+        var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "dmx-channels")
+        );
+
+    char *psz_chbase = var_CreateGetStringCommand( p_filter,
+                                                   CFG_PREFIX "dmx-chbase" );
+    if( psz_chbase && strlen(psz_chbase) > 0 )
+        p_atmo_config->setDMX_BaseChannels( psz_chbase );
+
+    free( psz_chbase );
+
+    /*
+      momolight options
+    */
+    p_atmo_config->setMoMo_Channels(
+        var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "momo-channels")
+       );
 }
 
+
 /*
 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,
@@ -982,7 +1539,6 @@ if this fails fallback to the buildin software
 */
 static void Atmo_SetupParameters(filter_t *p_filter)
 {
-    bool b_use_buildin_driver = true;
     char *psz_path;
     filter_sys_t *p_sys =  p_filter->p_sys;
 
@@ -994,8 +1550,16 @@ static void Atmo_SetupParameters(filter_t *p_filter)
     p_sys->i_atmo_width          = 64;
     p_sys->i_atmo_height         = 48;
 
+    p_sys->i_device_type = var_CreateGetIntegerCommand( p_filter,
+                                                        CFG_PREFIX "device");
 
-    vlc_mutex_init( &p_sys->filter_lock );
+    /*
+      i_device_type
+       0 => use AtmoWin Software (only win32)
+       1 => use AtmoClassicConnection (direct)
+       2 => use AtmoMultiConnection (direct up to four serial ports required)
+       3 => use AtmoDmxConnection (simple serial DMX Device up to 255 channels)
+    */
 
 
 #if defined(WIN32)
@@ -1003,16 +1567,45 @@ static void Atmo_SetupParameters(filter_t *p_filter)
     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 == false) {
+    if(p_sys->i_device_type == 0) {
 
         /* Load the Com Wrapper Library (source available) */
         p_sys->h_AtmoCtrl = LoadLibraryA("AtmoCtrlLib.dll");
+        if(p_sys->h_AtmoCtrl == NULL)
+        {
+            /*
+              be clever if the location of atmowina.exe is set
+              try to load the dll from the same folder :-)
+            */
+            char *psz_path = var_CreateGetStringCommand( p_filter,
+                                               CFG_PREFIX "atmowinexe" );
+            if( psz_path && strlen(psz_path) > 0 )
+            {
+                char *psz_bs = strrchr( psz_path , '\\');
+                if( psz_bs )
+                {
+                    *psz_bs = 0;
+                    /*
+                      now format a new dll filename with complete path
+                    */
+                    char *psz_dllname = NULL;
+                    asprintf( &psz_dllname, "%s\\AtmoCtrlLib.dll", psz_path );
+                    if( psz_dllname )
+                    {
+                        msg_Dbg( p_filter, "Try Loading '%s'", psz_dllname );
+                        p_sys->h_AtmoCtrl = LoadLibraryA( psz_dllname );
+                    }
+                    free( psz_dllname );
+                }
+            }
+            free( psz_path );
+        }
+
+
         if(p_sys->h_AtmoCtrl != NULL)
         {
-            msg_Dbg( p_filter, "LoadLibrary('AtmoCtrlLib.dll'); Success");
+            msg_Dbg( p_filter, "Load Library ok!");
 
             /* importing all required functions I hope*/
             p_sys->pf_ctrl_atmo_initialize =
@@ -1049,155 +1642,71 @@ static void Atmo_SetupParameters(filter_t *p_filter)
                 (void (*)(void))GetProcAddress(p_sys->h_AtmoCtrl,"AtmoSendPixelData");
             if(!p_sys->pf_ctrl_atmo_send_pixel_data)
                 msg_Err( p_filter, "export AtmoSendPixelData missing.");
+
+            p_sys->pf_ctrl_atmo_get_image_size =
+                (void (*)(int32_t*,int32_t*))GetProcAddress(p_sys->h_AtmoCtrl,"AtmoWinGetImageSize");
+            if(!p_sys->pf_ctrl_atmo_get_image_size)
+                msg_Err( p_filter, "export AtmoWinGetImageSize missing.");
+
         } else {
             /* the DLL is missing try internal filter ...*/
-            msg_Warn( p_filter, "AtmoCtrlLib.dll missing fallback to internal driver");
-            b_use_buildin_driver = true;
+            msg_Warn( p_filter, "AtmoCtrlLib.dll missing fallback to internal atmo classic driver");
+            p_sys->i_device_type = 1;
         }
     }
 #endif
 
-
-    if(b_use_buildin_driver == true) {
-        msg_Dbg( p_filter, "use buildin driver");
+    if(p_sys->i_device_type >= 1) {
+        msg_Dbg( p_filter, "try use buildin driver %d ", p_sys->i_device_type );
         /*
         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);
+        p_sys->p_atmo_config = new CAtmoConfig();
 
-                    if(i_res != ATMO_LOAD_GRADIENT_OK)
-                    {
-                        msg_Err( p_filter,"failed to load gradient '%s' with "\
-                                          "error %d",psz_gradient_file,i_res);
-                    }
-                }
-                free( psz_gradient_file );
-            }
+        p_sys->p_atmo_dyndata = new CAtmoDynData(
+                   (vlc_object_t *)p_filter,
+                   p_sys->p_atmo_config
+        );
 
-            p_sys->p_atmo_dyndata = new CAtmoDynData((vlc_object_t *)p_filter,
-                p_sys->p_atmo_config
-                );
+        Atmo_SetupConfig( p_filter, p_sys->p_atmo_config );
+        switch(p_sys->i_device_type)
+        {
+            case 1:
+                p_sys->p_atmo_config->setConnectionType( actClassicAtmo );
+                break;
 
-            msg_Dbg( p_filter, "buildin driver initialized");
+            case 2:
+                p_sys->p_atmo_config->setConnectionType( actMultiAtmo );
+                break;
 
-            free(psz_serialdev);
-        } else {
-            msg_Err(p_filter,"no serial devicename set");
+            case 3:
+                p_sys->p_atmo_config->setConnectionType( actDMX );
+                break;
+
+            case 4:
+                p_sys->p_atmo_config->setConnectionType( actMoMoLight );
+                break;
+
+            default:
+                msg_Warn( p_filter, "invalid device type %d found",
+                                    p_sys->i_device_type );
         }
+
+        msg_Dbg( p_filter, "buildin driver config set");
+
     }
 
     switch( p_filter->fmt_in.video.i_chroma )
     {
     case VLC_CODEC_I420:
     case VLC_CODEC_YV12:
-        // simple enough? Dionoea?
         p_sys->pf_extract_mini_image = ExtractMiniImage_YUV;
         break;
     default:
-        msg_Dbg( p_filter, "InitFilter-unsupported chroma: %4.4s",
+        msg_Warn( p_filter, "InitFilter-unsupported chroma: %4.4s",
                             (char *)&p_filter->fmt_in.video.i_chroma);
         p_sys->pf_extract_mini_image = NULL;
     }
@@ -1212,6 +1721,13 @@ static void Atmo_SetupParameters(filter_t *p_filter)
         p_sys->i_crop_width,
         p_sys->i_crop_height );
 
+    /*
+    for debugging purpose show the samplinggrid on each frame as
+    white dots
+    */
+    p_sys->b_show_dots = var_CreateGetBoolCommand( p_filter,
+        CFG_PREFIX "showdots"
+        );
 
 #if defined(__ATMO_DEBUG__)
     /* save debug images to a folder as Bitmap files ? */
@@ -1240,16 +1756,6 @@ static void Atmo_SetupParameters(filter_t *p_filter)
     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
@@ -1296,15 +1802,20 @@ static void Atmo_SetupParameters(filter_t *p_filter)
         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!
+
+
+    /*
+      if the external DLL was loaded successfully call AtmoInitialize -
+      (must be done for each thread where you want to use AtmoLight!)
     */
     int i = AtmoInitialize(p_filter, false);
+
 #if defined( WIN32 )
-    if((i != 1) && !b_use_buildin_driver)
+    if((i != 1) && (p_sys->i_device_type == 0))
     {
-        /* COM Server for AtmoLight not running ?
-        if the exe path is configured try to start the "userspace" 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" );
@@ -1320,8 +1831,8 @@ static void Atmo_SetupParameters(filter_t *p_filter)
                 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
+                  retry to initialize the library COM ... functionality
+                  after the server was launched
                 */
                 i = AtmoInitialize(p_filter, false);
             } else {
@@ -1335,6 +1846,24 @@ static void Atmo_SetupParameters(filter_t *p_filter)
     if(i == 1) /* Init Atmolight success... */
     {
         msg_Dbg( p_filter, "AtmoInitialize Ok!");
+        /*
+        configure
+           p_sys->i_atmo_width and p_sys->i_atmo_height
+           if the external AtmoWinA.exe is used, it may require
+           a other sample image size than 64 x 48
+           (this overrides the settings of the filter)
+        */
+        Atmo_SetupImageSize( p_filter );
+
+
+        if( p_sys->i_device_type >= 1 )
+        {
+           /*
+             AtmoConnection class initialized now we can initialize
+             the default zone and channel mappings
+           */
+           Atmo_SetupBuildZones( p_filter );
+        }
 
         /* Setup Transferbuffers for 64 x 48 , RGB with 32bit Per Pixel */
         AtmoCreateTransferBuffers(p_filter, BI_RGB, 4,
@@ -1344,6 +1873,7 @@ static void Atmo_SetupParameters(filter_t *p_filter)
 
         /* say the userspace driver that a live mode should be activated
         the functions returns the old mode for later restore!
+        - the buildin driver launches the live view thread in that case
         */
         p_sys->i_AtmoOldEffect = AtmoSwitchEffect(p_filter, emLivePicture);
 
@@ -1356,6 +1886,8 @@ static void Atmo_SetupParameters(filter_t *p_filter)
 
         /* enable other parts only if everything is fine */
         p_sys->b_enabled = true;
+
+        msg_Dbg( p_filter, "Atmo Filter Enabled Ok!");
     }
 
 }
@@ -1378,6 +1910,9 @@ static int CreateFilter( vlc_object_t *p_this )
         return VLC_ENOMEM;
     /* set all entries to zero */
     memset(p_sys, 0, sizeof( filter_sys_t ));
+    vlc_mutex_init( &p_sys->filter_lock );
+
+    msg_Dbg( p_filter, "Create Atmo Filter");
 
     /* further Setup Function pointers for videolan for calling my filter */
     p_filter->pf_video_filter = Filter;
@@ -1410,6 +1945,8 @@ 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;
 
+    msg_Dbg( p_filter, "Destroy Atmo Filter");
+
     DelStateVariableCallback(p_filter);
     DelCropVariableCallback(p_filter);
     DelAtmoSettingsVariablesCallbacks(p_filter);
@@ -1574,7 +2111,33 @@ static void ExtractMiniImage_YUV(filter_sys_t *p_sys,
             p_rgb_dst_line_green += 4;
             p_rgb_dst_line_blue  += 4;
         }
-    }
+   }
+
+   if(p_sys->b_show_dots)
+   {
+       for(i_row = 1; i_row < i_row_count; i_row++)
+       {
+           i_pixel_row = (i_row * p_sys->i_crop_height) / i_row_count
+                   + p_sys->i_crop_y_offset;
+
+           i_y_row = (i_pixel_row * p_inpic->p[Y_PLANE].i_visible_lines) /
+                   p_inpic->format.i_visible_height;
+
+           p_src_y = p_inpic->p[Y_PLANE].p_pixels +
+                   p_inpic->p[Y_PLANE].i_pitch * i_y_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;
+              i_xpos_y = (i_pixel_col * p_inpic->p[Y_PLANE].i_visible_pitch) /
+                         p_inpic->format.i_visible_width;
+
+              p_src_y[i_xpos_y] = 255;
+           }
+       }
+   }
+
 }
 
 
@@ -1610,7 +2173,7 @@ void SaveBitmap(filter_sys_t *p_sys, uint8_t *p_pixels, char *psz_filename)
     bmp_fileheader.bfSize = sizeof(BITMAPFILEHEADER) +
                             sizeof(BITMAPINFOHEADER) +
                             bmp_info.bmiHeader.biSizeImage;
-    bmp_fileheader.bfType = VLC_TWOCC('M','B');
+    bmp_fileheader.bfType = VLC_TWOCC('B','M');
     bmp_fileheader.bfOffBits = sizeof(BITMAPFILEHEADER) +
                                sizeof(BITMAPINFOHEADER);
 
@@ -1638,7 +2201,7 @@ static void CreateMiniImage( filter_t *p_filter, picture_t *p_inpic)
     pointer to RGB Buffer created in external libary as safe array which
     is locked inside AtmoLockTransferBuffer
     */
-    uint8_t *p_transfer = NULL;
+    uint8_t *p_transfer;
 #if defined( __ATMO_DEBUG__ )
     /* for debug out only used*/
     char sz_filename[MAX_PATH];
@@ -1672,20 +2235,25 @@ static void CreateMiniImage( filter_t *p_filter, picture_t *p_inpic)
     if((p_sys->b_saveframes == true) && (p_sys->sz_framepath[0] != 0 ))
     {
 
-        if((p_sys->i_framecounter & 127) == 0)
+        if((p_sys->ui_frame_counter & 127) == 0)
         {
-            sprintf(sz_filename,"%satmo_dbg_%06d.bmp",p_sys->sz_framepath,
-                p_sys->i_framecounter);
+            sprintf(sz_filename,"%satmo_dbg_%06u.bmp",p_sys->sz_framepath,
+                p_sys->ui_frame_counter);
             msg_Dbg(p_filter, "SaveFrame %s",sz_filename);
 
             SaveBitmap(p_sys, p_transfer, sz_filename);
         }
-        p_sys->i_framecounter++;
     }
+
+    msg_Dbg( p_filter, "AtmoFrame %u Time: %d ms", p_sys->ui_frame_counter, mdate() / 1000);
+    p_sys->ui_frame_counter++;
 #endif
 
+    p_sys->i_frames_processed++;
+
+
     /* show the colors on the wall */
-    AtmoSendPixelData(p_filter);
+    AtmoSendPixelData( p_filter );
 }
 
 
@@ -1702,6 +2270,8 @@ 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;
 
+    vlc_mutex_lock( &p_sys->filter_lock );
+
     if((p_sys->b_enabled == true) &&
         (p_sys->pf_extract_mini_image != NULL) &&
         (p_sys->b_pause_live == false))
@@ -1709,6 +2279,10 @@ static picture_t * Filter( filter_t *p_filter, picture_t *p_pic )
         CreateMiniImage(p_filter, p_pic);
     }
 
+    vlc_mutex_unlock( &p_sys->filter_lock );
+
+
+
     return p_pic;
 }
 
@@ -1802,14 +2376,7 @@ static void *FadeToColorThread(vlc_object_t *obj)
                 the VLC libaries? inside native win32 I would use an Event
                 (CreateEvent) and here an WaitForSingleObject?
                 */
-                if(!vlc_object_alive (p_fadethread)) break;
-                msleep(10000);
-                if(!vlc_object_alive (p_fadethread)) break;
-                msleep(10000);
-                if(!vlc_object_alive (p_fadethread)) break;
-                msleep(10000);
-                if(!vlc_object_alive (p_fadethread)) break;
-                msleep(10000);
+                msleep(40000);
             }
             free(p_source);
         } else {
@@ -1869,8 +2436,8 @@ static int StateCallback( vlc_object_t *p_this, char const *psz_cmd,
                controller */
             p_sys->b_pause_live = true;
 
-            // ggf. alten Thread abräumen should not happen....
-            CheckAndStopFadeThread(p_filter);
+            // clean up old thread - should not happen....
+            CheckAndStopFadeThread( p_filter );
 
             // perpare spawn fadeing thread
             vlc_mutex_lock( &p_sys->filter_lock );
@@ -1906,7 +2473,7 @@ static int StateCallback( vlc_object_t *p_this, char const *psz_cmd,
         if((newval.i_int == PLAYING_S) && (oldval.i_int == PAUSE_S))
         {
             /* playback continues check thread state */
-            CheckAndStopFadeThread(p_filter);
+            CheckAndStopFadeThread( p_filter );
             /* reactivate the Render function... to do its normal work */
             p_sys->b_pause_live = false;
         }
@@ -1920,7 +2487,7 @@ static int StateCallback( vlc_object_t *p_this, char const *psz_cmd,
 *****************************************************************************
 * 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??
+* my callback?
 *****************************************************************************/
 static void AddStateVariableCallback(filter_t *p_filter)
 {
@@ -2029,6 +2596,13 @@ static int AtmoSettingsCallback( vlc_object_t *p_this, char const *psz_var,
     filter_t *p_filter = (filter_t *)p_data;
     filter_sys_t *p_sys = (filter_sys_t *)p_filter->p_sys;
 
+    vlc_mutex_lock( &p_sys->filter_lock );
+
+    if( !strcmp( psz_var, CFG_PREFIX "showdots" ))
+    {
+        p_sys->b_show_dots = newval.b_bool;
+    }
+
     CAtmoConfig *p_atmo_config = p_sys->p_atmo_config;
     if(p_atmo_config)
     {
@@ -2042,31 +2616,31 @@ static int AtmoSettingsCallback( vlc_object_t *p_this, char const *psz_var,
         if( !strcmp( psz_var, CFG_PREFIX "filtermode" ))
             p_atmo_config->setLiveViewFilterMode( (AtmoFilterMode)newval.i_int);
 
-        else if( !strcmp( psz_var, CFG_PREFIX "PercentNew" ))
+        else if( !strcmp( psz_var, CFG_PREFIX "percentnew" ))
                  p_atmo_config->setLiveViewFilter_PercentNew( newval.i_int );
 
-        else if( !strcmp( psz_var, CFG_PREFIX "MeanLength" ))
+        else if( !strcmp( psz_var, CFG_PREFIX "meanlength" ))
                  p_atmo_config->setLiveViewFilter_MeanLength( newval.i_int );
 
-        else if( !strcmp( psz_var, CFG_PREFIX "MeanThreshold" ))
+        else if( !strcmp( psz_var, CFG_PREFIX "meanthreshold" ))
                  p_atmo_config->setLiveViewFilter_MeanThreshold( newval.i_int );
 
-        else if( !strcmp( psz_var, CFG_PREFIX "EdgeWeightning" ))
+        else if( !strcmp( psz_var, CFG_PREFIX "edgeweightning" ))
                  p_atmo_config->setLiveView_EdgeWeighting( newval.i_int );
 
-        else if( !strcmp( psz_var, CFG_PREFIX "Brightness" ))
+        else if( !strcmp( psz_var, CFG_PREFIX "brightness" ))
                  p_atmo_config->setLiveView_BrightCorrect( newval.i_int );
 
-        else if( !strcmp( psz_var, CFG_PREFIX "DarknessLimit" ))
+        else if( !strcmp( psz_var, CFG_PREFIX "darknesslimit" ))
                  p_atmo_config->setLiveView_DarknessLimit( newval.i_int );
 
-        else if( !strcmp( psz_var, CFG_PREFIX "HueWinSize" ))
+        else if( !strcmp( psz_var, CFG_PREFIX "huewinsize" ))
                  p_atmo_config->setLiveView_HueWinSize( newval.i_int );
 
-        else if( !strcmp( psz_var, CFG_PREFIX "SatWinSize" ))
+        else if( !strcmp( psz_var, CFG_PREFIX "satwinsize" ))
                  p_atmo_config->setLiveView_SatWinSize( newval.i_int );
 
-        else if( !strcmp( psz_var, CFG_PREFIX "FrameDelay" ))
+        else if( !strcmp( psz_var, CFG_PREFIX "framedelay" ))
                  p_atmo_config->setLiveView_FrameDelay( newval.i_int );
 
         else if( !strcmp( psz_var, CFG_PREFIX "whiteadj" ))
@@ -2082,6 +2656,9 @@ static int AtmoSettingsCallback( vlc_object_t *p_this, char const *psz_var,
                  p_atmo_config->setWhiteAdjustment_Blue( newval.i_int );
 
     }
+
+    vlc_mutex_unlock( &p_sys->filter_lock );
+
     return VLC_SUCCESS;
 }
 
@@ -2089,27 +2666,27 @@ static void AddAtmoSettingsVariablesCallbacks(filter_t *p_filter)
 {
    var_AddCallback( p_filter, CFG_PREFIX "filtermode",
                     AtmoSettingsCallback, p_filter );
-   var_AddCallback( p_filter, CFG_PREFIX "PercentNew",
+   var_AddCallback( p_filter, CFG_PREFIX "percentnew",
                     AtmoSettingsCallback, p_filter );
 
 
-   var_AddCallback( p_filter, CFG_PREFIX "MeanLength",
+   var_AddCallback( p_filter, CFG_PREFIX "meanlength",
                     AtmoSettingsCallback, p_filter );
-   var_AddCallback( p_filter, CFG_PREFIX "MeanThreshold",
+   var_AddCallback( p_filter, CFG_PREFIX "meanthreshold",
                     AtmoSettingsCallback, p_filter );
 
-   var_AddCallback( p_filter, CFG_PREFIX "EdgeWeightning",
+   var_AddCallback( p_filter, CFG_PREFIX "edgeweightning",
                     AtmoSettingsCallback, p_filter );
-   var_AddCallback( p_filter, CFG_PREFIX "Brightness",
+   var_AddCallback( p_filter, CFG_PREFIX "brightness",
                     AtmoSettingsCallback, p_filter );
-   var_AddCallback( p_filter, CFG_PREFIX "DarknessLimit",
+   var_AddCallback( p_filter, CFG_PREFIX "darknesslimit",
                     AtmoSettingsCallback, p_filter );
 
-   var_AddCallback( p_filter, CFG_PREFIX "HueWinSize",
+   var_AddCallback( p_filter, CFG_PREFIX "huewinsize",
                     AtmoSettingsCallback, p_filter );
-   var_AddCallback( p_filter, CFG_PREFIX "SatWinSize",
+   var_AddCallback( p_filter, CFG_PREFIX "satwinsize",
                     AtmoSettingsCallback, p_filter );
-   var_AddCallback( p_filter, CFG_PREFIX "FrameDelay",
+   var_AddCallback( p_filter, CFG_PREFIX "framedelay",
                     AtmoSettingsCallback, p_filter );
 
 
@@ -2121,6 +2698,10 @@ static void AddAtmoSettingsVariablesCallbacks(filter_t *p_filter)
                     AtmoSettingsCallback, p_filter );
    var_AddCallback( p_filter, CFG_PREFIX "white-blue",
                     AtmoSettingsCallback, p_filter );
+
+   var_AddCallback( p_filter, CFG_PREFIX "showdots",
+                    AtmoSettingsCallback, p_filter );
+
 }
 
 static void DelAtmoSettingsVariablesCallbacks( filter_t *p_filter )
@@ -2129,25 +2710,25 @@ static void DelAtmoSettingsVariablesCallbacks( filter_t *p_filter )
    var_DelCallback( p_filter, CFG_PREFIX "filtermode",
                     AtmoSettingsCallback, p_filter );
 
-   var_DelCallback( p_filter, CFG_PREFIX "PercentNew",
+   var_DelCallback( p_filter, CFG_PREFIX "percentnew",
                     AtmoSettingsCallback, p_filter );
-   var_DelCallback( p_filter, CFG_PREFIX "MeanLength",
+   var_DelCallback( p_filter, CFG_PREFIX "meanlength",
                     AtmoSettingsCallback, p_filter );
-   var_DelCallback( p_filter, CFG_PREFIX "MeanThreshold",
+   var_DelCallback( p_filter, CFG_PREFIX "meanthreshold",
                     AtmoSettingsCallback, p_filter );
 
-   var_DelCallback( p_filter, CFG_PREFIX "EdgeWeightning",
+   var_DelCallback( p_filter, CFG_PREFIX "edgeweightning",
                     AtmoSettingsCallback, p_filter );
-   var_DelCallback( p_filter, CFG_PREFIX "Brightness",
+   var_DelCallback( p_filter, CFG_PREFIX "brightness",
                     AtmoSettingsCallback, p_filter );
-   var_DelCallback( p_filter, CFG_PREFIX "DarknessLimit",
+   var_DelCallback( p_filter, CFG_PREFIX "darknesslimit",
                     AtmoSettingsCallback, p_filter );
 
-   var_DelCallback( p_filter, CFG_PREFIX "HueWinSize",
+   var_DelCallback( p_filter, CFG_PREFIX "huewinsize",
                     AtmoSettingsCallback, p_filter );
-   var_DelCallback( p_filter, CFG_PREFIX "SatWinSize",
+   var_DelCallback( p_filter, CFG_PREFIX "satwinsize",
                     AtmoSettingsCallback, p_filter );
-   var_DelCallback( p_filter, CFG_PREFIX "FrameDelay",
+   var_DelCallback( p_filter, CFG_PREFIX "framedelay",
                     AtmoSettingsCallback, p_filter );
 
 
@@ -2160,6 +2741,9 @@ static void DelAtmoSettingsVariablesCallbacks( filter_t *p_filter )
    var_DelCallback( p_filter, CFG_PREFIX "white-blue",
                     AtmoSettingsCallback, p_filter );
 
+   var_DelCallback( p_filter, CFG_PREFIX "showdots",
+                    AtmoSettingsCallback, p_filter );
+
 }