Async loading of game list

This commit is contained in:
Xpl0itR 2019-10-16 20:10:12 +01:00 committed by unknown
parent af3d06de27
commit 72862c2222
No known key found for this signature in database
GPG key ID: 91798184109676AD
5 changed files with 124 additions and 39 deletions

View file

@ -21,7 +21,7 @@ namespace Ryujinx.UI
{
public static Info Information { get; private set; }
#pragma warning disable 649
#pragma warning disable CS0649
[GUI] Window _aboutWin;
[GUI] Label _versionText;
[GUI] Image _ryujinxLogo;
@ -29,7 +29,7 @@ namespace Ryujinx.UI
[GUI] Image _gitHubLogo;
[GUI] Image _discordLogo;
[GUI] Image _twitterLogo;
#pragma warning restore 649
#pragma warning restore CS0649
public AboutWindow() : this(new Builder("Ryujinx.Ui.AboutWindow.glade")) { }

View file

@ -1,4 +1,4 @@
using JsonPrettyPrinterPlus;
using JsonPrettyPrinterPlus;
using LibHac;
using LibHac.Fs;
using LibHac.FsSystem;
@ -20,6 +20,8 @@ namespace Ryujinx.UI
{
public class ApplicationLibrary
{
public static event EventHandler<ApplicationAddedEventArgs> ApplicationAdded;
public static byte[] RyujinxNspIcon { get; private set; }
public static byte[] RyujinxXciIcon { get; private set; }
public static byte[] RyujinxNcaIcon { get; private set; }
@ -41,7 +43,8 @@ namespace Ryujinx.UI
public string Path { get; set; }
}
public static List<ApplicationData> ApplicationLibraryData { get; private set; }
public static float NumApplicationsFound { get; set; }
public static float NumApplicationsLoaded { get; set; }
private static Keyset KeySet;
private static SystemState.TitleLanguage DesiredTitleLanguage;
@ -59,7 +62,7 @@ namespace Ryujinx.UI
private static ApplicationMetadata AppMetadata;
public static void Init(List<string> AppDirs, Keyset keySet, SystemState.TitleLanguage desiredTitleLanguage)
public static void LoadApplications(List<string> AppDirs, Keyset keySet, SystemState.TitleLanguage desiredTitleLanguage)
{
KeySet = keySet;
DesiredTitleLanguage = desiredTitleLanguage;
@ -86,19 +89,29 @@ namespace Ryujinx.UI
foreach (string app in apps)
{
if ((Path.GetExtension(app) == ".xci") ||
(Path.GetExtension(app) == ".nca") ||
(Path.GetExtension(app) == ".nsp") ||
(Path.GetExtension(app) == ".pfs0")||
(Path.GetExtension(app) == ".nro") ||
(Path.GetExtension(app) == ".nso"))
{
applications.Add(app);
NumApplicationsFound++;
}
else if (Path.GetExtension(app) == ".nca")
{
Nca nca = new Nca(KeySet, new FileStream(app, FileMode.Open, FileAccess.Read).AsStorage());
if (nca.Header.ContentType != NcaContentType.Program)
{
continue;
}
applications.Add(app);
NumApplicationsFound++;
}
}
}
// Loops through applications list, creating a struct for each application and then adding the struct to a list of structs
ApplicationLibraryData = new List<ApplicationData>();
// Loops through applications list, creating a struct and then firing an event containing the struct for each application
foreach (string applicationPath in applications)
{
double filesize = new FileInfo(applicationPath).Length * 0.000000000931;
@ -308,12 +321,6 @@ 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 != NcaContentType.Program)
{
continue;
}
applicationIcon = RyujinxNcaIcon;
}
else if (Path.GetExtension(applicationPath) == ".nso")
@ -352,10 +359,21 @@ namespace Ryujinx.UI
Path = applicationPath,
};
ApplicationLibraryData.Add(data);
NumApplicationsLoaded++;
OnApplicationAdded(new ApplicationAddedEventArgs()
{
AppData = data,
AppsLoaded = NumApplicationsLoaded
});
}
}
protected static void OnApplicationAdded(ApplicationAddedEventArgs e)
{
ApplicationAdded?.Invoke(null, e);
}
private static byte[] GetResourceBytes(string resourceName)
{
Stream resourceStream = Assembly.GetCallingAssembly().GetManifestResourceStream(resourceName);
@ -461,4 +479,10 @@ namespace Ryujinx.UI
}
}
}
public class ApplicationAddedEventArgs : EventArgs
{
public ApplicationLibrary.ApplicationData AppData { get; set; }
public float AppsLoaded { get; set; }
}
}

View file

@ -17,6 +17,8 @@ using System.Text;
using System.Threading;
using Utf8Json;
using Utf8Json.Resolvers;
using System.Threading.Tasks;
using System.Collections.Generic;
namespace Ryujinx.UI
{
@ -74,7 +76,7 @@ namespace Ryujinx.UI
public static RichPresence DiscordPresence;
#pragma warning disable 649
#pragma warning disable CS0649
[GUI] Window _mainWin;
[GUI] CheckMenuItem _fullScreen;
[GUI] MenuItem _stopEmulation;
@ -89,7 +91,9 @@ namespace Ryujinx.UI
[GUI] CheckMenuItem _fileSizeToggle;
[GUI] CheckMenuItem _pathToggle;
[GUI] TreeView _gameTable;
#pragma warning restore 649
[GUI] Label _progressLabel;
[GUI] LevelBar _progressBar;
#pragma warning restore CS0649
public MainWindow(string[] args, Application gtkApplication) : this(new Builder("Ryujinx.Ui.MainWindow.glade"), args, gtkApplication) { }
@ -99,6 +103,8 @@ namespace Ryujinx.UI
DeleteEvent += Window_Close;
ApplicationLibrary.ApplicationAdded += Application_Added;
_renderer = new OglRenderer();
_audioOut = InitializeAudioEngine();
@ -110,8 +116,6 @@ namespace Ryujinx.UI
Configuration.Load(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.json"));
Configuration.InitialConfigure(_device);
ApplicationLibrary.Init(SwitchSettings.SwitchConfig.GameDirs, _device.System.KeySet, _device.System.State.DesiredTitleLanguage);
ApplyTheme();
if (DiscordIntegrationEnabled)
@ -138,7 +142,7 @@ namespace Ryujinx.UI
if (SwitchSettings.SwitchConfig.GuiColumns.FavColumn) { _favToggle.Active = true; }
if (SwitchSettings.SwitchConfig.GuiColumns.IconColumn) { _iconToggle.Active = true; }
if (SwitchSettings.SwitchConfig.GuiColumns.AppColumn) { _appToggle.Active = true; }
if (SwitchSettings.SwitchConfig.GuiColumns.AppColumn) { _appToggle.Active = true; }
if (SwitchSettings.SwitchConfig.GuiColumns.DevColumn) { _developerToggle.Active = true; }
if (SwitchSettings.SwitchConfig.GuiColumns.VersionColumn) { _versionToggle.Active = true; }
if (SwitchSettings.SwitchConfig.GuiColumns.TimePlayedColumn) { _timePlayedToggle.Active = true; }
@ -150,7 +154,9 @@ namespace Ryujinx.UI
_gameTable.Model = _tableStore = new ListStore(typeof(bool), typeof(Gdk.Pixbuf), typeof(string), typeof(string), typeof(string), typeof(string), typeof(string), typeof(string), typeof(string), typeof(string));
UpdateColumns();
#pragma warning disable CS4014
UpdateGameTable();
#pragma warning restore CS4014
}
public static void CreateErrorDialog(string errorMessage)
@ -230,19 +236,16 @@ namespace Ryujinx.UI
if (SwitchSettings.SwitchConfig.GuiColumns.PathColumn) { pathColumn.SortColumnId = 9; }
}
public static void UpdateGameTable()
public static async Task UpdateGameTable()
{
_tableStore.Clear();
ApplicationLibrary.Init(SwitchSettings.SwitchConfig.GameDirs, _device.System.KeySet, _device.System.State.DesiredTitleLanguage);
foreach (ApplicationLibrary.ApplicationData AppData in ApplicationLibrary.ApplicationLibraryData)
{
_tableStore.AppendValues(AppData.Favorite, new Gdk.Pixbuf(AppData.Icon, 75, 75), $"{AppData.TitleName}\n{AppData.TitleId.ToUpper()}", AppData.Developer, AppData.Version, AppData.TimePlayed, AppData.LastPlayed, AppData.FileExtension, AppData.FileSize, AppData.Path);
}
_tableStore.SetSortFunc(5, TimePlayedSort);
_tableStore.SetSortFunc(6, LastPlayedSort);
_tableStore.SetSortFunc(8, FileSizeSort);
ApplicationLibrary.NumApplicationsLoaded = 0;
ApplicationLibrary.NumApplicationsFound = 0;
await Task.Run(() => { ApplicationLibrary.LoadApplications(SwitchSettings.SwitchConfig.GameDirs, _device.System.KeySet, _device.System.State.DesiredTitleLanguage); });
}
internal void LoadApplication(string path)
@ -470,6 +473,13 @@ namespace Ryujinx.UI
}
//Events
private void Application_Added(object sender, ApplicationAddedEventArgs e)
{
_tableStore.AppendValues(e.AppData.Favorite, new Gdk.Pixbuf(e.AppData.Icon, 75, 75), $"{e.AppData.TitleName}\n{e.AppData.TitleId.ToUpper()}", e.AppData.Developer, e.AppData.Version, e.AppData.TimePlayed, e.AppData.LastPlayed, e.AppData.FileExtension, e.AppData.FileSize, e.AppData.Path);
_progressLabel.Text = $"{e.AppsLoaded}/{ApplicationLibrary.NumApplicationsFound} Games Loaded";
_progressBar.Value = e.AppsLoaded / ApplicationLibrary.NumApplicationsFound;
}
private void FavToggle_Toggled(object o, ToggledArgs args)
{
_tableStore.GetIter(out TreeIter treeIter, new TreePath(args.Path));

View file

@ -313,21 +313,72 @@
</packing>
</child>
<child>
<object class="GtkScrolledWindow" id="_gameTableWindow">
<object class="GtkBox" id="MainBox">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="shadow_type">in</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkTreeView" id="_gameTable">
<object class="GtkScrolledWindow" id="_gameTableWindow">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="reorderable">True</property>
<property name="hover_selection">True</property>
<signal name="row-activated" handler="Row_Activated" swapped="no"/>
<child internal-child="selection">
<object class="GtkTreeSelection"/>
<property name="shadow_type">in</property>
<child>
<object class="GtkTreeView" id="_gameTable">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="reorderable">True</property>
<property name="hover_selection">True</property>
<signal name="row-activated" handler="Row_Activated" swapped="no"/>
<child internal-child="selection">
<object class="GtkTreeSelection"/>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkBox" id="ProgressBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkLabel" id="_progressLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">5</property>
<property name="margin_right">5</property>
<property name="margin_top">2</property>
<property name="margin_bottom">2</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLevelBar" id="_progressBar">
<property name="width_request">200</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>

View file

@ -21,7 +21,7 @@ namespace Ryujinx.UI
private static bool _listeningForKeypress;
#pragma warning disable 649
#pragma warning disable CS0649
[GUI] Window _settingsWin;
[GUI] CheckButton _errorLogToggle;
[GUI] CheckButton _warningLogToggle;
@ -78,7 +78,7 @@ namespace Ryujinx.UI
[GUI] ToggleButton _plus1;
[GUI] ToggleButton _r1;
[GUI] ToggleButton _zR1;
#pragma warning restore 649
#pragma warning restore CS0649
public static void ConfigureSettings(Configuration Instance) { SwitchConfig = Instance; }