From c876d3bbefe0dc00c27ca0c12d29da5874946962 Mon Sep 17 00:00:00 2001 From: Dominik Riebeling Date: Wed, 15 Dec 2021 21:04:28 +0100 Subject: rbutil: Merge rbutil with utils folder. rbutil uses several components from the utils folder, and can be considered part of utils too. Having it in a separate folder is an arbitrary split that doesn't help anymore these days, so merge them. This also allows other utils to easily use libtools.make without the need to navigate to a different folder. Change-Id: I3fc2f4de19e3e776553efb5dea5f779dfec0dc21 --- utils/rbutilqt/base/playerbuildinfo.cpp | 362 ++++++++++++++++++++++++++++++++ 1 file changed, 362 insertions(+) create mode 100644 utils/rbutilqt/base/playerbuildinfo.cpp (limited to 'utils/rbutilqt/base/playerbuildinfo.cpp') diff --git a/utils/rbutilqt/base/playerbuildinfo.cpp b/utils/rbutilqt/base/playerbuildinfo.cpp new file mode 100644 index 0000000000..f118a9fd7a --- /dev/null +++ b/utils/rbutilqt/base/playerbuildinfo.cpp @@ -0,0 +1,362 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2020 by Dominik Riebeling + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include "playerbuildinfo.h" +#include "rbsettings.h" +#include "Logger.h" + +PlayerBuildInfo* PlayerBuildInfo::infoInstance = nullptr; + +PlayerBuildInfo* PlayerBuildInfo::instance() +{ + if (infoInstance == nullptr) { + infoInstance = new PlayerBuildInfo(); + } + return infoInstance; +} + +// server infos +const static struct { + PlayerBuildInfo::BuildInfo item; + const char* name; +} ServerInfoList[] = { + { PlayerBuildInfo::BuildVoiceLangs, "voices/:version:" }, + { PlayerBuildInfo::BuildVersion, ":build:/:target:" }, + { PlayerBuildInfo::BuildUrl, ":build:/build_url" }, + { PlayerBuildInfo::BuildVoiceUrl, ":build:/voice_url" }, + { PlayerBuildInfo::BuildManualUrl, ":build:/manual_url" }, + { PlayerBuildInfo::BuildSourceUrl, ":build:/source_url" }, + { PlayerBuildInfo::BuildFontUrl, ":build:/font_url" }, + + // other URLs -- those are not directly related to the build, but handled here. + { PlayerBuildInfo::DoomUrl, "other/doom_url" }, + { PlayerBuildInfo::Duke3DUrl, "other/duke3d_url" }, + { PlayerBuildInfo::PuzzFontsUrl, "other/puzzfonts_url" }, + { PlayerBuildInfo::QuakeUrl, "other/quake_url" }, + { PlayerBuildInfo::Wolf3DUrl, "other/wolf3d_url" }, + { PlayerBuildInfo::XWorldUrl, "other/xworld_url" }, + { PlayerBuildInfo::MidiPatchsetUrl, "other/patcheset_url" }, +}; + +const static struct { + PlayerBuildInfo::DeviceInfo item; + const char* name; +} PlayerInfoList[] = { + { PlayerBuildInfo::BuildStatus, "status/:target:" }, + { PlayerBuildInfo::DisplayName, ":target:/name" }, + { PlayerBuildInfo::BootloaderMethod, ":target:/bootloadermethod" }, + { PlayerBuildInfo::BootloaderName, ":target:/bootloadername" }, + { PlayerBuildInfo::BootloaderFile, ":target:/bootloaderfile" }, + { PlayerBuildInfo::BootloaderFilter, ":target:/bootloaderfilter" }, + { PlayerBuildInfo::Encoder, ":target:/encoder" }, + { PlayerBuildInfo::Brand, ":target:/brand" }, + { PlayerBuildInfo::PlayerPicture, ":target:/playerpic" }, + { PlayerBuildInfo::TargetNamesAll, "_targets/all" }, + { PlayerBuildInfo::TargetNamesEnabled, "_targets/enabled" }, + { PlayerBuildInfo::LanguageInfo, "languages/:target:" }, + { PlayerBuildInfo::LanguageList, "_languages/list" }, + { PlayerBuildInfo::UsbIdErrorList, "_usb/error" }, + { PlayerBuildInfo::UsbIdTargetList, "_usb/target" }, +}; + +const static struct { + PlayerBuildInfo::SystemUrl item; + const char* name; +} PlayerSystemUrls[] = { + { PlayerBuildInfo::BootloaderUrl, "bootloader/download_url" }, + { PlayerBuildInfo::BuildInfoUrl, "build_info_url" }, + { PlayerBuildInfo::GenlangUrl, "genlang_url" }, + { PlayerBuildInfo::ThemesUrl, "themes_url" }, + { PlayerBuildInfo::ThemesInfoUrl, "themes_info_url" }, + { PlayerBuildInfo::RbutilUrl, "rbutil_url" }, +}; + +PlayerBuildInfo::PlayerBuildInfo() : + serverInfo(nullptr), + playerInfo(":/ini/rbutil.ini", QSettings::IniFormat) +{ + +} + +void PlayerBuildInfo::setBuildInfo(QString file) +{ + if (serverInfo) + delete serverInfo; + LOG_INFO() << "updated:" << file; + serverInfo = new QSettings(file, QSettings::IniFormat); +} + +QVariant PlayerBuildInfo::value(BuildInfo item, BuildType type) +{ + // locate setting item in server info file + int i = 0; + while(ServerInfoList[i].item != item) + i++; + + // split of variant for target. + // we can have an optional variant part in the target string. + // For build info we don't use that. + QString target = RbSettings::value(RbSettings::CurrentPlatform).toString().split('.').at(0); + + QString s = ServerInfoList[i].name; + s.replace(":target:", target); + QString v; + switch(type) { + case TypeRelease: + v = "release"; + break; + case TypeCandidate: + v = "release-candidate"; + break; + case TypeDaily: + v = "daily"; + break; + case TypeDevel: + v = "development"; + break; + } + + QVariant result = QString(); + if (!serverInfo) + return result; + QStringList version = serverInfo->value(v + "/" + target, "").toStringList(); + s.replace(":build:", v); + s.replace(":version:", version.at(0)); + + // get value from server build-info + // we need to get a version string, otherwise the data is invalid. + // For invalid data return an empty string. + if(version.at(0).isEmpty()) { + LOG_INFO() << s << "(version invalid)"; + return result; + } + if(!s.isEmpty()) + result = serverInfo->value(s); + + // depending on the actual value we need more replacements. + switch(item) { + case BuildVersion: + result = result.toStringList().at(0); + break; + + case BuildUrl: + if(version.size() > 1) { + // version info has an URL appended. Takes precendence. + result = version.at(1); + } + break; + + case BuildVoiceLangs: + if (type == TypeDaily) + s = "voices/daily"; + result = serverInfo->value(s); + break; + + case BuildManualUrl: + { + // special case: if playerInfo has a non-empty manualname entry for the + // target, use that as target for the manual name. + QString manualtarget = playerInfo.value(target + "/manualname", "").toString(); + if(!manualtarget.isEmpty()) + target = manualtarget; + break; + } + + default: + break; + } + // if the value is a string we can replace some patterns. + // if we cannot convert it (f.e. for a QStringList) we leave as-is, since + // the conversion would return an empty type. + if (result.canConvert(QMetaType::QString)) + result = result.toString() + .replace("%TARGET%", target) + .replace("%VERSION%", version.at(0)); + + LOG_INFO() << "B:" << s << result; + return result; +} + +QVariant PlayerBuildInfo::value(DeviceInfo item, QString target) +{ + // locate setting item in server info file + int i = 0; + while(PlayerInfoList[i].item != item) + i++; + + // split of variant for target. + // we can have an optional variant part in the target string. + // For device info we use this. + if (target.isEmpty()) + target = RbSettings::value(RbSettings::CurrentPlatform).toString(); + + QVariant result = QString(); + + QString s = PlayerInfoList[i].name; + s.replace(":target:", target); + + switch(item) { + case BuildStatus: + { + // build status is the only value that doesn't depend on the version + // but the selected target instead. + bool ok = false; + if (serverInfo) + result = serverInfo->value(s).toInt(&ok); + if (!ok) + result = -1; + break; + } + case TargetNamesAll: + // list of all internal target names. Doesn't depend on the passed target. + result = targetNames(true); + break; + case TargetNamesEnabled: + // list of all non-disabled target names. Doesn't depend on the passed target. + result = targetNames(false); + break; + + case LanguageList: + // Return a map (language, display string). + { + // need to use (QString, QVariant) here, so we can put the map into + // a QVariant by itself. + QMap m; + + playerInfo.beginGroup("languages"); + QStringList a = playerInfo.childKeys(); + + for(int i = 0; i < a.size(); i++) { + QStringList v = playerInfo.value(a.at(i)).toStringList(); + m[v.at(0)] = v.at(1); + } + playerInfo.endGroup(); + result = m; + } + break; + + default: + result = playerInfo.value(s); + break; + } + + LOG_INFO() << "T:" << s << result; + return result; +} + +QVariant PlayerBuildInfo::value(DeviceInfo item, unsigned int match) +{ + QStringList result; + int i = 0; + while(PlayerInfoList[i].item != item) + i++; + QString s = PlayerInfoList[i].name; + + switch(item) { + case UsbIdErrorList: + { + // go through all targets and find the one indicated by the usb id "target". + // return list of matching players (since it could be more than one) + QStringList targets = targetNames(true); + for(int i = 0; i < targets.size(); i++) { + QStringList usbids = playerInfo.value(targets.at(i) + "/usberror").toStringList(); + for(int j = 0; j < usbids.size(); j++) { + if(usbids.at(j).toUInt(nullptr, 0) == match) { + result << targets.at(i); + } + } + } + break; + } + + case UsbIdTargetList: + { + QStringList targets = targetNames(true); + for(int i = 0; i < targets.size(); i++) { + QStringList usbids = playerInfo.value(targets.at(i) + "/usbid").toStringList(); + for(int j = 0; j < usbids.size(); j++) { + if(usbids.at(j).toUInt(nullptr, 0) == match) { + result << targets.at(i); + } + } + } + break; + } + + default: + break; + } + LOG_INFO() << "T:" << s << result; + return result; +} + +QVariant PlayerBuildInfo::value(SystemUrl item) +{ + // locate setting item in server info file + int i = 0; + while(PlayerSystemUrls[i].item != item) + i++; + + QVariant result = playerInfo.value(PlayerSystemUrls[i].name); + LOG_INFO() << "U:" << PlayerSystemUrls[i].name << result; + return result; +} + + +QString PlayerBuildInfo::statusAsString(QString platform) +{ + QString result; + switch(value(BuildStatus, platform).toInt()) + { + case STATUS_RETIRED: + result = tr("Stable (Retired)"); + break; + case STATUS_UNUSABLE: + result = tr("Unusable"); + break; + case STATUS_UNSTABLE: + result = tr("Unstable"); + break; + case STATUS_STABLE: + result = tr("Stable"); + break; + default: + result = tr("Unknown"); + break; + } + + return result; +} + + +QStringList PlayerBuildInfo::targetNames(bool all) +{ + QStringList result; + playerInfo.beginGroup("platforms"); + QStringList a = playerInfo.childKeys(); + playerInfo.endGroup(); + for(int i = 0; i < a.size(); i++) + { + QString target = playerInfo.value("platforms/" + a.at(i), "null").toString(); + if(playerInfo.value(target + "/status").toString() != "disabled" || all) { + result.append(target); + } + } + return result; +} + -- cgit v1.2.3