Merge pull request #5 from mnadareski/sweeper

Broad organizational and bug-fix changes
This commit is contained in:
2021-06-21 17:57:43 +01:00
committed by GitHub
13 changed files with 1199 additions and 624 deletions

View File

@@ -1,31 +1,37 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26124.0
# Visual Studio Version 16
VisualStudioVersion = 16.0.31321.278
MinimumVisualStudioVersion = 15.0.26124.0
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RedBookPlayer", "RedBookPlayer\RedBookPlayer.csproj", "{94944959-0352-4ABF-9C5C-19FF33747ECE}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RedBookPlayer", "RedBookPlayer\RedBookPlayer.csproj", "{94944959-0352-4ABF-9C5C-19FF33747ECE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSCore", "cscore\CSCore\CSCore.csproj", "{C97C30F9-30F3-4BA2-9A02-CF8644DEB616}"
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "cscore", "cscore", "{9A371299-4C59-4E46-9C3B-4FE024017491}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aaru.CommonTypes", "Aaru\Aaru.CommonTypes\Aaru.CommonTypes.csproj", "{F2B84194-26EB-4227-B1C5-6602517E85AE}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CSCore", "cscore\CSCore\CSCore.csproj", "{C81E7637-D25A-4545-8E27-4D83D973F4DC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aaru.Decoders", "Aaru\Aaru.Decoders\Aaru.Decoders.csproj", "{0BEB3088-B634-4289-AE17-CDF2D25D00D5}"
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Aaru", "Aaru", "{BAC4D43B-B6B0-495F-A147-1D4761D60134}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aaru.Images", "Aaru\Aaru.Images\Aaru.Images.csproj", "{74032CBC-339B-42F3-AF6F-E96C261F3E6A}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aaru.CommonTypes", "Aaru\Aaru.CommonTypes\Aaru.CommonTypes.csproj", "{F2B84194-26EB-4227-B1C5-6602517E85AE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aaru.Checksums", "Aaru\Aaru.Checksums\Aaru.Checksums.csproj", "{CC48B324-A532-4A45-87A6-6F91F7141E8D}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aaru.Decoders", "Aaru\Aaru.Decoders\Aaru.Decoders.csproj", "{0BEB3088-B634-4289-AE17-CDF2D25D00D5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aaru.Console", "Aaru\Aaru.Console\Aaru.Console.csproj", "{CCAA7AFE-C094-4D82-A66D-630DE8A3F545}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aaru.Helpers", "Aaru\Aaru.Helpers\Aaru.Helpers.csproj", "{F8BDF57B-1571-4CD0-84B3-B422088D359A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aaru.Helpers", "Aaru\Aaru.Helpers\Aaru.Helpers.csproj", "{F8BDF57B-1571-4CD0-84B3-B422088D359A}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aaru.Images", "Aaru\Aaru.Images\Aaru.Images.csproj", "{74032CBC-339B-42F3-AF6F-E96C261F3E6A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aaru.Compression", "Aaru\Aaru.Compression\Aaru.Compression.csproj", "{858398D1-7321-4763-8BAB-56BBFEC74E29}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aaru.Console", "Aaru\Aaru.Console\Aaru.Console.csproj", "{CCAA7AFE-C094-4D82-A66D-630DE8A3F545}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aaru.Filters", "Aaru\Aaru.Filters\Aaru.Filters.csproj", "{D571B8EF-903D-4353-BDD5-B834F9F029EF}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aaru.Checksums", "Aaru\Aaru.Checksums\Aaru.Checksums.csproj", "{CC48B324-A532-4A45-87A6-6F91F7141E8D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CUETools.Codecs", "Aaru\cuetools.net\CUETools.Codecs\CUETools.Codecs.csproj", "{1E8EB4FB-C16D-437F-B54C-0026D32E9230}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aaru.Compression", "Aaru\Aaru.Compression\Aaru.Compression.csproj", "{858398D1-7321-4763-8BAB-56BBFEC74E29}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CUETools.Codecs.Flake", "Aaru\cuetools.net\CUETools.Codecs.Flake\CUETools.Codecs.Flake.csproj", "{6089CEBC-C88F-4A4C-8717-676F7CC427B9}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aaru.Filters", "Aaru\Aaru.Filters\Aaru.Filters.csproj", "{D571B8EF-903D-4353-BDD5-B834F9F029EF}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "cuetools.net", "cuetools.net", "{7B180FCA-A2BB-48C8-AF36-2300C033C476}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CUETools.Codecs", "Aaru\cuetools.net\CUETools.Codecs\CUETools.Codecs.csproj", "{8F4AD79C-D5E5-44C4-9F03-B0DF4EE8BBA0}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CUETools.Codecs.Flake", "Aaru\cuetools.net\CUETools.Codecs.Flake\CUETools.Codecs.Flake.csproj", "{ED8E11B7-786F-4EFF-9E4C-B937B7A2DE89}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -36,9 +42,6 @@ Global
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{94944959-0352-4ABF-9C5C-19FF33747ECE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{94944959-0352-4ABF-9C5C-19FF33747ECE}.Debug|Any CPU.Build.0 = Debug|Any CPU
@@ -52,18 +55,18 @@ Global
{94944959-0352-4ABF-9C5C-19FF33747ECE}.Release|x64.Build.0 = Release|Any CPU
{94944959-0352-4ABF-9C5C-19FF33747ECE}.Release|x86.ActiveCfg = Release|Any CPU
{94944959-0352-4ABF-9C5C-19FF33747ECE}.Release|x86.Build.0 = Release|Any CPU
{C97C30F9-30F3-4BA2-9A02-CF8644DEB616}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C97C30F9-30F3-4BA2-9A02-CF8644DEB616}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C97C30F9-30F3-4BA2-9A02-CF8644DEB616}.Debug|x64.ActiveCfg = Debug|Any CPU
{C97C30F9-30F3-4BA2-9A02-CF8644DEB616}.Debug|x64.Build.0 = Debug|Any CPU
{C97C30F9-30F3-4BA2-9A02-CF8644DEB616}.Debug|x86.ActiveCfg = Debug|Any CPU
{C97C30F9-30F3-4BA2-9A02-CF8644DEB616}.Debug|x86.Build.0 = Debug|Any CPU
{C97C30F9-30F3-4BA2-9A02-CF8644DEB616}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C97C30F9-30F3-4BA2-9A02-CF8644DEB616}.Release|Any CPU.Build.0 = Release|Any CPU
{C97C30F9-30F3-4BA2-9A02-CF8644DEB616}.Release|x64.ActiveCfg = Release|Any CPU
{C97C30F9-30F3-4BA2-9A02-CF8644DEB616}.Release|x64.Build.0 = Release|Any CPU
{C97C30F9-30F3-4BA2-9A02-CF8644DEB616}.Release|x86.ActiveCfg = Release|Any CPU
{C97C30F9-30F3-4BA2-9A02-CF8644DEB616}.Release|x86.Build.0 = Release|Any CPU
{C81E7637-D25A-4545-8E27-4D83D973F4DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C81E7637-D25A-4545-8E27-4D83D973F4DC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C81E7637-D25A-4545-8E27-4D83D973F4DC}.Debug|x64.ActiveCfg = Debug|Any CPU
{C81E7637-D25A-4545-8E27-4D83D973F4DC}.Debug|x64.Build.0 = Debug|Any CPU
{C81E7637-D25A-4545-8E27-4D83D973F4DC}.Debug|x86.ActiveCfg = Debug|Any CPU
{C81E7637-D25A-4545-8E27-4D83D973F4DC}.Debug|x86.Build.0 = Debug|Any CPU
{C81E7637-D25A-4545-8E27-4D83D973F4DC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C81E7637-D25A-4545-8E27-4D83D973F4DC}.Release|Any CPU.Build.0 = Release|Any CPU
{C81E7637-D25A-4545-8E27-4D83D973F4DC}.Release|x64.ActiveCfg = Release|Any CPU
{C81E7637-D25A-4545-8E27-4D83D973F4DC}.Release|x64.Build.0 = Release|Any CPU
{C81E7637-D25A-4545-8E27-4D83D973F4DC}.Release|x86.ActiveCfg = Release|Any CPU
{C81E7637-D25A-4545-8E27-4D83D973F4DC}.Release|x86.Build.0 = Release|Any CPU
{F2B84194-26EB-4227-B1C5-6602517E85AE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F2B84194-26EB-4227-B1C5-6602517E85AE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F2B84194-26EB-4227-B1C5-6602517E85AE}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -88,42 +91,6 @@ Global
{0BEB3088-B634-4289-AE17-CDF2D25D00D5}.Release|x64.Build.0 = Release|Any CPU
{0BEB3088-B634-4289-AE17-CDF2D25D00D5}.Release|x86.ActiveCfg = Release|Any CPU
{0BEB3088-B634-4289-AE17-CDF2D25D00D5}.Release|x86.Build.0 = Release|Any CPU
{74032CBC-339B-42F3-AF6F-E96C261F3E6A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{74032CBC-339B-42F3-AF6F-E96C261F3E6A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{74032CBC-339B-42F3-AF6F-E96C261F3E6A}.Debug|x64.ActiveCfg = Debug|Any CPU
{74032CBC-339B-42F3-AF6F-E96C261F3E6A}.Debug|x64.Build.0 = Debug|Any CPU
{74032CBC-339B-42F3-AF6F-E96C261F3E6A}.Debug|x86.ActiveCfg = Debug|Any CPU
{74032CBC-339B-42F3-AF6F-E96C261F3E6A}.Debug|x86.Build.0 = Debug|Any CPU
{74032CBC-339B-42F3-AF6F-E96C261F3E6A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{74032CBC-339B-42F3-AF6F-E96C261F3E6A}.Release|Any CPU.Build.0 = Release|Any CPU
{74032CBC-339B-42F3-AF6F-E96C261F3E6A}.Release|x64.ActiveCfg = Release|Any CPU
{74032CBC-339B-42F3-AF6F-E96C261F3E6A}.Release|x64.Build.0 = Release|Any CPU
{74032CBC-339B-42F3-AF6F-E96C261F3E6A}.Release|x86.ActiveCfg = Release|Any CPU
{74032CBC-339B-42F3-AF6F-E96C261F3E6A}.Release|x86.Build.0 = Release|Any CPU
{CC48B324-A532-4A45-87A6-6F91F7141E8D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CC48B324-A532-4A45-87A6-6F91F7141E8D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CC48B324-A532-4A45-87A6-6F91F7141E8D}.Debug|x64.ActiveCfg = Debug|Any CPU
{CC48B324-A532-4A45-87A6-6F91F7141E8D}.Debug|x64.Build.0 = Debug|Any CPU
{CC48B324-A532-4A45-87A6-6F91F7141E8D}.Debug|x86.ActiveCfg = Debug|Any CPU
{CC48B324-A532-4A45-87A6-6F91F7141E8D}.Debug|x86.Build.0 = Debug|Any CPU
{CC48B324-A532-4A45-87A6-6F91F7141E8D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CC48B324-A532-4A45-87A6-6F91F7141E8D}.Release|Any CPU.Build.0 = Release|Any CPU
{CC48B324-A532-4A45-87A6-6F91F7141E8D}.Release|x64.ActiveCfg = Release|Any CPU
{CC48B324-A532-4A45-87A6-6F91F7141E8D}.Release|x64.Build.0 = Release|Any CPU
{CC48B324-A532-4A45-87A6-6F91F7141E8D}.Release|x86.ActiveCfg = Release|Any CPU
{CC48B324-A532-4A45-87A6-6F91F7141E8D}.Release|x86.Build.0 = Release|Any CPU
{CCAA7AFE-C094-4D82-A66D-630DE8A3F545}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CCAA7AFE-C094-4D82-A66D-630DE8A3F545}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CCAA7AFE-C094-4D82-A66D-630DE8A3F545}.Debug|x64.ActiveCfg = Debug|Any CPU
{CCAA7AFE-C094-4D82-A66D-630DE8A3F545}.Debug|x64.Build.0 = Debug|Any CPU
{CCAA7AFE-C094-4D82-A66D-630DE8A3F545}.Debug|x86.ActiveCfg = Debug|Any CPU
{CCAA7AFE-C094-4D82-A66D-630DE8A3F545}.Debug|x86.Build.0 = Debug|Any CPU
{CCAA7AFE-C094-4D82-A66D-630DE8A3F545}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CCAA7AFE-C094-4D82-A66D-630DE8A3F545}.Release|Any CPU.Build.0 = Release|Any CPU
{CCAA7AFE-C094-4D82-A66D-630DE8A3F545}.Release|x64.ActiveCfg = Release|Any CPU
{CCAA7AFE-C094-4D82-A66D-630DE8A3F545}.Release|x64.Build.0 = Release|Any CPU
{CCAA7AFE-C094-4D82-A66D-630DE8A3F545}.Release|x86.ActiveCfg = Release|Any CPU
{CCAA7AFE-C094-4D82-A66D-630DE8A3F545}.Release|x86.Build.0 = Release|Any CPU
{F8BDF57B-1571-4CD0-84B3-B422088D359A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F8BDF57B-1571-4CD0-84B3-B422088D359A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F8BDF57B-1571-4CD0-84B3-B422088D359A}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -136,6 +103,42 @@ Global
{F8BDF57B-1571-4CD0-84B3-B422088D359A}.Release|x64.Build.0 = Release|Any CPU
{F8BDF57B-1571-4CD0-84B3-B422088D359A}.Release|x86.ActiveCfg = Release|Any CPU
{F8BDF57B-1571-4CD0-84B3-B422088D359A}.Release|x86.Build.0 = Release|Any CPU
{74032CBC-339B-42F3-AF6F-E96C261F3E6A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{74032CBC-339B-42F3-AF6F-E96C261F3E6A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{74032CBC-339B-42F3-AF6F-E96C261F3E6A}.Debug|x64.ActiveCfg = Debug|Any CPU
{74032CBC-339B-42F3-AF6F-E96C261F3E6A}.Debug|x64.Build.0 = Debug|Any CPU
{74032CBC-339B-42F3-AF6F-E96C261F3E6A}.Debug|x86.ActiveCfg = Debug|Any CPU
{74032CBC-339B-42F3-AF6F-E96C261F3E6A}.Debug|x86.Build.0 = Debug|Any CPU
{74032CBC-339B-42F3-AF6F-E96C261F3E6A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{74032CBC-339B-42F3-AF6F-E96C261F3E6A}.Release|Any CPU.Build.0 = Release|Any CPU
{74032CBC-339B-42F3-AF6F-E96C261F3E6A}.Release|x64.ActiveCfg = Release|Any CPU
{74032CBC-339B-42F3-AF6F-E96C261F3E6A}.Release|x64.Build.0 = Release|Any CPU
{74032CBC-339B-42F3-AF6F-E96C261F3E6A}.Release|x86.ActiveCfg = Release|Any CPU
{74032CBC-339B-42F3-AF6F-E96C261F3E6A}.Release|x86.Build.0 = Release|Any CPU
{CCAA7AFE-C094-4D82-A66D-630DE8A3F545}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CCAA7AFE-C094-4D82-A66D-630DE8A3F545}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CCAA7AFE-C094-4D82-A66D-630DE8A3F545}.Debug|x64.ActiveCfg = Debug|Any CPU
{CCAA7AFE-C094-4D82-A66D-630DE8A3F545}.Debug|x64.Build.0 = Debug|Any CPU
{CCAA7AFE-C094-4D82-A66D-630DE8A3F545}.Debug|x86.ActiveCfg = Debug|Any CPU
{CCAA7AFE-C094-4D82-A66D-630DE8A3F545}.Debug|x86.Build.0 = Debug|Any CPU
{CCAA7AFE-C094-4D82-A66D-630DE8A3F545}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CCAA7AFE-C094-4D82-A66D-630DE8A3F545}.Release|Any CPU.Build.0 = Release|Any CPU
{CCAA7AFE-C094-4D82-A66D-630DE8A3F545}.Release|x64.ActiveCfg = Release|Any CPU
{CCAA7AFE-C094-4D82-A66D-630DE8A3F545}.Release|x64.Build.0 = Release|Any CPU
{CCAA7AFE-C094-4D82-A66D-630DE8A3F545}.Release|x86.ActiveCfg = Release|Any CPU
{CCAA7AFE-C094-4D82-A66D-630DE8A3F545}.Release|x86.Build.0 = Release|Any CPU
{CC48B324-A532-4A45-87A6-6F91F7141E8D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CC48B324-A532-4A45-87A6-6F91F7141E8D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CC48B324-A532-4A45-87A6-6F91F7141E8D}.Debug|x64.ActiveCfg = Debug|Any CPU
{CC48B324-A532-4A45-87A6-6F91F7141E8D}.Debug|x64.Build.0 = Debug|Any CPU
{CC48B324-A532-4A45-87A6-6F91F7141E8D}.Debug|x86.ActiveCfg = Debug|Any CPU
{CC48B324-A532-4A45-87A6-6F91F7141E8D}.Debug|x86.Build.0 = Debug|Any CPU
{CC48B324-A532-4A45-87A6-6F91F7141E8D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CC48B324-A532-4A45-87A6-6F91F7141E8D}.Release|Any CPU.Build.0 = Release|Any CPU
{CC48B324-A532-4A45-87A6-6F91F7141E8D}.Release|x64.ActiveCfg = Release|Any CPU
{CC48B324-A532-4A45-87A6-6F91F7141E8D}.Release|x64.Build.0 = Release|Any CPU
{CC48B324-A532-4A45-87A6-6F91F7141E8D}.Release|x86.ActiveCfg = Release|Any CPU
{CC48B324-A532-4A45-87A6-6F91F7141E8D}.Release|x86.Build.0 = Release|Any CPU
{858398D1-7321-4763-8BAB-56BBFEC74E29}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{858398D1-7321-4763-8BAB-56BBFEC74E29}.Debug|Any CPU.Build.0 = Debug|Any CPU
{858398D1-7321-4763-8BAB-56BBFEC74E29}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -160,29 +163,49 @@ Global
{D571B8EF-903D-4353-BDD5-B834F9F029EF}.Release|x64.Build.0 = Release|Any CPU
{D571B8EF-903D-4353-BDD5-B834F9F029EF}.Release|x86.ActiveCfg = Release|Any CPU
{D571B8EF-903D-4353-BDD5-B834F9F029EF}.Release|x86.Build.0 = Release|Any CPU
{1E8EB4FB-C16D-437F-B54C-0026D32E9230}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1E8EB4FB-C16D-437F-B54C-0026D32E9230}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1E8EB4FB-C16D-437F-B54C-0026D32E9230}.Debug|x64.ActiveCfg = Debug|Any CPU
{1E8EB4FB-C16D-437F-B54C-0026D32E9230}.Debug|x64.Build.0 = Debug|Any CPU
{1E8EB4FB-C16D-437F-B54C-0026D32E9230}.Debug|x86.ActiveCfg = Debug|Any CPU
{1E8EB4FB-C16D-437F-B54C-0026D32E9230}.Debug|x86.Build.0 = Debug|Any CPU
{1E8EB4FB-C16D-437F-B54C-0026D32E9230}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1E8EB4FB-C16D-437F-B54C-0026D32E9230}.Release|Any CPU.Build.0 = Release|Any CPU
{1E8EB4FB-C16D-437F-B54C-0026D32E9230}.Release|x64.ActiveCfg = Release|Any CPU
{1E8EB4FB-C16D-437F-B54C-0026D32E9230}.Release|x64.Build.0 = Release|Any CPU
{1E8EB4FB-C16D-437F-B54C-0026D32E9230}.Release|x86.ActiveCfg = Release|Any CPU
{1E8EB4FB-C16D-437F-B54C-0026D32E9230}.Release|x86.Build.0 = Release|Any CPU
{6089CEBC-C88F-4A4C-8717-676F7CC427B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6089CEBC-C88F-4A4C-8717-676F7CC427B9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6089CEBC-C88F-4A4C-8717-676F7CC427B9}.Debug|x64.ActiveCfg = Debug|Any CPU
{6089CEBC-C88F-4A4C-8717-676F7CC427B9}.Debug|x64.Build.0 = Debug|Any CPU
{6089CEBC-C88F-4A4C-8717-676F7CC427B9}.Debug|x86.ActiveCfg = Debug|Any CPU
{6089CEBC-C88F-4A4C-8717-676F7CC427B9}.Debug|x86.Build.0 = Debug|Any CPU
{6089CEBC-C88F-4A4C-8717-676F7CC427B9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6089CEBC-C88F-4A4C-8717-676F7CC427B9}.Release|Any CPU.Build.0 = Release|Any CPU
{6089CEBC-C88F-4A4C-8717-676F7CC427B9}.Release|x64.ActiveCfg = Release|Any CPU
{6089CEBC-C88F-4A4C-8717-676F7CC427B9}.Release|x64.Build.0 = Release|Any CPU
{6089CEBC-C88F-4A4C-8717-676F7CC427B9}.Release|x86.ActiveCfg = Release|Any CPU
{6089CEBC-C88F-4A4C-8717-676F7CC427B9}.Release|x86.Build.0 = Release|Any CPU
{8F4AD79C-D5E5-44C4-9F03-B0DF4EE8BBA0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8F4AD79C-D5E5-44C4-9F03-B0DF4EE8BBA0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8F4AD79C-D5E5-44C4-9F03-B0DF4EE8BBA0}.Debug|x64.ActiveCfg = Debug|Any CPU
{8F4AD79C-D5E5-44C4-9F03-B0DF4EE8BBA0}.Debug|x64.Build.0 = Debug|Any CPU
{8F4AD79C-D5E5-44C4-9F03-B0DF4EE8BBA0}.Debug|x86.ActiveCfg = Debug|Any CPU
{8F4AD79C-D5E5-44C4-9F03-B0DF4EE8BBA0}.Debug|x86.Build.0 = Debug|Any CPU
{8F4AD79C-D5E5-44C4-9F03-B0DF4EE8BBA0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8F4AD79C-D5E5-44C4-9F03-B0DF4EE8BBA0}.Release|Any CPU.Build.0 = Release|Any CPU
{8F4AD79C-D5E5-44C4-9F03-B0DF4EE8BBA0}.Release|x64.ActiveCfg = Release|Any CPU
{8F4AD79C-D5E5-44C4-9F03-B0DF4EE8BBA0}.Release|x64.Build.0 = Release|Any CPU
{8F4AD79C-D5E5-44C4-9F03-B0DF4EE8BBA0}.Release|x86.ActiveCfg = Release|Any CPU
{8F4AD79C-D5E5-44C4-9F03-B0DF4EE8BBA0}.Release|x86.Build.0 = Release|Any CPU
{ED8E11B7-786F-4EFF-9E4C-B937B7A2DE89}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ED8E11B7-786F-4EFF-9E4C-B937B7A2DE89}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ED8E11B7-786F-4EFF-9E4C-B937B7A2DE89}.Debug|x64.ActiveCfg = Debug|Any CPU
{ED8E11B7-786F-4EFF-9E4C-B937B7A2DE89}.Debug|x64.Build.0 = Debug|Any CPU
{ED8E11B7-786F-4EFF-9E4C-B937B7A2DE89}.Debug|x86.ActiveCfg = Debug|Any CPU
{ED8E11B7-786F-4EFF-9E4C-B937B7A2DE89}.Debug|x86.Build.0 = Debug|Any CPU
{ED8E11B7-786F-4EFF-9E4C-B937B7A2DE89}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ED8E11B7-786F-4EFF-9E4C-B937B7A2DE89}.Release|Any CPU.Build.0 = Release|Any CPU
{ED8E11B7-786F-4EFF-9E4C-B937B7A2DE89}.Release|x64.ActiveCfg = Release|Any CPU
{ED8E11B7-786F-4EFF-9E4C-B937B7A2DE89}.Release|x64.Build.0 = Release|Any CPU
{ED8E11B7-786F-4EFF-9E4C-B937B7A2DE89}.Release|x86.ActiveCfg = Release|Any CPU
{ED8E11B7-786F-4EFF-9E4C-B937B7A2DE89}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{C81E7637-D25A-4545-8E27-4D83D973F4DC} = {9A371299-4C59-4E46-9C3B-4FE024017491}
{F2B84194-26EB-4227-B1C5-6602517E85AE} = {BAC4D43B-B6B0-495F-A147-1D4761D60134}
{0BEB3088-B634-4289-AE17-CDF2D25D00D5} = {BAC4D43B-B6B0-495F-A147-1D4761D60134}
{F8BDF57B-1571-4CD0-84B3-B422088D359A} = {BAC4D43B-B6B0-495F-A147-1D4761D60134}
{74032CBC-339B-42F3-AF6F-E96C261F3E6A} = {BAC4D43B-B6B0-495F-A147-1D4761D60134}
{CCAA7AFE-C094-4D82-A66D-630DE8A3F545} = {BAC4D43B-B6B0-495F-A147-1D4761D60134}
{CC48B324-A532-4A45-87A6-6F91F7141E8D} = {BAC4D43B-B6B0-495F-A147-1D4761D60134}
{858398D1-7321-4763-8BAB-56BBFEC74E29} = {BAC4D43B-B6B0-495F-A147-1D4761D60134}
{D571B8EF-903D-4353-BDD5-B834F9F029EF} = {BAC4D43B-B6B0-495F-A147-1D4761D60134}
{7B180FCA-A2BB-48C8-AF36-2300C033C476} = {BAC4D43B-B6B0-495F-A147-1D4761D60134}
{8F4AD79C-D5E5-44C4-9F03-B0DF4EE8BBA0} = {7B180FCA-A2BB-48C8-AF36-2300C033C476}
{ED8E11B7-786F-4EFF-9E4C-B937B7A2DE89} = {7B180FCA-A2BB-48C8-AF36-2300C033C476}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {6BBF5459-C634-4145-961C-04EBE90FE66B}
EndGlobalSection
EndGlobal

View File

@@ -3,14 +3,17 @@ using NWaves.Filters.BiQuad;
namespace RedBookPlayer
{
/// <summary>
/// Filter for applying de-emphasis to audio
/// </summary>
public class DeEmphasisFilter : BiQuadFilter
{
static readonly double B0;
static readonly double B1;
static readonly double B2;
static readonly double A0;
static readonly double A1;
static readonly double A2;
private static readonly double B0;
private static readonly double B1;
private static readonly double B2;
private static readonly double A0;
private static readonly double A1;
private static readonly double A2;
static DeEmphasisFilter()
{

View File

@@ -4,12 +4,15 @@ using System.Threading;
namespace RedBookPlayer
{
/// <summary>
/// Recurring timer wrapper with a high degree of accuracy
/// </summary>
public class HiResTimer
{
static readonly float tickFrequency = 1000f / Stopwatch.Frequency;
volatile float interval;
volatile bool isRunning;
volatile float _interval;
volatile bool _isRunning;
public HiResTimer() : this(1f) {}
@@ -19,24 +22,25 @@ namespace RedBookPlayer
float.IsNaN(interval))
throw new ArgumentOutOfRangeException(nameof(interval));
this.interval = interval;
_interval = interval;
}
public float Interval
{
get => interval;
get => _interval;
set
{
if(value < 0f ||
float.IsNaN(value))
throw new ArgumentOutOfRangeException(nameof(value));
interval = value;
_interval = value;
}
}
public bool Enabled
{
get => _isRunning;
set
{
if(value)
@@ -44,23 +48,22 @@ namespace RedBookPlayer
else
Stop();
}
get => isRunning;
}
public event EventHandler<HiResTimerElapsedEventArgs> Elapsed;
public void Start()
{
if(isRunning)
if(_isRunning)
return;
isRunning = true;
_isRunning = true;
var thread = new Thread(ExecuteTimer);
thread.Priority = ThreadPriority.Highest;
thread.Start();
}
public void Stop() => isRunning = false;
public void Stop() => _isRunning = false;
void ExecuteTimer()
{
@@ -69,9 +72,9 @@ namespace RedBookPlayer
var stopwatch = new Stopwatch();
stopwatch.Start();
while(isRunning)
while(_isRunning)
{
nextTrigger += interval;
nextTrigger += _interval;
float elapsed;
while(true)
@@ -91,7 +94,7 @@ namespace RedBookPlayer
else
Thread.Sleep(10);
if(!isRunning)
if(!_isRunning)
return;
}
@@ -110,11 +113,4 @@ namespace RedBookPlayer
static float ElapsedHiRes(Stopwatch stopwatch) => stopwatch.ElapsedTicks * tickFrequency;
}
public class HiResTimerElapsedEventArgs : EventArgs
{
internal HiResTimerElapsedEventArgs(float delay) => Delay = delay;
public float Delay { get; }
}
}

View File

@@ -0,0 +1,11 @@
using System;
namespace RedBookPlayer
{
public class HiResTimerElapsedEventArgs : EventArgs
{
internal HiResTimerElapsedEventArgs(float delay) => Delay = delay;
public float Delay { get; }
}
}

View File

@@ -19,34 +19,37 @@ namespace RedBookPlayer
InitializeComponent();
}
/// <summary>
/// Apply a custom theme to the player
/// </summary>
/// <param name="theme">Path to the theme under the themes directory</param>
public static void ApplyTheme(string theme)
{
if((theme ?? "") == "")
{
// If no theme path is provided, we can ignore
if(string.IsNullOrWhiteSpace(theme))
return;
}
if(theme == "default")
// If the theme name is "default", we assume the internal theme is used
if(theme.Equals("default", StringComparison.CurrentCultureIgnoreCase))
{
Instance.ContentControl.Content = new PlayerView();
}
else
{
string themeDirectory = Directory.GetCurrentDirectory() + "/themes/" + theme;
string xamlPath = themeDirectory + "/view.xaml";
string themeDirectory = $"{Directory.GetCurrentDirectory()}/themes/{theme}";
string xamlPath = $"{themeDirectory}/view.xaml";
if(!File.Exists(xamlPath))
{
Console.WriteLine("Warning: specified theme doesn't exist, reverting to default");
return;
}
try
{
Instance.ContentControl.Content =
new PlayerView(File.ReadAllText(xamlPath).
Replace("Source=\"", $"Source=\"file://{themeDirectory}/"));
string xaml = File.ReadAllText(xamlPath);
xaml = xaml.Replace("Source=\"", $"Source=\"file://{themeDirectory}/");
Instance.ContentControl.Content = new PlayerView(xaml);
}
catch(XmlException ex)
{

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,44 @@
using System;
using CSCore;
using WaveFormat = CSCore.WaveFormat;
namespace RedBookPlayer
{
public class PlayerSource : IWaveSource
{
public delegate int ReadFunction(byte[] buffer, int offset, int count);
readonly ReadFunction _read;
public bool Run = true;
public PlayerSource(ReadFunction read) => _read = read;
public WaveFormat WaveFormat => new WaveFormat();
bool IAudioSource.CanSeek => throw new NotImplementedException();
public long Position
{
get => throw new NotImplementedException();
set => throw new NotImplementedException();
}
public long Length => throw new NotImplementedException();
public int Read(byte[] buffer, int offset, int count)
{
if(Run)
return _read(buffer, offset, count);
Array.Clear(buffer, offset, count);
return count;
}
public void Dispose() {}
public void Start() => Run = true;
public void Stop() => Run = false;
}
}

View File

@@ -4,7 +4,7 @@ using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Timers;
using Aaru.CommonTypes.Interfaces;
using Aaru.CommonTypes.Enums;
using Aaru.DiscImages;
using Aaru.Filters;
using Avalonia;
@@ -14,62 +14,269 @@ using Avalonia.Markup.Xaml;
using Avalonia.Media.Imaging;
using Avalonia.Platform;
using Avalonia.Threading;
using ReactiveUI;
namespace RedBookPlayer
{
public class PlayerView : UserControl
{
/// <summary>
/// Player representing the internal state and loaded image
/// </summary>
public static Player Player = new Player();
TextBlock currentTrack;
Image[] digits;
Timer updateTimer;
/// <summary>
/// Set of images representing the digits for the UI
/// </summary>
/// <remarks>
/// TODO: Does it make sense to have this as an array?
/// </remarks>
private Image[] _digits;
/// <summary>
/// Timer for performing UI updates
/// </summary>
private Timer _updateTimer;
public PlayerView() => InitializeComponent(null);
public PlayerView(string xaml) => InitializeComponent(xaml);
public async void LoadButton_Click(object sender, RoutedEventArgs e)
{
string path = await GetPath();
if(path == null)
{
return;
}
await Task.Run(() =>
{
var image = new AaruFormat();
IFilter filter = new ZZZNoFilter();
filter.Open(path);
image.Open(filter);
Player.Init(image, App.Settings.AutoPlay);
});
await Dispatcher.UIThread.InvokeAsync(() =>
{
MainWindow.Instance.Title = "RedBookPlayer - " + path.Split('/').Last().Split('\\').Last();
});
}
#region Helpers
/// <summary>
/// Generate a path selection dialog box
/// </summary>
/// <returns>User-selected path, if possible</returns>
public async Task<string> GetPath()
{
var dialog = new OpenFileDialog();
dialog.AllowMultiple = false;
var dialog = new OpenFileDialog { AllowMultiple = false };
List<string> knownExtensions = new AaruFormat().KnownExtensions.ToList();
dialog.Filters.Add(new FileDialogFilter
dialog.Filters.Add(new FileDialogFilter()
{
Name = "Aaru Image Format (*" + string.Join(", *", knownExtensions) + ")",
Extensions = knownExtensions.ConvertAll(e => e.Substring(1))
Extensions = knownExtensions.ConvertAll(e => e.TrimStart('.'))
});
return (await dialog.ShowAsync((Window)Parent.Parent))?.FirstOrDefault();
}
/// <summary>
/// Generate the digit string to be interpreted by the UI
/// </summary>
/// <returns>String representing the digits for the player</returns>
private string GenerateDigitString()
{
// If the player isn't initialized, return all '-' characters
if (!Player.Initialized)
return string.Empty.PadLeft(20, '-');
// Otherwise, take the current time into account
ulong sectorTime = Player.CurrentSector;
if (Player.SectionStartSector != 0)
sectorTime -= Player.SectionStartSector;
else
sectorTime += Player.TimeOffset;
int[] numbers = new int[]
{
Player.CurrentTrack + 1,
Player.CurrentIndex,
(int)(sectorTime / (75 * 60)),
(int)(sectorTime / 75 % 60),
(int)(sectorTime % 75),
Player.TotalTracks,
Player.TotalIndexes,
(int)(Player.TotalTime / (75 * 60)),
(int)(Player.TotalTime / 75 % 60),
(int)(Player.TotalTime % 75),
};
return string.Join("", numbers.Select(i => i.ToString().PadLeft(2, '0').Substring(0, 2)));
}
/// <summary>
/// Load the png image for a given character based on the theme
/// </summary>
/// <param name="character">Character to load the image for</param>
/// <returns>Bitmap representing the loaded image</returns>
/// <remarks>
/// TODO: Currently assumes that an image must always exist
/// </remarks>
private Bitmap GetBitmap(char character)
{
if(App.Settings.SelectedTheme == "default")
{
IAssetLoader assets = AvaloniaLocator.Current.GetService<IAssetLoader>();
return new Bitmap(assets.Open(new Uri($"avares://RedBookPlayer/Assets/{character}.png")));
}
else
{
string themeDirectory = $"{Directory.GetCurrentDirectory()}/themes/{App.Settings.SelectedTheme}";
using FileStream stream = File.Open($"{themeDirectory}/{character}.png", FileMode.Open);
return new Bitmap(stream);
}
}
/// <summary>
/// Initialize the displayed digits array
/// </summary>
private void Initialize()
{
_digits = new Image[]
{
this.FindControl<Image>("TrackDigit1"),
this.FindControl<Image>("TrackDigit2"),
this.FindControl<Image>("IndexDigit1"),
this.FindControl<Image>("IndexDigit2"),
this.FindControl<Image>("TimeDigit1"),
this.FindControl<Image>("TimeDigit2"),
this.FindControl<Image>("TimeDigit3"),
this.FindControl<Image>("TimeDigit4"),
this.FindControl<Image>("TimeDigit5"),
this.FindControl<Image>("TimeDigit6"),
this.FindControl<Image>("TotalTracksDigit1"),
this.FindControl<Image>("TotalTracksDigit2"),
this.FindControl<Image>("TotalIndexesDigit1"),
this.FindControl<Image>("TotalIndexesDigit2"),
this.FindControl<Image>("TotalTimeDigit1"),
this.FindControl<Image>("TotalTimeDigit2"),
this.FindControl<Image>("TotalTimeDigit3"),
this.FindControl<Image>("TotalTimeDigit4"),
this.FindControl<Image>("TotalTimeDigit5"),
this.FindControl<Image>("TotalTimeDigit6"),
};
}
/// <summary>
/// Initialize the UI based on the currently selected theme
/// </summary>
/// <param name="xaml">XAML data representing the theme, null for default</param>
private void InitializeComponent(string xaml)
{
DataContext = new PlayerViewModel();
if (xaml != null)
new AvaloniaXamlLoader().Load(xaml, null, this);
else
AvaloniaXamlLoader.Load(this);
Initialize();
_updateTimer = new Timer(1000 / 60);
_updateTimer.Elapsed += (sender, e) =>
{
try
{
UpdateView(sender, e);
}
catch(Exception ex)
{
Console.WriteLine(ex);
}
};
_updateTimer.AutoReset = true;
_updateTimer.Start();
}
/// <summary>
/// Indicates if the image is considered "playable" or not
/// </summary>
/// <param name="image">Aaruformat image file</param>
/// <returns>True if the image is playble, false otherwise</returns>
private bool IsPlayableImage(AaruFormat image)
{
// Invalid images can't be played
if (image == null)
return false;
// Tape images are not supported
if (image.IsTape)
return false;
// Determine based on media type
// TODO: Can we be more granular with sub types?
(string type, string _) = Aaru.CommonTypes.Metadata.MediaType.MediaTypeToString(image.Info.MediaType);
return type switch
{
"Compact Disc" => true,
"GD" => true, // Requires TOC generation
_ => false,
};
}
/// <summary>
/// Update the UI with the most recent information from the Player
/// </summary>
private void UpdateView(object sender, ElapsedEventArgs e)
{
Dispatcher.UIThread.InvokeAsync(() =>
{
string digitString = GenerateDigitString();
for (int i = 0; i < _digits.Length; i++)
{
if (_digits[i] != null)
_digits[i].Source = GetBitmap(digitString[i]);
}
if (Player.Initialized)
{
PlayerViewModel dataContext = (PlayerViewModel)DataContext;
dataContext.HiddenTrack = Player.TimeOffset > 150;
dataContext.ApplyDeEmphasis = Player.ApplyDeEmphasis;
dataContext.TrackHasEmphasis = Player.TrackHasEmphasis;
dataContext.CopyAllowed = Player.CopyAllowed;
dataContext.IsAudioTrack = Player.TrackType == TrackType.Audio;
dataContext.IsDataTrack = Player.TrackType != TrackType.Audio;
}
});
}
#endregion
#region Event Handlers
public async void LoadButton_Click(object sender, RoutedEventArgs e)
{
string path = await GetPath();
if (path == null)
return;
bool result = await Task.Run(() =>
{
var image = new AaruFormat();
var filter = new ZZZNoFilter();
filter.Open(path);
image.Open(filter);
if (IsPlayableImage(image))
{
Player.Init(image, App.Settings.AutoPlay);
return true;
}
else
return false;
});
if (result)
{
await Dispatcher.UIThread.InvokeAsync(() =>
{
MainWindow.Instance.Title = "RedBookPlayer - " + path.Split('/').Last().Split('\\').Last();
});
}
}
public void PlayButton_Click(object sender, RoutedEventArgs e) => Player.Play();
public void PauseButton_Click(object sender, RoutedEventArgs e) => Player.Pause();
@@ -80,208 +287,18 @@ namespace RedBookPlayer
public void PreviousTrackButton_Click(object sender, RoutedEventArgs e) => Player.PreviousTrack();
public void NextIndexButton_Click(object sender, RoutedEventArgs e) =>
Player.NextIndex(App.Settings.IndexButtonChangeTrack);
public void NextIndexButton_Click(object sender, RoutedEventArgs e) => Player.NextIndex(App.Settings.IndexButtonChangeTrack);
public void PreviousIndexButton_Click(object sender, RoutedEventArgs e) =>
Player.PreviousIndex(App.Settings.IndexButtonChangeTrack);
public void PreviousIndexButton_Click(object sender, RoutedEventArgs e) => Player.PreviousIndex(App.Settings.IndexButtonChangeTrack);
public void FastForwardButton_Click(object sender, RoutedEventArgs e) => Player.FastForward();
public void RewindButton_Click(object sender, RoutedEventArgs e) => Player.Rewind();
public void EnableDeEmphasisButton_Click(object sender, RoutedEventArgs e) => Player.EnableDeEmphasis();
public void EnableDeEmphasisButton_Click(object sender, RoutedEventArgs e) => Player.ToggleDeEmphasis(true);
public void DisableDeEmphasisButton_Click(object sender, RoutedEventArgs e) => Player.DisableDeEmphasis();
public void DisableDeEmphasisButton_Click(object sender, RoutedEventArgs e) => Player.ToggleDeEmphasis(false);
void UpdateView(object sender, ElapsedEventArgs e)
{
if(Player.Initialized)
{
ulong sectorTime = Player.CurrentSector;
if(Player.SectionStartSector != 0)
{
sectorTime -= Player.SectionStartSector;
}
else
{
sectorTime += Player.TimeOffset;
}
int[] numbers =
{
Player.CurrentTrack + 1, Player.CurrentIndex, (int)(sectorTime / (75 * 60)),
(int)(sectorTime / 75 % 60), (int)(sectorTime % 75), Player.TotalTracks, Player.TotalIndexes,
(int)(Player.TotalTime / (75 * 60)), (int)(Player.TotalTime / 75 % 60), (int)(Player.TotalTime % 75)
};
string digitString = string.Join("", numbers.Select(i => i.ToString().PadLeft(2, '0').Substring(0, 2)));
Dispatcher.UIThread.InvokeAsync(() =>
{
for(int i = 0; i < digits.Length; i++)
{
if(digits[i] != null)
{
digits[i].Source = GetBitmap(digitString[i]);
}
}
var dataContext = (PlayerViewModel)DataContext;
dataContext.HiddenTrack = Player.TimeOffset > 150;
dataContext.ApplyDeEmphasis = Player.ApplyDeEmphasis;
dataContext.TrackHasEmphasis = Player.TrackHasEmphasis;
dataContext.CopyAllowed = Player.CopyAllowed;
dataContext.IsAudioTrack = Player.TrackType_ == Player.TrackType.Audio;
dataContext.IsDataTrack = Player.TrackType_ == Player.TrackType.Data;
});
}
else
{
Dispatcher.UIThread.InvokeAsync(() =>
{
foreach(Image digit in digits)
{
if(digit != null)
{
digit.Source = GetBitmap('-');
}
}
});
}
}
Bitmap GetBitmap(char character)
{
if(App.Settings.SelectedTheme == "default")
{
IAssetLoader assets = AvaloniaLocator.Current.GetService<IAssetLoader>();
return new Bitmap(assets.Open(new Uri($"avares://RedBookPlayer/Assets/{character}.png")));
}
string themeDirectory = Directory.GetCurrentDirectory() + "/themes/" + App.Settings.SelectedTheme;
Bitmap bitmap;
using(FileStream stream = File.Open(themeDirectory + $"/{character}.png", FileMode.Open))
{
bitmap = new Bitmap(stream);
}
return bitmap;
}
public void Initialize()
{
digits = new Image[20];
digits[0] = this.FindControl<Image>("TrackDigit1");
digits[1] = this.FindControl<Image>("TrackDigit2");
digits[2] = this.FindControl<Image>("IndexDigit1");
digits[3] = this.FindControl<Image>("IndexDigit2");
digits[4] = this.FindControl<Image>("TimeDigit1");
digits[5] = this.FindControl<Image>("TimeDigit2");
digits[6] = this.FindControl<Image>("TimeDigit3");
digits[7] = this.FindControl<Image>("TimeDigit4");
digits[8] = this.FindControl<Image>("TimeDigit5");
digits[9] = this.FindControl<Image>("TimeDigit6");
digits[10] = this.FindControl<Image>("TotalTracksDigit1");
digits[11] = this.FindControl<Image>("TotalTracksDigit2");
digits[12] = this.FindControl<Image>("TotalIndexesDigit1");
digits[13] = this.FindControl<Image>("TotalIndexesDigit2");
digits[14] = this.FindControl<Image>("TotalTimeDigit1");
digits[15] = this.FindControl<Image>("TotalTimeDigit2");
digits[16] = this.FindControl<Image>("TotalTimeDigit3");
digits[17] = this.FindControl<Image>("TotalTimeDigit4");
digits[18] = this.FindControl<Image>("TotalTimeDigit5");
digits[19] = this.FindControl<Image>("TotalTimeDigit6");
currentTrack = this.FindControl<TextBlock>("CurrentTrack");
}
void InitializeComponent(string xaml)
{
DataContext = new PlayerViewModel();
if(xaml != null)
{
new AvaloniaXamlLoader().Load(xaml, null, this);
}
else
{
AvaloniaXamlLoader.Load(this);
}
Initialize();
updateTimer = new Timer(1000 / 60);
updateTimer.Elapsed += (sender, e) =>
{
try
{
UpdateView(sender, e);
}
catch(Exception ex)
{
Console.WriteLine(ex);
}
};
updateTimer.AutoReset = true;
updateTimer.Start();
}
}
public class PlayerViewModel : ReactiveObject
{
bool applyDeEmphasis;
bool copyAllowed;
bool hiddenTrack;
bool isAudioTrack;
bool isDataTrack;
bool trackHasEmphasis;
public bool ApplyDeEmphasis
{
get => applyDeEmphasis;
set => this.RaiseAndSetIfChanged(ref applyDeEmphasis, value);
}
public bool TrackHasEmphasis
{
get => trackHasEmphasis;
set => this.RaiseAndSetIfChanged(ref trackHasEmphasis, value);
}
public bool HiddenTrack
{
get => hiddenTrack;
set => this.RaiseAndSetIfChanged(ref hiddenTrack, value);
}
public bool CopyAllowed
{
get => copyAllowed;
set => this.RaiseAndSetIfChanged(ref copyAllowed, value);
}
public bool IsAudioTrack
{
get => isAudioTrack;
set => this.RaiseAndSetIfChanged(ref isAudioTrack, value);
}
public bool IsDataTrack
{
get => isDataTrack;
set => this.RaiseAndSetIfChanged(ref isDataTrack, value);
}
#endregion
}
}

View File

@@ -0,0 +1,49 @@
using ReactiveUI;
namespace RedBookPlayer
{
public class PlayerViewModel : ReactiveObject
{
private bool _applyDeEmphasis;
public bool ApplyDeEmphasis
{
get => _applyDeEmphasis;
set => this.RaiseAndSetIfChanged(ref _applyDeEmphasis, value);
}
private bool _trackHasEmphasis;
public bool TrackHasEmphasis
{
get => _trackHasEmphasis;
set => this.RaiseAndSetIfChanged(ref _trackHasEmphasis, value);
}
private bool _hiddenTrack;
public bool HiddenTrack
{
get => _hiddenTrack;
set => this.RaiseAndSetIfChanged(ref _hiddenTrack, value);
}
private bool _copyAllowed;
public bool CopyAllowed
{
get => _copyAllowed;
set => this.RaiseAndSetIfChanged(ref _copyAllowed, value);
}
private bool _isAudioTrack;
public bool IsAudioTrack
{
get => _isAudioTrack;
set => this.RaiseAndSetIfChanged(ref _isAudioTrack, value);
}
private bool _isDataTrack;
public bool IsDataTrack
{
get => _isDataTrack;
set => this.RaiseAndSetIfChanged(ref _isDataTrack, value);
}
}
}

View File

@@ -1,4 +1,7 @@
using Avalonia;
#if Windows
using System.Runtime.InteropServices;
#endif
using Avalonia;
using Avalonia.Logging.Serilog;
namespace RedBookPlayer

View File

@@ -6,18 +6,55 @@ namespace RedBookPlayer
{
public class Settings
{
string filePath;
/// <summary>
/// Indicates if discs should start playing on load
/// </summary>
public bool AutoPlay { get; set; } = false;
/// <summary>
/// Indicates if an index change can trigger a track change
/// </summary>
public bool IndexButtonChangeTrack { get; set; } = false;
/// <summary>
/// Indicates if the index 0 of track 1 is treated like a hidden track
/// </summary>
public bool AllowSkipHiddenTrack { get; set; } = false;
/// <summary>
/// Indicates if data tracks should be played like old, non-compliant players
/// </summary>
public bool PlayDataTracks { get; set; } = false;
/// <summary>
/// Generate a TOC if the disc is missing one
/// </summary>
public bool GenerateMissingTOC { get; set; } = true;
/// <summary>
/// Indicates the default playback volume
/// </summary>
public int Volume { get; set; } = 100;
/// <summary>
/// Indicates the currently selected theme
/// </summary>
public string SelectedTheme { get; set; } = "default";
/// <summary>
/// Path to the settings file
/// </summary>
private string _filePath;
public Settings() {}
public Settings(string filePath) => this.filePath = filePath;
public bool AutoPlay { get; set; }
public bool IndexButtonChangeTrack { get; set; }
public bool AllowSkipHiddenTrack { get; set; }
public int Volume { get; set; } = 100;
public string SelectedTheme { get; set; } = "default";
public Settings(string filePath) => _filePath = filePath;
/// <summary>
/// Load settings from a file
/// </summary>
/// <param name="filePath">Path to the settings JSON file</param>
/// <returns>Settings derived from the input file, if possible</returns>
public static Settings Load(string filePath)
{
if(File.Exists(filePath))
@@ -25,7 +62,7 @@ namespace RedBookPlayer
try
{
Settings settings = JsonSerializer.Deserialize<Settings>(File.ReadAllText(filePath));
settings.filePath = filePath;
settings._filePath = filePath;
MainWindow.ApplyTheme(settings.SelectedTheme);
@@ -42,6 +79,9 @@ namespace RedBookPlayer
return new Settings(filePath);
}
/// <summary>
/// Save settings to a file
/// </summary>
public void Save()
{
var options = new JsonSerializerOptions
@@ -50,7 +90,7 @@ namespace RedBookPlayer
};
string json = JsonSerializer.Serialize(this, options);
File.WriteAllText(filePath, json);
File.WriteAllText(_filePath, json);
}
}
}

View File

@@ -17,6 +17,14 @@
<CheckBox IsChecked="{Binding AllowSkipHiddenTrack}" Margin="0,0,8,0" />
<TextBlock VerticalAlignment="Center">Treat index 0 of track 1 as track 0 (hidden track)</TextBlock>
</WrapPanel>
<WrapPanel Margin="0,0,0,16">
<CheckBox IsChecked="{Binding PlayDataTracks}" Margin="0,0,8,0"/>
<TextBlock VerticalAlignment="Center">Play data tracks like old, non-compliant players</TextBlock>
</WrapPanel>
<WrapPanel Margin="0,0,0,16">
<CheckBox IsChecked="{Binding GenerateMissingTOC}" Margin="0,0,8,0"/>
<TextBlock VerticalAlignment="Center">Generate a TOC if the disc is missing one</TextBlock>
</WrapPanel>
<DockPanel Margin="0,0,0,16">
<TextBlock VerticalAlignment="Center" Margin="0,0,8,0" DockPanel.Dock="Left">Volume</TextBlock>
<TextBlock VerticalAlignment="Center" DockPanel.Dock="Right" Text="%" />

View File

@@ -8,49 +8,47 @@ namespace RedBookPlayer
{
public class SettingsWindow : Window
{
readonly Settings settings;
string selectedTheme;
ListBox themeList;
private readonly Settings _settings;
private string _selectedTheme;
private ListBox _themeList;
public SettingsWindow() {}
public SettingsWindow(Settings settings)
{
DataContext = this.settings = settings;
DataContext = _settings = settings;
InitializeComponent();
}
public void ThemeList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if(e.AddedItems.Count == 0)
{
if (e.AddedItems.Count == 0)
return;
}
selectedTheme = (string)e.AddedItems[0];
_selectedTheme = (string)e.AddedItems[0];
}
public void ApplySettings(object sender, RoutedEventArgs e)
{
if((selectedTheme ?? "") != "")
if (!string.IsNullOrWhiteSpace(_selectedTheme))
{
settings.SelectedTheme = selectedTheme;
MainWindow.ApplyTheme(selectedTheme);
_settings.SelectedTheme = _selectedTheme;
MainWindow.ApplyTheme(_selectedTheme);
}
PlayerView.Player.Volume = settings.Volume;
PlayerView.Player.Volume = _settings.Volume;
settings.Save();
_settings.Save();
}
public void UpdateView() => this.FindControl<TextBlock>("VolumeLabel").Text = settings.Volume.ToString();
public void UpdateView() => this.FindControl<TextBlock>("VolumeLabel").Text = _settings.Volume.ToString();
void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
themeList = this.FindControl<ListBox>("ThemeList");
themeList.SelectionChanged += ThemeList_SelectionChanged;
_themeList = this.FindControl<ListBox>("ThemeList");
_themeList.SelectionChanged += ThemeList_SelectionChanged;
List<string> items = new List<string>();
items.Add("default");
@@ -61,16 +59,14 @@ namespace RedBookPlayer
{
string themeName = dir.Split('/')[1];
if(!File.Exists($"themes/{themeName}/view.xaml"))
{
if (!File.Exists($"themes/{themeName}/view.xaml"))
continue;
}
items.Add(themeName);
}
}
themeList.Items = items;
_themeList.Items = items;
this.FindControl<Button>("ApplyButton").Click += ApplySettings;
this.FindControl<Slider>("VolumeSlider").PropertyChanged += (s, e) => UpdateView();