mirror of
https://github.com/SabreTools/MPF.git
synced 2026-07-02 17:24:48 +00:00
Create FrontendTool and move some methods to it
This commit is contained in:
@@ -141,6 +141,7 @@
|
||||
- Rename Tools to VersionTool
|
||||
- Move VersionTool to root of Core
|
||||
- Move InfoTool to root of Core
|
||||
- Create FrontendTool and move some methods to it
|
||||
|
||||
### 3.1.9a (2024-05-21)
|
||||
|
||||
|
||||
@@ -1,70 +1,9 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
|
||||
#pragma warning disable SYSLIB1045 // Convert to 'GeneratedRegexAttribute'.
|
||||
using SabreTools.RedumpLib.Data;
|
||||
|
||||
namespace MPF.Core
|
||||
{
|
||||
public static class InfoTool
|
||||
{
|
||||
#region Information Extraction
|
||||
|
||||
/// <summary>
|
||||
/// Get the current system from the drive volume label
|
||||
/// </summary>
|
||||
/// <returns>The system based on volume label, null if none detected</returns>
|
||||
public static RedumpSystem? GetRedumpSystemFromVolumeLabel(string? volumeLabel)
|
||||
{
|
||||
// If the volume label is empty, we can't do anything
|
||||
if (string.IsNullOrEmpty(volumeLabel))
|
||||
return null;
|
||||
|
||||
// Audio CD
|
||||
if (volumeLabel!.Equals("Audio CD", StringComparison.OrdinalIgnoreCase))
|
||||
return RedumpSystem.AudioCD;
|
||||
|
||||
// Microsoft Xbox
|
||||
if (volumeLabel.Equals("SEP13011042", StringComparison.OrdinalIgnoreCase))
|
||||
return RedumpSystem.MicrosoftXbox;
|
||||
else if (volumeLabel.Equals("SEP13011042072", StringComparison.OrdinalIgnoreCase))
|
||||
return RedumpSystem.MicrosoftXbox;
|
||||
|
||||
// Microsoft Xbox 360
|
||||
if (volumeLabel.Equals("XBOX360", StringComparison.OrdinalIgnoreCase))
|
||||
return RedumpSystem.MicrosoftXbox360;
|
||||
else if (volumeLabel.Equals("XGD2DVD_NTSC", StringComparison.OrdinalIgnoreCase))
|
||||
return RedumpSystem.MicrosoftXbox360;
|
||||
|
||||
// Microsoft Xbox 360 - Too overly broad even if a lot of discs use this
|
||||
//if (volumeLabel.Equals("CD_ROM", StringComparison.OrdinalIgnoreCase))
|
||||
// return RedumpSystem.MicrosoftXbox360; // Also for Xbox One?
|
||||
//if (volumeLabel.Equals("DVD_ROM", StringComparison.OrdinalIgnoreCase))
|
||||
// return RedumpSystem.MicrosoftXbox360;
|
||||
|
||||
// Sega Mega-CD / Sega-CD
|
||||
if (volumeLabel.Equals("Sega_CD", StringComparison.OrdinalIgnoreCase))
|
||||
return RedumpSystem.SegaMegaCDSegaCD;
|
||||
|
||||
// Sony PlayStation 3
|
||||
if (volumeLabel.Equals("PS3VOLUME", StringComparison.OrdinalIgnoreCase))
|
||||
return RedumpSystem.SonyPlayStation3;
|
||||
|
||||
// Sony PlayStation 4
|
||||
if (volumeLabel.Equals("PS4VOLUME", StringComparison.OrdinalIgnoreCase))
|
||||
return RedumpSystem.SonyPlayStation4;
|
||||
|
||||
// Sony PlayStation 5
|
||||
if (volumeLabel.Equals("PS5VOLUME", StringComparison.OrdinalIgnoreCase))
|
||||
return RedumpSystem.SonyPlayStation5;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Region Extraction
|
||||
|
||||
/// <summary>
|
||||
@@ -153,465 +92,5 @@ namespace MPF.Core
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Normalization
|
||||
|
||||
/// <summary>
|
||||
/// Adjust a disc title so that it will be processed correctly by Redump
|
||||
/// </summary>
|
||||
/// <param name="title">Existing title to potentially reformat</param>
|
||||
/// <param name="languages">Array of languages to use for assuming articles</param>
|
||||
/// <returns>The reformatted title</returns>
|
||||
public static string? NormalizeDiscTitle(string? title, Language?[]? languages)
|
||||
{
|
||||
// If we have no set languages, then assume English
|
||||
if (languages == null || languages.Length == 0)
|
||||
languages = [Language.English];
|
||||
|
||||
// Loop through all of the given languages
|
||||
foreach (var language in languages)
|
||||
{
|
||||
// If the new title is different, assume it was normalized and return it
|
||||
string? newTitle = NormalizeDiscTitle(title, language);
|
||||
if (newTitle != title)
|
||||
return newTitle;
|
||||
}
|
||||
|
||||
// If we didn't already try English, try it now
|
||||
if (!languages.Contains(Language.English))
|
||||
return NormalizeDiscTitle(title, Language.English);
|
||||
|
||||
// If all fails, then the title didn't need normalization
|
||||
return title;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adjust a disc title so that it will be processed correctly by Redump
|
||||
/// </summary>
|
||||
/// <param name="title">Existing title to potentially reformat</param>
|
||||
/// <param name="language">Language to use for assuming articles</param>
|
||||
/// <returns>The reformatted title</returns>
|
||||
/// <remarks>
|
||||
/// If the language of the title is unknown or if it's multilingual,
|
||||
/// pass in Language.English for standardized coverage.
|
||||
/// </remarks>
|
||||
public static string? NormalizeDiscTitle(string? title, Language? language)
|
||||
{
|
||||
// If we have an invalid title, just return it as-is
|
||||
if (string.IsNullOrEmpty(title))
|
||||
return title;
|
||||
|
||||
// If we have an invalid language, assume Language.English
|
||||
if (language == null)
|
||||
language = Language.English;
|
||||
|
||||
// Get the title split into parts
|
||||
string[] splitTitle = title!.Split(' ').Where(s => !string.IsNullOrEmpty(s)).ToArray();
|
||||
|
||||
// If we only have one part, we can't do anything
|
||||
if (splitTitle.Length <= 1)
|
||||
return title;
|
||||
|
||||
// Determine if we have a definite or indefinite article as the first item
|
||||
string firstItem = splitTitle[0];
|
||||
switch (firstItem.ToLowerInvariant())
|
||||
{
|
||||
// Latin script articles
|
||||
case "'n"
|
||||
when language is Language.Manx:
|
||||
case "a"
|
||||
when language is Language.English
|
||||
|| language is Language.Hungarian
|
||||
|| language is Language.Portuguese
|
||||
|| language is Language.Scots:
|
||||
case "a'"
|
||||
when language is Language.English
|
||||
|| language is Language.Hungarian
|
||||
|| language is Language.Irish
|
||||
|| language is Language.Gaelic: // Scottish Gaelic
|
||||
case "al"
|
||||
when language is Language.Breton:
|
||||
case "am"
|
||||
when language is Language.Gaelic: // Scottish Gaelic
|
||||
case "an"
|
||||
when language is Language.Breton
|
||||
|| language is Language.Cornish
|
||||
|| language is Language.English
|
||||
|| language is Language.Irish
|
||||
|| language is Language.Gaelic: // Scottish Gaelic
|
||||
case "anek"
|
||||
when language is Language.Nepali:
|
||||
case "ar"
|
||||
when language is Language.Breton:
|
||||
case "az"
|
||||
when language is Language.Hungarian:
|
||||
case "ān"
|
||||
when language is Language.Persian:
|
||||
case "as"
|
||||
when language is Language.Portuguese:
|
||||
case "d'"
|
||||
when language is Language.Luxembourgish:
|
||||
case "das"
|
||||
when language is Language.German:
|
||||
case "dat"
|
||||
when language is Language.Luxembourgish:
|
||||
case "de"
|
||||
when language is Language.Dutch:
|
||||
case "déi"
|
||||
when language is Language.Luxembourgish:
|
||||
case "dem"
|
||||
when language is Language.German
|
||||
|| language is Language.Luxembourgish:
|
||||
case "den"
|
||||
when language is Language.Dutch
|
||||
|| language is Language.German
|
||||
|| language is Language.Luxembourgish:
|
||||
case "der"
|
||||
when language is Language.Dutch
|
||||
|| language is Language.German
|
||||
|| language is Language.Luxembourgish:
|
||||
case "des"
|
||||
when language is Language.Dutch
|
||||
|| language is Language.French
|
||||
|| language is Language.German:
|
||||
case "die"
|
||||
when language is Language.Afrikaans
|
||||
|| language is Language.German:
|
||||
case "du"
|
||||
when language is Language.French:
|
||||
case "e"
|
||||
when language is Language.Papiamento:
|
||||
case "een"
|
||||
when language is Language.Dutch:
|
||||
case "egy"
|
||||
when language is Language.Hungarian:
|
||||
case "ei"
|
||||
when language is Language.Norwegian:
|
||||
case "ein"
|
||||
when language is Language.German
|
||||
|| language is Language.Norwegian:
|
||||
case "eine"
|
||||
when language is Language.German:
|
||||
case "einem"
|
||||
when language is Language.German:
|
||||
case "einen"
|
||||
when language is Language.German:
|
||||
case "einer"
|
||||
when language is Language.German:
|
||||
case "eines"
|
||||
when language is Language.German:
|
||||
case "eit"
|
||||
when language is Language.Norwegian:
|
||||
case "ek"
|
||||
when language is Language.Nepali:
|
||||
case "el"
|
||||
when language is Language.Arabic
|
||||
|| language is Language.Catalan
|
||||
|| language is Language.Spanish:
|
||||
case "els"
|
||||
when language is Language.Catalan:
|
||||
case "en"
|
||||
when language is Language.Danish
|
||||
|| language is Language.Luxembourgish
|
||||
|| language is Language.Norwegian
|
||||
|| language is Language.Swedish:
|
||||
case "eng"
|
||||
when language is Language.Luxembourgish:
|
||||
case "engem"
|
||||
when language is Language.Luxembourgish:
|
||||
case "enger"
|
||||
when language is Language.Luxembourgish:
|
||||
case "es"
|
||||
when language is Language.Catalan:
|
||||
case "et"
|
||||
when language is Language.Danish
|
||||
|| language is Language.Norwegian:
|
||||
case "ett"
|
||||
when language is Language.Swedish:
|
||||
case "euta"
|
||||
when language is Language.Nepali:
|
||||
case "euti"
|
||||
when language is Language.Nepali:
|
||||
case "gli"
|
||||
when language is Language.Italian:
|
||||
case "he"
|
||||
when language is Language.Hawaiian
|
||||
|| language is Language.Maori:
|
||||
case "het"
|
||||
when language is Language.Dutch:
|
||||
case "i"
|
||||
when language is Language.Italian
|
||||
|| language is Language.Khasi:
|
||||
case "il"
|
||||
when language is Language.Italian:
|
||||
case "in"
|
||||
when language is Language.Persian:
|
||||
case "ka"
|
||||
when language is Language.Hawaiian
|
||||
|| language is Language.Khasi:
|
||||
case "ke"
|
||||
when language is Language.Hawaiian:
|
||||
case "ki"
|
||||
when language is Language.Khasi:
|
||||
case "kunai"
|
||||
when language is Language.Nepali:
|
||||
case "l'"
|
||||
when language is Language.Catalan
|
||||
|| language is Language.French
|
||||
|| language is Language.Italian:
|
||||
case "la"
|
||||
when language is Language.Catalan
|
||||
|| language is Language.Esperanto
|
||||
|| language is Language.French
|
||||
|| language is Language.Italian
|
||||
|| language is Language.Spanish:
|
||||
case "las"
|
||||
when language is Language.Spanish:
|
||||
case "le"
|
||||
when language is Language.French
|
||||
|| language is Language.Interlingua
|
||||
|| language is Language.Italian:
|
||||
case "les"
|
||||
when language is Language.Catalan
|
||||
|| language is Language.French:
|
||||
case "lo"
|
||||
when language is Language.Catalan
|
||||
|| language is Language.Italian
|
||||
|| language is Language.Spanish:
|
||||
case "los"
|
||||
when language is Language.Catalan
|
||||
|| language is Language.Spanish:
|
||||
case "na"
|
||||
when language is Language.Irish
|
||||
|| language is Language.Gaelic: // Scottish Gaelic
|
||||
case "nam"
|
||||
when language is Language.Gaelic: // Scottish Gaelic
|
||||
case "nan"
|
||||
when language is Language.Gaelic: // Scottish Gaelic
|
||||
case "nā"
|
||||
when language is Language.Hawaiian:
|
||||
case "ngā"
|
||||
when language is Language.Maori:
|
||||
case "niște"
|
||||
when language is Language.Romanian:
|
||||
case "ny"
|
||||
when language is Language.Manx:
|
||||
case "o"
|
||||
when language is Language.Portuguese
|
||||
|| language is Language.Romanian:
|
||||
case "os"
|
||||
when language is Language.Portuguese:
|
||||
case "sa"
|
||||
when language is Language.Catalan:
|
||||
case "sang"
|
||||
when language is Language.Malay:
|
||||
case "se"
|
||||
when language is Language.Finnish:
|
||||
case "ses"
|
||||
when language is Language.Catalan:
|
||||
case "si"
|
||||
when language is Language.Malay:
|
||||
case "te"
|
||||
when language is Language.Maori:
|
||||
case "the"
|
||||
when language is Language.English
|
||||
|| language is Language.Scots:
|
||||
case "u"
|
||||
when language is Language.Khasi:
|
||||
case "ul"
|
||||
when language is Language.Breton:
|
||||
case "um"
|
||||
when language is Language.Portuguese:
|
||||
case "uma"
|
||||
when language is Language.Portuguese:
|
||||
case "umas"
|
||||
when language is Language.Portuguese:
|
||||
case "un"
|
||||
when language is Language.Breton
|
||||
|| language is Language.Catalan
|
||||
|| language is Language.French
|
||||
|| language is Language.Interlingua
|
||||
|| language is Language.Italian
|
||||
|| language is Language.Papiamento
|
||||
|| language is Language.Romanian
|
||||
|| language is Language.Spanish:
|
||||
case "un'"
|
||||
when language is Language.Italian:
|
||||
case "una"
|
||||
when language is Language.Catalan
|
||||
|| language is Language.Italian:
|
||||
case "unas"
|
||||
when language is Language.Spanish:
|
||||
case "une"
|
||||
when language is Language.French:
|
||||
case "uno"
|
||||
when language is Language.Italian:
|
||||
case "unos"
|
||||
when language is Language.Spanish:
|
||||
case "uns"
|
||||
when language is Language.Catalan
|
||||
|| language is Language.Portuguese:
|
||||
case "unei"
|
||||
when language is Language.Romanian:
|
||||
case "unes"
|
||||
when language is Language.Catalan:
|
||||
case "unor"
|
||||
when language is Language.Romanian:
|
||||
case "unui"
|
||||
when language is Language.Romanian:
|
||||
case "ur"
|
||||
when language is Language.Breton:
|
||||
case "y"
|
||||
when language is Language.Manx
|
||||
|| language is Language.Welsh:
|
||||
case "ye"
|
||||
when language is Language.Persian:
|
||||
case "yek"
|
||||
when language is Language.Persian:
|
||||
case "yn"
|
||||
when language is Language.Manx:
|
||||
case "yr"
|
||||
when language is Language.Welsh:
|
||||
|
||||
// Non-latin script articles
|
||||
case "ο"
|
||||
when language is Language.Greek:
|
||||
case "η"
|
||||
when language is Language.Greek:
|
||||
case "το"
|
||||
when language is Language.Greek:
|
||||
case "οι"
|
||||
when language is Language.Greek:
|
||||
case "τα"
|
||||
when language is Language.Greek:
|
||||
case "ένας"
|
||||
when language is Language.Greek:
|
||||
case "μια"
|
||||
when language is Language.Greek:
|
||||
case "ένα"
|
||||
when language is Language.Greek:
|
||||
case "еден"
|
||||
when language is Language.Macedonian:
|
||||
case "една"
|
||||
when language is Language.Macedonian:
|
||||
case "едно"
|
||||
when language is Language.Macedonian:
|
||||
case "едни"
|
||||
when language is Language.Macedonian:
|
||||
case "एउटा"
|
||||
when language is Language.Nepali:
|
||||
case "एउटी"
|
||||
when language is Language.Nepali:
|
||||
case "एक"
|
||||
when language is Language.Nepali:
|
||||
case "अनेक"
|
||||
when language is Language.Nepali:
|
||||
case "कुनै"
|
||||
when language is Language.Nepali:
|
||||
case "דער"
|
||||
when language is Language.Yiddish:
|
||||
case "די"
|
||||
when language is Language.Yiddish:
|
||||
case "דאָס"
|
||||
when language is Language.Yiddish:
|
||||
case "דעם"
|
||||
when language is Language.Yiddish:
|
||||
case "אַ"
|
||||
when language is Language.Yiddish:
|
||||
case "אַן"
|
||||
when language is Language.Yiddish:
|
||||
|
||||
break;
|
||||
|
||||
// Otherwise, just return it as-is
|
||||
default:
|
||||
return title;
|
||||
}
|
||||
|
||||
// Insert the first item if we have a `:` or `-`
|
||||
bool itemInserted = false;
|
||||
var newTitleBuilder = new StringBuilder();
|
||||
for (int i = 1; i < splitTitle.Length; i++)
|
||||
{
|
||||
string segment = splitTitle[i];
|
||||
if (!itemInserted && segment == ":")
|
||||
{
|
||||
itemInserted = true;
|
||||
newTitleBuilder.Append($", {firstItem} :");
|
||||
}
|
||||
else if (!itemInserted && segment == "-")
|
||||
{
|
||||
itemInserted = true;
|
||||
newTitleBuilder.Append($", {firstItem} -");
|
||||
}
|
||||
else if (!itemInserted && segment.EndsWith(":"))
|
||||
{
|
||||
itemInserted = true;
|
||||
newTitleBuilder.Append($" {segment.Substring(0, segment.Length - 1)}, {firstItem}:");
|
||||
}
|
||||
else if (!itemInserted && segment.EndsWith("-"))
|
||||
{
|
||||
itemInserted = true;
|
||||
newTitleBuilder.Append($" {segment.Substring(0, segment.Length - 1)}, {firstItem}-");
|
||||
}
|
||||
else
|
||||
{
|
||||
newTitleBuilder.Append($" {segment}");
|
||||
}
|
||||
}
|
||||
|
||||
// If we didn't insert the item yet, add it to the end
|
||||
string newTitle = newTitleBuilder.ToString().Trim();
|
||||
if (!itemInserted)
|
||||
newTitle = $"{newTitle}, {firstItem}";
|
||||
|
||||
return newTitle;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Normalize a split set of paths
|
||||
/// </summary>
|
||||
/// <param name="path">Path value to normalize</param>
|
||||
public static string NormalizeOutputPaths(string? path, bool getFullPath)
|
||||
{
|
||||
// The easy way
|
||||
try
|
||||
{
|
||||
// If we have an invalid path
|
||||
if (string.IsNullOrEmpty(path))
|
||||
return string.Empty;
|
||||
|
||||
// Remove quotes and angle brackets from path
|
||||
path = path!.Replace("\"", string.Empty);
|
||||
path = path!.Replace("<", string.Empty);
|
||||
path = path!.Replace(">", string.Empty);
|
||||
|
||||
// Try getting the combined path and returning that directly
|
||||
string fullPath = getFullPath ? Path.GetFullPath(path) : path;
|
||||
var fullDirectory = Path.GetDirectoryName(fullPath);
|
||||
string fullFile = Path.GetFileName(fullPath);
|
||||
|
||||
// Remove invalid path characters
|
||||
if (fullDirectory != null)
|
||||
{
|
||||
foreach (char c in Path.GetInvalidPathChars())
|
||||
fullDirectory = fullDirectory.Replace(c, '_');
|
||||
}
|
||||
|
||||
// Remove invalid filename characters
|
||||
foreach (char c in Path.GetInvalidFileNameChars())
|
||||
fullFile = fullFile.Replace(c, '_');
|
||||
|
||||
if (string.IsNullOrEmpty(fullDirectory))
|
||||
return fullFile;
|
||||
else
|
||||
return Path.Combine(fullDirectory, fullFile);
|
||||
}
|
||||
catch { }
|
||||
|
||||
return path ?? string.Empty;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ namespace MPF.Frontend
|
||||
_options = options;
|
||||
|
||||
// Output paths
|
||||
OutputPath = InfoTool.NormalizeOutputPaths(outputPath, false);
|
||||
OutputPath = FrontendTool.NormalizeOutputPaths(outputPath, false);
|
||||
|
||||
// UI information
|
||||
_drive = drive;
|
||||
@@ -594,7 +594,7 @@ namespace MPF.Frontend
|
||||
return ResultEventArgs.Failure("Error! Current configuration is not supported!");
|
||||
|
||||
// Fix the output paths, just in case
|
||||
OutputPath = InfoTool.NormalizeOutputPaths(OutputPath, false);
|
||||
OutputPath = FrontendTool.NormalizeOutputPaths(OutputPath, false);
|
||||
|
||||
// Validate that the output path isn't on the dumping drive
|
||||
if (_drive?.Name != null && OutputPath.StartsWith(_drive.Name))
|
||||
|
||||
526
MPF.Frontend/FrontendTool.cs
Normal file
526
MPF.Frontend/FrontendTool.cs
Normal file
@@ -0,0 +1,526 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
|
||||
namespace MPF.Frontend
|
||||
{
|
||||
public static class FrontendTool
|
||||
{
|
||||
#region Information Extraction
|
||||
|
||||
/// <summary>
|
||||
/// Get the current system from the drive volume label
|
||||
/// </summary>
|
||||
/// <returns>The system based on volume label, null if none detected</returns>
|
||||
public static RedumpSystem? GetRedumpSystemFromVolumeLabel(string? volumeLabel)
|
||||
{
|
||||
// If the volume label is empty, we can't do anything
|
||||
if (string.IsNullOrEmpty(volumeLabel))
|
||||
return null;
|
||||
|
||||
// Audio CD
|
||||
if (volumeLabel!.Equals("Audio CD", StringComparison.OrdinalIgnoreCase))
|
||||
return RedumpSystem.AudioCD;
|
||||
|
||||
// Microsoft Xbox
|
||||
if (volumeLabel.Equals("SEP13011042", StringComparison.OrdinalIgnoreCase))
|
||||
return RedumpSystem.MicrosoftXbox;
|
||||
else if (volumeLabel.Equals("SEP13011042072", StringComparison.OrdinalIgnoreCase))
|
||||
return RedumpSystem.MicrosoftXbox;
|
||||
|
||||
// Microsoft Xbox 360
|
||||
if (volumeLabel.Equals("XBOX360", StringComparison.OrdinalIgnoreCase))
|
||||
return RedumpSystem.MicrosoftXbox360;
|
||||
else if (volumeLabel.Equals("XGD2DVD_NTSC", StringComparison.OrdinalIgnoreCase))
|
||||
return RedumpSystem.MicrosoftXbox360;
|
||||
|
||||
// Microsoft Xbox 360 - Too overly broad even if a lot of discs use this
|
||||
//if (volumeLabel.Equals("CD_ROM", StringComparison.OrdinalIgnoreCase))
|
||||
// return RedumpSystem.MicrosoftXbox360; // Also for Xbox One?
|
||||
//if (volumeLabel.Equals("DVD_ROM", StringComparison.OrdinalIgnoreCase))
|
||||
// return RedumpSystem.MicrosoftXbox360;
|
||||
|
||||
// Sega Mega-CD / Sega-CD
|
||||
if (volumeLabel.Equals("Sega_CD", StringComparison.OrdinalIgnoreCase))
|
||||
return RedumpSystem.SegaMegaCDSegaCD;
|
||||
|
||||
// Sony PlayStation 3
|
||||
if (volumeLabel.Equals("PS3VOLUME", StringComparison.OrdinalIgnoreCase))
|
||||
return RedumpSystem.SonyPlayStation3;
|
||||
|
||||
// Sony PlayStation 4
|
||||
if (volumeLabel.Equals("PS4VOLUME", StringComparison.OrdinalIgnoreCase))
|
||||
return RedumpSystem.SonyPlayStation4;
|
||||
|
||||
// Sony PlayStation 5
|
||||
if (volumeLabel.Equals("PS5VOLUME", StringComparison.OrdinalIgnoreCase))
|
||||
return RedumpSystem.SonyPlayStation5;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Normalization
|
||||
|
||||
/// <summary>
|
||||
/// Adjust a disc title so that it will be processed correctly by Redump
|
||||
/// </summary>
|
||||
/// <param name="title">Existing title to potentially reformat</param>
|
||||
/// <param name="languages">Array of languages to use for assuming articles</param>
|
||||
/// <returns>The reformatted title</returns>
|
||||
public static string? NormalizeDiscTitle(string? title, Language?[]? languages)
|
||||
{
|
||||
// If we have no set languages, then assume English
|
||||
if (languages == null || languages.Length == 0)
|
||||
languages = [Language.English];
|
||||
|
||||
// Loop through all of the given languages
|
||||
foreach (var language in languages)
|
||||
{
|
||||
// If the new title is different, assume it was normalized and return it
|
||||
string? newTitle = NormalizeDiscTitle(title, language);
|
||||
if (newTitle != title)
|
||||
return newTitle;
|
||||
}
|
||||
|
||||
// If we didn't already try English, try it now
|
||||
if (!languages.Contains(Language.English))
|
||||
return NormalizeDiscTitle(title, Language.English);
|
||||
|
||||
// If all fails, then the title didn't need normalization
|
||||
return title;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adjust a disc title so that it will be processed correctly by Redump
|
||||
/// </summary>
|
||||
/// <param name="title">Existing title to potentially reformat</param>
|
||||
/// <param name="language">Language to use for assuming articles</param>
|
||||
/// <returns>The reformatted title</returns>
|
||||
/// <remarks>
|
||||
/// If the language of the title is unknown or if it's multilingual,
|
||||
/// pass in Language.English for standardized coverage.
|
||||
/// </remarks>
|
||||
public static string? NormalizeDiscTitle(string? title, Language? language)
|
||||
{
|
||||
// If we have an invalid title, just return it as-is
|
||||
if (string.IsNullOrEmpty(title))
|
||||
return title;
|
||||
|
||||
// If we have an invalid language, assume Language.English
|
||||
if (language == null)
|
||||
language = Language.English;
|
||||
|
||||
// Get the title split into parts
|
||||
string[] splitTitle = title!.Split(' ').Where(s => !string.IsNullOrEmpty(s)).ToArray();
|
||||
|
||||
// If we only have one part, we can't do anything
|
||||
if (splitTitle.Length <= 1)
|
||||
return title;
|
||||
|
||||
// Determine if we have a definite or indefinite article as the first item
|
||||
string firstItem = splitTitle[0];
|
||||
switch (firstItem.ToLowerInvariant())
|
||||
{
|
||||
// Latin script articles
|
||||
case "'n"
|
||||
when language is Language.Manx:
|
||||
case "a"
|
||||
when language is Language.English
|
||||
|| language is Language.Hungarian
|
||||
|| language is Language.Portuguese
|
||||
|| language is Language.Scots:
|
||||
case "a'"
|
||||
when language is Language.English
|
||||
|| language is Language.Hungarian
|
||||
|| language is Language.Irish
|
||||
|| language is Language.Gaelic: // Scottish Gaelic
|
||||
case "al"
|
||||
when language is Language.Breton:
|
||||
case "am"
|
||||
when language is Language.Gaelic: // Scottish Gaelic
|
||||
case "an"
|
||||
when language is Language.Breton
|
||||
|| language is Language.Cornish
|
||||
|| language is Language.English
|
||||
|| language is Language.Irish
|
||||
|| language is Language.Gaelic: // Scottish Gaelic
|
||||
case "anek"
|
||||
when language is Language.Nepali:
|
||||
case "ar"
|
||||
when language is Language.Breton:
|
||||
case "az"
|
||||
when language is Language.Hungarian:
|
||||
case "ān"
|
||||
when language is Language.Persian:
|
||||
case "as"
|
||||
when language is Language.Portuguese:
|
||||
case "d'"
|
||||
when language is Language.Luxembourgish:
|
||||
case "das"
|
||||
when language is Language.German:
|
||||
case "dat"
|
||||
when language is Language.Luxembourgish:
|
||||
case "de"
|
||||
when language is Language.Dutch:
|
||||
case "déi"
|
||||
when language is Language.Luxembourgish:
|
||||
case "dem"
|
||||
when language is Language.German
|
||||
|| language is Language.Luxembourgish:
|
||||
case "den"
|
||||
when language is Language.Dutch
|
||||
|| language is Language.German
|
||||
|| language is Language.Luxembourgish:
|
||||
case "der"
|
||||
when language is Language.Dutch
|
||||
|| language is Language.German
|
||||
|| language is Language.Luxembourgish:
|
||||
case "des"
|
||||
when language is Language.Dutch
|
||||
|| language is Language.French
|
||||
|| language is Language.German:
|
||||
case "die"
|
||||
when language is Language.Afrikaans
|
||||
|| language is Language.German:
|
||||
case "du"
|
||||
when language is Language.French:
|
||||
case "e"
|
||||
when language is Language.Papiamento:
|
||||
case "een"
|
||||
when language is Language.Dutch:
|
||||
case "egy"
|
||||
when language is Language.Hungarian:
|
||||
case "ei"
|
||||
when language is Language.Norwegian:
|
||||
case "ein"
|
||||
when language is Language.German
|
||||
|| language is Language.Norwegian:
|
||||
case "eine"
|
||||
when language is Language.German:
|
||||
case "einem"
|
||||
when language is Language.German:
|
||||
case "einen"
|
||||
when language is Language.German:
|
||||
case "einer"
|
||||
when language is Language.German:
|
||||
case "eines"
|
||||
when language is Language.German:
|
||||
case "eit"
|
||||
when language is Language.Norwegian:
|
||||
case "ek"
|
||||
when language is Language.Nepali:
|
||||
case "el"
|
||||
when language is Language.Arabic
|
||||
|| language is Language.Catalan
|
||||
|| language is Language.Spanish:
|
||||
case "els"
|
||||
when language is Language.Catalan:
|
||||
case "en"
|
||||
when language is Language.Danish
|
||||
|| language is Language.Luxembourgish
|
||||
|| language is Language.Norwegian
|
||||
|| language is Language.Swedish:
|
||||
case "eng"
|
||||
when language is Language.Luxembourgish:
|
||||
case "engem"
|
||||
when language is Language.Luxembourgish:
|
||||
case "enger"
|
||||
when language is Language.Luxembourgish:
|
||||
case "es"
|
||||
when language is Language.Catalan:
|
||||
case "et"
|
||||
when language is Language.Danish
|
||||
|| language is Language.Norwegian:
|
||||
case "ett"
|
||||
when language is Language.Swedish:
|
||||
case "euta"
|
||||
when language is Language.Nepali:
|
||||
case "euti"
|
||||
when language is Language.Nepali:
|
||||
case "gli"
|
||||
when language is Language.Italian:
|
||||
case "he"
|
||||
when language is Language.Hawaiian
|
||||
|| language is Language.Maori:
|
||||
case "het"
|
||||
when language is Language.Dutch:
|
||||
case "i"
|
||||
when language is Language.Italian
|
||||
|| language is Language.Khasi:
|
||||
case "il"
|
||||
when language is Language.Italian:
|
||||
case "in"
|
||||
when language is Language.Persian:
|
||||
case "ka"
|
||||
when language is Language.Hawaiian
|
||||
|| language is Language.Khasi:
|
||||
case "ke"
|
||||
when language is Language.Hawaiian:
|
||||
case "ki"
|
||||
when language is Language.Khasi:
|
||||
case "kunai"
|
||||
when language is Language.Nepali:
|
||||
case "l'"
|
||||
when language is Language.Catalan
|
||||
|| language is Language.French
|
||||
|| language is Language.Italian:
|
||||
case "la"
|
||||
when language is Language.Catalan
|
||||
|| language is Language.Esperanto
|
||||
|| language is Language.French
|
||||
|| language is Language.Italian
|
||||
|| language is Language.Spanish:
|
||||
case "las"
|
||||
when language is Language.Spanish:
|
||||
case "le"
|
||||
when language is Language.French
|
||||
|| language is Language.Interlingua
|
||||
|| language is Language.Italian:
|
||||
case "les"
|
||||
when language is Language.Catalan
|
||||
|| language is Language.French:
|
||||
case "lo"
|
||||
when language is Language.Catalan
|
||||
|| language is Language.Italian
|
||||
|| language is Language.Spanish:
|
||||
case "los"
|
||||
when language is Language.Catalan
|
||||
|| language is Language.Spanish:
|
||||
case "na"
|
||||
when language is Language.Irish
|
||||
|| language is Language.Gaelic: // Scottish Gaelic
|
||||
case "nam"
|
||||
when language is Language.Gaelic: // Scottish Gaelic
|
||||
case "nan"
|
||||
when language is Language.Gaelic: // Scottish Gaelic
|
||||
case "nā"
|
||||
when language is Language.Hawaiian:
|
||||
case "ngā"
|
||||
when language is Language.Maori:
|
||||
case "niște"
|
||||
when language is Language.Romanian:
|
||||
case "ny"
|
||||
when language is Language.Manx:
|
||||
case "o"
|
||||
when language is Language.Portuguese
|
||||
|| language is Language.Romanian:
|
||||
case "os"
|
||||
when language is Language.Portuguese:
|
||||
case "sa"
|
||||
when language is Language.Catalan:
|
||||
case "sang"
|
||||
when language is Language.Malay:
|
||||
case "se"
|
||||
when language is Language.Finnish:
|
||||
case "ses"
|
||||
when language is Language.Catalan:
|
||||
case "si"
|
||||
when language is Language.Malay:
|
||||
case "te"
|
||||
when language is Language.Maori:
|
||||
case "the"
|
||||
when language is Language.English
|
||||
|| language is Language.Scots:
|
||||
case "u"
|
||||
when language is Language.Khasi:
|
||||
case "ul"
|
||||
when language is Language.Breton:
|
||||
case "um"
|
||||
when language is Language.Portuguese:
|
||||
case "uma"
|
||||
when language is Language.Portuguese:
|
||||
case "umas"
|
||||
when language is Language.Portuguese:
|
||||
case "un"
|
||||
when language is Language.Breton
|
||||
|| language is Language.Catalan
|
||||
|| language is Language.French
|
||||
|| language is Language.Interlingua
|
||||
|| language is Language.Italian
|
||||
|| language is Language.Papiamento
|
||||
|| language is Language.Romanian
|
||||
|| language is Language.Spanish:
|
||||
case "un'"
|
||||
when language is Language.Italian:
|
||||
case "una"
|
||||
when language is Language.Catalan
|
||||
|| language is Language.Italian:
|
||||
case "unas"
|
||||
when language is Language.Spanish:
|
||||
case "une"
|
||||
when language is Language.French:
|
||||
case "uno"
|
||||
when language is Language.Italian:
|
||||
case "unos"
|
||||
when language is Language.Spanish:
|
||||
case "uns"
|
||||
when language is Language.Catalan
|
||||
|| language is Language.Portuguese:
|
||||
case "unei"
|
||||
when language is Language.Romanian:
|
||||
case "unes"
|
||||
when language is Language.Catalan:
|
||||
case "unor"
|
||||
when language is Language.Romanian:
|
||||
case "unui"
|
||||
when language is Language.Romanian:
|
||||
case "ur"
|
||||
when language is Language.Breton:
|
||||
case "y"
|
||||
when language is Language.Manx
|
||||
|| language is Language.Welsh:
|
||||
case "ye"
|
||||
when language is Language.Persian:
|
||||
case "yek"
|
||||
when language is Language.Persian:
|
||||
case "yn"
|
||||
when language is Language.Manx:
|
||||
case "yr"
|
||||
when language is Language.Welsh:
|
||||
|
||||
// Non-latin script articles
|
||||
case "ο"
|
||||
when language is Language.Greek:
|
||||
case "η"
|
||||
when language is Language.Greek:
|
||||
case "το"
|
||||
when language is Language.Greek:
|
||||
case "οι"
|
||||
when language is Language.Greek:
|
||||
case "τα"
|
||||
when language is Language.Greek:
|
||||
case "ένας"
|
||||
when language is Language.Greek:
|
||||
case "μια"
|
||||
when language is Language.Greek:
|
||||
case "ένα"
|
||||
when language is Language.Greek:
|
||||
case "еден"
|
||||
when language is Language.Macedonian:
|
||||
case "една"
|
||||
when language is Language.Macedonian:
|
||||
case "едно"
|
||||
when language is Language.Macedonian:
|
||||
case "едни"
|
||||
when language is Language.Macedonian:
|
||||
case "एउटा"
|
||||
when language is Language.Nepali:
|
||||
case "एउटी"
|
||||
when language is Language.Nepali:
|
||||
case "एक"
|
||||
when language is Language.Nepali:
|
||||
case "अनेक"
|
||||
when language is Language.Nepali:
|
||||
case "कुनै"
|
||||
when language is Language.Nepali:
|
||||
case "דער"
|
||||
when language is Language.Yiddish:
|
||||
case "די"
|
||||
when language is Language.Yiddish:
|
||||
case "דאָס"
|
||||
when language is Language.Yiddish:
|
||||
case "דעם"
|
||||
when language is Language.Yiddish:
|
||||
case "אַ"
|
||||
when language is Language.Yiddish:
|
||||
case "אַן"
|
||||
when language is Language.Yiddish:
|
||||
|
||||
break;
|
||||
|
||||
// Otherwise, just return it as-is
|
||||
default:
|
||||
return title;
|
||||
}
|
||||
|
||||
// Insert the first item if we have a `:` or `-`
|
||||
bool itemInserted = false;
|
||||
var newTitleBuilder = new StringBuilder();
|
||||
for (int i = 1; i < splitTitle.Length; i++)
|
||||
{
|
||||
string segment = splitTitle[i];
|
||||
if (!itemInserted && segment == ":")
|
||||
{
|
||||
itemInserted = true;
|
||||
newTitleBuilder.Append($", {firstItem} :");
|
||||
}
|
||||
else if (!itemInserted && segment == "-")
|
||||
{
|
||||
itemInserted = true;
|
||||
newTitleBuilder.Append($", {firstItem} -");
|
||||
}
|
||||
else if (!itemInserted && segment.EndsWith(":"))
|
||||
{
|
||||
itemInserted = true;
|
||||
newTitleBuilder.Append($" {segment.Substring(0, segment.Length - 1)}, {firstItem}:");
|
||||
}
|
||||
else if (!itemInserted && segment.EndsWith("-"))
|
||||
{
|
||||
itemInserted = true;
|
||||
newTitleBuilder.Append($" {segment.Substring(0, segment.Length - 1)}, {firstItem}-");
|
||||
}
|
||||
else
|
||||
{
|
||||
newTitleBuilder.Append($" {segment}");
|
||||
}
|
||||
}
|
||||
|
||||
// If we didn't insert the item yet, add it to the end
|
||||
string newTitle = newTitleBuilder.ToString().Trim();
|
||||
if (!itemInserted)
|
||||
newTitle = $"{newTitle}, {firstItem}";
|
||||
|
||||
return newTitle;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Normalize a split set of paths
|
||||
/// </summary>
|
||||
/// <param name="path">Path value to normalize</param>
|
||||
public static string NormalizeOutputPaths(string? path, bool getFullPath)
|
||||
{
|
||||
// The easy way
|
||||
try
|
||||
{
|
||||
// If we have an invalid path
|
||||
if (string.IsNullOrEmpty(path))
|
||||
return string.Empty;
|
||||
|
||||
// Remove quotes and angle brackets from path
|
||||
path = path!.Replace("\"", string.Empty);
|
||||
path = path!.Replace("<", string.Empty);
|
||||
path = path!.Replace(">", string.Empty);
|
||||
|
||||
// Try getting the combined path and returning that directly
|
||||
string fullPath = getFullPath ? Path.GetFullPath(path) : path;
|
||||
var fullDirectory = Path.GetDirectoryName(fullPath);
|
||||
string fullFile = Path.GetFileName(fullPath);
|
||||
|
||||
// Remove invalid path characters
|
||||
if (fullDirectory != null)
|
||||
{
|
||||
foreach (char c in Path.GetInvalidPathChars())
|
||||
fullDirectory = fullDirectory.Replace(c, '_');
|
||||
}
|
||||
|
||||
// Remove invalid filename characters
|
||||
foreach (char c in Path.GetInvalidFileNameChars())
|
||||
fullFile = fullFile.Replace(c, '_');
|
||||
|
||||
if (string.IsNullOrEmpty(fullDirectory))
|
||||
return fullFile;
|
||||
else
|
||||
return Path.Combine(fullDirectory, fullFile);
|
||||
}
|
||||
catch { }
|
||||
|
||||
return path ?? string.Empty;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -417,7 +417,7 @@ namespace MPF.Frontend
|
||||
if (labels == null || labels.Count == 0)
|
||||
{
|
||||
// Ignore common volume labels
|
||||
if (InfoTool.GetRedumpSystemFromVolumeLabel(driveLabel) != null)
|
||||
if (FrontendTool.GetRedumpSystemFromVolumeLabel(driveLabel) != null)
|
||||
return null;
|
||||
|
||||
return driveLabel;
|
||||
@@ -428,7 +428,7 @@ namespace MPF.Frontend
|
||||
if (labels.Count == 1 && (firstLabel == driveLabel || driveLabel == null))
|
||||
{
|
||||
// Ignore common volume labels
|
||||
if (InfoTool.GetRedumpSystemFromVolumeLabel(firstLabel) != null)
|
||||
if (FrontendTool.GetRedumpSystemFromVolumeLabel(firstLabel) != null)
|
||||
return null;
|
||||
|
||||
return firstLabel;
|
||||
@@ -438,14 +438,14 @@ namespace MPF.Frontend
|
||||
List<string> volLabels = [];
|
||||
|
||||
// Begin formatted output with the label from Windows, if it is unique and not a common volume label
|
||||
if (driveLabel != null && !labels.TryGetValue(driveLabel, out List<string>? value) && InfoTool.GetRedumpSystemFromVolumeLabel(driveLabel) == null)
|
||||
if (driveLabel != null && !labels.TryGetValue(driveLabel, out List<string>? value) && FrontendTool.GetRedumpSystemFromVolumeLabel(driveLabel) == null)
|
||||
volLabels.Add(driveLabel);
|
||||
|
||||
// Add remaining labels with their corresponding filesystems
|
||||
foreach (KeyValuePair<string, List<string>> label in labels)
|
||||
{
|
||||
// Ignore common volume labels
|
||||
if (InfoTool.GetRedumpSystemFromVolumeLabel(label.Key) == null)
|
||||
if (FrontendTool.GetRedumpSystemFromVolumeLabel(label.Key) == null)
|
||||
volLabels.Add($"{label.Key} ({string.Join(", ", [.. label.Value])})");
|
||||
}
|
||||
|
||||
|
||||
@@ -222,7 +222,7 @@ namespace MPF.Frontend.ViewModels
|
||||
if (!SubmissionInfo.CommonDiscInfo.Languages.Any())
|
||||
SubmissionInfo.CommonDiscInfo.Languages = [null];
|
||||
SubmissionInfo.CommonDiscInfo.LanguageSelection = LanguageSelections.Where(ls => ls.IsChecked).Select(ls => ls?.Value).ToArray();
|
||||
SubmissionInfo.CommonDiscInfo.Title = InfoTool.NormalizeDiscTitle(SubmissionInfo.CommonDiscInfo.Title, SubmissionInfo.CommonDiscInfo.Languages);
|
||||
SubmissionInfo.CommonDiscInfo.Title = FrontendTool.NormalizeDiscTitle(SubmissionInfo.CommonDiscInfo.Title, SubmissionInfo.CommonDiscInfo.Languages);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1421,7 +1421,7 @@ namespace MPF.Frontend.ViewModels
|
||||
else if (driveChanged)
|
||||
{
|
||||
var label = GetFormattedVolumeLabel(CurrentDrive) ?? this.CurrentSystem.LongName();
|
||||
string oldPath = InfoTool.NormalizeOutputPaths(this.OutputPath, false);
|
||||
string oldPath = FrontendTool.NormalizeOutputPaths(this.OutputPath, false);
|
||||
string oldFilename = Path.GetFileNameWithoutExtension(oldPath);
|
||||
var directory = Path.GetDirectoryName(oldPath);
|
||||
string filename = $"{label}{extension ?? ".bin"}";
|
||||
@@ -1447,7 +1447,7 @@ namespace MPF.Frontend.ViewModels
|
||||
// Otherwise, reset the extension of the currently set path
|
||||
else
|
||||
{
|
||||
string oldPath = InfoTool.NormalizeOutputPaths(this.OutputPath, false);
|
||||
string oldPath = FrontendTool.NormalizeOutputPaths(this.OutputPath, false);
|
||||
string filename = Path.GetFileNameWithoutExtension(oldPath);
|
||||
var directory = Path.GetDirectoryName(oldPath);
|
||||
filename = $"{filename}{extension ?? ".bin"}";
|
||||
@@ -1479,7 +1479,7 @@ namespace MPF.Frontend.ViewModels
|
||||
return RedumpSystem.IBMPCcompatible;
|
||||
|
||||
// Check volume labels first
|
||||
RedumpSystem? systemFromLabel = InfoTool.GetRedumpSystemFromVolumeLabel(drive.VolumeLabel);
|
||||
RedumpSystem? systemFromLabel = FrontendTool.GetRedumpSystemFromVolumeLabel(drive.VolumeLabel);
|
||||
if (systemFromLabel != null)
|
||||
return systemFromLabel;
|
||||
|
||||
@@ -1815,7 +1815,7 @@ namespace MPF.Frontend.ViewModels
|
||||
// Disable change handling
|
||||
DisableEventHandlers();
|
||||
|
||||
this.OutputPath = InfoTool.NormalizeOutputPaths(_environment.ContextOutputPath, false);
|
||||
this.OutputPath = FrontendTool.NormalizeOutputPaths(_environment.ContextOutputPath, false);
|
||||
|
||||
if (MediaTypes != null)
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using MPF.Core;
|
||||
using MPF.Frontend;
|
||||
using SabreTools.RedumpLib;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
using Xunit;
|
||||
@@ -23,7 +23,7 @@ namespace MPF.Test.Library
|
||||
if (!string.IsNullOrWhiteSpace(expectedPath))
|
||||
expectedPath = Path.GetFullPath(expectedPath);
|
||||
|
||||
string actualPath = InfoTool.NormalizeOutputPaths(outputPath, true);
|
||||
string actualPath = FrontendTool.NormalizeOutputPaths(outputPath, true);
|
||||
Assert.Equal(expectedPath, actualPath);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user