summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhorchi <vdr@jwendel.de>2018-09-24 18:58:53 +0200
committerhorchi <vdr@jwendel.de>2018-09-24 18:58:53 +0200
commitde40508e84fa064b369dea17c6d74e7ceba3fbb3 (patch)
tree2f9550e200cbc08060c9208bc83eca5ec6d65e3c
parent28cd8c6d77e5f1365be8746201e95c0d7162d9c0 (diff)
downloadvdr-plugin-seduatmo-de40508e84fa064b369dea17c6d74e7ceba3fbb3.tar.gz
vdr-plugin-seduatmo-de40508e84fa064b369dea17c6d74e7ceba3fbb3.tar.bz2
Auto device detection configurable0.0.50.0.4
-rw-r--r--HISTORY.h7
-rw-r--r--seduatmo.c42
-rw-r--r--seduthread.c144
-rw-r--r--seduthread.h23
4 files changed, 129 insertions, 87 deletions
diff --git a/HISTORY.h b/HISTORY.h
index 738e4ca..0d122ea 100644
--- a/HISTORY.h
+++ b/HISTORY.h
@@ -7,8 +7,8 @@
*
*/
-#define _VERSION "0.0.4"
-#define VERSION_DATE "29.01.2018"
+#define _VERSION "0.0.5"
+#define VERSION_DATE "24.09.2018"
#ifdef GIT_REV
# define VERSION _VERSION "-GIT" GIT_REV
@@ -19,6 +19,9 @@
/*
* ------------------------------------
+2018-09-24: Version 0.0.5
+ Auto device detection configurable
+
2018-02-29: Version 0.0.4
Improved recover handling
diff --git a/seduatmo.c b/seduatmo.c
index 770f787..b1382d0 100644
--- a/seduatmo.c
+++ b/seduatmo.c
@@ -6,6 +6,7 @@
* $Id: seduatmo.c,v 1.64 2012/11/28 06:29:24 wendel Exp $
*/
+#include <getopt.h>
#include <vdr/plugin.h>
#include "HISTORY.h"
@@ -57,7 +58,7 @@ class cPluginSeduatmo : public cPlugin
virtual ~cPluginSeduatmo();
virtual const char* Version(void) { return VERSION; }
virtual const char* Description(void) { return DESCRIPTION; }
- virtual const char* CommandLineHelp(void) { return 0; }
+ virtual const char* CommandLineHelp(void);
virtual bool ProcessArgs(int argc, char* argv[]);
virtual bool Initialize(void);
virtual bool Start(void);
@@ -76,6 +77,7 @@ class cPluginSeduatmo : public cPlugin
int startAtmo();
int stopAtmo();
+
cSeduThread* update;
int isRunning()
@@ -89,6 +91,7 @@ class cPluginSeduatmo : public cPlugin
private:
cLedConfs ledConfs;
+ int autodetectDevice;
};
//***************************************************************************
@@ -179,9 +182,10 @@ void cSeduPluginMenu::Store()
// Plugin
//***************************************************************************
-cPluginSeduatmo::cPluginSeduatmo(void)
+cPluginSeduatmo::cPluginSeduatmo()
{
update = 0;
+ autodetectDevice = no;
}
cPluginSeduatmo::~cPluginSeduatmo()
@@ -189,8 +193,38 @@ cPluginSeduatmo::~cPluginSeduatmo()
stopAtmo();
}
+//***************************************************************************
+// Process Args
+//***************************************************************************
+
+const char* cPluginSeduatmo::CommandLineHelp()
+{
+ return
+ " -d, --autodetect try autodetect of tty device (need root rights)\n"
+ ;
+}
+
bool cPluginSeduatmo::ProcessArgs(int argc, char* argv[])
{
+ int c;
+
+ static option long_options[] =
+ {
+ { "autodetect", no_argument, 0, 'd' },
+ { 0, 0, 0, 0 }
+ };
+
+ // check the arguments
+
+ while ((c = getopt_long(argc, argv, "d", long_options, 0)) != -1)
+ {
+ switch (c)
+ {
+ case 'd': autodetectDevice = yes; break;
+ default: tell(0, "Ignoring unknown argument '%c' '%s'", c, optarg);
+ }
+ }
+
return true;
}
@@ -203,7 +237,7 @@ bool cPluginSeduatmo::Initialize(void)
if (!ledConfs.Load(tmp, true))
{
free(tmp);
- return fail;
+ return false;
}
free(tmp);
@@ -228,7 +262,7 @@ int cPluginSeduatmo::startAtmo()
delete update;
}
- update = new cSeduThread();
+ update = new cSeduThread(autodetectDevice);
if (cfg.grabWidth <= 0 || cfg.grabHeight <= 0 || !cfg.ledCount)
tell(0, "Error: Invalid configuration in seduatmo.conf, aborting");
diff --git a/seduthread.c b/seduthread.c
index 2ba7bfb..e558345 100644
--- a/seduthread.c
+++ b/seduthread.c
@@ -22,8 +22,10 @@
// Object
//***************************************************************************
-cSeduThread::cSeduThread()
+cSeduThread::cSeduThread(int aAutodetectDevice)
{
+ autodetectDevice = aAutodetectDevice;
+
loopActive = false;
pixAverage = 0;
image = 0;
@@ -45,7 +47,7 @@ cSeduThread::~cSeduThread()
//***************************************************************************
void cSeduThread::Stop()
-{
+{
loopActive = false;
waitCondition.Broadcast(); // wakeup the thread
@@ -72,7 +74,7 @@ void cSeduThread::Action()
while (loopActive && Running())
{
if (!sedu.isOpen())
- {
+ {
if (last > time(0)-30)
{
waitCondition.TimedWait(mutex, 1000); // wait time in ms
@@ -81,7 +83,7 @@ void cSeduThread::Action()
last = time(0);
- if (sedu.open() != success)
+ if (sedu.open(autodetectDevice) != success)
continue;
}
@@ -117,13 +119,13 @@ void cSeduThread::Action()
putData();
if (cfg.viewMode != vmRainbow && cfg.viewMode != vmColorWheel)
- wait = 500; // less load on fixed color or black
+ wait = 500; // less load on fixed color or black
else
wait = 100; // for Rainbow sleep always 100ms
}
-
+
waitCondition.TimedWait(mutex, wait); // wait time in ms
- }
+ }
sedu.close();
loopActive = false;
@@ -149,9 +151,9 @@ int cSeduThread::grabImage()
int softHdGrabService = (softHdPlugin && softHdPlugin->Service(ATMO1_GRAB_SERVICE, 0));
if (!softHdGrabService)
- return error("Can't find softhddevice %s, aborting grab, retrying in 10 seconds!",
+ return error("Can't find softhddevice %s, aborting grab, retrying in 10 seconds!",
softHdPlugin ? "service" : "plugin");
-
+
// grab image at sofhddevice
req.width = cfg.grabWidth;
@@ -160,7 +162,7 @@ int cSeduThread::grabImage()
if (!softHdPlugin->Service(ATMO1_GRAB_SERVICE, &req) || !req.img)
return fail;
-
+
tell(2, "Got image with %dx%d pixel; %d bytes", req.width, req.height, req.size);
image = (Pixel*)req.img;
@@ -188,24 +190,24 @@ int cSeduThread::detectCineBars()
for (off = 0; off < imageHeight/5; off++) // cinebar height max 1/5 of the screen height
{
int above = 0;
-
+
for (int x = 0; x < imageWidth; x++)
{
p = &image[off*imageWidth + x];
-
+
if (p->r > threshold || p->g > threshold || p->b > threshold)
above++;
-
+
p = &image[((imageHeight-1)-off)*imageWidth + x];
-
+
if (p->r > threshold || p->g > threshold || p->b > threshold)
above++;
}
-
+
if (above > imageWidth/8) // max 1/8 failed pixel
break;
}
-
+
if (cineBarsHor != off)
{
static int last = 0;
@@ -227,30 +229,30 @@ int cSeduThread::detectCineBars()
}
// check vertical bars
-
+
if (cfg.detectCineBars == cbVertical || cfg.detectCineBars == cbBoth)
{
for (off = 0; off < imageWidth/5; off++) // cinebar height max 1/5 of the screen width
{
int above = 0;
-
+
for (int y = 0; y < imageHeight; y++)
{
p = &image[y*imageWidth + off];
-
+
if (p->r > threshold || p->g > threshold || p->b > threshold)
above++;
-
+
p = &image[y*imageWidth + ((imageWidth-1)-off)];
-
+
if (p->r > threshold || p->g > threshold || p->b > threshold)
above++;
}
-
+
if (above > imageHeight/6) // max 1/6 failed pixel
break;
}
-
+
if (cineBarsVer != off)
{
static int last = 0;
@@ -285,7 +287,7 @@ int cSeduThread::putData()
if (!sedu.isOpen())
{
- if (sedu.open() != success)
+ if (sedu.open(autodetectDevice) != success)
return fail;
}
@@ -314,13 +316,13 @@ int cSeduThread::putData()
default: break;
}
-
+
sedu.writeStartSeq();
-
+
// loop over all LEDs
for (int led = 0; led < cfg.ledCount; led++)
- {
+ {
Pixel pixel = {0,0,0,0};
Pixel* p = &pixel;
@@ -350,13 +352,13 @@ int cSeduThread::putData()
{
p = &pFixedCol;
}
-
+
sedu.writePix(p);
}
-
+
sedu.writeEndSeq();
sedu.read();
-
+
return success;
}
@@ -385,7 +387,7 @@ int cSeduThread::getPixel(int ledIdx, Pixel* pixel)
if (led->x < 0 || led->y < 0)
{
- tell(0, "Invalid position for (%d/%d) led %d, ignoring",
+ tell(0, "Invalid position for (%d/%d) led %d, ignoring",
led->x, led->y, ledIdx);
return 0;
}
@@ -426,7 +428,7 @@ int cSeduThread::getPixel(int ledIdx, Pixel* pixel)
break;
}
}
-
+
if (!sum.getCount())
return error("Fatal missing range for led %d", ledIdx);
@@ -475,7 +477,7 @@ void cSeduThread::whiteAdj(Pixel* p)
{
p->r = (double)p->r * (0.01 * cfg.adjRed);
p->b = (double)p->b * (0.01 * cfg.adjBlue);
- p->g = (double)p->g * (0.01 * cfg.adjGreen);
+ p->g = (double)p->g * (0.01 * cfg.adjGreen);
}
}
@@ -485,11 +487,11 @@ void cSeduThread::whiteAdj(Pixel* p)
void cSeduThread::gammaAdj(Pixel* p)
{
- if (p && !isBlack(p) && cfg.gamma > 10)
+ if (p && !isBlack(p) && cfg.gamma > 10)
{
double g = cfg.gamma / 10.0;
- p->r = (unsigned char)(pow(p->r / 255.0, g) * 255.0);
+ p->r = (unsigned char)(pow(p->r / 255.0, g) * 255.0);
p->g = (unsigned char)(pow(p->g / 255.0, g) * 255.0);
p->b = (unsigned char)(pow(p->b / 255.0, g) * 255.0);
}
@@ -524,7 +526,7 @@ Pixel cSeduThread::getColorWheel(int moving, int led)
static int callCount = 0;
int steps = 360 / cfg.ledCount;
int color = 0;
-
+
if (moving && !(callCount++ % (cfg.effectSpeed / 100)))
{
// calculate spinng wheel with given effect speed
@@ -542,16 +544,16 @@ Pixel cSeduThread::getColorWheel(int moving, int led)
if (color >= 360)
color -= 360;
-
+
// convert color from HSV to RGB
Pixel p = hsv2rgb(color, 1, 1);
-
+
// create a single Pixel
-
+
gammaAdj(&p);
whiteAdj(&p);
-
+
return p;
}
@@ -565,8 +567,8 @@ Pixel cSeduThread::getColorWheel(int moving, int led)
cSeduLine::cSeduLine()
{
dataBytesSend = 0;
- fd = na;
- bzero(&oldtio, sizeof(oldtio));
+ fd = na;
+ bzero(&oldtio, sizeof(oldtio));
deviceName = 0;
setMode(smMiniDMX);
@@ -587,9 +589,9 @@ void cSeduLine::setMode(SeduMode aMode, int channels)
byteStart = 0x5A;
byteMode = 0xA2;
byteEnd = 0xA5;
-
+
dataBytes = 512;
-
+
break;
}
case smTpm2:
@@ -597,9 +599,9 @@ void cSeduLine::setMode(SeduMode aMode, int channels)
byteStart = 0xC9;
byteMode = 0xDA;
byteEnd = 0x36;
-
+
dataBytes = channels*3;
-
+
break;
}
}
@@ -616,7 +618,7 @@ int cSeduLine::detect()
FILE* fd;
regex_t reg;
char line[200];
-
+
free(deviceName);
deviceName = 0;
@@ -626,19 +628,19 @@ int cSeduLine::detect()
regfree(&reg);
return fail;
}
-
+
if (!(fd = fopen("/proc/tty/driver/usbserial", "r")))
{
tell(0, "Could not open '/proc/tty/driver/usbserial' '%m'");
-
+
regfree(&reg);
return fail;
}
-
- while (fgets(line, sizeof(line), fd))
+
+ while (fgets(line, sizeof(line), fd))
{
char* p;
-
+
if (!regexec(&reg, line, 0, 0, 0) && (p = index(line, ':')))
{
*p = 0;
@@ -646,16 +648,16 @@ int cSeduLine::detect()
break;
}
}
-
+
fclose(fd);
regfree(&reg);
-
- if (!deviceName)
+
+ if (!deviceName)
{
- tell(0, "Could not auto detect a usb device like '%s' in '/proc/tty/driver/usbserial'");
+ tell(0, "Could not auto detect a usb device like '%s' in '/proc/tty/driver/usbserial'", pattern);
return fail;
}
-
+
return success;
}
@@ -663,18 +665,20 @@ int cSeduLine::detect()
// Open/Close
//***************************************************************************
-int cSeduLine::open()
+int cSeduLine::open(int tryAutoDetect)
{
struct termios newtio;
- if (detect() != success)
+ if (!tryAutoDetect || detect() != success)
{
free(deviceName);
deviceName = strdup("/dev/ttySEDU");
- tell(0, "Falling back to '%s'", deviceName);
+
+ if (tryAutoDetect)
+ tell(0, "Falling back to '%s'", deviceName);
}
- if (isOpen())
+ if (isOpen())
close();
// open serial line with 8 data bits, no parity, 1 stop bit
@@ -683,12 +687,12 @@ int cSeduLine::open()
{
fd = na;
tell(0, "Error: Opening '%s' failed", deviceName);
-
+
return fail;
}
tell(0, "Opening '%s' succeeded!", deviceName);
-
+
// configure serial line
tcgetattr(fd, &oldtio);
@@ -700,7 +704,7 @@ int cSeduLine::open()
CS8 : 8n1 (8bit,no parity,1 stopbit)
CLOCAL : local connection, no modem control
CREAD : enable receiving characters */
-
+
newtio.c_cflag = B500000 | CS8 | CLOCAL | CREAD;
newtio.c_iflag = IGNPAR;
newtio.c_oflag = 0;
@@ -739,15 +743,15 @@ int cSeduLine::read()
timeval tv;
unsigned char c;
MsTime start = msNow();
-
+
if (!isOpen())
return fail;
// check if something to read ...
-
+
tv.tv_sec = 0;
tv.tv_usec = 100000;
-
+
FD_ZERO(&readfs);
FD_SET(fd, &readfs);
select(fd+1, &readfs, 0, 0, &tv);
@@ -774,7 +778,7 @@ int cSeduLine::write(unsigned char b)
if (checkLine() != success)
return 0;
-
+
tell(3, "send: 0x%02X", b);
return ::write(fd, &b, 1);
@@ -845,10 +849,10 @@ int cSeduLine::checkLine()
return fail;
// check if space to write ...
-
+
FD_ZERO(&port);
FD_SET(fd, &port);
-
+
if (select(fd+1, 0, &port, 0, 0) == -1)
{
tell(0, "Error: select() %m");
diff --git a/seduthread.h b/seduthread.h
index 23688c4..53261dd 100644
--- a/seduthread.h
+++ b/seduthread.h
@@ -23,13 +23,13 @@ class PixQueue
void clear() { while (!pQueue.empty()) pQueue.pop(); r=g=b=0; }
int getCount() { return pQueue.size(); }
- void push(Pixel* p)
- {
+ void push(Pixel* p)
+ {
pQueue.push(*p);
-
+
r += p->r;
g += p->g;
- b += p->b;
+ b += p->b;
// remove old entrys from queue and sum
@@ -38,7 +38,7 @@ class PixQueue
r -= pQueue.front().r;
g -= pQueue.front().g;
b -= pQueue.front().b;
-
+
pQueue.pop();
}
}
@@ -49,7 +49,7 @@ class PixQueue
p->g = g / pQueue.size();
p->b = b / pQueue.size();
}
-
+
protected:
std::queue <Pixel> pQueue;
@@ -83,7 +83,7 @@ class PixSum
}
protected:
-
+
unsigned int r;
unsigned int g;
unsigned int b;
@@ -101,7 +101,7 @@ class cSeduLine : public cSeduService
cSeduLine();
~cSeduLine() { close(); }
- int open();
+ int open(int tryAutoDetect);
int close();
int isOpen() { return fd != na; }
@@ -122,7 +122,7 @@ class cSeduLine : public cSeduService
private:
int detect();
-
+
// data
int dataBytesSend;
@@ -146,7 +146,7 @@ class cSeduThread : public cThread, public cSeduService
{
public:
- cSeduThread();
+ cSeduThread(int aAutodetectDevice);
~cSeduThread();
int isRunning() { return Running(); }
@@ -154,7 +154,7 @@ class cSeduThread : public cThread, public cSeduService
// interface
void Stop();
-
+
private:
void Action(void);
@@ -173,6 +173,7 @@ class cSeduThread : public cThread, public cSeduService
// data
+ int autodetectDevice;
cSeduLine sedu;
cMutex mutex;