From: Kai Lauterbach Date: Thu, 3 Jun 2010 17:21:52 +0000 (+0200) Subject: atmo: add support for Fnordlicht devices X-Git-Tag: 1.2.0-pre1~6330 X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=c215f7b79628a32373cf0041152cff1a5042d15b;p=vlc atmo: add support for Fnordlicht devices 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 --- diff --git a/modules/video_filter/Modules.am b/modules/video_filter/Modules.am index b6c13773de..ea46c31c68 100644 --- a/modules/video_filter/Modules.am +++ b/modules/video_filter/Modules.am @@ -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 diff --git a/modules/video_filter/atmo/AtmoConfig.cpp b/modules/video_filter/atmo/AtmoConfig.cpp index ec6c519587..1003ff08bd 100644 --- a/modules/video_filter/atmo/AtmoConfig.cpp +++ b/modules/video_filter/atmo/AtmoConfig.cpp @@ -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; + +} diff --git a/modules/video_filter/atmo/AtmoConfig.h b/modules/video_filter/atmo/AtmoConfig.h index 656c20ed72..62848dd362 100644 --- a/modules/video_filter/atmo/AtmoConfig.h +++ b/modules/video_filter/atmo/AtmoConfig.h @@ -19,16 +19,15 @@ # include #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 diff --git a/modules/video_filter/atmo/AtmoDefs.h b/modules/video_filter/atmo/AtmoDefs.h index ed48e880f3..739978a6fd 100644 --- a/modules/video_filter/atmo/AtmoDefs.h +++ b/modules/video_filter/atmo/AtmoDefs.h @@ -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 { diff --git a/modules/video_filter/atmo/AtmoTools.cpp b/modules/video_filter/atmo/AtmoTools.cpp index 69e07739cc..e96bb32315 100644 --- a/modules/video_filter/atmo/AtmoTools.cpp +++ b/modules/video_filter/atmo/AtmoTools.cpp @@ -13,6 +13,7 @@ #include "AtmoDmxSerialConnection.h" #include "AtmoMultiConnection.h" #include "MoMoConnection.h" +#include "FnordlichtConnection.h" #include "AtmoExternalCaptureInput.h" #include @@ -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 index 0000000000..4f026e5cd6 --- /dev/null +++ b/modules/video_filter/atmo/FnordlichtConnection.cpp @@ -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 +#include + +#if !defined(WIN32) +#include +#include +#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 index 0000000000..08f9cf1431 --- /dev/null +++ b/modules/video_filter/atmo/FnordlichtConnection.h @@ -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 +#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 diff --git a/modules/video_filter/atmo/atmo.cpp b/modules/video_filter/atmo/atmo.cpp index addb87c8e6..e8cfe4d5d2 100644 --- a/modules/video_filter/atmo/atmo.cpp +++ b/modules/video_filter/atmo/atmo.cpp @@ -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;