Merge remote-tracking branch 'origin/master' into ftdi_basic

This commit is contained in:
LordGrey
2024-05-25 23:35:13 +02:00
388 changed files with 20045 additions and 12428 deletions

View File

@@ -15,9 +15,8 @@ public:
{
}
Image(unsigned width, unsigned height) :
Image(int width, int height) :
Image(width, height, Pixel_T())
{
}
@@ -28,7 +27,7 @@ public:
/// @param height The height of the image
/// @param background The color of the image
///
Image(unsigned width, unsigned height, const Pixel_T background) :
Image(int width, int height, const Pixel_T background) :
_d_ptr(new ImageData<Pixel_T>(width, height, background))
{
}
@@ -78,7 +77,7 @@ public:
///
/// @return The width of the image
///
inline unsigned width() const
inline int width() const
{
return _d_ptr->width();
}
@@ -88,7 +87,7 @@ public:
///
/// @return The height of the image
///
inline unsigned height() const
inline int height() const
{
return _d_ptr->height();
}
@@ -111,7 +110,7 @@ public:
///
/// @return const reference to specified pixel
///
uint8_t blue(unsigned pixel) const
uint8_t blue(int pixel) const
{
return _d_ptr->blue(pixel);
}
@@ -121,7 +120,7 @@ public:
///
/// @param x The x index
/// @param y The y index
const Pixel_T& operator()(unsigned x, unsigned y) const
const Pixel_T& operator()(int x, int y) const
{
return _d_ptr->operator()(x, y);
}
@@ -129,7 +128,7 @@ public:
///
/// @return reference to specified pixel
///
Pixel_T& operator()(unsigned x, unsigned y)
Pixel_T& operator()(int x, int y)
{
return _d_ptr->operator()(x, y);
}
@@ -137,7 +136,7 @@ public:
/// Resize the image
/// @param width The width of the image
/// @param height The height of the image
void resize(unsigned width, unsigned height)
void resize(int width, int height)
{
_d_ptr->resize(width, height);
}
@@ -198,12 +197,11 @@ private:
///
/// @return The index into the underlying data-vector
///
inline unsigned toIndex(unsigned x, unsigned y) const
inline int toIndex(int x, int y) const
{
return _d_ptr->toIndex(x, y);
}
private:
QSharedDataPointer<ImageData<Pixel_T>> _d_ptr;
};

View File

@@ -1,12 +1,9 @@
#pragma once
// STL includes
#include <vector>
#include <cstdint>
#include <cstring>
#include <algorithm>
#include <cassert>
#include <type_traits>
#include <utils/ColorRgb.h>
// QT includes
@@ -24,10 +21,10 @@ class ImageData : public QSharedData
public:
typedef Pixel_T pixel_type;
ImageData(unsigned width, unsigned height, const Pixel_T background) :
ImageData(int width, int height, const Pixel_T background) :
_width(width),
_height(height),
_pixels(new Pixel_T[width * height + 1])
_pixels(new Pixel_T[static_cast<size_t>(width) * static_cast<size_t>(height)])
{
std::fill(_pixels, _pixels + width * height, background);
}
@@ -36,9 +33,9 @@ public:
QSharedData(other),
_width(other._width),
_height(other._height),
_pixels(new Pixel_T[other._width * other._height + 1])
_pixels(new Pixel_T[static_cast<size_t>(other._width) * static_cast<size_t>(other._height)])
{
memcpy(_pixels, other._pixels, static_cast<ulong>(other._width) * static_cast<ulong>(other._height) * sizeof(Pixel_T));
memcpy(_pixels, other._pixels, static_cast<size_t>(other._width) * static_cast<size_t>(other._height) * sizeof(Pixel_T));
}
ImageData& operator=(ImageData rhs)
@@ -74,52 +71,57 @@ public:
delete[] _pixels;
}
inline unsigned width() const
inline int width() const
{
return _width;
}
inline unsigned height() const
inline int height() const
{
return _height;
}
uint8_t red(unsigned pixel) const
uint8_t red(int pixel) const
{
return (_pixels + pixel)->red;
}
uint8_t green(unsigned pixel) const
uint8_t green(int pixel) const
{
return (_pixels + pixel)->green;
}
uint8_t blue(unsigned pixel) const
uint8_t blue(int pixel) const
{
return (_pixels + pixel)->blue;
}
const Pixel_T& operator()(unsigned x, unsigned y) const
const Pixel_T& operator()(int x, int y) const
{
return _pixels[toIndex(x,y)];
}
Pixel_T& operator()(unsigned x, unsigned y)
Pixel_T& operator()(int x, int y)
{
return _pixels[toIndex(x,y)];
}
void resize(unsigned width, unsigned height)
void resize(int width, int height)
{
if (width == _width && height == _height)
return;
if ((width * height) > unsigned((_width * _height)))
{
delete[] _pixels;
_pixels = new Pixel_T[width*height + 1];
return;
}
// Allocate a new buffer without initializing the content
Pixel_T* newPixels = new Pixel_T[static_cast<size_t>(width) * static_cast<size_t>(height)];
// Release the old buffer without copying data
delete[] _pixels;
// Update the pointer to the new buffer
_pixels = newPixels;
_width = width;
_height = height;
}
@@ -137,11 +139,13 @@ public:
void toRgb(ImageData<ColorRgb>& image) const
{
if (image.width() != _width || image.height() != _height)
{
image.resize(_width, _height);
}
const unsigned imageSize = _width * _height;
const int imageSize = _width * _height;
for (unsigned idx = 0; idx < imageSize; idx++)
for (int idx = 0; idx < imageSize; idx++)
{
const Pixel_T & color = _pixels[idx];
image.memptr()[idx] = ColorRgb{color.red, color.green, color.blue};
@@ -157,26 +161,22 @@ public:
{
if (_width != 1 || _height != 1)
{
_width = 1;
_height = 1;
delete[] _pixels;
_pixels = new Pixel_T[2];
resize(1,1);
}
memset(_pixels, 0, static_cast<unsigned long>(_width) * static_cast<unsigned long>(_height) * sizeof(Pixel_T));
// Set the single pixel to the default background
_pixels[0] = Pixel_T();
}
private:
inline unsigned toIndex(unsigned x, unsigned y) const
inline int toIndex(int x, int y) const
{
return y * _width + x;
}
private:
/// The width of the image
unsigned _width;
int _width;
/// The height of the image
unsigned _height;
int _height;
/// The pixels of the image
Pixel_T* _pixels;
};

View File

@@ -3,6 +3,8 @@
#include <utils/FileUtils.h>
#include <QJsonObject>
#include <QPair>
#include <QStringList>
#include <utils/Logger.h>
namespace JsonUtils {
@@ -14,7 +16,7 @@ namespace JsonUtils {
/// @param[in] ignError Ignore errors during file read (no log output)
/// @return true on success else false
///
bool readFile(const QString& path, QJsonObject& obj, Logger* log, bool ignError=false);
QPair<bool, QStringList> readFile(const QString& path, QJsonObject& obj, Logger* log, bool ignError=false);
///
/// @brief read a schema file and resolve $refs
@@ -33,7 +35,7 @@ namespace JsonUtils {
/// @param[in] log The logger of the caller to print errors
/// @return true on success else false
///
bool parse(const QString& path, const QString& data, QJsonObject& obj, Logger* log);
QPair<bool, QStringList> parse(const QString& path, const QString& data, QJsonObject& obj, Logger* log);
///
/// @brief parse a json QString and get a QJsonArray. Overloaded function
@@ -42,8 +44,8 @@ namespace JsonUtils {
/// @param[out] arr Retuns the parsed QJsonArray
/// @param[in] log The logger of the caller to print errors
/// @return true on success else false
///
bool parse(const QString& path, const QString& data, QJsonArray& arr, Logger* log);
//
QPair<bool, QStringList> parse(const QString& path, const QString& data, QJsonArray& arr, Logger* log);
///
/// @brief parse a json QString and get a QJsonDocument
@@ -53,7 +55,7 @@ namespace JsonUtils {
/// @param[in] log The logger of the caller to print errors
/// @return true on success else false
///
bool parse(const QString& path, const QString& data, QJsonDocument& doc, Logger* log);
QPair<bool, QStringList> parse(const QString& path, const QString& data, QJsonDocument& doc, Logger* log);
///
/// @brief Validate json data against a schema
@@ -63,7 +65,7 @@ namespace JsonUtils {
/// @param[in] log The logger of the caller to print errors
/// @return true on success else false
///
bool validate(const QString& file, const QJsonObject& json, const QString& schemaPath, Logger* log);
QPair<bool, QStringList> validate(const QString& file, const QJsonObject& json, const QString& schemaPath, Logger* log);
///
/// @brief Validate json data against a schema
@@ -73,7 +75,7 @@ namespace JsonUtils {
/// @param[in] log The logger of the caller to print errors
/// @return true on success else false
///
bool validate(const QString& file, const QJsonObject& json, const QJsonObject& schema, Logger* log);
QPair<bool, QStringList> validate(const QString& file, const QJsonObject& json, const QJsonObject& schema, Logger* log);
///
/// @brief Write json data to file

View File

@@ -6,6 +6,8 @@
#include <QMap>
#include <QAtomicInteger>
#include <QList>
#include <QJsonArray>
#include <QScopedPointer>
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
#include <QRecursiveMutex>
@@ -14,8 +16,6 @@
#endif
// stl includes
#include <stdio.h>
#include <stdarg.h>
#ifdef _WIN32
#include <stdexcept>
#endif
@@ -59,7 +59,7 @@ public:
QString function;
unsigned int line;
QString fileName;
uint64_t utime;
qint64 utime;
QString message;
LogLevel level;
QString levelString;
@@ -74,7 +74,7 @@ public:
void setMinLevel(LogLevel level) { _minLevel = static_cast<int>(level); }
LogLevel getMinLevel() const { return static_cast<LogLevel>(int(_minLevel)); }
QString getName() const { return _name; }
QString getSubName() const { return _subname; }
QString getSubName() const { return _subName; }
signals:
void newLogMessage(Logger::T_LOG_MESSAGE);
@@ -95,7 +95,7 @@ private:
static QAtomicInteger<int> GLOBAL_MIN_LOG_LEVEL;
const QString _name;
const QString _subname;
const QString _subName;
const bool _syslogEnabled;
const unsigned _loggerId;
@@ -107,18 +107,28 @@ class LoggerManager : public QObject
{
Q_OBJECT
private:
// Run LoggerManager as singleton
LoggerManager();
LoggerManager(const LoggerManager&) = delete;
LoggerManager(LoggerManager&&) = delete;
LoggerManager& operator=(const LoggerManager&) = delete;
LoggerManager& operator=(LoggerManager&&) = delete;
static QScopedPointer<LoggerManager> instance;
public:
static LoggerManager* getInstance();
const QList<Logger::T_LOG_MESSAGE>* getLogMessageBuffer() const { return &_logMessageBuffer; }
~LoggerManager() override;
static QScopedPointer<LoggerManager>& getInstance();
public slots:
void handleNewLogMessage(const Logger::T_LOG_MESSAGE&);
QJsonArray getLogMessageBuffer(Logger::LogLevel filter=Logger::UNSET) const;
signals:
void newLogMessage(const Logger::T_LOG_MESSAGE&);
protected:
LoggerManager();
private:
QList<Logger::T_LOG_MESSAGE> _logMessageBuffer;
const int _loggerMaxMsgBufferSize;

View File

@@ -47,7 +47,9 @@ private slots:
private:
Logger* _log;
/// True when internet access is allowed
bool _internetAccessAllowed;
bool _isInternetAccessAllowed;
/// True when internet access is restricted by a white list
bool _isInternetAccessRestricted;
/// Whitelisted ip addresses
QList<QHostAddress> _ipWhitelist;

View File

@@ -111,7 +111,7 @@ namespace NetUtils {
if (hostname.endsWith(".local") || hostname.endsWith(".local."))
{
QHostAddress resolvedAddress;
QMetaObject::invokeMethod(&MdnsBrowser::getInstance(), "resolveAddress",
QMetaObject::invokeMethod(MdnsBrowser::getInstance().data(), "resolveAddress",
Qt::BlockingQueuedConnection,
Q_RETURN_ARG(bool, isHostAddressOK),
Q_ARG(Logger*, log), Q_ARG(QString, hostname), Q_ARG(QHostAddress&, resolvedAddress));
@@ -163,7 +163,7 @@ namespace NetUtils {
if (hostname.endsWith("._tcp.local"))
{
//Treat hostname as service instance name that requires to be resolved into an mDNS-Hostname first
QMdnsEngine::Record service = MdnsBrowser::getInstance().getServiceInstanceRecord(hostname.toUtf8());
QMdnsEngine::Record service = MdnsBrowser::getInstance().data()->getServiceInstanceRecord(hostname.toUtf8());
if (!service.target().isEmpty())
{
Info(log, "Resolved service [%s] to mDNS hostname [%s], service port [%d]", QSTRING_CSTR(hostname), service.target().constData(), service.port());

View File

@@ -1,4 +1,5 @@
#pragma once
#ifndef PIXELFORMAT_H
#define PIXELFORMAT_H
#include <QString>
@@ -14,9 +15,7 @@ enum class PixelFormat {
BGR32,
NV12,
I420,
#ifdef HAVE_TURBO_JPEG
MJPEG,
#endif
NO_CHANGE
};
@@ -57,12 +56,10 @@ inline PixelFormat parsePixelFormat(const QString& pixelFormat)
{
return PixelFormat::NV12;
}
#ifdef HAVE_TURBO_JPEG
else if (format.compare("mjpeg") == 0)
{
return PixelFormat::MJPEG;
}
#endif
// return the default NO_CHANGE
return PixelFormat::NO_CHANGE;
@@ -103,12 +100,10 @@ inline QString pixelFormatToString(const PixelFormat& pixelFormat)
{
return "NV12";
}
#ifdef HAVE_TURBO_JPEG
else if (pixelFormat == PixelFormat::MJPEG)
{
return "MJPEG";
}
#endif
// return the default NO_CHANGE
return "NO_CHANGE";
@@ -166,3 +161,5 @@ inline QString flipModeToString(const FlipMode& flipMode)
// return the default NO_CHANGE
return "NO_CHANGE";
}
#endif // PIXELFORMAT_H

View File

@@ -3,9 +3,8 @@
#include <QString>
#include <QByteArray>
namespace Process {
void restartHyperion(int exitCode = 0);
QByteArray command_exec(const QString& cmd, const QByteArray& data = {});
namespace Process
{
void restartHyperion(int exitCode = 0);
QByteArray command_exec(const QString& cmd, const QByteArray& data = {});
}

View File

@@ -1,6 +1,6 @@
#pragma once
#define QSTRING_CSTR(str) str.toLocal8Bit().constData()
#define QSTRING_CSTR(str) str.toUtf8().constData()
typedef QList< int > QIntList;

View File

@@ -96,7 +96,7 @@ namespace hyperion {
static_cast<uint8_t>(channelConfig[0].toInt(defaultR)),
static_cast<uint8_t>(channelConfig[1].toInt(defaultG)),
static_cast<uint8_t>(channelConfig[2].toInt(defaultB)),
"ChannelAdjust_" + channelName.toUpper()
channelName
);
}
@@ -177,44 +177,6 @@ namespace hyperion {
return adjustment;
}
/**
* Construct the 'led-string' with the integration area definition per led and the color
* ordering of the RGB channels
* @param ledsConfig The configuration of the led areas
* @param deviceOrder The default RGB channel ordering
* @return The constructed ledstring
*/
static LedString createLedString(const QJsonArray& ledConfigArray, const ColorOrder deviceOrder)
{
LedString ledString;
const QString deviceOrderStr = colorOrderToString(deviceOrder);
for (signed i = 0; i < ledConfigArray.size(); ++i)
{
const QJsonObject& ledConfig = ledConfigArray[i].toObject();
Led led;
led.minX_frac = qMax(0.0, qMin(1.0, ledConfig["hmin"].toDouble()));
led.maxX_frac = qMax(0.0, qMin(1.0, ledConfig["hmax"].toDouble()));
led.minY_frac = qMax(0.0, qMin(1.0, ledConfig["vmin"].toDouble()));
led.maxY_frac = qMax(0.0, qMin(1.0, ledConfig["vmax"].toDouble()));
// Fix if the user swapped min and max
if (led.minX_frac > led.maxX_frac)
{
std::swap(led.minX_frac, led.maxX_frac);
}
if (led.minY_frac > led.maxY_frac)
{
std::swap(led.minY_frac, led.maxY_frac);
}
// Get the order of the rgb channels for this led (default is device order)
led.colorOrder = stringToColorOrder(ledConfig["colorOrder"].toString(deviceOrderStr));
ledString.leds().push_back(led);
}
return ledString;
}
static QSize getLedLayoutGridSize(const QJsonArray& ledConfigArray)
{
std::vector<int> midPointsX;

View File

@@ -31,7 +31,9 @@ public:
if (!schemaChecker.validate(configTree).first)
{
for (int i = 0; i < messages.size(); ++i)
{
std::cout << messages[i].toStdString() << std::endl;
}
std::cerr << "Validation failed for configuration file: " << config.toStdString() << std::endl;
return -3;
@@ -61,9 +63,10 @@ public:
if (error.error != QJsonParseError::NoError)
{
// report to the user the failure and their locations in the document.
int errorLine(0), errorColumn(0);
int errorLine(0);
int errorColumn(0);
for( int i=0, count=qMin( error.offset,config.size()); i<count; ++i )
for(long i=0, count=qMin( error.offset,config.size()); i<count; ++i )
{
++errorColumn;
if(config.at(i) == '\n' )

View File

@@ -30,6 +30,9 @@ namespace settings {
NETWORK,
FLATBUFSERVER,
PROTOSERVER,
OSEVENTS,
CECEVENTS,
SCHEDEVENTS,
INVALID
};
@@ -42,29 +45,32 @@ namespace settings {
{
switch (type)
{
case BGEFFECT: return "backgroundEffect";
case FGEFFECT: return "foregroundEffect";
case BLACKBORDER: return "blackborderdetector";
case BOBLSERVER: return "boblightServer";
case COLOR: return "color";
case DEVICE: return "device";
case EFFECTS: return "effects";
case NETFORWARD: return "forwarder";
case SYSTEMCAPTURE: return "framegrabber";
case GENERAL: return "general";
case V4L2: return "grabberV4L2";
case AUDIO: return "grabberAudio";
case JSONSERVER: return "jsonServer";
case LEDCONFIG: return "ledConfig";
case LEDS: return "leds";
case LOGGER: return "logger";
case SMOOTHING: return "smoothing";
case WEBSERVER: return "webConfig";
case INSTCAPTURE: return "instCapture";
case NETWORK: return "network";
case FLATBUFSERVER: return "flatbufServer";
case PROTOSERVER: return "protoServer";
default: return "invalid";
case BGEFFECT: return "backgroundEffect";
case FGEFFECT: return "foregroundEffect";
case BLACKBORDER: return "blackborderdetector";
case BOBLSERVER: return "boblightServer";
case COLOR: return "color";
case DEVICE: return "device";
case EFFECTS: return "effects";
case NETFORWARD: return "forwarder";
case SYSTEMCAPTURE: return "framegrabber";
case GENERAL: return "general";
case V4L2: return "grabberV4L2";
case AUDIO: return "grabberAudio";
case JSONSERVER: return "jsonServer";
case LEDCONFIG: return "ledConfig";
case LEDS: return "leds";
case LOGGER: return "logger";
case SMOOTHING: return "smoothing";
case WEBSERVER: return "webConfig";
case INSTCAPTURE: return "instCapture";
case NETWORK: return "network";
case FLATBUFSERVER: return "flatbufServer";
case PROTOSERVER: return "protoServer";
case OSEVENTS: return "osEvents";
case CECEVENTS: return "cecEvents";
case SCHEDEVENTS: return "schedEvents";
default: return "invalid";
}
}
@@ -97,6 +103,9 @@ namespace settings {
else if (type == "network") return NETWORK;
else if (type == "flatbufServer") return FLATBUFSERVER;
else if (type == "protoServer") return PROTOSERVER;
else if (type == "osEvents") return OSEVENTS;
else if (type == "cecEvents") return CECEVENTS;
else if (type == "schedEvents") return SCHEDEVENTS;
else return INVALID;
}
}