Commit f0051192 authored by André Weber's avatar André Weber

enhanced & corrected AtmoLight filter module

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