mirror of
https://github.com/claunia/romrepomgr.git
synced 2025-12-16 19:24:51 +00:00
Compare commits
10 Commits
38cc8da72f
...
c5da48fa47
| Author | SHA1 | Date | |
|---|---|---|---|
|
c5da48fa47
|
|||
|
03c69d3671
|
|||
|
2d54cbdf23
|
|||
|
134f8c7183
|
|||
|
368e243bca
|
|||
|
23efc69abc
|
|||
|
cf0f79338a
|
|||
|
743b49c4f0
|
|||
|
8f9bf7036b
|
|||
|
ed7d61d926
|
@@ -31,10 +31,6 @@
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Philips.CodeAnalysis.MaintainabilityAnalyzers">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Roslynator.Analyzers">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
<PackageVersion Include="System.Security.Principal.Windows" Version="5.0.0"/>
|
||||
<PackageVersion Include="Text.Analyzers" Version="4.14.0"/>
|
||||
<PackageVersion Include="winfsp.net" Version="2.1.25156"/>
|
||||
<PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="3.116.1" Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))'"/>
|
||||
|
||||
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3"/>
|
||||
<PackageVersion Include="SabreTools.Hashing" Version="1.2.3"/>
|
||||
|
||||
96
RomRepoMgr.Core/Models/lsar.cs
Normal file
96
RomRepoMgr.Core/Models/lsar.cs
Normal file
@@ -0,0 +1,96 @@
|
||||
using System;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace RomRepoMgr.Core.Models;
|
||||
|
||||
[JsonSerializable(typeof(lsar))]
|
||||
public partial class lsarJsonContext : JsonSerializerContext {}
|
||||
|
||||
public class lsar
|
||||
{
|
||||
public int lsarFormatVersion { get; set; }
|
||||
public string lsarEncoding { get; set; }
|
||||
public int lsarConfidence { get; set; }
|
||||
public string lsarFormatName { get; set; }
|
||||
public lsarProperties lsarProperties { get; set; }
|
||||
public lsarContents[] lsarContents { get; set; }
|
||||
public int lsarError { get; set; }
|
||||
public string lsarInnerFormatName { get; set; }
|
||||
public lsarProperties lsarInnerProperties { get; set; }
|
||||
}
|
||||
|
||||
public class lsarProperties
|
||||
{
|
||||
public string[] XADVolumes { get; set; }
|
||||
public string XADComment { get; set; }
|
||||
public string XADArchiveName { get; set; }
|
||||
public bool XADIsSolid { get; set; }
|
||||
public DateTime XADCreationDate { get; set; }
|
||||
public DateTime XADLastModificationDate { get; set; }
|
||||
public string ARJOriginalArchiveName { get; set; }
|
||||
}
|
||||
|
||||
public class lsarContents
|
||||
{
|
||||
public long XADCompressedSize { get; set; }
|
||||
public long XADDataLength { get; set; }
|
||||
public short ZipFlags { get; set; }
|
||||
public short ZipFileAttributes { get; set; }
|
||||
public long XADDataOffset { get; set; }
|
||||
public long XADIndex { get; set; }
|
||||
public string ZipOSName { get; set; }
|
||||
public short XADPosixPermissions { get; set; }
|
||||
public uint ZipCRC32 { get; set; }
|
||||
public int ZipLocalDate { get; set; }
|
||||
public short ZipOS { get; set; }
|
||||
public short ZipCompressionMethod { get; set; }
|
||||
public string XADCompressionName { get; set; }
|
||||
public short ZipExtractVersion { get; set; }
|
||||
public string XADFileName { get; set; }
|
||||
public DateTime XADLastModificationDate { get; set; }
|
||||
public short XADDOSFileAttributes { get; set; }
|
||||
public long XADFileSize { get; set; }
|
||||
public bool TARIsSparseFile { get; set; }
|
||||
public long XADFirstSolidEntry { get; set; }
|
||||
public string XADSolidObject { get; set; }
|
||||
public long XADFirstSolidIndex { get; set; }
|
||||
public short XADPosixUser { get; set; }
|
||||
public short XADPosixGroup { get; set; }
|
||||
public bool XADIsSolid { get; set; }
|
||||
public DateTime XADLastAccessDate { get; set; }
|
||||
public int ARJCRC32 { get; set; }
|
||||
public int ARJMethod { get; set; }
|
||||
public int ARJMinimumVersion { get; set; }
|
||||
public int ARJFileType { get; set; }
|
||||
public int ARJFlags { get; set; }
|
||||
public string ARJOSName { get; set; }
|
||||
public int ARJOS { get; set; }
|
||||
public int ARJVersion { get; set; }
|
||||
public int GzipExtraFlags { get; set; }
|
||||
public string GzipFilename { get; set; }
|
||||
public int GzipOS { get; set; }
|
||||
public short LHAHeaderLevel { get; set; }
|
||||
public string LHAExtFileNameData { get; set; }
|
||||
public short LHACRC16 { get; set; }
|
||||
public string LHAOSName { get; set; }
|
||||
public int LHAOS { get; set; }
|
||||
public string RAR5OSName { get; set; }
|
||||
public int RAR5Attributes { get; set; }
|
||||
public long RAR5DataLength { get; set; }
|
||||
public long RAR5CompressionMethod { get; set; }
|
||||
public long RAR5DictionarySize { get; set; }
|
||||
public uint RAR5CRC32 { get; set; }
|
||||
public int RAR5Flags { get; set; }
|
||||
public int RAR5DataOffset { get; set; }
|
||||
public int RAR5CompressionVersion { get; set; }
|
||||
public int RAR5CompressionInformation { get; set; }
|
||||
public int RAR5OS { get; set; }
|
||||
public RAR5InputParts[] RAR5InputParts { get; set; }
|
||||
}
|
||||
|
||||
public class RAR5InputParts
|
||||
{
|
||||
public uint CRC32 { get; set; }
|
||||
public long InputLength { get; set; }
|
||||
public long Offset { get; set; }
|
||||
}
|
||||
@@ -1,9 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Newtonsoft.Json;
|
||||
using RomRepoMgr.Core.Aaru;
|
||||
@@ -14,24 +17,28 @@ using RomRepoMgr.Database;
|
||||
using RomRepoMgr.Database.Models;
|
||||
using SabreTools.FileTypes.Aaru;
|
||||
using SabreTools.FileTypes.CHD;
|
||||
using SharpCompress.Compressors;
|
||||
using SharpCompress.Compressors.LZMA;
|
||||
using CompressionMode = SharpCompress.Compressors.CompressionMode;
|
||||
|
||||
namespace RomRepoMgr.Core.Workers;
|
||||
|
||||
public sealed class FileImporter(bool onlyKnown, bool deleteAfterImport)
|
||||
public sealed class FileImporter
|
||||
(
|
||||
Context _ctx,
|
||||
ConcurrentBag<DbFile> _newFiles,
|
||||
ConcurrentBag<DbDisk> _newDisks,
|
||||
ConcurrentBag<DbMedia> _newMedias,
|
||||
bool onlyKnown,
|
||||
bool deleteAfterImport
|
||||
)
|
||||
{
|
||||
const long BUFFER_SIZE = 131072;
|
||||
static readonly Lock DbLock = new();
|
||||
readonly Context _ctx = Context.Create(Settings.Settings.Current.DatabasePath);
|
||||
readonly List<DbDisk> _newDisks = [];
|
||||
readonly List<DbFile> _newFiles = [];
|
||||
readonly List<DbMedia> _newMedias = [];
|
||||
readonly Dictionary<string, DbDisk> _pendingDisksByMd5 = [];
|
||||
readonly Dictionary<string, DbDisk> _pendingDisksBySha1 = [];
|
||||
readonly Dictionary<string, DbFile> _pendingFiles = [];
|
||||
readonly Dictionary<string, DbMedia> _pendingMediasByMd5 = [];
|
||||
readonly Dictionary<string, DbMedia> _pendingMediasBySha1 = [];
|
||||
const long BUFFER_SIZE = 131072;
|
||||
static readonly Lock DbLock = new();
|
||||
readonly Dictionary<string, DbDisk> _pendingDisksByMd5 = [];
|
||||
readonly Dictionary<string, DbDisk> _pendingDisksBySha1 = [];
|
||||
readonly Dictionary<string, DbFile> _pendingFiles = [];
|
||||
readonly Dictionary<string, DbMedia> _pendingMediasByMd5 = [];
|
||||
readonly Dictionary<string, DbMedia> _pendingMediasBySha1 = [];
|
||||
readonly Dictionary<string, DbMedia> _pendingMediasBySha256 = [];
|
||||
string _archiveFolder;
|
||||
string _lastMessage;
|
||||
@@ -83,57 +90,61 @@ public sealed class FileImporter(bool onlyKnown, bool deleteAfterImport)
|
||||
Maximum = Files.Count
|
||||
});
|
||||
|
||||
List<string> files = [];
|
||||
Archives = [];
|
||||
ConcurrentBag<string> files = [];
|
||||
ConcurrentBag<string> archives = [];
|
||||
|
||||
foreach(string file in Files)
|
||||
{
|
||||
try
|
||||
{
|
||||
SetProgress?.Invoke(this,
|
||||
new ProgressEventArgs
|
||||
{
|
||||
Value = _position
|
||||
});
|
||||
Parallel.ForEach(Files,
|
||||
file =>
|
||||
{
|
||||
try
|
||||
{
|
||||
SetProgress?.Invoke(this,
|
||||
new ProgressEventArgs
|
||||
{
|
||||
Value = _position
|
||||
});
|
||||
|
||||
SetMessage?.Invoke(this,
|
||||
new MessageEventArgs
|
||||
{
|
||||
Message = "Checking archives. Found " +
|
||||
Archives.Count +
|
||||
" archives and " +
|
||||
files.Count +
|
||||
" files."
|
||||
});
|
||||
SetMessage?.Invoke(this,
|
||||
new MessageEventArgs
|
||||
{
|
||||
Message = "Checking archives. Found " +
|
||||
archives.Count +
|
||||
" archives and " +
|
||||
files.Count +
|
||||
" files."
|
||||
});
|
||||
|
||||
SetMessage2?.Invoke(this,
|
||||
new MessageEventArgs
|
||||
{
|
||||
Message = string.Format("Checking if file {0} is an archive...",
|
||||
Path.GetFileName(file))
|
||||
});
|
||||
SetMessage2?.Invoke(this,
|
||||
new MessageEventArgs
|
||||
{
|
||||
Message =
|
||||
$"Checking if file {Path.GetFileName(file)} is an archive..."
|
||||
});
|
||||
|
||||
SetIndeterminateProgress2?.Invoke(this, System.EventArgs.Empty);
|
||||
SetIndeterminateProgress2?.Invoke(this, System.EventArgs.Empty);
|
||||
|
||||
string archiveFormat = GetArchiveFormat(file, out _);
|
||||
string archiveFormat = GetArchiveFormat(file, out _);
|
||||
|
||||
// If a floppy contains only the archive, unar will recognize it, on its skipping of SFXs.
|
||||
if(archiveFormat != null && FAT.Identify(file)) archiveFormat = null;
|
||||
// If a floppy contains only the archive, unar will recognize it, on its skipping of SFXs.
|
||||
if(archiveFormat != null && FAT.Identify(file)) archiveFormat = null;
|
||||
|
||||
if(archiveFormat != null)
|
||||
Archives.Add(file);
|
||||
else
|
||||
files.Add(file);
|
||||
if(archiveFormat != null)
|
||||
archives.Add(file);
|
||||
else
|
||||
files.Add(file);
|
||||
|
||||
_position++;
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
Console.WriteLine("Exception while checking file {0}: {1}", Path.GetFileName(file), ex.Message);
|
||||
}
|
||||
}
|
||||
Interlocked.Increment(ref _position);
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
Console.WriteLine("Exception while checking file {0}: {1}",
|
||||
Path.GetFileName(file),
|
||||
ex.Message);
|
||||
}
|
||||
});
|
||||
|
||||
Files = files;
|
||||
Files = files.Order().ToList();
|
||||
Archives = archives.Order().ToList();
|
||||
|
||||
SetMessage?.Invoke(this,
|
||||
new MessageEventArgs
|
||||
@@ -304,7 +315,10 @@ public sealed class FileImporter(bool onlyKnown, bool deleteAfterImport)
|
||||
Message = Localization.ExtractingArchive
|
||||
});
|
||||
|
||||
ExtractArchive(archive, _archiveFolder);
|
||||
if(archiveFormat is "Zip")
|
||||
ZipFile.ExtractToDirectory(archive, _archiveFolder);
|
||||
else
|
||||
ExtractArchive(archive, _archiveFolder);
|
||||
|
||||
Files = Directory.GetFiles(_archiveFolder, "*", SearchOption.AllDirectories).Order().ToList();
|
||||
|
||||
@@ -461,8 +475,8 @@ public sealed class FileImporter(bool onlyKnown, bool deleteAfterImport)
|
||||
|
||||
Dictionary<ChecksumType, string> checksums = checksumWorker.End();
|
||||
|
||||
var uSize = (ulong)inFs.Length;
|
||||
var fileInDb = true;
|
||||
ulong uSize = (ulong)inFs.Length;
|
||||
bool fileInDb = true;
|
||||
|
||||
bool knownFile = _pendingFiles.TryGetValue(checksums[ChecksumType.Sha512], out DbFile dbFile);
|
||||
|
||||
@@ -505,10 +519,10 @@ public sealed class FileImporter(bool onlyKnown, bool deleteAfterImport)
|
||||
|
||||
if(!knownFile) _pendingFiles[checksums[ChecksumType.Sha512]] = dbFile;
|
||||
|
||||
var sha384Bytes = new byte[48];
|
||||
byte[] sha384Bytes = new byte[48];
|
||||
string sha384 = checksums[ChecksumType.Sha384];
|
||||
|
||||
for(var i = 0; i < 48; i++)
|
||||
for(int i = 0; i < 48; i++)
|
||||
{
|
||||
if(sha384[i * 2] >= 0x30 && sha384[i * 2] <= 0x39)
|
||||
sha384Bytes[i] = (byte)((sha384[i * 2] - 0x30) * 0x10);
|
||||
@@ -696,9 +710,9 @@ public sealed class FileImporter(bool onlyKnown, bool deleteAfterImport)
|
||||
|
||||
if(chd.MD5 != null)
|
||||
{
|
||||
var chdArray = new char[32];
|
||||
char[] chdArray = new char[32];
|
||||
|
||||
for(var i = 0; i < 16; i++)
|
||||
for(int i = 0; i < 16; i++)
|
||||
{
|
||||
int nibble1 = chd.MD5[i] >> 4;
|
||||
int nibble2 = chd.MD5[i] & 0xF;
|
||||
@@ -715,9 +729,9 @@ public sealed class FileImporter(bool onlyKnown, bool deleteAfterImport)
|
||||
|
||||
if(chd.SHA1 != null)
|
||||
{
|
||||
var chdArray = new char[40];
|
||||
char[] chdArray = new char[40];
|
||||
|
||||
for(var i = 0; i < 20; i++)
|
||||
for(int i = 0; i < 20; i++)
|
||||
{
|
||||
int nibble1 = chd.SHA1[i] >> 4;
|
||||
int nibble2 = chd.SHA1[i] & 0xF;
|
||||
@@ -732,11 +746,11 @@ public sealed class FileImporter(bool onlyKnown, bool deleteAfterImport)
|
||||
sha1 = new string(chdArray);
|
||||
}
|
||||
|
||||
var uSize = (ulong)inFs.Length;
|
||||
var diskInDb = true;
|
||||
ulong uSize = (ulong)inFs.Length;
|
||||
bool diskInDb = true;
|
||||
DbDisk dbDisk = null;
|
||||
var knownDisk = false;
|
||||
var knownDiskWasBigger = false;
|
||||
bool knownDisk = false;
|
||||
bool knownDiskWasBigger = false;
|
||||
|
||||
if(sha1 != null) knownDisk = _pendingDisksBySha1.TryGetValue(sha1, out dbDisk);
|
||||
|
||||
@@ -887,7 +901,7 @@ public sealed class FileImporter(bool onlyKnown, bool deleteAfterImport)
|
||||
Message = Localization.CopyingFile
|
||||
});
|
||||
|
||||
var buffer = new byte[BUFFER_SIZE];
|
||||
byte[] buffer = new byte[BUFFER_SIZE];
|
||||
|
||||
while(inFs.Position + BUFFER_SIZE <= inFs.Length)
|
||||
{
|
||||
@@ -978,9 +992,9 @@ public sealed class FileImporter(bool onlyKnown, bool deleteAfterImport)
|
||||
|
||||
if(aif.MD5 != null)
|
||||
{
|
||||
var chdArray = new char[32];
|
||||
char[] chdArray = new char[32];
|
||||
|
||||
for(var i = 0; i < 16; i++)
|
||||
for(int i = 0; i < 16; i++)
|
||||
{
|
||||
int nibble1 = aif.MD5[i] >> 4;
|
||||
int nibble2 = aif.MD5[i] & 0xF;
|
||||
@@ -997,9 +1011,9 @@ public sealed class FileImporter(bool onlyKnown, bool deleteAfterImport)
|
||||
|
||||
if(aif.SHA1 != null)
|
||||
{
|
||||
var chdArray = new char[40];
|
||||
char[] chdArray = new char[40];
|
||||
|
||||
for(var i = 0; i < 20; i++)
|
||||
for(int i = 0; i < 20; i++)
|
||||
{
|
||||
int nibble1 = aif.SHA1[i] >> 4;
|
||||
int nibble2 = aif.SHA1[i] & 0xF;
|
||||
@@ -1016,9 +1030,9 @@ public sealed class FileImporter(bool onlyKnown, bool deleteAfterImport)
|
||||
|
||||
if(aif.SHA256 != null)
|
||||
{
|
||||
var chdArray = new char[64];
|
||||
char[] chdArray = new char[64];
|
||||
|
||||
for(var i = 0; i < 32; i++)
|
||||
for(int i = 0; i < 32; i++)
|
||||
{
|
||||
int nibble1 = aif.SHA256[i] >> 4;
|
||||
int nibble2 = aif.SHA256[i] & 0xF;
|
||||
@@ -1033,11 +1047,11 @@ public sealed class FileImporter(bool onlyKnown, bool deleteAfterImport)
|
||||
sha256 = new string(chdArray);
|
||||
}
|
||||
|
||||
var uSize = (ulong)inFs.Length;
|
||||
var mediaInDb = true;
|
||||
ulong uSize = (ulong)inFs.Length;
|
||||
bool mediaInDb = true;
|
||||
DbMedia dbMedia = null;
|
||||
var knownMedia = false;
|
||||
var knownMediaWasBigger = false;
|
||||
bool knownMedia = false;
|
||||
bool knownMediaWasBigger = false;
|
||||
|
||||
if(sha256 != null) knownMedia = _pendingMediasBySha256.TryGetValue(sha256, out dbMedia);
|
||||
|
||||
@@ -1229,7 +1243,7 @@ public sealed class FileImporter(bool onlyKnown, bool deleteAfterImport)
|
||||
Message = Localization.CopyingFile
|
||||
});
|
||||
|
||||
var buffer = new byte[BUFFER_SIZE];
|
||||
byte[] buffer = new byte[BUFFER_SIZE];
|
||||
|
||||
while(inFs.Position + BUFFER_SIZE <= inFs.Length)
|
||||
{
|
||||
@@ -1288,13 +1302,13 @@ public sealed class FileImporter(bool onlyKnown, bool deleteAfterImport)
|
||||
|
||||
public void SaveChanges()
|
||||
{
|
||||
SetIndeterminateProgress2?.Invoke(this, System.EventArgs.Empty);
|
||||
SetIndeterminateProgress?.Invoke(this, System.EventArgs.Empty);
|
||||
|
||||
SetMessage2?.Invoke(this,
|
||||
new MessageEventArgs
|
||||
{
|
||||
Message = Localization.SavingChangesToDatabase
|
||||
});
|
||||
SetMessage?.Invoke(this,
|
||||
new MessageEventArgs
|
||||
{
|
||||
Message = Localization.SavingChangesToDatabase
|
||||
});
|
||||
|
||||
lock(DbLock)
|
||||
{
|
||||
@@ -1351,28 +1365,19 @@ public sealed class FileImporter(bool onlyKnown, bool deleteAfterImport)
|
||||
lsarProcess.Start();
|
||||
string lsarOutput = lsarProcess.StandardOutput.ReadToEnd();
|
||||
lsarProcess.WaitForExit();
|
||||
string format = null;
|
||||
var jsReader = new JsonTextReader(new StringReader(lsarOutput));
|
||||
|
||||
while(jsReader.Read())
|
||||
lsar lsar = JsonConvert.DeserializeObject<lsar>(lsarOutput);
|
||||
|
||||
if(lsar is null)
|
||||
{
|
||||
switch(jsReader.TokenType)
|
||||
{
|
||||
case JsonToken.PropertyName when jsReader.Value?.ToString() == "XADFileName":
|
||||
counter++;
|
||||
counter = 0;
|
||||
|
||||
break;
|
||||
case JsonToken.PropertyName when jsReader.Value?.ToString() == "lsarFormatName":
|
||||
jsReader.Read();
|
||||
|
||||
if(jsReader.TokenType == JsonToken.String && jsReader.Value != null)
|
||||
format = jsReader.Value.ToString();
|
||||
|
||||
break;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
return counter == 0 ? null : format;
|
||||
counter = lsar.lsarContents.Length;
|
||||
|
||||
return lsar.lsarFormatName;
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Avalonia.Media;
|
||||
using ReactiveUI;
|
||||
using RomRepoMgr.Core.EventArgs;
|
||||
@@ -12,6 +11,7 @@ public class RomImporter : ReactiveObject
|
||||
double _maximum;
|
||||
double _minimum;
|
||||
double _progress;
|
||||
bool _progressVisible = true;
|
||||
Color _statusColor;
|
||||
string _statusMessage;
|
||||
public string Filename { get; internal init; }
|
||||
@@ -53,6 +53,12 @@ public class RomImporter : ReactiveObject
|
||||
set => this.RaiseAndSetIfChanged(ref _statusColor, value);
|
||||
}
|
||||
|
||||
public bool ProgressVisible
|
||||
{
|
||||
get => _progressVisible;
|
||||
set => this.RaiseAndSetIfChanged(ref _progressVisible, value);
|
||||
}
|
||||
|
||||
internal void OnErrorOccurred(object sender, ErrorEventArgs e)
|
||||
{
|
||||
StatusMessage = e.Message;
|
||||
@@ -88,21 +94,23 @@ public class RomImporter : ReactiveObject
|
||||
|
||||
internal void OnWorkFinished(object sender, MessageEventArgs e)
|
||||
{
|
||||
Indeterminate = false;
|
||||
Maximum = 1;
|
||||
Minimum = 0;
|
||||
Progress = 1;
|
||||
StatusMessage = e.Message;
|
||||
Running = false;
|
||||
Indeterminate = false;
|
||||
Maximum = 1;
|
||||
Minimum = 0;
|
||||
Progress = 1;
|
||||
StatusMessage = e.Message;
|
||||
Running = false;
|
||||
ProgressVisible = false;
|
||||
}
|
||||
|
||||
public void OnImportedRom(object sender, ImportedRomItemEventArgs e)
|
||||
{
|
||||
Indeterminate = false;
|
||||
Maximum = 1;
|
||||
Minimum = 0;
|
||||
Progress = 1;
|
||||
StatusMessage = e.Item.Status;
|
||||
Running = false;
|
||||
Indeterminate = false;
|
||||
Maximum = 1;
|
||||
Minimum = 0;
|
||||
Progress = 1;
|
||||
StatusMessage = e.Item.Status;
|
||||
Running = false;
|
||||
ProgressVisible = false;
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,6 @@
|
||||
<PackageReference Include="Roslynator.Analyzers"/>
|
||||
<PackageReference Include="Roslynator.CodeAnalysis.Analyzers"/>
|
||||
<PackageReference Include="Roslynator.Formatting.Analyzers"/>
|
||||
<PackageReference Include="SkiaSharp.NativeAssets.Linux"/>
|
||||
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer"/>
|
||||
<PackageReference Include="Text.Analyzers"/>
|
||||
</ItemGroup>
|
||||
|
||||
@@ -12,6 +12,8 @@ using Avalonia.Threading;
|
||||
using ReactiveUI;
|
||||
using RomRepoMgr.Core.EventArgs;
|
||||
using RomRepoMgr.Core.Workers;
|
||||
using RomRepoMgr.Database;
|
||||
using RomRepoMgr.Database.Models;
|
||||
using RomRepoMgr.Models;
|
||||
using RomRepoMgr.Resources;
|
||||
|
||||
@@ -19,31 +21,36 @@ namespace RomRepoMgr.ViewModels;
|
||||
|
||||
public class ImportRomFolderViewModel : ViewModelBase
|
||||
{
|
||||
bool _canClose;
|
||||
bool _canStart;
|
||||
string _folderPath;
|
||||
bool _isImporting;
|
||||
bool _isReady;
|
||||
bool _knownOnlyChecked;
|
||||
int _listPosition;
|
||||
bool _progress2IsIndeterminate;
|
||||
double _progress2Maximum;
|
||||
double _progress2Minimum;
|
||||
double _progress2Value;
|
||||
bool _progress2Visible;
|
||||
bool _progressIsIndeterminate;
|
||||
double _progressMaximum;
|
||||
double _progressMinimum;
|
||||
double _progressValue;
|
||||
bool _progressVisible;
|
||||
bool _recurseArchivesChecked;
|
||||
bool _removeFilesChecked;
|
||||
bool _removeFilesEnabled;
|
||||
FileImporter _rootImporter;
|
||||
string _statusMessage;
|
||||
string _statusMessage2;
|
||||
bool _statusMessage2Visible;
|
||||
readonly Stopwatch _stopwatch = new();
|
||||
readonly Context _ctx = Context.Create(Settings.Settings.Current.DatabasePath);
|
||||
readonly ConcurrentBag<DbDisk> _newDisks = [];
|
||||
readonly ConcurrentBag<DbFile> _newFiles = [];
|
||||
readonly ConcurrentBag<DbMedia> _newMedias = [];
|
||||
readonly Stopwatch _stopwatch = new();
|
||||
bool _canClose;
|
||||
bool _canStart;
|
||||
string _folderPath;
|
||||
bool _isImporting;
|
||||
bool _isReady;
|
||||
bool _knownOnlyChecked;
|
||||
int _listPosition;
|
||||
bool _progress2IsIndeterminate;
|
||||
double _progress2Maximum;
|
||||
double _progress2Minimum;
|
||||
double _progress2Value;
|
||||
bool _progress2Visible;
|
||||
bool _progressIsIndeterminate;
|
||||
double _progressMaximum;
|
||||
double _progressMinimum;
|
||||
double _progressValue;
|
||||
bool _progressVisible;
|
||||
bool _recurseArchivesChecked;
|
||||
bool _removeFilesChecked;
|
||||
bool _removeFilesEnabled;
|
||||
FileImporter _rootImporter;
|
||||
string _statusMessage;
|
||||
string _statusMessage2;
|
||||
bool _statusMessage2Visible;
|
||||
|
||||
|
||||
public ImportRomFolderViewModel()
|
||||
{
|
||||
@@ -207,17 +214,17 @@ public class ImportRomFolderViewModel : ViewModelBase
|
||||
|
||||
void Start()
|
||||
{
|
||||
_rootImporter = new FileImporter(KnownOnlyChecked, RemoveFilesChecked);
|
||||
_rootImporter.SetMessage += SetMessage;
|
||||
_rootImporter = new FileImporter(_ctx, _newFiles, _newDisks, _newMedias, KnownOnlyChecked, RemoveFilesChecked);
|
||||
_rootImporter.SetMessage += SetMessage;
|
||||
_rootImporter.SetIndeterminateProgress += SetIndeterminateProgress;
|
||||
_rootImporter.SetProgress += SetProgress;
|
||||
_rootImporter.SetProgressBounds += SetProgressBounds;
|
||||
_rootImporter.Finished += EnumeratingFilesFinished;
|
||||
ProgressIsIndeterminate = true;
|
||||
ProgressVisible = true;
|
||||
CanClose = false;
|
||||
CanStart = false;
|
||||
IsImporting = true;
|
||||
_rootImporter.SetProgress += SetProgress;
|
||||
_rootImporter.SetProgressBounds += SetProgressBounds;
|
||||
_rootImporter.Finished += EnumeratingFilesFinished;
|
||||
ProgressIsIndeterminate = true;
|
||||
ProgressVisible = true;
|
||||
CanClose = false;
|
||||
CanStart = false;
|
||||
IsImporting = true;
|
||||
|
||||
_ = Task.Run(() => _rootImporter.FindFiles(FolderPath));
|
||||
}
|
||||
@@ -310,7 +317,13 @@ public class ImportRomFolderViewModel : ViewModelBase
|
||||
Indeterminate = true
|
||||
};
|
||||
|
||||
var worker = new FileImporter(KnownOnlyChecked, RemoveFilesChecked);
|
||||
var worker = new FileImporter(_ctx,
|
||||
_newFiles,
|
||||
_newDisks,
|
||||
_newMedias,
|
||||
KnownOnlyChecked,
|
||||
RemoveFilesChecked);
|
||||
|
||||
worker.SetIndeterminateProgress2 += model.OnSetIndeterminateProgress;
|
||||
worker.SetMessage2 += model.OnSetMessage;
|
||||
worker.SetProgress2 += model.OnSetProgress;
|
||||
@@ -322,13 +335,14 @@ public class ImportRomFolderViewModel : ViewModelBase
|
||||
|
||||
worker.ImportFile(file);
|
||||
|
||||
worker.SaveChanges();
|
||||
Interlocked.Increment(ref _listPosition);
|
||||
});
|
||||
|
||||
_stopwatch.Stop();
|
||||
Console.WriteLine("Took " + _stopwatch.Elapsed.TotalSeconds + " seconds to process files.");
|
||||
|
||||
_rootImporter.SaveChanges();
|
||||
|
||||
_rootImporter.UpdateRomStats();
|
||||
|
||||
_listPosition = 0;
|
||||
@@ -351,32 +365,35 @@ public class ImportRomFolderViewModel : ViewModelBase
|
||||
ProgressMinimum = 0;
|
||||
ProgressValue = 0;
|
||||
ProgressIsIndeterminate = false;
|
||||
Progress2Visible = true;
|
||||
StatusMessage2Visible = true;
|
||||
Progress2Visible = false;
|
||||
StatusMessage2Visible = false;
|
||||
_listPosition = 0;
|
||||
_stopwatch.Restart();
|
||||
|
||||
foreach(string archive in _rootImporter.Archives)
|
||||
{
|
||||
StatusMessage = "Processing archive: " + Path.GetFileName(archive);
|
||||
ProgressValue = _listPosition++;
|
||||
Parallel.ForEach(_rootImporter.Archives,
|
||||
archive =>
|
||||
{
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
StatusMessage = "Processing archive: " + Path.GetFileName(archive);
|
||||
ProgressValue = _listPosition;
|
||||
});
|
||||
|
||||
// Create FileImporter
|
||||
var archiveImporter = new FileImporter(KnownOnlyChecked, RemoveFilesChecked);
|
||||
// Create FileImporter
|
||||
var archiveImporter = new FileImporter(_ctx,
|
||||
_newFiles,
|
||||
_newDisks,
|
||||
_newMedias,
|
||||
KnownOnlyChecked,
|
||||
RemoveFilesChecked);
|
||||
|
||||
archiveImporter.SetIndeterminateProgress2 += SetIndeterminateProgress2;
|
||||
archiveImporter.SetMessage2 += SetMessage2;
|
||||
archiveImporter.SetProgress2 += SetProgress2;
|
||||
archiveImporter.SetProgressBounds2 += SetProgress2Bounds;
|
||||
// Extract archive
|
||||
bool ret = archiveImporter.ExtractArchive(archive);
|
||||
|
||||
// Extract archive
|
||||
bool ret = archiveImporter.ExtractArchive(archive);
|
||||
if(!ret) return;
|
||||
|
||||
if(!ret) continue;
|
||||
|
||||
// Process files in archive
|
||||
Parallel.ForEach(archiveImporter.Files,
|
||||
file =>
|
||||
// Process files in archive
|
||||
foreach(string file in archiveImporter.Files)
|
||||
{
|
||||
var model = new RomImporter
|
||||
{
|
||||
@@ -384,7 +401,13 @@ public class ImportRomFolderViewModel : ViewModelBase
|
||||
Indeterminate = true
|
||||
};
|
||||
|
||||
var worker = new FileImporter(KnownOnlyChecked, RemoveFilesChecked);
|
||||
var worker = new FileImporter(_ctx,
|
||||
_newFiles,
|
||||
_newDisks,
|
||||
_newMedias,
|
||||
KnownOnlyChecked,
|
||||
RemoveFilesChecked);
|
||||
|
||||
worker.SetIndeterminateProgress2 += model.OnSetIndeterminateProgress;
|
||||
worker.SetMessage2 += model.OnSetMessage;
|
||||
worker.SetProgress2 += model.OnSetProgress;
|
||||
@@ -396,17 +419,14 @@ public class ImportRomFolderViewModel : ViewModelBase
|
||||
|
||||
worker.ImportFile(file);
|
||||
|
||||
worker.SaveChanges();
|
||||
|
||||
worker.Files.Clear();
|
||||
});
|
||||
}
|
||||
|
||||
// Remove temporary files
|
||||
archiveImporter.CleanupExtractedArchive();
|
||||
// Remove temporary files
|
||||
archiveImporter.CleanupExtractedArchive();
|
||||
|
||||
// Save database changes
|
||||
archiveImporter.SaveChanges();
|
||||
}
|
||||
Interlocked.Increment(ref _listPosition);
|
||||
});
|
||||
|
||||
_stopwatch.Stop();
|
||||
Console.WriteLine("Took " + _stopwatch.Elapsed.TotalSeconds + " seconds to process archives.");
|
||||
|
||||
@@ -105,7 +105,8 @@
|
||||
<ProgressBar Minimum="{Binding Minimum, Mode=OneWay}"
|
||||
Maximum="{Binding Maximum, Mode=OneWay}"
|
||||
Value="{Binding Progress, Mode=OneWay}"
|
||||
IsIndeterminate="{Binding Indeterminate, Mode=OneWay}" />
|
||||
IsIndeterminate="{Binding Indeterminate, Mode=OneWay}"
|
||||
IsVisible="{Binding ProgressVisible, Mode=OneWay}" />
|
||||
</DataTemplate>
|
||||
</DataGridTemplateColumn.CellTemplate>
|
||||
</DataGridTemplateColumn>
|
||||
|
||||
@@ -2,7 +2,7 @@ using Avalonia.Controls;
|
||||
|
||||
namespace RomRepoMgr.Views;
|
||||
|
||||
public class ImportRomFolder : Window
|
||||
public partial class ImportRomFolder : Window
|
||||
{
|
||||
public ImportRomFolder()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user