Load metadata from JSONs

This commit is contained in:
Xpl0itR 2019-09-22 17:39:36 +01:00 committed by unknown
parent 620367672a
commit 384367b56c
No known key found for this signature in database
GPG key ID: 91798184109676AD
2 changed files with 137 additions and 152 deletions

View file

@ -1,4 +1,5 @@
using LibHac;
using JsonPrettyPrinterPlus;
using LibHac;
using LibHac.Fs;
using LibHac.FsSystem;
using LibHac.FsSystem.NcaUtils;
@ -10,28 +11,20 @@ using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using Utf8Json;
using Utf8Json.Resolvers;
using SystemState = Ryujinx.HLE.HOS.SystemState;
namespace Ryujinx.UI
{
public class ApplicationLibrary
{
private static Keyset KeySet;
private static SystemState.TitleLanguage DesiredTitleLanguage;
private const double SecondsPerMinute = 60.0;
private const double SecondsPerHour = SecondsPerMinute * 60;
private const double SecondsPerDay = SecondsPerHour * 24;
public static byte[] RyujinxNspIcon { get; private set; }
public static byte[] RyujinxXciIcon { get; private set; }
public static byte[] RyujinxNcaIcon { get; private set; }
public static byte[] RyujinxNroIcon { get; private set; }
public static byte[] RyujinxNsoIcon { get; private set; }
public static List<ApplicationData> ApplicationLibraryData { get; private set; }
public struct ApplicationData
{
public bool Fav;
@ -47,6 +40,24 @@ namespace Ryujinx.UI
public string Path;
}
public static List<ApplicationData> ApplicationLibraryData { get; private set; }
private static Keyset KeySet;
private static SystemState.TitleLanguage DesiredTitleLanguage;
private const double SecondsPerMinute = 60.0;
private const double SecondsPerHour = SecondsPerMinute * 60;
private const double SecondsPerDay = SecondsPerHour * 24;
private struct ApplicationMetadata
{
public bool Fav;
public double TimePlayed;
public string LastPlayed;
}
private static ApplicationMetadata AppMetadata;
public static void Init(List<string> AppDirs, Keyset keySet, SystemState.TitleLanguage desiredTitleLanguage)
{
KeySet = keySet;
@ -297,7 +308,7 @@ namespace Ryujinx.UI
if (Path.GetExtension(applicationPath) == ".nca")
{
Nca nca = new Nca(KeySet, new FileStream(applicationPath, FileMode.Open, FileAccess.Read).AsStorage(false));
if (nca.Header.ContentType != ContentType.Program)
if (nca.Header.ContentType != NcaContentType.Program)
{
continue;
}
@ -323,18 +334,18 @@ namespace Ryujinx.UI
}
}
string[] userData = GetUserData(titleId, "00000000000000000000000000000001");
(bool, string, string) metaData = GetMetadata(titleId);
ApplicationData data = new ApplicationData()
{
Fav = bool.Parse(userData[2]),
Fav = metaData.Item1,
Icon = applicationIcon,
TitleName = titleName,
TitleId = titleId,
Developer = developer,
Version = version,
TimePlayed = userData[0],
LastPlayed = userData[1],
TimePlayed = metaData.Item2,
LastPlayed = metaData.Item3,
FileExt = Path.GetExtension(applicationPath).ToUpper().Remove(0 ,1),
FileSize = (filesize < 1) ? (filesize * 1024).ToString("0.##") + "MB" : filesize.ToString("0.##") + "GB",
Path = applicationPath,
@ -388,82 +399,53 @@ namespace Ryujinx.UI
return controlNca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.None);
}
private static string[] GetUserData(string TitleId, string UserId)
private static (bool, string, string) GetMetadata(string TitleId)
{
try
string metadataFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "RyuFs", "games", TitleId, "gui");
string metadataFile = Path.Combine(metadataFolder, "metadata.json");
IJsonFormatterResolver resolver = CompositeResolver.Create(new[] { StandardResolver.AllowPrivateSnakeCase });
if (!File.Exists(metadataFile))
{
string[] userData = new string[3];
string savePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "RyuFs", "GUI", UserId, TitleId);
Directory.CreateDirectory(metadataFolder);
//Time Played
if (File.Exists(Path.Combine(savePath, "TimePlayed.dat")) == false)
AppMetadata = new ApplicationMetadata
{
Directory.CreateDirectory(savePath);
using (FileStream file = File.OpenWrite(Path.Combine(savePath, "TimePlayed.dat")))
{
file.Write(Encoding.ASCII.GetBytes("0"));
}
}
Fav = false,
TimePlayed = 0,
LastPlayed = "Never"
};
using (FileStream fs = File.OpenRead(Path.Combine(savePath, "TimePlayed.dat")))
{
using (StreamReader sr = new StreamReader(fs))
{
float timePlayed = float.Parse(sr.ReadLine());
if (timePlayed < SecondsPerMinute)
{
userData[0] = $"{timePlayed}s";
}
else if (timePlayed < SecondsPerHour)
{
userData[0] = $"{Math.Round(timePlayed / SecondsPerMinute, 2, MidpointRounding.AwayFromZero)} mins";
}
else if (timePlayed < SecondsPerDay)
{
userData[0] = $"{Math.Round(timePlayed / SecondsPerHour , 2, MidpointRounding.AwayFromZero)} hrs";
}
else
{
userData[0] = $"{Math.Round(timePlayed / SecondsPerDay , 2, MidpointRounding.AwayFromZero)} days";
}
}
}
//Last Played
if (File.Exists(Path.Combine(savePath, "LastPlayed.dat")) == false)
{
Directory.CreateDirectory(savePath);
using (FileStream file = File.OpenWrite(Path.Combine(savePath, "LastPlayed.dat")))
{
file.Write(Encoding.ASCII.GetBytes("Never"));
}
}
using (FileStream fs = File.OpenRead(Path.Combine(savePath, "LastPlayed.dat")))
{
using (StreamReader sr = new StreamReader(fs))
{
userData[1] = sr.ReadLine();
}
}
//Fav Games
if (File.Exists(Path.Combine(savePath, "Fav.dat")))
{
userData[2] = "true";
}
else
{
userData[2] = "false";
}
return userData;
byte[] saveData = JsonSerializer.Serialize(AppMetadata, resolver);
File.WriteAllText(metadataFile, Encoding.UTF8.GetString(saveData, 0, saveData.Length).PrettyPrintJson());
}
catch
using (Stream stream = File.OpenRead(metadataFile))
{
return new string[] { "Unknown", "Unknown", "false" };
AppMetadata = JsonSerializer.Deserialize<ApplicationMetadata>(stream, resolver);
}
string timePlayed;
if (AppMetadata.TimePlayed < SecondsPerMinute)
{
timePlayed = $"{AppMetadata.TimePlayed}s";
}
else if (AppMetadata.TimePlayed < SecondsPerHour)
{
timePlayed = $"{Math.Round(AppMetadata.TimePlayed / SecondsPerMinute, 2, MidpointRounding.AwayFromZero)} mins";
}
else if (AppMetadata.TimePlayed < SecondsPerDay)
{
timePlayed = $"{Math.Round(AppMetadata.TimePlayed / SecondsPerHour, 2, MidpointRounding.AwayFromZero)} hrs";
}
else
{
timePlayed = $"{Math.Round(AppMetadata.TimePlayed / SecondsPerDay, 2, MidpointRounding.AwayFromZero)} days";
}
return (AppMetadata.Fav, timePlayed, AppMetadata.LastPlayed);
}
private static byte[] NspOrXciIcon(string applicationPath)

View file

@ -1,3 +1,4 @@
using JsonPrettyPrinterPlus;
using DiscordRPC;
using Gtk;
using GUI = Gtk.Builder.ObjectAttribute;
@ -13,6 +14,8 @@ using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using Utf8Json;
using Utf8Json.Resolvers;
namespace Ryujinx.UI
{
@ -36,8 +39,6 @@ namespace Ryujinx.UI
private static bool _firstLoadComplete = false;
private static string _userId = "00000000000000000000000000000001";
private static TreeViewColumn favColumn;
private static TreeViewColumn appColumn;
private static TreeViewColumn devColumn;
@ -48,6 +49,15 @@ namespace Ryujinx.UI
private static TreeViewColumn fileSizeColumn;
private static TreeViewColumn pathColumn;
private struct ApplicationMetadata
{
public bool Fav;
public double TimePlayed;
public string LastPlayed;
}
private static ApplicationMetadata AppMetadata;
public static bool DiscordIntegrationEnabled { get; set; }
public static DiscordRpcClient DiscordClient;
@ -355,40 +365,35 @@ namespace Ryujinx.UI
DiscordClient.SetPresence(DiscordPresence);
}
try
string metadataFolder = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "RyuFs", "games", _device.System.TitleID, "gui");
string metadataFile = System.IO.Path.Combine(metadataFolder, "metadata.json");
IJsonFormatterResolver resolver = CompositeResolver.Create(new[] { StandardResolver.AllowPrivateSnakeCase });
if (!File.Exists(metadataFile))
{
string savePath = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "RyuFs", "GUI", _userId, _device.System.TitleID);
Directory.CreateDirectory(metadataFolder);
if (File.Exists(System.IO.Path.Combine(savePath, "TimePlayed.dat")) == false)
AppMetadata = new ApplicationMetadata
{
Directory.CreateDirectory(savePath);
using (FileStream stream = File.OpenWrite(System.IO.Path.Combine(savePath, "TimePlayed.dat")))
{
stream.Write(Encoding.ASCII.GetBytes("0"));
}
}
Fav = false,
TimePlayed = 0,
LastPlayed = "Never"
};
if (File.Exists(System.IO.Path.Combine(savePath, "LastPlayed.dat")) == false)
{
Directory.CreateDirectory(savePath);
using (FileStream stream = File.OpenWrite(System.IO.Path.Combine(savePath, "LastPlayed.dat")))
{
stream.Write(Encoding.ASCII.GetBytes("Never"));
}
}
using (FileStream stream = File.OpenWrite(System.IO.Path.Combine(savePath, "LastPlayed.dat")))
{
using (StreamWriter writer = new StreamWriter(stream))
{
writer.WriteLine(DateTime.UtcNow);
}
}
byte[] data = JsonSerializer.Serialize(AppMetadata, resolver);
File.WriteAllText(metadataFile, Encoding.UTF8.GetString(data, 0, data.Length).PrettyPrintJson());
}
catch (ArgumentNullException)
using (Stream stream = File.OpenRead(metadataFile))
{
Logger.PrintWarning(LogClass.Application, $"Could not access save path to retrieve time/last played data using: UserID: {_userId}, TitleID: {_device.System.TitleID}");
AppMetadata = JsonSerializer.Deserialize<ApplicationMetadata>(stream, resolver);
}
AppMetadata.LastPlayed = DateTime.UtcNow.ToString();
byte[] saveData = JsonSerializer.Serialize(AppMetadata, resolver);
File.WriteAllText(metadataFile, Encoding.UTF8.GetString(saveData, 0, saveData.Length).PrettyPrintJson());
}
}
@ -412,39 +417,35 @@ namespace Ryujinx.UI
if (_gameLoaded)
{
try
{
string savePath = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "RyuFs", "GUI", _userId, _device.System.TitleID);
double currentPlayTime = 0;
string metadataFolder = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "RyuFs", "games", _device.System.TitleID, "gui");
string metadataFile = System.IO.Path.Combine(metadataFolder, "metadata.json");
using (FileStream stream = File.OpenRead(System.IO.Path.Combine(savePath, "LastPlayed.dat")))
IJsonFormatterResolver resolver = CompositeResolver.Create(new[] { StandardResolver.AllowPrivateSnakeCase });
if (!File.Exists(metadataFile))
{
Directory.CreateDirectory(metadataFolder);
AppMetadata = new ApplicationMetadata
{
using (StreamReader reader = new StreamReader(stream))
{
DateTime startTime = DateTime.Parse(reader.ReadLine());
Fav = false,
TimePlayed = 0,
LastPlayed = "Never"
};
using (FileStream lastPlayedStream = File.OpenRead(System.IO.Path.Combine(savePath, "TimePlayed.dat")))
{
using (StreamReader lastPlayedReader = new StreamReader(lastPlayedStream))
{
currentPlayTime = double.Parse(lastPlayedReader.ReadLine());
}
}
using (FileStream timePlayedStream = File.OpenWrite(System.IO.Path.Combine(savePath, "TimePlayed.dat")))
{
using (StreamWriter timePlayedWriter = new StreamWriter(timePlayedStream))
{
timePlayedWriter.WriteLine(currentPlayTime + Math.Round(DateTime.UtcNow.Subtract(startTime).TotalSeconds, MidpointRounding.AwayFromZero));
}
}
}
}
byte[] data = JsonSerializer.Serialize(AppMetadata, resolver);
File.WriteAllText(metadataFile, Encoding.UTF8.GetString(data, 0, data.Length).PrettyPrintJson());
}
catch (ArgumentNullException)
using (Stream stream = File.OpenRead(metadataFile))
{
Logger.PrintWarning(LogClass.Application, $"Could not access save path to retrieve time/last played data using: UserID: {_userId}, TitleID: {_device.System.TitleID}");
AppMetadata = JsonSerializer.Deserialize<ApplicationMetadata>(stream, resolver);
}
AppMetadata.TimePlayed += Math.Round(DateTime.UtcNow.Subtract(DateTime.Parse(AppMetadata.LastPlayed)).TotalSeconds, MidpointRounding.AwayFromZero);
byte[] saveData = JsonSerializer.Serialize(AppMetadata, resolver);
File.WriteAllText(metadataFile, Encoding.UTF8.GetString(saveData, 0, saveData.Length).PrettyPrintJson());
}
Profile.FinishProfiling();
@ -480,26 +481,31 @@ namespace Ryujinx.UI
private void FavToggle_Toggled(object o, ToggledArgs args)
{
_tableStore.GetIter(out TreeIter treeIter, new TreePath(args.Path));
string savePath = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "RyuFs", "GUI", _userId, _tableStore.GetValue(treeIter, 2).ToString().Split("\n")[1].ToLower());
string titleid = _tableStore.GetValue(treeIter, 2).ToString().Split("\n")[1].ToLower();
string metadataPath = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "RyuFs", "games", titleid, "gui", "metadata.json");
IJsonFormatterResolver resolver = CompositeResolver.Create(new[] { StandardResolver.AllowPrivateSnakeCase });
using (Stream stream = File.OpenRead(metadataPath))
{
AppMetadata = JsonSerializer.Deserialize<ApplicationMetadata>(stream, resolver);
}
if ((bool)_tableStore.GetValue(treeIter, 0))
{
_tableStore.SetValue(treeIter, 0, false);
if (File.Exists(System.IO.Path.Combine(savePath, "Fav.dat")))
{
File.Delete(System.IO.Path.Combine(savePath, "Fav.dat"));
}
AppMetadata.Fav = false;
}
else
{
_tableStore.SetValue(treeIter, 0, true);
if (!File.Exists(System.IO.Path.Combine(savePath, "Fav.dat")))
{
using (File.Create(System.IO.Path.Combine(savePath, "Fav.dat"))) { };
}
AppMetadata.Fav = true;
}
byte[] saveData = JsonSerializer.Serialize(AppMetadata, resolver);
File.WriteAllText(metadataPath, Encoding.UTF8.GetString(saveData, 0, saveData.Length).PrettyPrintJson());
}
private void Row_Activated(object o, RowActivatedArgs args)
@ -710,9 +716,6 @@ namespace Ryujinx.UI
string aValue = model.GetValue(a, 5).ToString();
string bValue = model.GetValue(b, 5).ToString();
if (aValue == "Unknown") { aValue = "0s"; }
if (bValue == "Unknown") { bValue = "0s"; }
if (aValue.Length > 4 && aValue.Substring(aValue.Length - 4) == "mins")
{
aValue = (float.Parse(aValue.Substring(0, aValue.Length - 5)) * 60).ToString();