Async loading of game list
This commit is contained in:
parent
af3d06de27
commit
72862c2222
5 changed files with 124 additions and 39 deletions
|
@ -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")) { }
|
||||
|
||||
|
|
|
@ -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; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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; }
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue