summaryrefslogtreecommitdiff
path: root/utils/rbutilqt/base/playerbuildinfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'utils/rbutilqt/base/playerbuildinfo.cpp')
-rw-r--r--utils/rbutilqt/base/playerbuildinfo.cpp362
1 files changed, 362 insertions, 0 deletions
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 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * Copyright (C) 2020 by Dominik Riebeling
10 *
11 * All files in this archive are subject to the GNU General Public License.
12 * See the file COPYING in the source tree root for full license agreement.
13 *
14 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
15 * KIND, either express or implied.
16 *
17 ****************************************************************************/
18
19#include "playerbuildinfo.h"
20#include "rbsettings.h"
21#include "Logger.h"
22
23PlayerBuildInfo* PlayerBuildInfo::infoInstance = nullptr;
24
25PlayerBuildInfo* PlayerBuildInfo::instance()
26{
27 if (infoInstance == nullptr) {
28 infoInstance = new PlayerBuildInfo();
29 }
30 return infoInstance;
31}
32
33// server infos
34const static struct {
35 PlayerBuildInfo::BuildInfo item;
36 const char* name;
37} ServerInfoList[] = {
38 { PlayerBuildInfo::BuildVoiceLangs, "voices/:version:" },
39 { PlayerBuildInfo::BuildVersion, ":build:/:target:" },
40 { PlayerBuildInfo::BuildUrl, ":build:/build_url" },
41 { PlayerBuildInfo::BuildVoiceUrl, ":build:/voice_url" },
42 { PlayerBuildInfo::BuildManualUrl, ":build:/manual_url" },
43 { PlayerBuildInfo::BuildSourceUrl, ":build:/source_url" },
44 { PlayerBuildInfo::BuildFontUrl, ":build:/font_url" },
45
46 // other URLs -- those are not directly related to the build, but handled here.
47 { PlayerBuildInfo::DoomUrl, "other/doom_url" },
48 { PlayerBuildInfo::Duke3DUrl, "other/duke3d_url" },
49 { PlayerBuildInfo::PuzzFontsUrl, "other/puzzfonts_url" },
50 { PlayerBuildInfo::QuakeUrl, "other/quake_url" },
51 { PlayerBuildInfo::Wolf3DUrl, "other/wolf3d_url" },
52 { PlayerBuildInfo::XWorldUrl, "other/xworld_url" },
53 { PlayerBuildInfo::MidiPatchsetUrl, "other/patcheset_url" },
54};
55
56const static struct {
57 PlayerBuildInfo::DeviceInfo item;
58 const char* name;
59} PlayerInfoList[] = {
60 { PlayerBuildInfo::BuildStatus, "status/:target:" },
61 { PlayerBuildInfo::DisplayName, ":target:/name" },
62 { PlayerBuildInfo::BootloaderMethod, ":target:/bootloadermethod" },
63 { PlayerBuildInfo::BootloaderName, ":target:/bootloadername" },
64 { PlayerBuildInfo::BootloaderFile, ":target:/bootloaderfile" },
65 { PlayerBuildInfo::BootloaderFilter, ":target:/bootloaderfilter" },
66 { PlayerBuildInfo::Encoder, ":target:/encoder" },
67 { PlayerBuildInfo::Brand, ":target:/brand" },
68 { PlayerBuildInfo::PlayerPicture, ":target:/playerpic" },
69 { PlayerBuildInfo::TargetNamesAll, "_targets/all" },
70 { PlayerBuildInfo::TargetNamesEnabled, "_targets/enabled" },
71 { PlayerBuildInfo::LanguageInfo, "languages/:target:" },
72 { PlayerBuildInfo::LanguageList, "_languages/list" },
73 { PlayerBuildInfo::UsbIdErrorList, "_usb/error" },
74 { PlayerBuildInfo::UsbIdTargetList, "_usb/target" },
75};
76
77const static struct {
78 PlayerBuildInfo::SystemUrl item;
79 const char* name;
80} PlayerSystemUrls[] = {
81 { PlayerBuildInfo::BootloaderUrl, "bootloader/download_url" },
82 { PlayerBuildInfo::BuildInfoUrl, "build_info_url" },
83 { PlayerBuildInfo::GenlangUrl, "genlang_url" },
84 { PlayerBuildInfo::ThemesUrl, "themes_url" },
85 { PlayerBuildInfo::ThemesInfoUrl, "themes_info_url" },
86 { PlayerBuildInfo::RbutilUrl, "rbutil_url" },
87};
88
89PlayerBuildInfo::PlayerBuildInfo() :
90 serverInfo(nullptr),
91 playerInfo(":/ini/rbutil.ini", QSettings::IniFormat)
92{
93
94}
95
96void PlayerBuildInfo::setBuildInfo(QString file)
97{
98 if (serverInfo)
99 delete serverInfo;
100 LOG_INFO() << "updated:" << file;
101 serverInfo = new QSettings(file, QSettings::IniFormat);
102}
103
104QVariant PlayerBuildInfo::value(BuildInfo item, BuildType type)
105{
106 // locate setting item in server info file
107 int i = 0;
108 while(ServerInfoList[i].item != item)
109 i++;
110
111 // split of variant for target.
112 // we can have an optional variant part in the target string.
113 // For build info we don't use that.
114 QString target = RbSettings::value(RbSettings::CurrentPlatform).toString().split('.').at(0);
115
116 QString s = ServerInfoList[i].name;
117 s.replace(":target:", target);
118 QString v;
119 switch(type) {
120 case TypeRelease:
121 v = "release";
122 break;
123 case TypeCandidate:
124 v = "release-candidate";
125 break;
126 case TypeDaily:
127 v = "daily";
128 break;
129 case TypeDevel:
130 v = "development";
131 break;
132 }
133
134 QVariant result = QString();
135 if (!serverInfo)
136 return result;
137 QStringList version = serverInfo->value(v + "/" + target, "").toStringList();
138 s.replace(":build:", v);
139 s.replace(":version:", version.at(0));
140
141 // get value from server build-info
142 // we need to get a version string, otherwise the data is invalid.
143 // For invalid data return an empty string.
144 if(version.at(0).isEmpty()) {
145 LOG_INFO() << s << "(version invalid)";
146 return result;
147 }
148 if(!s.isEmpty())
149 result = serverInfo->value(s);
150
151 // depending on the actual value we need more replacements.
152 switch(item) {
153 case BuildVersion:
154 result = result.toStringList().at(0);
155 break;
156
157 case BuildUrl:
158 if(version.size() > 1) {
159 // version info has an URL appended. Takes precendence.
160 result = version.at(1);
161 }
162 break;
163
164 case BuildVoiceLangs:
165 if (type == TypeDaily)
166 s = "voices/daily";
167 result = serverInfo->value(s);
168 break;
169
170 case BuildManualUrl:
171 {
172 // special case: if playerInfo has a non-empty manualname entry for the
173 // target, use that as target for the manual name.
174 QString manualtarget = playerInfo.value(target + "/manualname", "").toString();
175 if(!manualtarget.isEmpty())
176 target = manualtarget;
177 break;
178 }
179
180 default:
181 break;
182 }
183 // if the value is a string we can replace some patterns.
184 // if we cannot convert it (f.e. for a QStringList) we leave as-is, since
185 // the conversion would return an empty type.
186 if (result.canConvert(QMetaType::QString))
187 result = result.toString()
188 .replace("%TARGET%", target)
189 .replace("%VERSION%", version.at(0));
190
191 LOG_INFO() << "B:" << s << result;
192 return result;
193}
194
195QVariant PlayerBuildInfo::value(DeviceInfo item, QString target)
196{
197 // locate setting item in server info file
198 int i = 0;
199 while(PlayerInfoList[i].item != item)
200 i++;
201
202 // split of variant for target.
203 // we can have an optional variant part in the target string.
204 // For device info we use this.
205 if (target.isEmpty())
206 target = RbSettings::value(RbSettings::CurrentPlatform).toString();
207
208 QVariant result = QString();
209
210 QString s = PlayerInfoList[i].name;
211 s.replace(":target:", target);
212
213 switch(item) {
214 case BuildStatus:
215 {
216 // build status is the only value that doesn't depend on the version
217 // but the selected target instead.
218 bool ok = false;
219 if (serverInfo)
220 result = serverInfo->value(s).toInt(&ok);
221 if (!ok)
222 result = -1;
223 break;
224 }
225 case TargetNamesAll:
226 // list of all internal target names. Doesn't depend on the passed target.
227 result = targetNames(true);
228 break;
229 case TargetNamesEnabled:
230 // list of all non-disabled target names. Doesn't depend on the passed target.
231 result = targetNames(false);
232 break;
233
234 case LanguageList:
235 // Return a map (language, display string).
236 {
237 // need to use (QString, QVariant) here, so we can put the map into
238 // a QVariant by itself.
239 QMap<QString, QVariant> m;
240
241 playerInfo.beginGroup("languages");
242 QStringList a = playerInfo.childKeys();
243
244 for(int i = 0; i < a.size(); i++) {
245 QStringList v = playerInfo.value(a.at(i)).toStringList();
246 m[v.at(0)] = v.at(1);
247 }
248 playerInfo.endGroup();
249 result = m;
250 }
251 break;
252
253 default:
254 result = playerInfo.value(s);
255 break;
256 }
257
258 LOG_INFO() << "T:" << s << result;
259 return result;
260}
261
262QVariant PlayerBuildInfo::value(DeviceInfo item, unsigned int match)
263{
264 QStringList result;
265 int i = 0;
266 while(PlayerInfoList[i].item != item)
267 i++;
268 QString s = PlayerInfoList[i].name;
269
270 switch(item) {
271 case UsbIdErrorList:
272 {
273 // go through all targets and find the one indicated by the usb id "target".
274 // return list of matching players (since it could be more than one)
275 QStringList targets = targetNames(true);
276 for(int i = 0; i < targets.size(); i++) {
277 QStringList usbids = playerInfo.value(targets.at(i) + "/usberror").toStringList();
278 for(int j = 0; j < usbids.size(); j++) {
279 if(usbids.at(j).toUInt(nullptr, 0) == match) {
280 result << targets.at(i);
281 }
282 }
283 }
284 break;
285 }
286
287 case UsbIdTargetList:
288 {
289 QStringList targets = targetNames(true);
290 for(int i = 0; i < targets.size(); i++) {
291 QStringList usbids = playerInfo.value(targets.at(i) + "/usbid").toStringList();
292 for(int j = 0; j < usbids.size(); j++) {
293 if(usbids.at(j).toUInt(nullptr, 0) == match) {
294 result << targets.at(i);
295 }
296 }
297 }
298 break;
299 }
300
301 default:
302 break;
303 }
304 LOG_INFO() << "T:" << s << result;
305 return result;
306}
307
308QVariant PlayerBuildInfo::value(SystemUrl item)
309{
310 // locate setting item in server info file
311 int i = 0;
312 while(PlayerSystemUrls[i].item != item)
313 i++;
314
315 QVariant result = playerInfo.value(PlayerSystemUrls[i].name);
316 LOG_INFO() << "U:" << PlayerSystemUrls[i].name << result;
317 return result;
318}
319
320
321QString PlayerBuildInfo::statusAsString(QString platform)
322{
323 QString result;
324 switch(value(BuildStatus, platform).toInt())
325 {
326 case STATUS_RETIRED:
327 result = tr("Stable (Retired)");
328 break;
329 case STATUS_UNUSABLE:
330 result = tr("Unusable");
331 break;
332 case STATUS_UNSTABLE:
333 result = tr("Unstable");
334 break;
335 case STATUS_STABLE:
336 result = tr("Stable");
337 break;
338 default:
339 result = tr("Unknown");
340 break;
341 }
342
343 return result;
344}
345
346
347QStringList PlayerBuildInfo::targetNames(bool all)
348{
349 QStringList result;
350 playerInfo.beginGroup("platforms");
351 QStringList a = playerInfo.childKeys();
352 playerInfo.endGroup();
353 for(int i = 0; i < a.size(); i++)
354 {
355 QString target = playerInfo.value("platforms/" + a.at(i), "null").toString();
356 if(playerInfo.value(target + "/status").toString() != "disabled" || all) {
357 result.append(target);
358 }
359 }
360 return result;
361}
362