mirror of
https://github.com/hyperion-project/hyperion.ng.git
synced 2025-03-01 10:33:28 +00:00
Windows compilation support (#738)
* Disable AVAHI * Replace SysInfo backport with Qt SysInfo * Update vscode config * Update LedDevices * Update Logger * Update hyperiond * Update hyperion-remote * Exclude avahi * Empty definition for Process * PythonInit path broken * Exclude PiBlaster and link ws2_32 * more avahi * resolve ui bug * Update Compile howto * JsonAPI QtGrabber missing * fix error * ssize_t replacement * Nope, doesn't work * Adjust compile description and verify winSDK * Update ci script * Update ci script * Update ci * Update ci script * update Logger * Update PythonInit * added Azure & GitHub Actions, Logger, PythonInit * resolve merge conflicts * revert ssize_t in FadeCandy * look at registry for QT5 & use find_package(Python) if cmake >= 3.12 * second try * another try * and yet another test * qt5 registry search undone * Package creation test * finished package creation. only fine tuning is required :-) Signed-off-by: Paulchen-Panther <Paulchen-Panter@protonmail.com> * Dependencies for Windows finished Signed-off-by: Paulchen-Panther <Paulchen-Panter@protonmail.com> * use 'add_definitions()' until CMake 3.12 Signed-off-by: Paulchen-Panther <Paulchen-Panter@protonmail.com> * Update .github/workflows/pull-request.yml Co-Authored-By: Paulchen Panther <16664240+Paulchen-Panther@users.noreply.github.com> * Update cmake/Dependencies.cmake Co-Authored-By: brindosch <edeltraud70@gmx.de> * fix typo/ add VCINSTALLDIR var * fix again * Undo change again (Not working) * fix QT grabber Signed-off-by: Paulchen-Panther <Paulchen-Panter@protonmail.com> * first NSIS test Signed-off-by: Paulchen-Panther <Paulchen-Panter@protonmail.com> * Update NSIS package * surprise :-) Signed-off-by: Paulchen-Panther <Paulchen-Panter@protonmail.com> * Update NSIS package * fix: NSIS .bmps * Add nsis templates * Force windows gui app * fix: QSysInfo required Qt5.6, now it's 5.4 again * Update: Remove platform component and adjust package name * Add macOS as system name * Update docs * fix: Allow gh actions ci also for forks with branches * Add ReadMe docs, mention windows, add vscode linux debug config * fix: readme visual * reduce/hide banner/copyright/log message Infos here: https://docs.microsoft.com/de-de/visualstudio/msbuild/msbuild-command-line-reference?view=vs-2019#switches * Fix PythonInit * vscode: Add runner task * fix(vscode): compiler path gcc ver independent * fix azure * vscode: add windows run tasks * move process detection * main: add windows process detection * Azure file shredder * Update docs Co-authored-by: Paulchen Panther <16664240+Paulchen-Panther@users.noreply.github.com> Co-authored-by: Paulchen-Panther <Paulchen-Panter@protonmail.com>
This commit is contained in:
@@ -3,13 +3,21 @@
|
||||
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <syslog.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <syslog.h>
|
||||
#elif _WIN32
|
||||
#include <windows.h>
|
||||
#include <Shlwapi.h>
|
||||
#pragma comment(lib, "Shlwapi.lib")
|
||||
#endif
|
||||
#include <QFileInfo>
|
||||
#include <time.h>
|
||||
|
||||
static const char * LogLevelStrings[] = { "", "DEBUG", "INFO", "WARNING", "ERROR" };
|
||||
#ifndef _WIN32
|
||||
static const int LogLevelSysLog[] = { LOG_DEBUG, LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERR };
|
||||
#endif
|
||||
static unsigned int loggerCount = 0;
|
||||
static unsigned int loggerId = 0;
|
||||
|
||||
@@ -99,8 +107,19 @@ Logger::Logger ( QString name, LogLevel minLevel )
|
||||
{
|
||||
#ifdef __GLIBC__
|
||||
const char* _appname_char = program_invocation_short_name;
|
||||
#else
|
||||
#elif !defined(_WIN32)
|
||||
const char* _appname_char = getprogname();
|
||||
#else
|
||||
char fileName[MAX_PATH];
|
||||
char *_appname_char;
|
||||
HINSTANCE hinst = GetModuleHandle(NULL);
|
||||
if (GetModuleFileNameA(hinst, fileName, sizeof(fileName)))
|
||||
{
|
||||
_appname_char = PathFindFileName(fileName);
|
||||
*(PathFindExtension(fileName)) = 0;
|
||||
}
|
||||
else
|
||||
_appname_char = "unknown";
|
||||
#endif
|
||||
_appname = QString(_appname_char).toLower();
|
||||
|
||||
@@ -108,7 +127,9 @@ Logger::Logger ( QString name, LogLevel minLevel )
|
||||
|
||||
if (_syslogEnabled && loggerCount == 1 )
|
||||
{
|
||||
#ifndef _WIN32
|
||||
openlog (_appname_char, LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL0);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,8 +137,10 @@ Logger::~Logger()
|
||||
{
|
||||
//Debug(this, "logger '%s' destroyed", QSTRING_CSTR(_name) );
|
||||
loggerCount--;
|
||||
#ifndef _WIN32
|
||||
if ( loggerCount == 0 )
|
||||
closelog();
|
||||
#endif
|
||||
}
|
||||
|
||||
void Logger::Message(LogLevel level, const char* sourceFile, const char* func, unsigned int line, const char* fmt, ...)
|
||||
@@ -142,8 +165,10 @@ void Logger::Message(LogLevel level, const char* sourceFile, const char* func, u
|
||||
|
||||
std::cout << QString("[" + repMsg.appName + " " + repMsg.loggerName + "] <" + LogLevelStrings[repMsg.level] + "> " + repMsg.message).toStdString() << std::endl;
|
||||
|
||||
#ifndef _WIN32
|
||||
if ( _syslogEnabled && repMsg.level >= Logger::WARNING )
|
||||
syslog (LogLevelSysLog[repMsg.level], "Previous line repeats %d times", _repeatCount);
|
||||
#endif
|
||||
|
||||
_repeatCount = 0;
|
||||
};
|
||||
@@ -185,10 +210,10 @@ void Logger::Message(LogLevel level, const char* sourceFile, const char* func, u
|
||||
}
|
||||
|
||||
std::cout << QString("[" + _appname + " " + _name + "] <" + LogLevelStrings[level] + "> " + location + msg).toStdString() << std::endl;
|
||||
|
||||
#ifndef _WIN32
|
||||
if ( _syslogEnabled && level >= Logger::WARNING )
|
||||
syslog (LogLevelSysLog[level], "%s", msg);
|
||||
|
||||
#endif
|
||||
_repeatMessage = logMsg;
|
||||
}
|
||||
}
|
||||
|
@@ -1,3 +1,19 @@
|
||||
#ifdef _WIN32
|
||||
#include <utils/Logger.h>
|
||||
#include <QString>
|
||||
#include <QByteArray>
|
||||
namespace Process {
|
||||
|
||||
void restartHyperion(bool asNewProcess){}
|
||||
|
||||
QByteArray command_exec(QString cmd, QByteArray data)
|
||||
{
|
||||
return QSTRING_CSTR(QString());
|
||||
}
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
#include <utils/Process.h>
|
||||
#include <utils/Logger.h>
|
||||
|
||||
@@ -55,3 +71,5 @@ QByteArray command_exec(QString cmd, QByteArray data)
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
@@ -58,9 +58,9 @@ void RgbChannelAdjustment::apply(uint8_t input, uint8_t brightness, uint8_t & re
|
||||
|
||||
if (!_initialized[input])
|
||||
{
|
||||
_mapping[RED ][input] = qMin( ((_brightness * input * _adjust[RED ]) / 65025), UINT8_MAX);
|
||||
_mapping[GREEN][input] = qMin( ((_brightness * input * _adjust[GREEN]) / 65025), UINT8_MAX);
|
||||
_mapping[BLUE ][input] = qMin( ((_brightness * input * _adjust[BLUE ]) / 65025), UINT8_MAX);
|
||||
_mapping[RED ][input] = qMin( ((_brightness * input * _adjust[RED ]) / 65025), (int)UINT8_MAX);
|
||||
_mapping[GREEN][input] = qMin( ((_brightness * input * _adjust[GREEN]) / 65025), (int)UINT8_MAX);
|
||||
_mapping[BLUE ][input] = qMin( ((_brightness * input * _adjust[BLUE ]) / 65025), (int)UINT8_MAX);
|
||||
_initialized[input] = true;
|
||||
}
|
||||
red = _mapping[RED ][input];
|
||||
|
@@ -2,34 +2,21 @@
|
||||
|
||||
#include <QHostInfo>
|
||||
#include <QSysInfo>
|
||||
#include <iostream>
|
||||
#include <sys/utsname.h>
|
||||
#include "HyperionConfig.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
#include <stdarg.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
SysInfo* SysInfo::_instance = nullptr;
|
||||
|
||||
SysInfo::SysInfo()
|
||||
: QObject()
|
||||
{
|
||||
SysInfo::QUnixOSVersion v;
|
||||
findUnixOsVersion(v);
|
||||
|
||||
_sysinfo.kernelType = kernelType();
|
||||
_sysinfo.kernelVersion = kernelVersion();
|
||||
_sysinfo.architecture = currentCpuArchitecture();
|
||||
_sysinfo.kernelType = QSysInfo::kernelType();
|
||||
_sysinfo.kernelVersion = QSysInfo::kernelVersion();
|
||||
_sysinfo.architecture = QSysInfo::currentCpuArchitecture();
|
||||
_sysinfo.wordSize = QString::number(QSysInfo::WordSize);
|
||||
_sysinfo.productType = v.productType;
|
||||
_sysinfo.productVersion = v.productVersion;
|
||||
_sysinfo.prettyName = v.prettyName;
|
||||
_sysinfo.productType = QSysInfo::productType();
|
||||
_sysinfo.productVersion = QSysInfo::productVersion();
|
||||
_sysinfo.prettyName = QSysInfo::prettyProductName();
|
||||
_sysinfo.hostName = QHostInfo::localHostName();
|
||||
_sysinfo.domainName = QHostInfo::localDomainName();
|
||||
_sysinfo.domainName = QHostInfo::localDomainName();
|
||||
}
|
||||
|
||||
SysInfo::~SysInfo()
|
||||
@@ -40,259 +27,6 @@ SysInfo::HyperionSysInfo SysInfo::get()
|
||||
{
|
||||
if ( SysInfo::_instance == nullptr )
|
||||
SysInfo::_instance = new SysInfo();
|
||||
|
||||
|
||||
return SysInfo::_instance->_sysinfo;
|
||||
}
|
||||
|
||||
|
||||
|
||||
QString SysInfo::kernelType()
|
||||
{
|
||||
#if defined(Q_OS_WIN)
|
||||
return QStringLiteral("winnt");
|
||||
#elif defined(Q_OS_UNIX)
|
||||
struct utsname u;
|
||||
if (uname(&u) == 0)
|
||||
return QString::fromLatin1(u.sysname).toLower();
|
||||
#endif
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString SysInfo::kernelVersion()
|
||||
{
|
||||
struct utsname u;
|
||||
if (uname(&u) == 0)
|
||||
return QString::fromLocal8Bit(u.release).toLower();
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString SysInfo::machineHostName()
|
||||
{
|
||||
#if defined(Q_OS_LINUX)
|
||||
// gethostname(3) on Linux just calls uname(2), so do it ourselves and avoid a memcpy
|
||||
struct utsname u;
|
||||
if (uname(&u) == 0)
|
||||
return QString::fromLocal8Bit(u.nodename);
|
||||
#else
|
||||
char hostName[512];
|
||||
if (gethostname(hostName, sizeof(hostName)) == -1)
|
||||
return QString();
|
||||
hostName[sizeof(hostName) - 1] = '\0';
|
||||
return QString::fromLocal8Bit(hostName);
|
||||
#endif
|
||||
return QString();
|
||||
}
|
||||
|
||||
|
||||
QString SysInfo::currentCpuArchitecture()
|
||||
{
|
||||
#if defined(Q_OS_UNIX)
|
||||
long ret = -1;
|
||||
struct utsname u;
|
||||
|
||||
if (ret == -1)
|
||||
ret = uname(&u);
|
||||
|
||||
// we could use detectUnixVersion() above, but we only need a field no other function does
|
||||
if (ret != -1)
|
||||
{
|
||||
// the use of QT_BUILD_INTERNAL here is simply to ensure all branches build
|
||||
// as we don't often build on some of the less common platforms
|
||||
# if defined(Q_PROCESSOR_ARM)
|
||||
if (strcmp(u.machine, "aarch64") == 0)
|
||||
return QStringLiteral("arm64");
|
||||
if (strncmp(u.machine, "armv", 4) == 0)
|
||||
return QStringLiteral("arm");
|
||||
# endif
|
||||
# if defined(Q_PROCESSOR_POWER)
|
||||
// harmonize "powerpc" and "ppc" to "power"
|
||||
if (strncmp(u.machine, "ppc", 3) == 0)
|
||||
return QLatin1String("power") + QLatin1String(u.machine + 3);
|
||||
if (strncmp(u.machine, "powerpc", 7) == 0)
|
||||
return QLatin1String("power") + QLatin1String(u.machine + 7);
|
||||
if (strcmp(u.machine, "Power Macintosh") == 0)
|
||||
return QLatin1String("power");
|
||||
# endif
|
||||
# if defined(Q_PROCESSOR_X86)
|
||||
// harmonize all "i?86" to "i386"
|
||||
if (strlen(u.machine) == 4 && u.machine[0] == 'i' && u.machine[2] == '8' && u.machine[3] == '6')
|
||||
return QStringLiteral("i386");
|
||||
if (strcmp(u.machine, "amd64") == 0) // Solaris
|
||||
return QStringLiteral("x86_64");
|
||||
# endif
|
||||
return QString::fromLatin1(u.machine);
|
||||
}
|
||||
#endif
|
||||
return QString();
|
||||
}
|
||||
|
||||
bool SysInfo::findUnixOsVersion(SysInfo::QUnixOSVersion &v)
|
||||
{
|
||||
if (readEtcOsRelease(v))
|
||||
return true;
|
||||
if (readEtcLsbRelease(v))
|
||||
return true;
|
||||
#if defined(Q_OS_LINUX)
|
||||
if (readEtcRedHatRelease(v))
|
||||
return true;
|
||||
if (readEtcDebianVersion(v))
|
||||
return true;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
QByteArray SysInfo::getEtcFileFirstLine(const char *fileName)
|
||||
{
|
||||
QByteArray buffer = getEtcFileContent(fileName);
|
||||
if (buffer.isEmpty())
|
||||
return QByteArray();
|
||||
|
||||
const char *ptr = buffer.constData();
|
||||
int eol = buffer.indexOf("\n");
|
||||
return QByteArray(ptr, eol).trimmed();
|
||||
}
|
||||
|
||||
bool SysInfo::readEtcRedHatRelease(SysInfo::QUnixOSVersion &v)
|
||||
{
|
||||
// /etc/redhat-release analysed should be a one line file
|
||||
// the format of its content is <Vendor_ID release Version>
|
||||
// i.e. "Red Hat Enterprise Linux Workstation release 6.5 (Santiago)"
|
||||
QByteArray line = getEtcFileFirstLine("/etc/redhat-release");
|
||||
if (line.isEmpty())
|
||||
return false;
|
||||
|
||||
v.prettyName = QString::fromLatin1(line);
|
||||
|
||||
const char keyword[] = "release ";
|
||||
int releaseIndex = line.indexOf(keyword);
|
||||
v.productType = QString::fromLatin1(line.mid(0, releaseIndex)).remove(QLatin1Char(' '));
|
||||
int spaceIndex = line.indexOf(' ', releaseIndex + strlen(keyword));
|
||||
v.productVersion = QString::fromLatin1(line.mid(releaseIndex + strlen(keyword),
|
||||
spaceIndex > -1 ? spaceIndex - releaseIndex - int(strlen(keyword)) : -1));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SysInfo::readEtcDebianVersion(SysInfo::QUnixOSVersion &v)
|
||||
{
|
||||
// /etc/debian_version analysed should be a one line file
|
||||
// the format of its content is <Release_ID/sid>
|
||||
// i.e. "jessie/sid"
|
||||
QByteArray line = getEtcFileFirstLine("/etc/debian_version");
|
||||
if (line.isEmpty())
|
||||
return false;
|
||||
|
||||
v.productType = QStringLiteral("Debian");
|
||||
v.productVersion = QString::fromLatin1(line);
|
||||
return true;
|
||||
}
|
||||
|
||||
QString SysInfo::unquote(const char *begin, const char *end)
|
||||
{
|
||||
if (*begin == '"') {
|
||||
Q_ASSERT(end[-1] == '"');
|
||||
return QString::fromLatin1(begin + 1, end - begin - 2);
|
||||
}
|
||||
return QString::fromLatin1(begin, end - begin);
|
||||
}
|
||||
|
||||
QByteArray SysInfo::getEtcFileContent(const char *filename)
|
||||
{
|
||||
// we're avoiding QFile here
|
||||
int fd = open(filename, O_RDONLY);
|
||||
if (fd == -1)
|
||||
return QByteArray();
|
||||
|
||||
struct stat sbuf;
|
||||
if (::fstat(fd, &sbuf) == -1) {
|
||||
close(fd);
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
QByteArray buffer(sbuf.st_size, Qt::Uninitialized);
|
||||
buffer.resize(read(fd, buffer.data(), sbuf.st_size));
|
||||
close(fd);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
bool SysInfo::readEtcFile(SysInfo::QUnixOSVersion &v, const char *filename,
|
||||
const QByteArray &idKey, const QByteArray &versionKey, const QByteArray &prettyNameKey)
|
||||
{
|
||||
|
||||
QByteArray buffer = getEtcFileContent(filename);
|
||||
if (buffer.isEmpty())
|
||||
return false;
|
||||
|
||||
const char *ptr = buffer.constData();
|
||||
const char *end = buffer.constEnd();
|
||||
const char *eol;
|
||||
QByteArray line;
|
||||
for ( ; ptr != end; ptr = eol + 1) {
|
||||
// find the end of the line after ptr
|
||||
eol = static_cast<const char *>(memchr(ptr, '\n', end - ptr));
|
||||
if (!eol)
|
||||
eol = end - 1;
|
||||
line.setRawData(ptr, eol - ptr);
|
||||
|
||||
if (line.startsWith(idKey)) {
|
||||
ptr += idKey.length();
|
||||
v.productType = unquote(ptr, eol);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (line.startsWith(prettyNameKey)) {
|
||||
ptr += prettyNameKey.length();
|
||||
v.prettyName = unquote(ptr, eol);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (line.startsWith(versionKey)) {
|
||||
ptr += versionKey.length();
|
||||
v.productVersion = unquote(ptr, eol);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SysInfo::readEtcOsRelease(SysInfo::QUnixOSVersion &v)
|
||||
{
|
||||
return readEtcFile(v, "/etc/os-release", QByteArrayLiteral("ID="),
|
||||
QByteArrayLiteral("VERSION_ID="), QByteArrayLiteral("PRETTY_NAME="));
|
||||
}
|
||||
|
||||
bool SysInfo::readEtcLsbRelease(SysInfo::QUnixOSVersion &v)
|
||||
{
|
||||
bool ok = readEtcFile(v, "/etc/lsb-release", QByteArrayLiteral("DISTRIB_ID="),
|
||||
QByteArrayLiteral("DISTRIB_RELEASE="), QByteArrayLiteral("DISTRIB_DESCRIPTION="));
|
||||
if (ok && (v.prettyName.isEmpty() || v.prettyName == v.productType)) {
|
||||
// some distributions have redundant information for the pretty name,
|
||||
// so try /etc/<lowercasename>-release
|
||||
|
||||
// we're still avoiding QFile here
|
||||
QByteArray distrorelease = "/etc/" + v.productType.toLatin1().toLower() + "-release";
|
||||
int fd = open(distrorelease, O_RDONLY);
|
||||
if (fd != -1) {
|
||||
struct stat sbuf;
|
||||
if (::fstat(fd, &sbuf) != -1 && sbuf.st_size > v.prettyName.length()) {
|
||||
// file apparently contains interesting information
|
||||
QByteArray buffer(sbuf.st_size, Qt::Uninitialized);
|
||||
buffer.resize(read(fd, buffer.data(), sbuf.st_size));
|
||||
v.prettyName = QString::fromLatin1(buffer.trimmed());
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
// some distributions have a /etc/lsb-release file that does not provide the values
|
||||
// we are looking for, i.e. DISTRIB_ID, DISTRIB_RELEASE and DISTRIB_DESCRIPTION.
|
||||
// Assuming that neither DISTRIB_ID nor DISTRIB_RELEASE were found, or contained valid values,
|
||||
// returning false for readEtcLsbRelease will allow further /etc/<lowercasename>-release parsing.
|
||||
return ok && !(v.productType.isEmpty() && v.productVersion.isEmpty());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user