]> git.sesse.net Git - vlc/commitdiff
atmo: add support for Fnordlicht devices
authorKai Lauterbach <lauterbach.kai@web.de>
Thu, 3 Jun 2010 17:21:52 +0000 (19:21 +0200)
committerAndré Weber <atmo@videolan.org>
Thu, 3 Jun 2010 17:24:24 +0000 (19:24 +0200)
The Fnordlicht-Class implements only parts of the fnordlicht-protocol:
sync, stop, start_bootloader, boot_enter_application and fade_rgb
Have a look at http://github.com/fd0/fnordlicht/raw/master/doc/PROTOCOL
for more details.

Signed-off-by: André Weber <atmo@videolan.org>
modules/video_filter/Modules.am
modules/video_filter/atmo/AtmoConfig.cpp
modules/video_filter/atmo/AtmoConfig.h
modules/video_filter/atmo/AtmoDefs.h
modules/video_filter/atmo/AtmoTools.cpp
modules/video_filter/atmo/FnordlichtConnection.cpp [new file with mode: 0644]
modules/video_filter/atmo/FnordlichtConnection.h [new file with mode: 0644]
modules/video_filter/atmo/atmo.cpp

index b6c13773deea3fe5be91e2a038578c24a92d16a2..ea46c31c6801474a8be43106df7359dbcedf8123 100644 (file)
@@ -71,6 +71,7 @@ SOURCES_atmo = atmo/atmo.cpp \
        atmo/DmxTools.cpp atmo/DmxTools.h \
        atmo/AtmoMultiConnection.cpp atmo/AtmoMultiConnection.h \
        atmo/MoMoConnection.cpp atmo/MoMoConnection.h \
+       atmo/FnordlichtConnection.cpp atmo/FnordlichtConnection.h \
        atmo/AtmoPacketQueue.cpp atmo/AtmoPacketQueue.h
 SOURCES_gradfun = gradfun.c gradfun.h
 noinst_HEADERS = filter_picture.h
index ec6c519587c0c5c6057f6e0493cd65079a4d7195..1003ff08bd0361ac9aa2fb6f5b8b5b226e2ba89a 100644 (file)
@@ -44,6 +44,10 @@ CAtmoConfig::CAtmoConfig()
   m_AtmoZoneDefCount = -1;
   m_DMX_BaseChannels = NULL;
 
+  m_chWhiteAdj_Red   = NULL;
+  m_chWhiteAdj_Green = NULL;
+  m_chWhiteAdj_Blue  = NULL;
+
   LoadDefaults();
 }
 
@@ -59,6 +63,10 @@ CAtmoConfig::~CAtmoConfig() {
      m_ZoneDefinitions = NULL;
    }
 
+   delete []m_chWhiteAdj_Red;
+   delete []m_chWhiteAdj_Green;
+   delete []m_chWhiteAdj_Blue;
+
    free( m_DMX_BaseChannels );
 
 #if defined (_ATMO_VLC_PLUGIN_)
@@ -99,8 +107,6 @@ void CAtmoConfig::LoadDefaults() {
 
     m_UpdateEdgeWeightningFlag = 0;
 
-
-
     m_Software_gamma_mode = agcNone;
     m_Software_gamma_red    = 10;
     m_Software_gamma_green  = 10;
@@ -110,18 +116,29 @@ void CAtmoConfig::LoadDefaults() {
     m_WhiteAdjustment_Red    = 255;
     m_WhiteAdjustment_Green  = 255;
     m_WhiteAdjustment_Blue   = 255;
-       m_UseSoftwareWhiteAdj    = 1;
+    m_UseSoftwareWhiteAdj    = 1;
+
+    m_WhiteAdjPerChannel = ATMO_FALSE;
+    m_chWhiteAdj_Count = 0;
+
+    delete []m_chWhiteAdj_Red;
+    delete []m_chWhiteAdj_Green;
+    delete []m_chWhiteAdj_Blue;
+
+    m_chWhiteAdj_Red   = NULL;
+    m_chWhiteAdj_Green = NULL;
+    m_chWhiteAdj_Blue  = NULL;
 
-       m_ColorChanger_iSteps    = 50;
-       m_ColorChanger_iDelay    = 25;
+    m_ColorChanger_iSteps    = 50;
+    m_ColorChanger_iDelay    = 25;
 
-       m_LrColorChanger_iSteps  = 50;
-       m_LrColorChanger_iDelay  = 25;
+    m_LrColorChanger_iSteps  = 50;
+    m_LrColorChanger_iDelay  = 25;
 
     m_IsSetShutdownColor     = 1;
-       m_ShutdownColor_Red      = 0;
-       m_ShutdownColor_Green    = 0;
-       m_ShutdownColor_Blue     = 0;
+    m_ShutdownColor_Red      = 0;
+    m_ShutdownColor_Green    = 0;
+    m_ShutdownColor_Blue     = 0;
 
     m_StaticColor_Red        = 127; // ??
     m_StaticColor_Green      = 192;
@@ -145,6 +162,7 @@ void CAtmoConfig::LoadDefaults() {
     m_LiveView_DisplayNr        = 0;
     m_LiveView_FrameDelay       = 30;
     m_LiveView_GDI_FrameRate    = 25;
+    m_LiveView_RowsPerFrame     = 0;
 
 
     m_Hardware_global_gamma    = 128;
@@ -161,6 +179,7 @@ void CAtmoConfig::LoadDefaults() {
     m_DMX_RGB_Channels        = 5; // so wie atmolight
 
     m_MoMo_Channels           = 3; // default momo, there exists also a 4 ch version!
+    m_Fnordlicht_Amount       = 2; // default fnordlicht, there are 2 fnordlicht's!
 
     m_ZonesTopCount            = 1;
     m_ZonesBottomCount         = 1;
@@ -168,7 +187,6 @@ void CAtmoConfig::LoadDefaults() {
     m_ZoneSummary              = ATMO_FALSE;
     UpdateZoneCount();
 
-
     clearAllChannelMappings();
     m_CurrentChannelAssignment = 0;
     CAtmoChannelAssignment *temp = new CAtmoChannelAssignment();
@@ -201,6 +219,25 @@ void CAtmoConfig::Assign(CAtmoConfig *pAtmoConfigSrc) {
     this->m_WhiteAdjustment_Blue     = pAtmoConfigSrc->m_WhiteAdjustment_Blue;
     this->m_UseSoftwareWhiteAdj      = pAtmoConfigSrc->m_UseSoftwareWhiteAdj;
 
+    this->m_WhiteAdjPerChannel       = pAtmoConfigSrc->m_WhiteAdjPerChannel;
+    this->m_chWhiteAdj_Count         = pAtmoConfigSrc->m_chWhiteAdj_Count;
+    delete []m_chWhiteAdj_Red;
+    delete []m_chWhiteAdj_Green;
+    delete []m_chWhiteAdj_Blue;
+    if(m_chWhiteAdj_Count > 0)
+    {
+       m_chWhiteAdj_Red   = new int[ m_chWhiteAdj_Count ];
+       m_chWhiteAdj_Green = new int[ m_chWhiteAdj_Count ];
+       m_chWhiteAdj_Blue  = new int[ m_chWhiteAdj_Count ];
+       memcpy(m_chWhiteAdj_Red, pAtmoConfigSrc->m_chWhiteAdj_Red, sizeof(int) * m_chWhiteAdj_Count);
+       memcpy(m_chWhiteAdj_Green, pAtmoConfigSrc->m_chWhiteAdj_Green, sizeof(int) * m_chWhiteAdj_Count);
+       memcpy(m_chWhiteAdj_Blue, pAtmoConfigSrc->m_chWhiteAdj_Blue, sizeof(int) * m_chWhiteAdj_Count);
+    } else {
+       m_chWhiteAdj_Red   = NULL;
+       m_chWhiteAdj_Green = NULL;
+       m_chWhiteAdj_Blue  = NULL;
+    }
+
     this->m_IsSetShutdownColor       = pAtmoConfigSrc->m_IsSetShutdownColor;
     this->m_ShutdownColor_Red        = pAtmoConfigSrc->m_ShutdownColor_Red;
     this->m_ShutdownColor_Green      = pAtmoConfigSrc->m_ShutdownColor_Green;
@@ -223,7 +260,6 @@ void CAtmoConfig::Assign(CAtmoConfig *pAtmoConfigSrc) {
 
     this->m_show_statistics               = pAtmoConfigSrc->m_show_statistics;
 
-
     this->m_LiveView_EdgeWeighting  =  pAtmoConfigSrc->m_LiveView_EdgeWeighting;
     this->m_LiveView_BrightCorrect  =  pAtmoConfigSrc->m_LiveView_BrightCorrect;
     this->m_LiveView_DarknessLimit  =  pAtmoConfigSrc->m_LiveView_DarknessLimit;
@@ -236,6 +272,7 @@ void CAtmoConfig::Assign(CAtmoConfig *pAtmoConfigSrc) {
     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_LiveView_RowsPerFrame   =  pAtmoConfigSrc->m_LiveView_RowsPerFrame;
 
     this->m_ZonesTopCount             = pAtmoConfigSrc->m_ZonesTopCount;
     this->m_ZonesBottomCount          = pAtmoConfigSrc->m_ZonesBottomCount;
@@ -255,6 +292,8 @@ void CAtmoConfig::Assign(CAtmoConfig *pAtmoConfigSrc) {
 
     this->m_MoMo_Channels            = pAtmoConfigSrc->m_MoMo_Channels;
 
+    this->m_Fnordlicht_Amount        = pAtmoConfigSrc->m_Fnordlicht_Amount;
+
     this->m_CurrentChannelAssignment = pAtmoConfigSrc->m_CurrentChannelAssignment;
 
     clearChannelMappings();
@@ -278,8 +317,6 @@ void CAtmoConfig::Assign(CAtmoConfig *pAtmoConfigSrc) {
     UpdateZoneDefinitionCount();
 }
 
-
-
 int CAtmoConfig::getNumChannelAssignments() {
     int z=0;
     for(int i=0;i<10;i++)
@@ -336,8 +373,6 @@ void CAtmoConfig::UpdateZoneCount()
      m_computed_zones_count++;
 }
 
-
-
 int CAtmoConfig::getZoneCount()
 {
     return(m_computed_zones_count);
@@ -423,3 +458,50 @@ void CAtmoConfig::setDMX_BaseChannels(char *channels)
      m_DMX_BaseChannels = strdup(channels);
 }
 
+void CAtmoConfig::getChannelWhiteAdj(int channel,int &red,int &green,int &blue)
+{
+  if(channel >= m_chWhiteAdj_Count)
+  {
+     red = 256;
+     green = 256;
+     blue = 256;
+
+  } else {
+
+    red   = m_chWhiteAdj_Red[ channel ];
+    green = m_chWhiteAdj_Green[ channel ];
+    blue  = m_chWhiteAdj_Blue[ channel ];
+
+  }
+}
+
+void CAtmoConfig::setChannelWhiteAdj(int channel,int red,int green,int blue)
+{
+    if(channel >= m_chWhiteAdj_Count)
+    {
+       int *tmp = new int[channel+1];
+       if(m_chWhiteAdj_Red)
+          memcpy( tmp, m_chWhiteAdj_Red, m_chWhiteAdj_Count * sizeof(int) );
+       delete []m_chWhiteAdj_Red;
+       m_chWhiteAdj_Red = tmp;
+
+       tmp = new int[channel + 1];
+       if(m_chWhiteAdj_Green)
+          memcpy( tmp, m_chWhiteAdj_Green, m_chWhiteAdj_Count * sizeof(int) );
+       delete []m_chWhiteAdj_Green;
+       m_chWhiteAdj_Green = tmp;
+
+       tmp = new int[channel + 1];
+       if(m_chWhiteAdj_Blue)
+          memcpy( tmp, m_chWhiteAdj_Blue, m_chWhiteAdj_Count * sizeof(int) );
+       delete []m_chWhiteAdj_Blue;
+       m_chWhiteAdj_Blue = tmp;
+
+       m_chWhiteAdj_Count = channel + 1;
+   }
+
+   m_chWhiteAdj_Red[channel]   = red;
+   m_chWhiteAdj_Green[channel] = green;
+   m_chWhiteAdj_Blue[channel]  = blue;
+
+}
index 656c20ed72135e350d9b6c1973dee29fb036dc03..62848dd3622ba418f03ee9d738a769f6bc6d12e9 100644 (file)
 #   include <string.h>
 #endif
 
-
 class CAtmoConfig {
 
     protected:
-          int m_IsShowConfigDialog;    
+       int m_IsShowConfigDialog;
 #if defined(_ATMO_VLC_PLUGIN_)
        char *m_devicename;
        char *m_devicenames[3]; // additional Devices ?
 #else
-          int m_Comport;
+       int m_Comport;
        int m_Comports[3]; // additional Comports
 #endif
        enum AtmoConnectionType m_eAtmoConnectionType;
@@ -42,11 +41,17 @@ class CAtmoConfig {
        int m_WhiteAdjustment_Green;
        int m_WhiteAdjustment_Blue;
 
+       ATMO_BOOL m_WhiteAdjPerChannel;
+       int  m_chWhiteAdj_Count;
+       int *m_chWhiteAdj_Red;
+       int *m_chWhiteAdj_Green;
+       int *m_chWhiteAdj_Blue;
+
     protected:
        int m_IsSetShutdownColor;
-          int m_ShutdownColor_Red;
-          int m_ShutdownColor_Green;
-          int m_ShutdownColor_Blue;
+       int m_ShutdownColor_Red;
+       int m_ShutdownColor_Green;
+       int m_ShutdownColor_Blue;
 
     protected:
        /* Config Values for Color Changer */
@@ -76,7 +81,6 @@ class CAtmoConfig {
         CAtmoZoneDefinition **m_ZoneDefinitions;
         int m_AtmoZoneDefCount;
 
-
         /*
           zone layout description for generating the default Zone weightning
         */
@@ -94,7 +98,6 @@ class CAtmoConfig {
     public:
         int getZoneCount();
 
-
     protected:
         /* Live View Parameters (most interesting) */
         AtmoFilterMode m_LiveViewFilterMode;
@@ -104,6 +107,9 @@ class CAtmoConfig {
 
         ATMO_BOOL m_show_statistics;
 
+        // number of rows to process each frame
+        int m_LiveView_RowsPerFrame;
+
         // weighting of distance to edge
         int m_LiveView_EdgeWeighting; //  = 8;
         // brightness correction
@@ -154,6 +160,9 @@ class CAtmoConfig {
     protected:
          int m_MoMo_Channels;
 
+    protected:
+         int m_Fnordlicht_Amount;
+
     protected:
          AtmoGammaCorrect m_Software_gamma_mode;
 
@@ -165,7 +174,6 @@ class CAtmoConfig {
     public:
         volatile int m_UpdateEdgeWeightningFlag;
 
-
     public:
        CAtmoConfig();
        virtual ~CAtmoConfig();
@@ -210,6 +218,13 @@ class CAtmoConfig {
         ATMO_BOOL isUseSoftwareWhiteAdj() { return m_UseSoftwareWhiteAdj; }
         void setUseSoftwareWhiteAdj(ATMO_BOOL value) { m_UseSoftwareWhiteAdj = value; }
 
+/* White ADJ per Channel settings */
+        ATMO_BOOL isWhiteAdjPerChannel() { return  m_WhiteAdjPerChannel; }
+        void setWhiteAdjPerChannel( ATMO_BOOL value) { m_WhiteAdjPerChannel = value; }
+
+        void setChannelWhiteAdj(int channel,int red,int green,int blue);
+        void getChannelWhiteAdj(int channel,int &red,int &green,int &blue);
+
         int isSetShutdownColor()     { return m_IsSetShutdownColor; }
         void SetSetShutdownColor(int value) { m_IsSetShutdownColor = value; }
         int getShutdownColor_Red()   { return m_ShutdownColor_Red; }
@@ -236,7 +251,6 @@ class CAtmoConfig {
         int getStaticColor_Blue()  { return m_StaticColor_Blue;  }
         void  setStaticColor_Blue(int value) { m_StaticColor_Blue=value; }
 
-
         AtmoConnectionType getConnectionType() { return m_eAtmoConnectionType; }
         void setConnectionType(AtmoConnectionType value) { m_eAtmoConnectionType = value; }
 
@@ -258,6 +272,9 @@ class CAtmoConfig {
         int getLiveView_EdgeWeighting() { return m_LiveView_EdgeWeighting; }
         void setLiveView_EdgeWeighting(int value) { m_LiveView_EdgeWeighting=value; }
 
+        int getLiveView_RowsPerFrame() { return m_LiveView_RowsPerFrame; }
+        void setLiveView_RowsPerFrame(int value) { m_LiveView_RowsPerFrame=value; }
+
         int getLiveView_BrightCorrect() { return m_LiveView_BrightCorrect; }
         void setLiveView_BrightCorrect(int value) { m_LiveView_BrightCorrect=value; }
 
@@ -312,7 +329,6 @@ class CAtmoConfig {
         int getHardware_gamma_blue() { return m_Hardware_gamma_blue; }
         void setHardware_gamma_blue(int value) { m_Hardware_gamma_blue=value; }
 
-
         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; }
@@ -359,6 +375,9 @@ class CAtmoConfig {
         int getMoMo_Channels() { return m_MoMo_Channels; }
         void setMoMo_Channels(int chCount) { m_MoMo_Channels = chCount; }
 
+        int getFnordlicht_Amount() { return m_Fnordlicht_Amount; }
+        void setFnordlicht_Amount(int fnordlichtAmount) { m_Fnordlicht_Amount = fnordlichtAmount; }
+
 };
 
 #endif
index ed48e880f31caf5f65c1bb5f92de9b3619dc5e9b..739978a6fdc82becf4b8e0946b0b402cdff6616e 100644 (file)
@@ -114,7 +114,8 @@ enum AtmoConnectionType
       actNUL = 3,
       actMultiAtmo = 4,
       actMondolight = 5,
-      actMoMoLight  = 6
+      actMoMoLight = 6,
+      actFnordlicht = 7
 };
 static const char *AtmoDeviceTypes[] = {
       "Atmo-Classic",
@@ -123,10 +124,10 @@ static const char *AtmoDeviceTypes[] = {
       "Nul-Device",
       "Multi-Atmo",
       "Mondolight",
-      "MoMoLight"
-
+      "MoMoLight",
+      "Fnordlicht"
   };
-#define ATMO_DEVICE_COUNT 7
+#define ATMO_DEVICE_COUNT 8
 
 #if defined(_ATMO_VLC_PLUGIN_)
 enum EffectMode {
index 69e07739ccd2e6a66394e24684b53c4457cff89e..e96bb32315190cff7bde02adf3da776730d4b988 100644 (file)
@@ -13,6 +13,7 @@
 #include "AtmoDmxSerialConnection.h"
 #include "AtmoMultiConnection.h"
 #include "MoMoConnection.h"
+#include "FnordlichtConnection.h"
 #include "AtmoExternalCaptureInput.h"
 #include <math.h>
 
@@ -27,7 +28,6 @@
 #   include "AtmoGdiDisplayCaptureInput.h"
 #endif
 
-
 CAtmoTools::CAtmoTools(void)
 {
 }
@@ -40,7 +40,6 @@ void CAtmoTools::ShowShutdownColor(CAtmoDynData *pDynData)
 {
     pDynData->LockCriticalSection();
 
-
     CAtmoConnection *atmoConnection = pDynData->getAtmoConnection();
     CAtmoConfig *atmoConfig = pDynData->getAtmoConfig();
     if((atmoConnection != NULL) && (atmoConfig!=NULL) && atmoConfig->isSetShutdownColor()) {
@@ -403,6 +402,24 @@ ATMO_BOOL CAtmoTools::RecreateConnection(CAtmoDynData *pDynData)
                return ATMO_TRUE;
            }
 
+           case actFnordlicht: {
+               CFnordlichtConnection *tempConnection = new CFnordlichtConnection( 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();
                return ATMO_FALSE;
diff --git a/modules/video_filter/atmo/FnordlichtConnection.cpp b/modules/video_filter/atmo/FnordlichtConnection.cpp
new file mode 100644 (file)
index 0000000..4f026e5
--- /dev/null
@@ -0,0 +1,464 @@
+/*
+ * FnordlichtConnection.h: class to access a FnordlichtLight Hardware
+ * - the description could be found
+ * here: http://github.com/fd0/fnordlicht/raw/master/doc/PROTOCOL
+ *
+ * (C) Kai Lauterbach (klaute at gmail.com)
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Id$
+ */
+
+
+#include "AtmoDefs.h"
+#include "FnordlichtConnection.h"
+
+#if !defined(_ATMO_VLC_PLUGIN_)
+# include "FnordlichtConfigDialog.h"
+#endif
+
+#include <stdio.h>
+#include <fcntl.h>
+
+#if !defined(WIN32)
+#include <termios.h>
+#include <unistd.h>
+#endif
+
+CFnordlichtConnection::CFnordlichtConnection(CAtmoConfig *cfg)
+    : CAtmoConnection(cfg)
+{
+    m_hComport = INVALID_HANDLE_VALUE;
+}
+
+CFnordlichtConnection::~CFnordlichtConnection()
+{
+}
+
+ATMO_BOOL CFnordlichtConnection::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 = 19200;       // 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 = B19200;
+    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
+
+    // sync fnordlicht
+    if ( sync() )
+        // stop fading on all devices
+        if ( stop(255) )
+            return true; // fnordlicht initialized...
+
+    return false; // something is going wrong...
+}
+
+void CFnordlichtConnection::CloseConnection()
+{
+    if ( m_hComport != INVALID_HANDLE_VALUE )
+    {
+        reset(255);
+
+#if defined(WIN32)
+        CloseHandle(m_hComport);
+#else
+        close(m_hComport);
+#endif
+        m_hComport = INVALID_HANDLE_VALUE;
+    }
+}
+
+ATMO_BOOL CFnordlichtConnection::isOpen(void)
+{
+    return (m_hComport != INVALID_HANDLE_VALUE);
+}
+
+ATMO_BOOL CFnordlichtConnection::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; //no hardware adjust required
+}
+
+/*
+    def fade_rgb(addr, r, g, b, step, delay)
+       $dev.write addr.chr
+       $dev.write "\x01"
+       $dev.write step.chr
+       $dev.write delay.chr
+       $dev.write r.chr
+       $dev.write g.chr
+       $dev.write b.chr
+       $dev.write "\x00\x00\x00\x00\x00"
+       $dev.write "\x00\x00\x00"
+       $dev.flush
+    end
+*/
+ATMO_BOOL CFnordlichtConnection::SendData(pColorPacket data)
+{
+    if ( m_hComport == INVALID_HANDLE_VALUE )
+        return ATMO_FALSE;
+
+    int amount = getAmountFnordlichter();
+    unsigned char buffer[15];
+    memset(&buffer, 0, sizeof(buffer) ); // zero buffer
+    int iBytesWritten;
+
+    Lock();
+
+    buffer[1] = 0x01; // fade to rgb color
+    buffer[2] = 0x80; // in two steps
+    buffer[3] = 0x01; // 1ms pause between steps
+
+    // send all packages to all fnordlicht's
+    for( unsigned char i=0; i < amount; i++ )
+    {
+        int idx;
+        if ( m_ChannelAssignment && i < m_NumAssignedChannels )
+            idx = m_ChannelAssignment[i];
+        else
+            idx = -1; // no channel assigned to fnordlicht[i]
+
+        if( idx >= 0 && idx <= data->numColors )
+        {
+            // fnordlicht address equals to a MoMo Channel
+            buffer[0] = i; // fnordlicht address (0..254, 255 = broadcast)
+            buffer[4] = data->zone[idx].r;
+            buffer[5] = data->zone[idx].g;
+            buffer[6] = data->zone[idx].b;
+        }
+
+#if defined(WIN32)
+        // send to COM-Port
+        WriteFile( m_hComport, buffer, sizeof(buffer),
+                    (DWORD*)&iBytesWritten, NULL );
+#else
+        iBytesWritten = write(m_hComport, buffer, sizeof(buffer));
+        tcflush(m_hComport, TCIOFLUSH);
+        tcdrain(m_hComport); // flush buffer
+#endif
+
+        if (iBytesWritten != sizeof(buffer))
+        {
+            Unlock();
+            return ATMO_FALSE; // shouldn't be...
+        }
+
+    }
+
+    Unlock();
+
+    return ATMO_TRUE;
+}
+
+
+ATMO_BOOL CFnordlichtConnection::CreateDefaultMapping(CAtmoChannelAssignment *ca)
+{
+    if ( !ca )
+        return ATMO_FALSE;
+    ca->setSize( getAmountFnordlichter() );  // 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 CFnordlichtConnection::getAmountFnordlichter()
+{
+   return m_pAtmoConfig->getFnordlicht_Amount();
+}
+
+/*
+    def sync(addr = 0)
+       1.upto(15) do
+          $dev.write "\e"
+       end
+       $dev.write addr.chr
+       $dev.flush
+    end
+*/
+ATMO_BOOL CFnordlichtConnection::sync(void)
+{
+    if ( m_hComport == INVALID_HANDLE_VALUE )
+        return ATMO_FALSE;
+
+    unsigned char buffer[16];
+
+    int iBytesWritten;
+
+    Lock();
+
+    // fill buffer with 15 escape character
+    memset(&buffer, 0x1b, sizeof(buffer)-1);
+
+    buffer[sizeof(buffer)-1] = 0x00; // append one zero byte
+
+#if defined(WIN32)
+        // send to COM-Port
+        WriteFile( m_hComport, buffer, sizeof(buffer),
+                    (DWORD*)&iBytesWritten, NULL );
+#else
+        iBytesWritten = write(m_hComport, buffer, sizeof(buffer));
+        tcflush(m_hComport, TCIOFLUSH);
+        tcdrain(m_hComport); // flush buffer
+#endif
+
+    Unlock();
+
+    return (iBytesWritten == sizeof(buffer)) ? ATMO_TRUE : ATMO_FALSE;
+
+}
+
+/*
+    def stop(addr, fading = 1)
+       $dev.write addr.chr
+       $dev.write "\x08"
+       $dev.write fading.chr
+       $dev.write "\x00\x00\x00\x00"
+       $dev.write "\x00\x00\x00\x00\x00"
+       $dev.write "\x00\x00\x00"
+       $dev.flush
+    end
+*/
+ATMO_BOOL CFnordlichtConnection::stop(unsigned char addr)
+{
+    if(m_hComport == INVALID_HANDLE_VALUE)
+        return ATMO_FALSE;
+
+    unsigned char buffer[15];
+    memset(&buffer, 0, sizeof(buffer)); // zero buffer
+    int iBytesWritten;
+
+    Lock();
+
+    buffer[0] = addr; // fnordlicht address (255 = broadcast)
+    buffer[1] = 0x08; // stop command
+    buffer[2] = 1;    // fading
+
+#if defined(WIN32)
+        // send to COM-Port
+        WriteFile( m_hComport, buffer, sizeof(buffer),
+                    (DWORD*)&iBytesWritten, NULL );
+#else
+        iBytesWritten = write(m_hComport, buffer, sizeof(buffer));
+        tcflush(m_hComport, TCIOFLUSH);
+        tcdrain(m_hComport); // flush buffer
+#endif
+
+    Unlock();
+
+    return (iBytesWritten == sizeof(buffer)) ? ATMO_TRUE : ATMO_FALSE;
+}
+
+/*
+*/
+ATMO_BOOL CFnordlichtConnection::reset(unsigned char addr)
+{
+    if(m_hComport == INVALID_HANDLE_VALUE)
+        return ATMO_FALSE;
+
+    stop(255);
+
+    if ( sync() && start_bootloader(addr) )
+    {
+#if defined(_ATMO_VLC_PLUGIN_)
+        do_sleep(200000); // wait 200ms
+#else
+        do_sleep(200); // wait 200ms
+#endif
+        if ( sync() && boot_enter_application(addr) )
+                return ATMO_TRUE;
+    }
+
+    return ATMO_FALSE;
+}
+
+/*
+    def start_bootloader(addr)
+        $dev.write(addr.chr)
+        $dev.write("\x80")
+        $dev.write("\x6b\x56\x27\xfc")
+        $dev.write("\x00\x00\x00\x00\x00\x00\x00\x00\x00")
+        $dev.flush
+    end
+*/
+ATMO_BOOL CFnordlichtConnection::start_bootloader(unsigned char addr)
+{
+    if(m_hComport == INVALID_HANDLE_VALUE)
+        return ATMO_FALSE;
+
+    unsigned char buffer[15];
+    memset(&buffer, 0, sizeof(buffer)); // zero buffer
+    int iBytesWritten;
+
+    Lock();
+
+    buffer[0] = addr; // fnordlicht address (255 = broadcast)
+    buffer[1] = 0x80; // start_bootloader
+    buffer[2] = 0x6b;
+    buffer[3] = 0x56;
+    buffer[4] = 0x27;
+    buffer[5] = 0xfc;
+
+#if defined(WIN32)
+        // send to COM-Port
+        WriteFile( m_hComport, buffer, sizeof(buffer),
+                    (DWORD*)&iBytesWritten, NULL );
+#else
+        iBytesWritten = write(m_hComport, buffer, sizeof(buffer));
+        tcflush(m_hComport, TCIOFLUSH);
+        tcdrain(m_hComport); // flush buffer
+#endif
+
+    Unlock();
+
+    return (iBytesWritten == sizeof(buffer)) ? ATMO_TRUE : ATMO_FALSE;
+}
+
+/*
+    def boot_enter_application(addr)
+        $dev.write(addr.chr)
+        $dev.write("\x87")
+        $dev.write("\x00"*13)
+        $dev.flush
+    end
+*/
+ATMO_BOOL CFnordlichtConnection::boot_enter_application(unsigned char addr)
+{
+    if(m_hComport == INVALID_HANDLE_VALUE)
+        return ATMO_FALSE;
+
+    unsigned char buffer[15];
+    memset(&buffer, 0, sizeof(buffer)); // zero buffer
+    int iBytesWritten;
+
+    Lock();
+
+    buffer[0] = addr; // fnordlicht address (255 = broadcast)
+    buffer[1] = 0x87; // boot_ender_application command
+
+#if defined(WIN32)
+        // send to COM-Port
+        WriteFile( m_hComport, buffer, sizeof(buffer),
+                    (DWORD*)&iBytesWritten, NULL );
+#else
+        iBytesWritten = write(m_hComport, buffer, sizeof(buffer));
+        tcflush(m_hComport, TCIOFLUSH);
+        tcdrain(m_hComport); // flush buffer
+#endif
+
+    Unlock();
+
+    return (iBytesWritten == sizeof(buffer)) ? ATMO_TRUE : ATMO_FALSE;
+}
+
+#if !defined(_ATMO_VLC_PLUGIN_)
+
+char *CFnordlichtConnection::getChannelName(int ch)
+{
+    char buf[60];
+    if( ch < 0 ) return NULL;
+    if( ch >= getAmountFnordlichter() ) return NULL;
+
+    sprintf(buf,"Number [%d]",ch);
+    return strdup(buf);
+    // sorry asprintf is not defined on Visual Studio :)
+    // return (asprintf(&ret, "Number [%d]", ch) != -1) ? ret : NULL;
+
+}
+
+ATMO_BOOL CFnordlichtConnection::ShowConfigDialog(HINSTANCE hInst, HWND parent,
+                                                    CAtmoConfig *cfg)
+{
+    CFnordlichtConfigDialog *dlg = new CFnordlichtConfigDialog(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/FnordlichtConnection.h b/modules/video_filter/atmo/FnordlichtConnection.h
new file mode 100644 (file)
index 0000000..08f9cf1
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * FnordlichtConnection.h: class to access a FnordlichtLight Hardware
+ * - the description could be found
+ * here: http://github.com/fd0/fnordlicht/raw/master/doc/PROTOCOL
+ *
+ * (C) Kai Lauterbach (klaute at gmail.com)
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Id$
+ */
+#ifndef _FnordlichtConnection_h_
+#define _FnordlichtConnection_h_
+
+#include "AtmoDefs.h"
+#include "AtmoConnection.h"
+#include "AtmoConfig.h"
+
+#if defined(WIN32)
+#   include <windows.h>
+#endif
+
+
+class CFnordlichtConnection : public CAtmoConnection
+{
+    private:
+        HANDLE m_hComport;
+
+        ATMO_BOOL sync(void);
+        ATMO_BOOL stop(unsigned char addr);
+        ATMO_BOOL reset(unsigned char addr);
+        ATMO_BOOL start_bootloader(unsigned char addr);
+        ATMO_BOOL boot_enter_application(unsigned char addr);
+
+#if defined(WIN32)
+        DWORD  m_dwLastWin32Error;
+    public:
+        DWORD getLastError() { return m_dwLastWin32Error; }
+#endif
+
+    public:
+        CFnordlichtConnection (CAtmoConfig *cfg);
+        virtual ~CFnordlichtConnection (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 getAmountFnordlichter();
+
+        virtual const char *getDevicePath() { return "fnordlicht"; }
+
+#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 addb87c8e6a23ebe3b983bc7dd4c736cac19f864..e8cfe4d5d2bb1ac553e975034f746efced453b01 100644 (file)
@@ -139,7 +139,8 @@ static const int pi_device_type_values[] = {
      1, /* AtmoLight classic */
      2, /* Quattro AtmoLight */
      3, /* DMX Device */
-     4  /* MoMoLight device */
+     4, /* MoMoLight device */
+     5  /* fnordlicht */
 };
 static const char *const ppsz_device_type_descriptions[] = {
 #if defined( WIN32 )
@@ -148,7 +149,8 @@ static const char *const ppsz_device_type_descriptions[] = {
         N_("Classic AtmoLight"),
         N_("Quattro AtmoLight"),
         N_("DMX"),
-        N_("MoMoLight")
+        N_("MoMoLight"),
+        N_("fnordlicht")
 };
 
 #define DMX_CHANNELS_TEXT      N_("Count of AtmoLight channels")
@@ -162,6 +164,11 @@ static const char *const ppsz_device_type_descriptions[] = {
 #define MOMO_CHANNELS_LONGTEXT  N_("Depending on your MoMoLight hardware " \
                                    "choose 3 or 4 channels")
 
+#define FNORDLICHT_AMOUNT_TEXT      N_("Count of fnordlicht's")
+#define FNORDLICHT_AMOUNT_LONGTEXT  N_("Depending on the amount your " \
+                                   "fnordlicht hardware " \
+                                   "choose 1 to 4 channels")
+
 #if defined( WIN32 )
 #  define DEFAULT_DEVICE   0
 #else
@@ -376,7 +383,7 @@ add_string(CFG_PREFIX "serialdev", "COM1", NULL,
 add_file(CFG_PREFIX "atmowinexe", NULL, NULL,
          ATMOWINEXE_TEXT, ATMOWINEXE_LONGTEXT, false )
 #else
-add_string(CFG_PREFIX "serialdev", "/dev/ttyS01", NULL,
+add_string(CFG_PREFIX "serialdev", "/dev/ttyUSB0", NULL,
            SERIALDEV_TEXT, SERIALDEV_LONGTEXT, false )
 #endif
 
@@ -421,6 +428,13 @@ 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)
 
+/* 2,2,4 means 2 is the default value, 1 minimum amount,
+   4 maximum amount
+*/
+set_section( N_("fnordlicht options" ), 0 )
+add_integer_with_range(CFG_PREFIX "fnordlicht-amount",   2, 1, 4, NULL,
+                       FNORDLICHT_AMOUNT_TEXT,
+                       FNORDLICHT_AMOUNT_LONGTEXT, false)
 
 
 /*
@@ -652,6 +666,7 @@ static const char *const ppsz_filter_options[] = {
         "dmx-channels",
         "dmx-chbase",
         "momo-channels",
+        "fnordlicht-amount",
 
 #if defined(WIN32 )
         "atmowinexe",
@@ -1523,6 +1538,14 @@ static void Atmo_SetupConfig(filter_t *p_filter, CAtmoConfig *p_atmo_config)
     p_atmo_config->setMoMo_Channels(
         var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "momo-channels")
        );
+
+    /*
+      fnordlicht options
+    */
+    p_atmo_config->setFnordlicht_Amount(
+        var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "fnordlicht-amount")
+       );
+
 }
 
 
@@ -1603,55 +1626,64 @@ static void Atmo_SetupParameters(filter_t *p_filter)
 
             /* importing all required functions I hope*/
             p_sys->pf_ctrl_atmo_initialize =
-                (int32_t (*)(void))GetProcAddress(p_sys->h_AtmoCtrl,"AtmoInitialize");
+                (int32_t (*)(void))GetProcAddress(p_sys->h_AtmoCtrl,
+                            "AtmoInitialize");
             if(!p_sys->pf_ctrl_atmo_initialize)
                 msg_Err( p_filter, "export AtmoInitialize missing.");
 
             p_sys->pf_ctrl_atmo_finalize =
-                (void (*)(int32_t))GetProcAddress(p_sys->h_AtmoCtrl,"AtmoFinalize");
+                (void (*)(int32_t))GetProcAddress(p_sys->h_AtmoCtrl,
+                            "AtmoFinalize");
             if(!p_sys->pf_ctrl_atmo_finalize)
                 msg_Err( p_filter, "export AtmoFinalize missing.");
 
             p_sys->pf_ctrl_atmo_switch_effect =
-                (int32_t(*)(int32_t))GetProcAddress(p_sys->h_AtmoCtrl,"AtmoSwitchEffect");
+                (int32_t(*)(int32_t))GetProcAddress(p_sys->h_AtmoCtrl,
+                            "AtmoSwitchEffect");
             if(!p_sys->pf_ctrl_atmo_switch_effect)
                 msg_Err( p_filter, "export AtmoSwitchEffect missing.");
 
             p_sys->pf_ctrl_atmo_set_live_source =
-                (int32_t(*)(int32_t))GetProcAddress(p_sys->h_AtmoCtrl,"AtmoSetLiveSource");
+                (int32_t(*)(int32_t))GetProcAddress(p_sys->h_AtmoCtrl,
+                            "AtmoSetLiveSource");
             if(!p_sys->pf_ctrl_atmo_set_live_source)
                 msg_Err( p_filter, "export AtmoSetLiveSource missing.");
 
             p_sys->pf_ctrl_atmo_create_transfer_buffers =
-                (void (*)(int32_t, int32_t, int32_t , int32_t))GetProcAddress(p_sys->h_AtmoCtrl,"AtmoCreateTransferBuffers");
+                (void (*)(int32_t, int32_t, int32_t , int32_t))
+                    GetProcAddress(p_sys->h_AtmoCtrl,"AtmoCreateTransferBuffers");
             if(!p_sys->pf_ctrl_atmo_create_transfer_buffers)
                 msg_Err( p_filter, "export AtmoCreateTransferBuffers missing.");
 
             p_sys->pf_ctrl_atmo_lock_transfer_buffer=
-                (uint8_t*(*) (void))GetProcAddress(p_sys->h_AtmoCtrl,"AtmoLockTransferBuffer");
+                (uint8_t*(*) (void))GetProcAddress(p_sys->h_AtmoCtrl,
+                            "AtmoLockTransferBuffer");
             if(!p_sys->pf_ctrl_atmo_lock_transfer_buffer)
                 msg_Err( p_filter, "export AtmoLockTransferBuffer missing.");
 
             p_sys->pf_ctrl_atmo_send_pixel_data =
-                (void (*)(void))GetProcAddress(p_sys->h_AtmoCtrl,"AtmoSendPixelData");
+                (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");
+                (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 atmo classic driver");
+            msg_Warn( p_filter,
+                "AtmoCtrlLib.dll missing fallback to internal atmo classic driver");
             p_sys->i_device_type = 1;
         }
     }
 #endif
 
     if(p_sys->i_device_type >= 1) {
-        msg_Dbg( p_filter, "try use buildin driver %d ", p_sys->i_device_type );
+        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
@@ -1684,6 +1716,10 @@ static void Atmo_SetupParameters(filter_t *p_filter)
                 p_sys->p_atmo_config->setConnectionType( actMoMoLight );
                 break;
 
+            case 5:
+                p_sys->p_atmo_config->setConnectionType( actFnordlicht );
+                break;
+
             default:
                 msg_Warn( p_filter, "invalid device type %d found",
                                     p_sys->i_device_type );
@@ -2227,7 +2263,8 @@ static void CreateMiniImage( filter_t *p_filter, picture_t *p_inpic)
         }
     }
 
-    msg_Dbg( p_filter, "AtmoFrame %u Time: %d ms", p_sys->ui_frame_counter, mdate() / 1000);
+    msg_Dbg( p_filter, "AtmoFrame %u Time: %d ms", p_sys->ui_frame_counter,
+                mdate() / 1000);
     p_sys->ui_frame_counter++;
 #endif
 
@@ -2762,10 +2799,14 @@ static void atmo_parse_crop(char *psz_cropconfig,
             i_crop_bottom = strtol( psz_end, &psz_end, 10 );
             if( *psz_end != '\0' ) return;
 
-            i_width = fmt_render.i_visible_width - i_crop_left - i_crop_right;
+            i_width = fmt_render.i_visible_width -
+                        i_crop_left -
+                        i_crop_right;
             i_visible_width = i_width;
 
-            i_height = fmt_render.i_visible_height - i_crop_top - i_crop_bottom;
+            i_height = fmt_render.i_visible_height -
+                        i_crop_top -
+                        i_crop_bottom;
             i_visible_height = i_height;
 
             i_x_offset = i_crop_left;