Commit 1b637157 authored by Antoine Cellerier's avatar Antoine Cellerier

video filter module - for thehomebrewAmbiLight (AtmoLight) [2/3]: atmo-video_filter.diff

parent bcb07441
This diff is collapsed.
/*
* AtmoCalculations.h: see calculations.h of the linux version... one to one copy
* calculations.h: calculations needed by the input devices
*
* See the README.txt file for copyright information and how to reach the author(s).
*
* $Id$
*/
#ifndef _AtmoCalculations_h_
#define _AtmoCalculations_h_
#include "AtmoDefs.h"
#include "AtmoConfig.h"
tColorPacket CalcColorsAnalyzeHSV(CAtmoConfig *pAtmoConfig, tHSVColor *HSV_Img);
tHSVColor RGB2HSV(tRGBColor color);
tRGBColor HSV2RGB(tHSVColor color);
#endif
/*
* AtmoConfig.cpp: Class for holding all configuration values of AtmoWin - stores
* the values and retrieves its values from registry
*
* See the README.txt file for copyright information and how to reach the author(s).
*
* $Id$
*/
#include <stdio.h>
#include <string.h>
#include "AtmoConfig.h"
/* Import Hint
if somebody Adds new config option this has to be done in the following
files and includes!
AtmoConfig.h -- extend class definition!, and add get... and set... Methods!
so that the real variables are still hidden inside the class!
AtmoConfigRegistry.cpp --> SaveToRegistry();
AtmoConfigRegistry.cpp --> LoadFromRegistry();
AtmoConfig.cpp --> Assign( ... );
*/
CAtmoConfig::CAtmoConfig()
{
// setup basic configruation structures...
m_IsShowConfigDialog = 0;
m_eAtmoConnectionType = actSerialPort;
for(int i=0;i<10;i++)
m_ChannelAssignments[i] = NULL;
#if defined (_ATMO_VLC_PLUGIN_)
m_devicename = NULL;
#endif
// load all config values with there defaults
LoadDefaults();
// CAtmoZoneDefinition *m_ZoneDefinitions[ATMO_NUM_CHANNELS];
// generate default channel parameters which may be loaded later from .bmp files
for(int i=0;i<ATMO_NUM_CHANNELS;i++) {
m_ZoneDefinitions[i] = new CAtmoZoneDefinition();
m_ZoneDefinitions[i]->setZoneNumber(i);
switch(i) {
case 0: // summary channel
m_ZoneDefinitions[i]->Fill(255);
break;
case 1: // left channel
m_ZoneDefinitions[i]->FillGradientFromLeft();
break;
case 2: // right channel
m_ZoneDefinitions[i]->FillGradientFromRight();
break;
case 3: // top channel
m_ZoneDefinitions[i]->FillGradientFromTop();
break;
case 4: // bottom channel
m_ZoneDefinitions[i]->FillGradientFromBottom();
break;
}
}
}
CAtmoConfig::~CAtmoConfig() {
// and finally cleanup...
clearAllChannelMappings();
#if !defined (WIN32)
if(m_devicename)
free(m_devicename);
#endif
}
void CAtmoConfig::LoadDefaults() {
// m_eAtmoConnectionType = actSerialPort;
// m_Comport
m_eEffectMode = emDisabled;
m_WhiteAdjustment_Red = 255;
m_WhiteAdjustment_Green = 255;
m_WhiteAdjustment_Blue = 255;
m_UseSoftwareWhiteAdj = 1;
m_ColorChanger_iSteps = 50;
m_ColorChanger_iDelay = 25;
m_LrColorChanger_iSteps = 50;
m_LrColorChanger_iDelay = 25;
m_IsSetShutdownColor = 1;
m_ShutdownColor_Red = 0;
m_ShutdownColor_Green = 0;
m_ShutdownColor_Blue = 0;
m_StaticColor_Red = 127; // ??
m_StaticColor_Green = 192;
m_StaticColor_Blue = 255;
m_LiveViewFilterMode = afmCombined;
m_LiveViewFilter_PercentNew = 50;
m_LiveViewFilter_MeanLength = 300;
m_LiveViewFilter_MeanThreshold = 40;
m_LiveView_EdgeWeighting = 8;
m_LiveView_BrightCorrect = 100;
m_LiveView_DarknessLimit = 5;
m_LiveView_HueWinSize = 3;
m_LiveView_SatWinSize = 3;
m_LiveView_WidescreenMode = 0;
m_LiveView_HOverscanBorder = 0;
m_LiveView_VOverscanBorder = 0;
m_LiveView_DisplayNr = 0;
m_LiveView_FrameDelay = 0;
m_Hardware_global_gamma = 128;
m_Hardware_global_contrast = 100;
m_Hardware_contrast_red = 100;
m_Hardware_contrast_green = 100;
m_Hardware_contrast_blue = 100;
m_Hardware_gamma_red = 22;
m_Hardware_gamma_green = 22;
m_Hardware_gamma_blue = 22;
clearAllChannelMappings();
m_CurrentChannelAssignment = 0;
tChannelAssignment *temp = temp = new tChannelAssignment;
temp->system = true;
for(int i=0;i<ATMO_NUM_CHANNELS;i++)
temp->mappings[i] = i;
strcpy(temp->name,"Standard");
this->m_ChannelAssignments[0] = temp;
}
void CAtmoConfig::Assign(CAtmoConfig *pAtmoConfigSrc) {
#if defined(_ATMO_VLC_PLUGIN_)
this->setSerialDevice(pAtmoConfigSrc->getSerialDevice());
#else
this->m_Comport = pAtmoConfigSrc->m_Comport;
#endif
this->m_eAtmoConnectionType = pAtmoConfigSrc->m_eAtmoConnectionType;
this->m_eEffectMode = pAtmoConfigSrc->m_eEffectMode;
this->m_WhiteAdjustment_Red = pAtmoConfigSrc->m_WhiteAdjustment_Red;
this->m_WhiteAdjustment_Green = pAtmoConfigSrc->m_WhiteAdjustment_Green;
this->m_WhiteAdjustment_Blue = pAtmoConfigSrc->m_WhiteAdjustment_Blue;
this->m_UseSoftwareWhiteAdj = pAtmoConfigSrc->m_UseSoftwareWhiteAdj;
this->m_IsSetShutdownColor = pAtmoConfigSrc->m_IsSetShutdownColor;
this->m_ShutdownColor_Red = pAtmoConfigSrc->m_ShutdownColor_Red;
this->m_ShutdownColor_Green = pAtmoConfigSrc->m_ShutdownColor_Green;
this->m_ShutdownColor_Blue = pAtmoConfigSrc->m_ShutdownColor_Blue;
this->m_ColorChanger_iSteps = pAtmoConfigSrc->m_ColorChanger_iSteps;
this->m_ColorChanger_iDelay = pAtmoConfigSrc->m_ColorChanger_iDelay;
this->m_LrColorChanger_iSteps = pAtmoConfigSrc->m_LrColorChanger_iSteps;
this->m_LrColorChanger_iDelay = pAtmoConfigSrc->m_LrColorChanger_iDelay;
this->m_StaticColor_Red = pAtmoConfigSrc->m_StaticColor_Red;
this->m_StaticColor_Green = pAtmoConfigSrc->m_StaticColor_Green;
this->m_StaticColor_Blue = pAtmoConfigSrc->m_StaticColor_Blue;
this->m_LiveViewFilterMode = pAtmoConfigSrc->m_LiveViewFilterMode;
this->m_LiveViewFilter_PercentNew = pAtmoConfigSrc->m_LiveViewFilter_PercentNew;
this->m_LiveViewFilter_MeanLength = pAtmoConfigSrc->m_LiveViewFilter_MeanLength;
this->m_LiveViewFilter_MeanThreshold = pAtmoConfigSrc->m_LiveViewFilter_MeanThreshold;
this->m_LiveView_EdgeWeighting = pAtmoConfigSrc->m_LiveView_EdgeWeighting;
this->m_LiveView_BrightCorrect = pAtmoConfigSrc->m_LiveView_BrightCorrect;
this->m_LiveView_DarknessLimit = pAtmoConfigSrc->m_LiveView_DarknessLimit;
this->m_LiveView_HueWinSize = pAtmoConfigSrc->m_LiveView_HueWinSize;
this->m_LiveView_SatWinSize = pAtmoConfigSrc->m_LiveView_SatWinSize;
this->m_LiveView_WidescreenMode = pAtmoConfigSrc->m_LiveView_WidescreenMode;
this->m_LiveView_HOverscanBorder = pAtmoConfigSrc->m_LiveView_HOverscanBorder;
this->m_LiveView_VOverscanBorder = pAtmoConfigSrc->m_LiveView_VOverscanBorder;
this->m_LiveView_DisplayNr = pAtmoConfigSrc->m_LiveView_DisplayNr;
this->m_LiveView_FrameDelay = pAtmoConfigSrc->m_LiveView_FrameDelay;
clearChannelMappings();
for(int i=1;i<pAtmoConfigSrc->getNumChannelAssignments();i++) {
tChannelAssignment *ta = pAtmoConfigSrc->m_ChannelAssignments[i];
if(ta!=NULL) {
tChannelAssignment *dest = this->m_ChannelAssignments[i];
if(dest == NULL) {
dest = new tChannelAssignment;
this->m_ChannelAssignments[i] = dest;
}
memcpy(dest, ta, sizeof(tChannelAssignment));
}
}
}
int CAtmoConfig::getNumChannelAssignments() {
int z=0;
for(int i=0;i<10;i++)
if(this->m_ChannelAssignments[i]!=NULL) z++;
return z;
}
void CAtmoConfig::clearChannelMappings() {
for(int i=1;i<10;i++) {
tChannelAssignment *ca = m_ChannelAssignments[i];
if(ca!=NULL)
delete ca;
m_ChannelAssignments[i] = NULL;
}
}
void CAtmoConfig::clearAllChannelMappings() {
for(int i=0;i<10;i++) {
tChannelAssignment *ca = m_ChannelAssignments[i];
if(ca!=NULL)
delete ca;
m_ChannelAssignments[i] = NULL;
}
}
void CAtmoConfig::AddChannelAssignment(tChannelAssignment *ta) {
for(int i=0;i<10;i++) {
if(m_ChannelAssignments[i] == NULL) {
m_ChannelAssignments[i] = ta;
break;
}
}
}
void CAtmoConfig::SetChannelAssignment(int index, tChannelAssignment *ta) {
if(m_ChannelAssignments[index]!=NULL)
delete m_ChannelAssignments[index];
m_ChannelAssignments[index] = ta;
}
CAtmoZoneDefinition *CAtmoConfig::getZoneDefinition(int zoneIndex) {
if(zoneIndex < 0)
return NULL;
if(zoneIndex >= ATMO_NUM_CHANNELS)
return NULL;
return m_ZoneDefinitions[zoneIndex];
}
This diff is collapsed.
/*
* AtmoConnection.cpp: generic/abstract class defining all methods for the
* communication with the hardware
*
* See the README.txt file for copyright information and how to reach the author(s).
*
* $Id$
*/
#include "AtmoConnection.h"
CAtmoConnection::CAtmoConnection(CAtmoConfig *cfg)
{
this->m_pAtmoConfig = cfg;
if(cfg->getNumChannelAssignments()>0) {
tChannelAssignment *ca = cfg->getChannelAssignment(0);
for(int i=0;i<ATMO_NUM_CHANNELS;i++) {
m_ChannelAssignment[i] = ca->mappings[i];
}
} else {
for(int i=0;i<ATMO_NUM_CHANNELS;i++) {
m_ChannelAssignment[i] = i;
}
}
}
void CAtmoConnection::SetChannelAssignment(tChannelAssignment *ca) {
for(int i=0;i<ATMO_NUM_CHANNELS;i++) {
m_ChannelAssignment[i] = ca->mappings[i];
}
}
CAtmoConnection::~CAtmoConnection(void)
{
if(isOpen())
CloseConnection();
}
/*
* AtmoConnection.h: generic/abstract class defining all methods for the
* communication with the hardware
*
* See the README.txt file for copyright information and how to reach the author(s).
*
* $Id$
*/
#ifndef _AtmoConnection_h_
#define _AtmoConnection_h_
#include "AtmoDefs.h"
#include "AtmoConfig.h"
class CAtmoConnection
{
protected:
CAtmoConfig *m_pAtmoConfig;
int m_ChannelAssignment[ATMO_NUM_CHANNELS];
public:
CAtmoConnection(CAtmoConfig *cfg);
virtual ~CAtmoConnection(void);
virtual ATMO_BOOL OpenConnection() { return false; }
virtual void CloseConnection() {};
virtual ATMO_BOOL isOpen(void) { return false; }
virtual ATMO_BOOL SendData(unsigned char numChannels,
int red[],
int green[],
int blue[]) { return false; }
virtual ATMO_BOOL SendData(tColorPacket data) { return false; }
virtual ATMO_BOOL setChannelColor(int channel, tRGBColor color) { return false; }
virtual ATMO_BOOL setChannelValues(int numValues,unsigned char *channel_values) { return false; }
virtual ATMO_BOOL HardwareWhiteAdjust(int global_gamma,
int global_contrast,
int contrast_red,
int contrast_green,
int contrast_blue,
int gamma_red,
int gamma_green,
int gamma_blue,
ATMO_BOOL storeToEeprom) { return false; }
virtual void SetChannelAssignment(tChannelAssignment *ca);
};
#endif
/*
* AtmoDefs.h: a lot of globals defines for the color computation - most of this file
* is an one to one copy of "defs.h" from Atmo VDR Plugin
*
* See the README.txt file for copyright information and how to reach the author(s).
*
* $Id$
*/
#ifndef _AtmoDefs_h_
#define _AtmoDefs_h_
#if defined(__LIBVLC__)
# include "config.h"
# include <vlc/vlc.h>
/* some things need to be changed if this code is used inside VideoLan Filter Module */
# define _ATMO_VLC_PLUGIN_
# define ATMO_BOOL vlc_bool_t
# define ATMO_TRUE VLC_TRUE
# define ATMO_FALSE VLC_FALSE
#else
typedef int ATMO_BOOL;
# define ATMO_TRUE 1
# define ATMO_FALSE 0
#endif
#if !defined(WIN32)
#define INVALID_HANDLE_VALUE -1
typedef int HANDLE;
typedef unsigned long DWORD;
#define BI_RGB 0L
#if !defined(_BITMAPFILEHEADER_)
#define _BITMAPFILEHEADER_
typedef struct
#ifdef HAVE_ATTRIBUTE_PACKED
__attribute__((__packed__))
#endif
{
uint16_t bfType;
uint32_t bfSize;
uint16_t bfReserved1;
uint16_t bfReserved2;
uint32_t bfOffBits;
} BITMAPFILEHEADER, *LPBITMAPFILEHEADER, *PBITMAPFILEHEADER;
#endif
#endif
#define FCC(ch4) ((((DWORD)(ch4) & 0xFF) << 24) | \
(((DWORD)(ch4) & 0xFF00) << 8) | \
(((DWORD)(ch4) & 0xFF0000) >> 8) | \
(((DWORD)(ch4) & 0xFF000000) >> 24))
// maximal Anzahl Kanle...
#define ATMO_NUM_CHANNELS 5
// capture width/height
#define CAP_WIDTH 64
#define CAP_HEIGHT 48
// imagesize
#define IMAGE_SIZE (CAP_WIDTH * CAP_HEIGHT)
enum AtmoConnectionType
{
actSerialPort = 0,
actDummy = 1,
actDMX = 2
};
static const char *AtmoDeviceTypes[] = {
"Atmo",
"Dummy",
"DMX"
};
#define ATMO_DEVICE_COUNT 3
#if defined(_ATMO_VLC_PLUGIN_)
enum EffectMode {
emUndefined = -1,
emDisabled = 0,
emStaticColor = 1,
emLivePicture = 2
};
#else
enum EffectMode {
emUndefined = -1,
emDisabled = 0,
emStaticColor = 1,
emLivePicture = 2,
emColorChange = 3,
emLrColorChange = 4
};
#endif
enum AtmoFilterMode {
afmNoFilter,
afmCombined,
afmPercent
};
typedef struct {
ATMO_BOOL system;
char name[64];
int mappings[ATMO_NUM_CHANNELS];
} tChannelAssignment;
// --- tRGBColor --------------------------------------------------------------
typedef struct
{
unsigned char r, g, b;
} tRGBColor;
// --- tColorPacket -----------------------------------------------------------
typedef struct
{
tRGBColor channel[ATMO_NUM_CHANNELS];
} tColorPacket;
// --- tRGBColorLongInt -------------------------------------------------------
typedef struct
{
long int r, g, b;
} tRGBColorLongInt;
// --- tColorPacketLongInt ----------------------------------------------------
typedef struct
{
tRGBColorLongInt channel[ATMO_NUM_CHANNELS];
} tColorPacketLongInt;
// --- tWeightPacket ----------------------------------------------------------
typedef struct
{
int channel[ATMO_NUM_CHANNELS];
} tWeightPacket;
// --- tHSVColor --------------------------------------------------------------
typedef struct
{
unsigned char h, s, v;
} tHSVColor;
#endif
/*
* AtmoDynData.cpp: class for holding all variable data - which may be
* passed between function calls, into threads instead of the use
* of global variables
*
* See the README.txt file for copyright information and how to reach the author(s).
*
* $Id$
*/
#include "AtmoDynData.h"
#if defined(_ATMO_VLC_PLUGIN_)
CAtmoDynData::CAtmoDynData(vlc_object_t *p_atmo_filter, CAtmoConfig *pAtmoConfig) {
this->p_atmo_filter = p_atmo_filter;
this->m_pAtmoConfig = pAtmoConfig;
this->m_pAtmoConnection = NULL;
this->m_pCurrentEffectThread = NULL;
vlc_mutex_init( p_atmo_filter, &m_lock );
}
#else
CAtmoDynData::CAtmoDynData(HINSTANCE hInst, CAtmoConfig *pAtmoConfig, CAtmoDisplays *pAtmoDisplays) {
this->m_pAtmoConfig = pAtmoConfig;
this->m_pAtmoDisplays = pAtmoDisplays;
this->m_pAtmoConnection = NULL;
this->m_pCurrentEffectThread = NULL;
this->m_hInst = hInst;
InitializeCriticalSection(&m_RemoteCallCriticalSection);
}
#endif
CAtmoDynData::~CAtmoDynData(void)
{
#if defined(_ATMO_VLC_PLUGIN_)
vlc_mutex_destroy( &m_lock );
#else
DeleteCriticalSection(&m_RemoteCallCriticalSection);
#endif
}
void CAtmoDynData::LockCriticalSection() {
#if defined(_ATMO_VLC_PLUGIN_)
vlc_mutex_lock( &m_lock );
#else
EnterCriticalSection(&m_RemoteCallCriticalSection);
#endif
}
void CAtmoDynData::UnLockCriticalSection() {
#if defined(_ATMO_VLC_PLUGIN_)
vlc_mutex_unlock( &m_lock );
#else
LeaveCriticalSection(&m_RemoteCallCriticalSection);
#endif
}
/*
* AtmoDynData.h: class for holding all variable data - which may be passed
* between function calls, into threads instead of the use of global variables
*
* See the README.txt file for copyright information and how to reach the author(s).
*
* $Id$
*/
#ifndef _AtmoDynData_h_
#define _AtmoDynData_h_
#include "AtmoDefs.h"
#include "AtmoThread.h"
#include "AtmoConfig.h"
#include "AtmoConnection.h"
#if !defined(_ATMO_VLC_PLUGIN_)
# include "AtmoDisplays.h"
#else
# include <vlc/vlc.h>
# include <vlc_threads_funcs.h>
#endif
/*
the idea behind this class is to avoid a mix of persistent value and
volatile values in CAtmoConfig class because some parameters and variables
exists only for the current process and won't be stored to the registry
(Simple thought its a container... )
you ask? why I didn't used a struct for it? ..mmh I like classes?
Problem: MultiThreading! todo semaphore, mutex!
Allways stop the current effect Thread before changing AtmoConnection or
AtmoConfig!
*/
class CAtmoDynData
{
private:
CThread *m_pCurrentEffectThread;
CAtmoConnection *m_pAtmoConnection;
CAtmoConfig *m_pAtmoConfig;
#if !defined(_ATMO_VLC_PLUGIN_)
CAtmoDisplays *m_pAtmoDisplays;
HINSTANCE m_hInst;
CRITICAL_SECTION m_RemoteCallCriticalSection;
#else
vlc_object_t *p_atmo_filter;
vlc_mutex_t m_lock;
#endif
public:
#if !defined(_ATMO_VLC_PLUGIN_)
CAtmoDynData(HINSTANCE hInst,
CAtmoConfig *pAtmoConfig,
CAtmoDisplays *pAtmoDisplays);
#else
CAtmoDynData(vlc_object_t *p_atmo_filter,
CAtmoConfig *pAtmoConfig);
#endif
~CAtmoDynData(void);
CThread *getEffectThread() { return m_pCurrentEffectThread; }
void setEffectThread(CThread *value) { m_pCurrentEffectThread = value; }
CAtmoConnection *getAtmoConnection() { return m_pAtmoConnection; }
void setAtmoConnection(CAtmoConnection *value) { m_pAtmoConnection = value; }
CAtmoConfig *getAtmoConfig() { return m_pAtmoConfig; }
#if !defined(_ATMO_VLC_PLUGIN_)
CAtmoDisplays *getAtmoDisplays() { return m_pAtmoDisplays; }
HINSTANCE getHinstance() { return m_hInst; }
#else
vlc_object_t *getAtmoFilter() { return p_atmo_filter; }
#endif
void LockCriticalSection();
void UnLockCriticalSection();
};
#endif
This diff is collapsed.
#ifndef _AtmoExternalCaptureInput_h_
#define _AtmoExternalCaptureInput_h_
#include "AtmoDefs.h"
#if defined(WIN32)
# include <windows.h>
# else
# if defined(_ATMO_VLC_PLUGIN_)
// need bitmap info header
# include <vlc_codecs.h>
# endif
#endif
#if !defined(_ATMO_VLC_PLUGIN_)
# include <comdef.h>
# include "AtmoWin_h.h"
#endif
#include "AtmoInput.h"
#include "AtmoThread.h"
#include "AtmoConfig.h"
#include "AtmoDynData.h"
#include "AtmoCalculations.h"
class CAtmoExternalCaptureInput :
public CAtmoInput,
public CThread
{
protected:
#if defined(_ATMO_VLC_PLUGIN_)
vlc_cond_t m_WakeupCond;
vlc_mutex_t m_WakeupLock;
#else
HANDLE m_hWakeupEvent;
#endif
BITMAPINFOHEADER m_CurrentFrameHeader;
void *m_pCurrentFramePixels;
virtual DWORD Execute(void);
void CalcColors();
public:
/*
this method is called from the com server AtmoLiveViewControlImpl!
or inside videolan from the filter method to start a new processing
*/
void DeliverNewSourceDataPaket(BITMAPINFOHEADER *bmpInfoHeader,void *pixelData);
public:
CAtmoExternalCaptureInput(CAtmoDynData *pAtmoDynData);
virtual ~CAtmoExternalCaptureInput(void);
/*
Opens the input-device. Parameters (e.g. the device-name)
Returns true if the input-device was opened successfully.
input-device can be the GDI surface of screen (windows only)
or the videolan filter
*/
virtual ATMO_BOOL Open(void);
/*
Closes the input-device.
Returns true if the input-device was closed successfully.
*/
virtual ATMO_BOOL Close(void);
/*
this method is called from the AtmoLiveView thread - to get the
new color packet (a packet is an RGB triple for each channel)
*/
virtual tColorPacket GetColorPacket(void);
/*
this method is also called from the AtmoLiveView thread - to
resync on a frame
*/
virtual void WaitForNextFrame(DWORD timeout);
};
#endif
/*
* AtmoInput.cpp: abstract class for retrieving precalculated image data
* from different sources in the live view mode
*
*
* See the README.txt file for copyright information and how to reach the author(s).
*
* $Id$
*/
#include "AtmoInput.h"
CAtmoInput::CAtmoInput(CAtmoDynData *pAtmoDynData)
{
this->m_pAtmoDynData = pAtmoDynData;
}
CAtmoInput::~CAtmoInput(void)
{
}
void CAtmoInput::WaitForNextFrame(DWORD timeout)
{
return;
}
/*
* AtmoInput.h: abstract class for retrieving precalculated image data from
* different sources in the live view mode
*
*
* See the README.txt file for copyright information and how to reach the author(s).
*
* $Id$
*/
#ifndef _AtmoInput_h_
#define _AtmoInput_h_
#include "AtmoDefs.h"
#include "AtmoDynData.h"
/*
basic definition of an AtmoLight data/image source ...
*/
class CAtmoInput {
protected:
tColorPacket m_ColorPacket;
volatile ATMO_BOOL m_FrameArrived;
CAtmoDynData *m_pAtmoDynData;
public:
CAtmoInput(CAtmoDynData *pAtmoDynData);
virtual ~CAtmoInput(void);
// Opens the input-device.
// Returns true if the input-device was opened successfully.
virtual ATMO_BOOL Open(void) { return ATMO_FALSE; }
// Closes the input-device.
// Returns true if the input-device was closed successfully.
virtual ATMO_BOOL Close(void) { return ATMO_FALSE; }
// Returns the calculated tColorPacket for further processing (e.g. filtering).
virtual tColorPacket GetColorPacket(void) { return m_ColorPacket; }
// wait for the arrival of the next frame...(to come in sync again)
virtual void WaitForNextFrame(DWORD timeout);
};
#endif
/*
* AtmoLiveView.cpp: this effect outputs colors as result of a picture
* content (most complex effect) see thread.c of the linux VDR version -
* to fully understand what happens here..
*
* See the README.txt file for copyright information and how to reach the author(s).
*
* $Id$
*/
#include "AtmoDefs.h"
#include "AtmoLiveView.h"
#include "AtmoOutputFilter.h"
#include "AtmoTools.h"
#if defined(_ATMO_VLC_PLUGIN_)
# include <vlc/vlc.h>
#else
# include "AtmoGdiDisplayCaptureInput.h"
#endif
#include "AtmoExternalCaptureInput.h"
#if defined(_ATMO_VLC_PLUGIN_)
CAtmoLiveView::CAtmoLiveView(CAtmoDynData *pAtmoDynData) :
CThread(pAtmoDynData->getAtmoFilter())
{
this->m_pAtmoDynData = pAtmoDynData;
m_pAtmoInput = NULL;
}
#else
CAtmoLiveView::CAtmoLiveView(CAtmoDynData *pAtmoDynData)
{
this->m_pAtmoDynData = pAtmoDynData;
m_LiveViewSource = lvsGDI;
m_CurrentLiveViewSource = lvsGDI;
m_InputChangedEvent = CreateEvent(NULL,ATMO_FALSE,ATMO_FALSE,NULL);
m_pAtmoInput = NULL;
InitializeCriticalSection(&m_InputChangeCriticalSection);
}
#endif
CAtmoLiveView::~CAtmoLiveView(void)
{
#if !defined(_ATMO_VLC_PLUGIN_)
DeleteCriticalSection(&m_InputChangeCriticalSection);
CloseHandle(m_InputChangedEvent);
#endif
}
#if !defined(_ATMO_VLC_PLUGIN_)
STDMETHODIMP CAtmoLiveView::setLiveViewSource(enum ComLiveViewSource dwModus)
{
if(dwModus != m_LiveViewSource) {
m_LiveViewSource = dwModus;
/*
you may ask why I don't use a critical section here and directly acces the
the variable of the Thread?
Just because you would need very much / often entering / leaving the critical
section ... and in this case It could be avoid ...
assigning the value to the "mirror" variable m_LiveViewSource which is compare
in every run of the thread with its current value ... if there is a change
the thread can proceed switching the live source ... until this is done
the thread calling this method is waiting...
*/
// I don't expect that it will take longer than 500ms to switch...
if(WaitForSingleObject(m_InputChangedEvent,500) == WAIT_TIMEOUT)
return S_FALSE; // if not so the switch seems be have failed (badly)
}
return S_OK;
}
STDMETHODIMP CAtmoLiveView::getCurrentLiveViewSource(enum ComLiveViewSource *modus) {
*modus = m_LiveViewSource;
return S_OK;
}
#endif
DWORD CAtmoLiveView::Execute(void)
{
#if defined(_ATMO_VLC_PLUGIN_)
mtime_t ticks;
#else
DWORD ticks;
#endif
int i_frame_counter = 0;
CAtmoInput *newInput,*oldInput;
tColorPacket ColorPacket;
CAtmoConnection *pAtmoConnection = this->m_pAtmoDynData->getAtmoConnection();
if((pAtmoConnection == NULL) || (pAtmoConnection->isOpen() == ATMO_FALSE)) return 0;
CAtmoConfig *pAtmoConfig = this->m_pAtmoDynData->getAtmoConfig();
/*
this object does post processing of the pixel data
like jump /scenechange detection fading over the colors
*/
CAtmoOutputFilter *filter = new CAtmoOutputFilter(this->m_pAtmoDynData->getAtmoConfig());
#if defined(_ATMO_VLC_PLUGIN_)
/* this thread is the data preprocess which gets the real 64x48 pixel
and converts them into the RGB channel values - this is done in
another thread to keep this thread at a constant timing - to that
color output is updated 25 times a second
*/
m_pAtmoInput = new CAtmoExternalCaptureInput(m_pAtmoDynData);
#else
if(m_LiveViewSource == lvsGDI)
m_pAtmoInput = new CAtmoGdiDisplayCaptureInput(m_pAtmoDynData);
else
m_pAtmoInput = new CAtmoExternalCaptureInput(m_pAtmoDynData);
#endif
if(m_pAtmoInput->Open() == ATMO_TRUE)
{
/*
wait for the first frame to go in sync with the other thread
*/
#if defined(_ATMO_VLC_PLUGIN_)
msg_Dbg( m_pAtmoThread, "CAtmoLiveView::Execute(void)");
#endif
m_pAtmoInput->WaitForNextFrame(500);
while(this->m_bTerminated == ATMO_FALSE)
{
/* atmoInput - capture Thread Running... */
#if defined(_ATMO_VLC_PLUGIN_)
ticks = mdate();
#else
ticks = GetTickCount();
#endif
/* grab current Packet from Input! */
ColorPacket = m_pAtmoInput->GetColorPacket();
/* pass it through the outputfilters! */
ColorPacket = filter->Filtering(ColorPacket);
/* apply gamma later ;-) not implemented yet */
ColorPacket = CAtmoTools::ApplyGamma(pAtmoConfig, ColorPacket);
/*
apply white calibration - only if it is not
done by the hardware
*/
if(pAtmoConfig->isUseSoftwareWhiteAdj())
ColorPacket = CAtmoTools::WhiteCalibration(pAtmoConfig,
ColorPacket);
/* send color data to the the hardware... */
pAtmoConnection->SendData(ColorPacket);
/*
experimental do sync every 100 Frames to the image producer
thread because GetTickCount precision is really poor ;-)
*/
i_frame_counter++;
if(i_frame_counter == 100) {
m_pAtmoInput->WaitForNextFrame(50);
i_frame_counter = 0;
#if !defined(WIN32)
/* kludge for pthreads? when running GDB debugger using the same condition variable
to often results in haging wait timedout...
*/
#ifdef _ATMO_KLUDGE_
vlc_mutex_lock( &m_TerminateLock );
vlc_cond_destroy( &m_TerminateCond );
vlc_cond_init( m_pAtmoThread, &m_TerminateCond );
vlc_mutex_unlock( &m_TerminateLock );
#endif
#endif
continue;
}
#if !defined(_ATMO_VLC_PLUGIN_)
/*
Check if Input Source has changed - through an async
call from the com interface?
*/
if(m_CurrentLiveViewSource != m_LiveViewSource) {
oldInput = m_pAtmoInput;
m_pAtmoInput = NULL;
if(m_LiveViewSource == lvsGDI) {
// create new GDI Input Source...
newInput = new CAtmoGdiDisplayCaptureInput(m_pAtmoDynData);
newInput->Open(); // should not fail now... hope is the best!
} else if(m_LiveViewSource == lvsExternal) {
newInput = new CAtmoExternalCaptureInput(m_pAtmoDynData);
newInput->Open();
}
m_CurrentLiveViewSource = m_LiveViewSource;
m_pAtmoInput = newInput;
oldInput->Close();
delete oldInput;
/*
signal the call to the method "setLiveViewSource" the source
was switched...
*/
SetEvent(m_InputChangedEvent);
// do sync with input thread
m_pAtmoInput->WaitForNextFrame(100);
continue;
}
#endif
/*
calculate RunTime of thread abbove (doesn't work well - so
this threads comes out of sync with Image producer and the
framerate (25fps) drifts away
*/
#if defined(_ATMO_VLC_PLUGIN_)
ticks = ((mdate() - ticks) + 999)/1000;
#else
ticks = GetTickCount() - ticks;
#endif
if(ticks < 40)
{
// ThreadSleep -> AtmoThread.cpp
if(this->ThreadSleep(40 - ticks)==ATMO_FALSE)
break;
}
}
/* shutdown the input processor thread */
m_pAtmoInput->Close();
}
delete m_pAtmoInput;
m_pAtmoInput = NULL;
#if !defined(_ATMO_VLC_PLUGIN_)
/*
if there is a pending call to setLiveViewSource let him surely return before
destroying the thread and this class instance...
*/
SetEvent(m_InputChangedEvent);
#endif
delete filter;
return 0;
}
/*
* AtmoLiveView.h: this effect outputs colors as result of a picture content
* (most complex effect) see thread.c of the linux version - to fully understand
* what happes here..
*
* See the README.txt file for copyright information and how to reach the author(s).
*
* $Id$
*/
#ifndef _AtmoLiveView_h_
#define _AtmoLiveView_h_
#include "AtmoDefs.h"
#if !defined(_ATMO_VLC_PLUGIN_)
# include <comdef.h>
# include "AtmoWin_h.h"
# include <windows.h>
#endif
#include "AtmoThread.h"
#include "AtmoConfig.h"
#include "AtmoConnection.h"
#include "AtmoInput.h"
class CAtmoLiveView : public CThread
{
protected:
virtual DWORD Execute(void);
#if !defined(_ATMO_VLC_PLUGIN_)
public:
STDMETHODIMP setLiveViewSource(enum ComLiveViewSource dwModus);
STDMETHODIMP getCurrentLiveViewSource(enum ComLiveViewSource *modus);
#endif
protected:
CAtmoDynData *m_pAtmoDynData;
CAtmoInput *m_pAtmoInput;
#if !defined(_ATMO_VLC_PLUGIN_)
ComLiveViewSource m_LiveViewSource;
ComLiveViewSource m_CurrentLiveViewSource;
CRITICAL_SECTION m_InputChangeCriticalSection;
HANDLE m_InputChangedEvent;
#endif
public:
CAtmoLiveView(CAtmoDynData *pAtmoDynData);
virtual ~CAtmoLiveView(void);
CAtmoInput *getAtmoInput() { return m_pAtmoInput; }
#if !defined(_ATMO_VLC_PLUGIN_)
ComLiveViewSource getLiveViewSource() { return m_CurrentLiveViewSource; }
#endif
};
#endif
/*
* AtmoOutputFilter.cpp: Post Processor for the color data retrieved from
* a CAtmoInput
*
* mostly 1:1 from vdr-linux-src "filter.c" copied
*
* See the README.txt file for copyright information and how to reach the author(s).
*
* $Id$
*/
#include <string.h>
#include "AtmoOutputFilter.h"
CAtmoOutputFilter::CAtmoOutputFilter(CAtmoConfig *atmoConfig)
{
this->m_pAtmoConfig = atmoConfig;
ResetFilter();
}
CAtmoOutputFilter::~CAtmoOutputFilter(void)
{
}
void CAtmoOutputFilter::ResetFilter(void)
{
// reset filter values
MeanFilter(true);
PercentFilter(true);
}
tColorPacket CAtmoOutputFilter::Filtering(tColorPacket ColorPacket)
{
filter_input = ColorPacket;
switch (m_pAtmoConfig->getLiveViewFilterMode())
{
case afmNoFilter:
filter_output = filter_input;
break;
case afmCombined:
MeanFilter(false);
break;
case afmPercent:
PercentFilter(false);
break;
default:
filter_output = filter_input;
break;
}
return filter_output;
}
void CAtmoOutputFilter::PercentFilter(ATMO_BOOL init)
{
// last values needed for the percentage filter
static tColorPacket filter_output_old;
if (init) // Initialization
{
memset(&filter_output_old, 0, sizeof(filter_output_old));
return;
}
int percentNew = this->m_pAtmoConfig->getLiveViewFilter_PercentNew();
for (int ch = 0; ch < ATMO_NUM_CHANNELS; ch++)
{
filter_output.channel[ch].r = (filter_input.channel[ch].r *
(100-percentNew) + filter_output_old.channel[ch].r * percentNew) / 100;
filter_output.channel[ch].g = (filter_input.channel[ch].g *
(100-percentNew) + filter_output_old.channel[ch].g * percentNew) / 100;
filter_output.channel[ch].b = (filter_input.channel[ch].b *
(100-percentNew) + filter_output_old.channel[ch].b * percentNew) / 100;
}
filter_output_old = filter_output;
}
void CAtmoOutputFilter::MeanFilter(ATMO_BOOL init)
{
// needed vor the running mean value filter
static tColorPacketLongInt mean_sums;
static tColorPacket mean_values;
// needed for the percentage filter
static tColorPacket filter_output_old;
static int filter_length_old;
char reinitialize = 0;
if (init) // Initialization
{
memset(&filter_output_old, 0, sizeof(filter_output_old));
memset(&mean_sums, 0, sizeof(mean_sums));
memset(&mean_values, 0, sizeof(mean_values));
return;
}
int AtmoSetup_Filter_MeanLength = m_pAtmoConfig->getLiveViewFilter_MeanLength();
int AtmoSetup_Filter_PercentNew = m_pAtmoConfig->getLiveViewFilter_PercentNew();
int AtmoSetup_Filter_MeanThreshold = m_pAtmoConfig->getLiveViewFilter_MeanThreshold();
// if filter_length has changed
if (filter_length_old != AtmoSetup_Filter_MeanLength)
{
// force reinitialization of the filter
reinitialize = 1;
}
filter_length_old = AtmoSetup_Filter_MeanLength;
if (filter_length_old < 20) filter_length_old = 20; // avoid division by 0
for (int ch = 0; ch < ATMO_NUM_CHANNELS; ch++)
{
// calculate the mean-value filters
mean_sums.channel[ch].r +=
(long int)(filter_input.channel[ch].r - mean_values.channel[ch].r); // red
mean_values.channel[ch].r = mean_sums.channel[ch].r / ((long int)filter_length_old / 20);
mean_sums.channel[ch].g +=
(long int)(filter_input.channel[ch].g - mean_values.channel[ch].g); // green
mean_values.channel[ch].g = mean_sums.channel[ch].g / ((long int)filter_length_old / 20);
mean_sums.channel[ch].b +=
(long int)(filter_input.channel[ch].b - mean_values.channel[ch].b); // blue
mean_values.channel[ch].b = mean_sums.channel[ch].b / ((long int)filter_length_old / 20);
// check, if there is a jump -> check if differences between actual values and filter values are too big
long int dist; // distance between the two colors in the 3D RGB space
dist = (mean_values.channel[ch].r - filter_input.channel[ch].r) *
(mean_values.channel[ch].r - filter_input.channel[ch].r) +
(mean_values.channel[ch].g - filter_input.channel[ch].g) *
(mean_values.channel[ch].g - filter_input.channel[ch].g) +
(mean_values.channel[ch].b - filter_input.channel[ch].b) *
(mean_values.channel[ch].b - filter_input.channel[ch].b);
/*
if (dist > 0) { dist = (long int)sqrt((double)dist); }
avoid sqrt(0) (TODO: necessary?)
I think its cheaper to calculate the square of something ..? insteas geting the square root?
*/
double distMean = ((double)AtmoSetup_Filter_MeanThreshold * 3.6f);
distMean = distMean * distMean;
/*
compare calculated distance with the filter threshold
if ((dist > (long int)((double)AtmoSetup.Filter_MeanThreshold * 3.6f)) || ( reinitialize == 1))
*/
if ((dist > distMean) || ( reinitialize == 1))
{
// filter jump detected -> set the long filters to the result of the short filters
filter_output.channel[ch] = mean_values.channel[ch] = filter_input.channel[ch];
mean_sums.channel[ch].r = filter_input.channel[ch].r *
(filter_length_old / 20);
mean_sums.channel[ch].g = filter_input.channel[ch].g *
(filter_length_old / 20);
mean_sums.channel[ch].b = filter_input.channel[ch].b *
(filter_length_old / 20);
}
else
{
// apply an additional percent filter and return calculated values
filter_output.channel[ch].r = (mean_values.channel[ch].r *
(100-AtmoSetup_Filter_PercentNew) +
filter_output_old.channel[ch].r * AtmoSetup_Filter_PercentNew) / 100;
filter_output.channel[ch].g = (mean_values.channel[ch].g *
(100-AtmoSetup_Filter_PercentNew) +
filter_output_old.channel[ch].g * AtmoSetup_Filter_PercentNew) / 100;
filter_output.channel[ch].b = (mean_values.channel[ch].b *
(100-AtmoSetup_Filter_PercentNew) +
filter_output_old.channel[ch].b * AtmoSetup_Filter_PercentNew) / 100;
}
}
filter_output_old = filter_output;
}
/*
* AtmoOutputFilter.h: Post Processor for the color data retrieved from a CAtmoInput
*
* mostly 1:1 from Linux-src "filter.c" copied
*
* See the README.txt file for copyright information and how to reach the author(s).
*
* $Id$
*/
#ifndef _AtmoOutputFilter_h_
#define _AtmoOutputFilter_h_
#include "AtmoConfig.h"
#include "AtmoDefs.h"
class CAtmoOutputFilter
{
private:
tColorPacket filter_input; // input of the filter
tColorPacket filter_output; // output of the filter
void PercentFilter(ATMO_BOOL init);
void MeanFilter(ATMO_BOOL init);
CAtmoConfig *m_pAtmoConfig;
public:
public:
CAtmoOutputFilter(CAtmoConfig *atmoConfig);
virtual ~CAtmoOutputFilter(void);
void ResetFilter(void);
tColorPacket Filtering(tColorPacket ColorPacket);
};
#endif
/*
* AtmoSerialConnection.cpp: Class for communication with the serial hardware of
* Atmo Light, opens and configures the serial port
*
* See the README.txt file for copyright information and how to reach the author(s).
*
* $Id$
*/
#include "AtmoDefs.h"
#include "AtmoSerialConnection.h"
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#if !defined(WIN32)
#include <termios.h>
#include <unistd.h>
#endif
/*
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <vdr/tools.h>
*/
CAtmoSerialConnection::CAtmoSerialConnection(CAtmoConfig *cfg) : CAtmoConnection(cfg) {
m_hComport = INVALID_HANDLE_VALUE;
}
CAtmoSerialConnection::~CAtmoSerialConnection() {
CloseConnection();
}
ATMO_BOOL CAtmoSerialConnection::OpenConnection() {
#if defined(_ATMO_VLC_PLUGIN_)
char *serdevice = m_pAtmoConfig->getSerialDevice();
if(!serdevice)
return ATMO_FALSE;
#else
int portNummer = m_pAtmoConfig->getComport();
m_dwLastWin32Error = 0;
if(portNummer < 1) return ATMO_FALSE; // make no real sense;-)
#endif
CloseConnection();
#if !defined(_ATMO_VLC_PLUGIN_)
char comport[16]; // com4294967295
sprintf(comport,"com%d",portNummer);
#endif
#if defined(WIN32)
# if defined(_ATMO_VLC_PLUGIN_)
m_hComport = CreateFile(serdevice, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
# else
m_hComport = CreateFile(comport, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
# endif
if(m_hComport == INVALID_HANDLE_VALUE) {
// we have a problem here can't open com port... somebody else may use it?
// m_dwLastWin32Error = GetLastError();
return ATMO_FALSE;
}
/* change serial settings (Speed, stopbits etc.) */
DCB dcb; // fr comport-parameter
dcb.DCBlength = sizeof(DCB);
GetCommState (m_hComport, &dcb); // ger current serialport settings
dcb.BaudRate = 38400; // set speed
dcb.ByteSize = 8; // set databits
dcb.Parity = NOPARITY; // set parity
dcb.StopBits = ONESTOPBIT; // set one stop bit
SetCommState (m_hComport, &dcb); // apply settings
#else
int bconst = B38400;
# if defined(_ATMO_VLC_PLUGIN_)
m_hComport = open(serdevice,O_RDWR |O_NOCTTY);
# else
m_hComport = open(comport,O_RDWR | O_NOCTTY);
# endif
if(m_hComport < 0) {
return ATMO_FALSE;
}
struct termios tio;
memset(&tio,0,sizeof(tio));
tio.c_cflag = (CS8 | CREAD | HUPCL | CLOCAL);
tio.c_iflag = (INPCK | BRKINT);
cfsetispeed(&tio, bconst);
cfsetospeed(&tio, bconst);
if(!tcsetattr(m_hComport, TCSANOW, &tio)) {
tcflush(m_hComport, TCIOFLUSH);
} else {
// can't change parms
close(m_hComport);
m_hComport = -1;
return false;
}
#endif
return true;
}
void CAtmoSerialConnection::CloseConnection() {
if(m_hComport!=INVALID_HANDLE_VALUE) {
#if defined(WIN32)
CloseHandle(m_hComport);
#else
close(m_hComport);
#endif
m_hComport = INVALID_HANDLE_VALUE;
}
}
ATMO_BOOL CAtmoSerialConnection::isOpen(void) {
return (m_hComport != INVALID_HANDLE_VALUE);
}
ATMO_BOOL CAtmoSerialConnection::HardwareWhiteAdjust(int global_gamma,
int global_contrast,
int contrast_red,
int contrast_green,
int contrast_blue,
int gamma_red,
int gamma_green,
int gamma_blue,
ATMO_BOOL storeToEeprom) {
if(m_hComport == INVALID_HANDLE_VALUE)
return ATMO_FALSE;
DWORD iBytesWritten;
/*
[0] = 255
[1] = 00
[2] = 00
[3] = 101
[4] brightness 0..255 ?
[5] Contrast Red 11 .. 100
[6] Contrast Green 11 .. 100
[7] Contrast Blue 11 .. 100
[8] Gamma Red 11 .. 35
[9] Gamma Red 11 .. 35
[10] Gamma Red 11 .. 35
[11] Globale Contrast 11 .. 100
[12] Store Data: 199 (else 0)
*/
unsigned char sendBuffer[16];
sendBuffer[0] = 0xFF;
sendBuffer[1] = 0x00;
sendBuffer[2] = 0x00;
sendBuffer[3] = 101;
sendBuffer[4] = (global_gamma & 255);
sendBuffer[5] = (contrast_red & 255);
sendBuffer[6] = (contrast_green & 255);
sendBuffer[7] = (contrast_blue & 255);
sendBuffer[8] = (gamma_red & 255);
sendBuffer[9] = (gamma_green & 255);
sendBuffer[10] = (gamma_blue & 255);
sendBuffer[11] = (global_contrast & 255);
if(storeToEeprom == ATMO_TRUE)
sendBuffer[12] = 199; // store to eeprom!
else
sendBuffer[12] = 0;
#if defined(WIN32)
WriteFile(m_hComport, sendBuffer, 13, &iBytesWritten, NULL); // send to COM-Port
#else
iBytesWritten = write(m_hComport, sendBuffer, 13);
tcdrain(m_hComport);
#endif
return (iBytesWritten == 13) ? ATMO_TRUE : ATMO_FALSE;
}
ATMO_BOOL CAtmoSerialConnection::SendData(tColorPacket data) {
if(m_hComport == INVALID_HANDLE_VALUE)
return ATMO_FALSE;
unsigned char buffer[19];
DWORD iBytesWritten;
buffer[0] = 0xFF; // Start Byte
buffer[1] = 0x00; // Start channel 0
buffer[2] = 0x00; // Start channel 0
buffer[3] = 15; //
int iBuffer = 4;
for(int i=0;i<5;i++) {
if(m_ChannelAssignment[i]>=0) {
buffer[iBuffer++] = data.channel[m_ChannelAssignment[i]].r;
buffer[iBuffer++] = data.channel[m_ChannelAssignment[i]].g;
buffer[iBuffer++] = data.channel[m_ChannelAssignment[i]].b;
} else {
buffer[iBuffer++] = 0;
buffer[iBuffer++] = 0;
buffer[iBuffer++] = 0;
}
}
#if defined(WIN32)
WriteFile(m_hComport, buffer, 19, &iBytesWritten, NULL); // send to COM-Port
#else
iBytesWritten = write(m_hComport, buffer, 19);
tcdrain(m_hComport);
#endif
return (iBytesWritten == 19) ? ATMO_TRUE : ATMO_FALSE;
}
ATMO_BOOL CAtmoSerialConnection::SendData(unsigned char numChannels,
int red[],
int green[],
int blue[])
{
if(m_hComport == INVALID_HANDLE_VALUE)
return ATMO_FALSE;
DWORD bufSize = 4 + numChannels*3;
unsigned char *buffer = new unsigned char[bufSize];
DWORD iBytesWritten;
buffer[0] = 0xFF; // Start Byte
buffer[1] = 0x00; // Start Kanal 0
buffer[2] = 0x00; // Start Kanal 0
buffer[3] = numChannels * 3; //
int iBuffer = 4;
for(int i=0;i<numChannels;i++) {
if(m_ChannelAssignment[i]>=0) {
buffer[iBuffer++] = red[m_ChannelAssignment[i]] & 255;
buffer[iBuffer++] = green[m_ChannelAssignment[i]] & 255;
buffer[iBuffer++] = blue[m_ChannelAssignment[i]] & 255;
} else {
buffer[iBuffer++] = 0;
buffer[iBuffer++] = 0;
buffer[iBuffer++] = 0;
}
}
#if defined(WIN32)
WriteFile(m_hComport, buffer, bufSize, &iBytesWritten, NULL);
#else
iBytesWritten = write(m_hComport, buffer, bufSize);
tcdrain(m_hComport);
#endif
delete buffer;
return (iBytesWritten == bufSize) ? ATMO_TRUE : ATMO_FALSE;
}
/*
* AtmoCom.h: Class for communication with the serial hardware of Atmo Light,
* opens and configures the serial port
*
* See the README.txt file for copyright information and how to reach the author(s).
*
* $Id$
*/
#ifndef _AtmoSerialConnection_h_
#define _AtmoSerialConnection_h_
#include "AtmoDefs.h"
#include "AtmoConnection.h"
#include "AtmoConfig.h"
#if defined(WIN32)
# include <windows.h>
#endif
class CAtmoSerialConnection : public CAtmoConnection {
private:
HANDLE m_hComport;
#if defined(WIN32)
DWORD m_dwLastWin32Error;
public:
DWORD getLastError() { return m_dwLastWin32Error; }
#endif
public:
CAtmoSerialConnection(CAtmoConfig *cfg);
virtual ~CAtmoSerialConnection(void);
virtual ATMO_BOOL OpenConnection();
virtual void CloseConnection();
virtual ATMO_BOOL isOpen(void);
virtual ATMO_BOOL SendData(unsigned char numChannels,
int red[],
int green[],
int blue[]);
virtual ATMO_BOOL SendData(tColorPacket data);
virtual ATMO_BOOL HardwareWhiteAdjust(int global_gamma,
int global_contrast,
int contrast_red,
int contrast_green,
int contrast_blue,
int gamma_red,
int gamma_green,
int gamma_blue,
ATMO_BOOL storeToEeprom);
};
#endif
/*
* AtmoThread.cpp: Base thread class for all threads inside AtmoWin
*
* See the README.txt file for copyright information and how to reach the author(s).
*
* $Id$
*/
#include "AtmoThread.h"
#if defined(_ATMO_VLC_PLUGIN_)
CThread::CThread(vlc_object_t *pOwner)
{
int err;
m_pAtmoThread = (atmo_thread_t *)vlc_object_create( pOwner,
sizeof(atmo_thread_t) );
if(m_pAtmoThread)
{
m_pAtmoThread->p_thread = this;
this->m_pOwner = pOwner;
vlc_object_attach( m_pAtmoThread, m_pOwner);
vlc_mutex_init( m_pAtmoThread, &m_TerminateLock );
err = vlc_cond_init( m_pAtmoThread, &m_TerminateCond );
if(err) {
msg_Err( m_pAtmoThread, "vlc_cond_init failed %d",err);
}
}
}
#else
CThread::CThread(void)
{
m_hThread = CreateThread(NULL, 0, CThread::ThreadProc ,
this, CREATE_SUSPENDED, &m_dwThreadID);
m_hTerminateEvent = CreateEvent(NULL,ATMO_FALSE,ATMO_FALSE,NULL);
}
#endif
#if defined(_ATMO_VLC_PLUGIN_)
CThread::~CThread(void)
{
if(m_pAtmoThread)
{
vlc_mutex_destroy( &m_TerminateLock );
vlc_cond_destroy( &m_TerminateCond );
vlc_object_detach(m_pAtmoThread);
vlc_object_destroy(m_pAtmoThread);
}
}
#else
CThread::~CThread(void)
{
CloseHandle(m_hThread);
CloseHandle(m_hTerminateEvent);
}
#endif
#if defined(_ATMO_VLC_PLUGIN_)
void CThread::ThreadProc(atmo_thread_t *pAtmoThread)
{
CThread *pThread = (CThread *)pAtmoThread->p_thread;
if(pThread) {
// give feedback I'am running?
vlc_thread_ready( pThread->m_pAtmoThread );
pThread->Execute();
}
}
#else
DWORD WINAPI CThread::ThreadProc(LPVOID lpParameter)
{
CThread *aThread = (CThread *)lpParameter;
if(aThread)
return aThread->Execute();
else
return (DWORD)-1;
}
#endif
DWORD CThread::Execute(void)
{
/*
to do implement! override!
while(!bTerminated) {
...
}
*/
return 0;
}
void CThread::Terminate(void)
{
// Set Termination Flag and EventObject!
// and wait for Termination
m_bTerminated = ATMO_TRUE;
#if defined(_ATMO_VLC_PLUGIN_)
if(m_pAtmoThread)
{
vlc_mutex_lock( &m_TerminateLock );
vlc_cond_signal( &m_TerminateCond );
vlc_mutex_unlock( &m_TerminateLock );
vlc_object_kill( m_pAtmoThread );
vlc_thread_join( m_pAtmoThread );
}
#else
SetEvent(m_hTerminateEvent);
WaitForSingleObject(m_hThread,INFINITE);
#endif
}
void CThread::Run()
{
m_bTerminated = ATMO_FALSE;
#if defined(_ATMO_VLC_PLUGIN_)
m_pAtmoThread->b_die = VLC_FALSE;
if(vlc_thread_create( m_pAtmoThread,
"Atmo-CThread-Class",
CThread::ThreadProc,
VLC_THREAD_PRIORITY_LOW,
VLC_FALSE ))
{
msg_Err( m_pOwner, "cannot launch one of the AtmoLight threads");
}
#else
ResetEvent(m_hTerminateEvent);
ResumeThread(m_hThread);
#endif
}
/*
does a sleep if the sleep was interrupted through
the thread kill event return false...
*/
ATMO_BOOL CThread::ThreadSleep(DWORD millisekunden)
{
#if defined(_ATMO_VLC_PLUGIN_)
vlc_mutex_lock( &m_TerminateLock );
int value = vlc_cond_timedwait(&m_TerminateCond,
&m_TerminateLock,
mdate() + (mtime_t)(millisekunden * 1000));
vlc_mutex_unlock( &m_TerminateLock );
return (value != 0);
#else
DWORD res = WaitForSingleObject(m_hTerminateEvent,millisekunden);
return (res == WAIT_TIMEOUT);
#endif
}
/*
* AtmoThread.h: Base thread class for all threads inside AtmoWin
*
*
* See the README.txt file for copyright information and how to reach the author(s).
*
* $Id$
*/
#ifndef _AtmoThread_h_
#define _AtmoThread_h_
#include "AtmoDefs.h"
#if defined(_ATMO_VLC_PLUGIN_)
// use threading stuff from videolan!
# include <vlc/vlc.h>
# include <vlc_threads_funcs.h>
# include <vlc_threads.h>
typedef struct
{
VLC_COMMON_MEMBERS
void *p_thread; /* cast to CThread * */
} atmo_thread_t;
#else
# include <windows.h>
#endif
class CThread
{
protected:
#if defined(_ATMO_VLC_PLUGIN_)
atmo_thread_t *m_pAtmoThread;
vlc_mutex_t m_TerminateLock;
vlc_cond_t m_TerminateCond;
vlc_object_t *m_pOwner;
#else
HANDLE m_hThread;
DWORD m_dwThreadID;
HANDLE m_hTerminateEvent;
#endif
volatile ATMO_BOOL m_bTerminated;
private:
#if defined(_ATMO_VLC_PLUGIN_)
static void ThreadProc(atmo_thread_t *pAtmoThread);
#else
static DWORD WINAPI ThreadProc(LPVOID lpParameter);
#endif
protected:
virtual DWORD Execute(void);
ATMO_BOOL ThreadSleep(DWORD millisekunden);
public:
#if defined(_ATMO_VLC_PLUGIN_)
CThread(vlc_object_t *pOwner);
#else
CThread(void);
#endif
virtual ~CThread(void);
void Terminate(void);
void Run();
};
#endif
/*
* AtmoTools.cpp: Collection of tool and helperfunction
*
* See the README.txt file for copyright information and how to reach the author(s).
*
* $Id$
*/
#include "AtmoTools.h"
#include "AtmoLiveView.h"
#include "AtmoSerialConnection.h"
#if !defined(_ATMO_VLC_PLUGIN_)
# include "AtmoColorChanger.h"
# include "AtmoLeftRightColorChanger.h"
# include "AtmoDummyConnection.h"
# include "AtmoDmxSerialConnection.h"
#endif
CAtmoTools::CAtmoTools(void)
{
}
CAtmoTools::~CAtmoTools(void)
{
}
void CAtmoTools::ShowShutdownColor(CAtmoDynData *pDynData)
{
pDynData->LockCriticalSection();
CAtmoConnection *atmoConnection = pDynData->getAtmoConnection();
CAtmoConfig *atmoConfig = pDynData->getAtmoConfig();
if((atmoConnection != NULL) && (atmoConfig!=NULL)) {
int r[ATMO_NUM_CHANNELS],g[ATMO_NUM_CHANNELS],b[ATMO_NUM_CHANNELS],i;
// set a special color? on shutdown of the software? mostly may use black or so ...
// if this function ist disabled ... atmo will continuing to show the last color...
if(atmoConnection->isOpen() == ATMO_TRUE) {
if(atmoConfig->isSetShutdownColor() == 1) {
for(i=0;i<ATMO_NUM_CHANNELS;i++) {
r[i] = atmoConfig->getShutdownColor_Red();
g[i] = atmoConfig->getShutdownColor_Green();
b[i] = atmoConfig->getShutdownColor_Blue();
}
atmoConnection->SendData(ATMO_NUM_CHANNELS,r,g,b);
}
}
}
pDynData->UnLockCriticalSection();
}
EffectMode CAtmoTools::SwitchEffect(CAtmoDynData *pDynData, EffectMode newEffectMode)
{
// may need a critical section??
if(pDynData == NULL) {
return emUndefined;
}
pDynData->LockCriticalSection();
CAtmoConfig *atmoConfig = pDynData->getAtmoConfig();
if(atmoConfig == NULL) {
pDynData->UnLockCriticalSection();
return emUndefined;
}
CAtmoConnection *atmoConnection = pDynData->getAtmoConnection();
EffectMode oldEffectMode = atmoConfig->getEffectMode();
CThread *currentEffect = pDynData->getEffectThread();
// stop and delete/cleanup current Effect Thread...
pDynData->setEffectThread(NULL);
if(currentEffect!=NULL) {
currentEffect->Terminate();
delete currentEffect;
currentEffect = NULL;
}
if((atmoConnection!=NULL) && (atmoConnection->isOpen()==ATMO_TRUE)) {
// neuen EffectThread nur mit aktiver Connection starten...
switch(newEffectMode) {
case emDisabled:
break;
case emStaticColor:
// get values from config - and put them to all channels?
int r[ATMO_NUM_CHANNELS],g[ATMO_NUM_CHANNELS],b[ATMO_NUM_CHANNELS];
for(int i=0;i<ATMO_NUM_CHANNELS;i++) {
r[i] = (atmoConfig->getStaticColor_Red() * atmoConfig->getWhiteAdjustment_Red())/255;
g[i] = (atmoConfig->getStaticColor_Green() * atmoConfig->getWhiteAdjustment_Green())/255;
b[i] = (atmoConfig->getStaticColor_Blue() * atmoConfig->getWhiteAdjustment_Blue())/255;
}
atmoConnection->SendData(ATMO_NUM_CHANNELS,r,g,b);
break;
case emLivePicture:
currentEffect = new CAtmoLiveView(pDynData);
break;
#if !defined(_ATMO_VLC_PLUGIN_)
case emColorChange:
currentEffect = new CAtmoColorChanger(atmoConnection, atmoConfig);
break;
#endif
#if !defined(_ATMO_VLC_PLUGIN_)
case emLrColorChange:
currentEffect = new CAtmoLeftRightColorChanger(atmoConnection, atmoConfig);
break;
#endif
}
}
atmoConfig->setEffectMode(newEffectMode);
pDynData->setEffectThread(currentEffect);
if(currentEffect!=NULL)
currentEffect->Run();
pDynData->UnLockCriticalSection();
return oldEffectMode;
}
ATMO_BOOL CAtmoTools::RecreateConnection(CAtmoDynData *pDynData)
{
pDynData->LockCriticalSection();
CAtmoConnection *current = pDynData->getAtmoConnection();
AtmoConnectionType act = pDynData->getAtmoConfig()->getConnectionType();
pDynData->setAtmoConnection(NULL);
if(current != NULL) {
current->CloseConnection();
delete current;
}
switch(act) {
case actSerialPort: {
CAtmoSerialConnection *tempConnection = new CAtmoSerialConnection(pDynData->getAtmoConfig());
if(tempConnection->OpenConnection() == ATMO_FALSE) {
#if !defined(_ATMO_VLC_PLUGIN_)
char errorMsgBuf[200];
sprintf(errorMsgBuf,"Failed to open serial port com%d with errorcode: %d (0x%x)",
pDynData->getAtmoConfig()->getComport(),
tempConnection->getLastError(),
tempConnection->getLastError()
);
MessageBox(0,errorMsgBuf,"Error",MB_ICONERROR | MB_OK);
#endif
delete tempConnection;
pDynData->UnLockCriticalSection();
return ATMO_FALSE;
}
pDynData->setAtmoConnection(tempConnection);
CAtmoTools::SetChannelAssignment(pDynData,
pDynData->getAtmoConfig()->getCurrentChannelAssignment());
pDynData->UnLockCriticalSection();
return ATMO_TRUE;
}
#if !defined(_ATMO_VLC_PLUGIN_)
case actDummy: {
CAtmoDummyConnection *tempConnection = new CAtmoDummyConnection(pDynData->getHinstance(),
pDynData->getAtmoConfig());
if(tempConnection->OpenConnection() == ATMO_FALSE) {
delete tempConnection;
pDynData->UnLockCriticalSection();
return ATMO_FALSE;
}
pDynData->setAtmoConnection(tempConnection);
CAtmoTools::SetChannelAssignment(pDynData, pDynData->getAtmoConfig()->getCurrentChannelAssignment());
pDynData->UnLockCriticalSection();
return ATMO_TRUE;
}
case actDMX: {
// create here your DMX connections... instead of the dummy....
CAtmoDmxSerialConnection *tempConnection = new CAtmoDmxSerialConnection(pDynData->getAtmoConfig());
if(tempConnection->OpenConnection() == ATMO_FALSE) {
delete tempConnection;
pDynData->UnLockCriticalSection();
return ATMO_FALSE;
}
pDynData->setAtmoConnection(tempConnection);
CAtmoTools::SetChannelAssignment(pDynData, pDynData->getAtmoConfig()->getCurrentChannelAssignment());
pDynData->UnLockCriticalSection();
return ATMO_TRUE;
}
#endif
default: {
pDynData->UnLockCriticalSection();
return ATMO_FALSE;
}
}
}
tColorPacket CAtmoTools::WhiteCalibration(CAtmoConfig *pAtmoConfig, tColorPacket ColorPacket)
{
int w_adj_red = pAtmoConfig->getWhiteAdjustment_Red();
int w_adj_green = pAtmoConfig->getWhiteAdjustment_Green();
int w_adj_blue = pAtmoConfig->getWhiteAdjustment_Blue();
for (int i = 0; i < ATMO_NUM_CHANNELS; i++) {
ColorPacket.channel[i].r = (unsigned char)(((int)w_adj_red * (int)ColorPacket.channel[i].r) / 255);
ColorPacket.channel[i].g = (unsigned char)(((int)w_adj_green * (int)ColorPacket.channel[i].g) / 255);
ColorPacket.channel[i].b = (unsigned char)(((int)w_adj_blue * (int)ColorPacket.channel[i].b) / 255);
}
return ColorPacket;
}
tColorPacket CAtmoTools::ApplyGamma(CAtmoConfig *pAtmoConfig, tColorPacket ColorPacket)
{
return ColorPacket;
}
int CAtmoTools::SetChannelAssignment(CAtmoDynData *pDynData, int index)
{
CAtmoConfig *pAtmoConfig = pDynData->getAtmoConfig();
CAtmoConnection *pAtmoConnection = pDynData->getAtmoConnection();
int oldIndex = pAtmoConfig->getCurrentChannelAssignment();
tChannelAssignment *ca = pAtmoConfig->getChannelAssignment(index);
if((ca!=NULL) && (pAtmoConnection!=NULL)) {
pAtmoConnection->SetChannelAssignment(ca);
pAtmoConfig->setCurrentChannelAssignment(index);
}
return oldIndex;
}
#if !defined(_ATMO_VLC_PLUGIN_)
void CAtmoTools::SaveBitmap(HDC hdc,HBITMAP hBmp,char *fileName) {
BITMAPINFO bmpInfo;
BITMAPFILEHEADER bmpFileHeader;
ZeroMemory(&bmpInfo, sizeof(BITMAPINFO));
bmpInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
GetDIBits(hdc,hBmp,0,0,NULL,&bmpInfo,DIB_RGB_COLORS);
if(bmpInfo.bmiHeader.biSizeImage<=0)
bmpInfo.bmiHeader.biSizeImage=bmpInfo.bmiHeader.biWidth * abs(bmpInfo.bmiHeader.biHeight)*(bmpInfo.bmiHeader.biBitCount+7)/8;
void *pBuf = malloc(bmpInfo.bmiHeader.biSizeImage);
bmpInfo.bmiHeader.biCompression=BI_RGB;
GetDIBits(hdc,hBmp,0,bmpInfo.bmiHeader.biHeight,pBuf, &bmpInfo, DIB_RGB_COLORS);
bmpFileHeader.bfReserved1=0;
bmpFileHeader.bfReserved2=0;
bmpFileHeader.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+bmpInfo.bmiHeader.biSizeImage;
bmpFileHeader.bfType='MB';
bmpFileHeader.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
FILE *fp = NULL;
fp = fopen(fileName,"wb");
fwrite(&bmpFileHeader,sizeof(BITMAPFILEHEADER),1,fp);
fwrite(&bmpInfo.bmiHeader,sizeof(BITMAPINFOHEADER),1,fp);
fwrite(pBuf,bmpInfo.bmiHeader.biSizeImage,1,fp);
fclose(fp);
}
#endif
/*
* AtmoTools.h: Collection of tool and helperfunction
*
* See the README.txt file for copyright information and how to reach the author(s).
*
* $Id$
*/
#ifndef _AtmoTools_h_
#define _AtmoTools_h_
#include "AtmoDefs.h"
#include "AtmoConfig.h"
#include "AtmoConnection.h"
#include "AtmoDynData.h"
/*
implements some tool functions - for use in different classes - and cases!
to avoid copy and paste code ...
*/
class CAtmoTools
{
private:
CAtmoTools(void);
~CAtmoTools(void);
public:
static EffectMode SwitchEffect(CAtmoDynData *pDynData, EffectMode newEffectMode);
static void ShowShutdownColor(CAtmoDynData *pDynData);
static ATMO_BOOL RecreateConnection(CAtmoDynData *pDynData);
static tColorPacket WhiteCalibration(CAtmoConfig *pAtmoConfig, tColorPacket ColorPacket);
static tColorPacket ApplyGamma(CAtmoConfig *pAtmoConfig, tColorPacket ColorPacket);
static int SetChannelAssignment(CAtmoDynData *pDynData, int index);
#if !defined(_ATMO_VLC_PLUGIN_)
static void SaveBitmap(HDC hdc,HBITMAP hBmp,char *fileName);
#endif
};
#endif
#include "AtmoDefs.h"
#if defined (WIN32)
# include <windows.h>
#else
# include <vlc_codecs.h>
#endif
#include <math.h>
#include <stdio.h>
#include "AtmoZoneDefinition.h"
CAtmoZoneDefinition::CAtmoZoneDefinition(void)
{
}
CAtmoZoneDefinition::~CAtmoZoneDefinition(void)
{
}
void CAtmoZoneDefinition::Fill(unsigned char value)
{
for(int i=0; i < IMAGE_SIZE; i++)
m_BasicWeight[i] = value;
}
// max weight to left
void CAtmoZoneDefinition::FillGradientFromLeft()
{
int index = 0;
unsigned char col_norm;
for(int row=0; row < CAP_HEIGHT; row++) {
for(int col=0; col < CAP_WIDTH; col++) {
// should be a value between 0 .. 255?
col_norm = (255 * (CAP_WIDTH-col-1)) / (CAP_WIDTH-1);
m_BasicWeight[index++] = col_norm;
}
}
}
// max weight to right
void CAtmoZoneDefinition::FillGradientFromRight()
{
int index = 0;
unsigned char col_norm;
for(int row=0; row < CAP_HEIGHT; row++) {
for(int col=0; col < CAP_WIDTH; col++) {
col_norm = (255 * col) / (CAP_WIDTH-1); // should be a value between 0 .. 255?
m_BasicWeight[index++] = col_norm;
}
}
}
// max weight from top
void CAtmoZoneDefinition::FillGradientFromTop()
{
int index = 0;
unsigned char row_norm;
for(int row=0; row < CAP_HEIGHT; row++) {
row_norm = (255 * (CAP_HEIGHT-row-1)) / (CAP_HEIGHT-1); // should be a value between 0 .. 255?
for(int col=0; col < CAP_WIDTH; col++) {
m_BasicWeight[index++] = row_norm;
}
}
}
// max weight from bottom
void CAtmoZoneDefinition::FillGradientFromBottom()
{
int index = 0;
unsigned char row_norm;
for(int row=0; row < CAP_HEIGHT; row++) {
row_norm = (255 * row) / (CAP_HEIGHT-1); // should be a value between 0 .. 255?
for(int col=0; col < CAP_WIDTH; col++) {
m_BasicWeight[index++] = row_norm;
}
}
}
int CAtmoZoneDefinition::LoadGradientFromBitmap(char *pszBitmap)
{
// transform 256 color image (gray scale!)
// into m_basicWeight or use the GREEN value of a 24bit image!
// channel of a true color bitmap!
BITMAPINFO bmpInfo;
BITMAPFILEHEADER bmpFileHeader;
/*
#define ATMO_LOAD_GRADIENT_OK 0
#define ATMO_LOAD_GRADIENT_FAILED_SIZE 1
#define ATMO_LOAD_GRADIENT_FAILED_HEADER 2
*/
FILE *bmp = fopen(pszBitmap, "rb");
if(!bmp)
return ATMO_LOAD_GRADIENT_FILENOTFOND;
if(fread(&bmpFileHeader, sizeof(BITMAPFILEHEADER), 1, bmp) != 1)
{
fclose(bmp);
return ATMO_LOAD_GRADIENT_FAILED_SIZE;
}
if(bmpFileHeader.bfType != 'MB')
{
fclose(bmp);
return ATMO_LOAD_GRADIENT_FAILED_HEADER;
}
if(fread(&bmpInfo, sizeof(BITMAPINFO), 1, bmp) != 1)
{
fclose(bmp);
return ATMO_LOAD_GRADIENT_FAILED_SIZE;
}
if(bmpInfo.bmiHeader.biCompression != BI_RGB)
{
fclose(bmp);
return ATMO_LOAD_GRADIENT_FAILED_FORMAT;
}
if((bmpInfo.bmiHeader.biBitCount != 8) && (bmpInfo.bmiHeader.biBitCount != 24))
{
fclose(bmp);
return ATMO_LOAD_GRADIENT_FAILED_FORMAT;
}
int width = bmpInfo.bmiHeader.biWidth;
int height = bmpInfo.bmiHeader.biHeight;
ATMO_BOOL invertDirection = (height > 0);
height = abs(height);
if((width != CAP_WIDTH) || (height != CAP_HEIGHT))
{
fclose(bmp);
return ATMO_LOAD_GRADIENT_FAILED_SIZE;
}
fseek(bmp, bmpFileHeader.bfOffBits, SEEK_SET);
int imageSize = width * height * bmpInfo.bmiHeader.biBitCount/8;
unsigned char *pixelBuffer = (unsigned char *)malloc(imageSize);
if(fread(pixelBuffer,imageSize,1,bmp) != 1)
{
fclose(bmp);
return ATMO_LOAD_GRADIENT_FAILED_SIZE;
}
if(bmpInfo.bmiHeader.biBitCount == 8)
{
int ydest;
for(int y=0;y < CAP_HEIGHT; y++) {
if(invertDirection) {
ydest = (CAP_HEIGHT - y - 1);
} else {
ydest = y;
}
for(int x=0;x < CAP_WIDTH; x++) {
// palette should be grey scale - so that index 0 is black and
// index 255 means white!
// everything else would produce funny results!
m_BasicWeight[ydest * CAP_WIDTH + x] =
pixelBuffer[y * CAP_WIDTH + x];
}
}
}
if(bmpInfo.bmiHeader.biBitCount == 24)
{
int ydest;
for(int y=0;y < CAP_HEIGHT; y++) {
if(invertDirection) {
ydest = (CAP_HEIGHT - y - 1);
} else {
ydest = y;
}
for(int x=0;x < CAP_WIDTH; x++) {
// use the green value as reference...
m_BasicWeight[ydest * CAP_WIDTH + x] =
pixelBuffer[y * CAP_WIDTH * 3 + (x*3) + 1 ];
}
}
}
free(pixelBuffer);
fclose(bmp);
return ATMO_LOAD_GRADIENT_OK;
}
void CAtmoZoneDefinition::UpdateWeighting(int *destWeight,
int WidescreenMode,
int newEdgeWeightning)
{
/*
use the values in m_BasicWeight and newWeightning to
update the direct control array for the output thread!
*/
int index = 0;
for(int row=0; row < CAP_HEIGHT; row++) {
for(int col=0; col < CAP_HEIGHT; col++) {
if ((WidescreenMode == 1) && ((row <= CAP_HEIGHT/8) || (row >= (7*CAP_HEIGHT)/8)))
{
destWeight[index] = 0;
} else {
destWeight[index] = (int)(255.0 * (float)pow( ((float)m_BasicWeight[index])/255.0 , newEdgeWeightning));
}
index++;
}
}
}
void CAtmoZoneDefinition::setZoneNumber(int num)
{
m_zonenumber = num;
}
int CAtmoZoneDefinition::getZoneNumber()
{
return m_zonenumber;
}
#ifndef _AtmoZoneDefinition_h_
#define _AtmoZoneDefinition_h_
#include "AtmoDefs.h"
#define ATMO_LOAD_GRADIENT_OK 0
#define ATMO_LOAD_GRADIENT_FILENOTFOND 1
#define ATMO_LOAD_GRADIENT_FAILED_SIZE 2
#define ATMO_LOAD_GRADIENT_FAILED_HEADER 3
#define ATMO_LOAD_GRADIENT_FAILED_FORMAT 4
class CAtmoZoneDefinition
{
private:
int m_zonenumber; // just for identification and channel assignment!
unsigned char m_BasicWeight[IMAGE_SIZE];
public:
CAtmoZoneDefinition(void);
~CAtmoZoneDefinition(void);
void Fill(unsigned char value);
void FillGradientFromLeft();
void FillGradientFromRight();
void FillGradientFromTop();
void FillGradientFromBottom();
int LoadGradientFromBitmap(char *pszBitmap);
void UpdateWeighting(int *destWeight,
int WidescreenMode,
int newEdgeWeightning);
void setZoneNumber(int num);
int getZoneNumber();
};
#endif
This diff is collapsed.
SOURCES_atmo = atmo.cpp AtmoDefs.h AtmoCalculations.cpp AtmoCalculations.h AtmoConfig.cpp AtmoConfig.h AtmoConnection.cpp AtmoConnection.h AtmoDynData.cpp AtmoDynData.h AtmoExternalCaptureInput.cpp AtmoExternalCaptureInput.h AtmoInput.cpp AtmoInput.h AtmoLiveView.cpp AtmoLiveView.h AtmoOutputFilter.cpp AtmoOutputFilter.h AtmoSerialConnection.cpp AtmoSerialConnection.h AtmoThread.cpp AtmoThread.h AtmoTools.cpp AtmoTools.h AtmoZoneDefinition.cpp AtmoZoneDefinition.h
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 diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment