mirror of
https://github.com/aaru-dps/RedBookPlayer.git
synced 2025-12-16 19:24:41 +00:00
Merge pull request #5 from mnadareski/sweeper
Broad organizational and bug-fix changes
This commit is contained in:
@@ -1,31 +1,37 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio 15
|
# Visual Studio Version 16
|
||||||
VisualStudioVersion = 15.0.26124.0
|
VisualStudioVersion = 16.0.31321.278
|
||||||
MinimumVisualStudioVersion = 15.0.26124.0
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
@@ -36,9 +42,6 @@ Global
|
|||||||
Release|x64 = Release|x64
|
Release|x64 = Release|x64
|
||||||
Release|x86 = Release|x86
|
Release|x86 = Release|x86
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
|
||||||
HideSolutionNode = FALSE
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
{94944959-0352-4ABF-9C5C-19FF33747ECE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{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
|
{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|x64.Build.0 = Release|Any CPU
|
||||||
{94944959-0352-4ABF-9C5C-19FF33747ECE}.Release|x86.ActiveCfg = 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
|
{94944959-0352-4ABF-9C5C-19FF33747ECE}.Release|x86.Build.0 = Release|Any CPU
|
||||||
{C97C30F9-30F3-4BA2-9A02-CF8644DEB616}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{C81E7637-D25A-4545-8E27-4D83D973F4DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{C97C30F9-30F3-4BA2-9A02-CF8644DEB616}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{C81E7637-D25A-4545-8E27-4D83D973F4DC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{C97C30F9-30F3-4BA2-9A02-CF8644DEB616}.Debug|x64.ActiveCfg = Debug|Any CPU
|
{C81E7637-D25A-4545-8E27-4D83D973F4DC}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
{C97C30F9-30F3-4BA2-9A02-CF8644DEB616}.Debug|x64.Build.0 = Debug|Any CPU
|
{C81E7637-D25A-4545-8E27-4D83D973F4DC}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
{C97C30F9-30F3-4BA2-9A02-CF8644DEB616}.Debug|x86.ActiveCfg = Debug|Any CPU
|
{C81E7637-D25A-4545-8E27-4D83D973F4DC}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
{C97C30F9-30F3-4BA2-9A02-CF8644DEB616}.Debug|x86.Build.0 = Debug|Any CPU
|
{C81E7637-D25A-4545-8E27-4D83D973F4DC}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
{C97C30F9-30F3-4BA2-9A02-CF8644DEB616}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{C81E7637-D25A-4545-8E27-4D83D973F4DC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{C97C30F9-30F3-4BA2-9A02-CF8644DEB616}.Release|Any CPU.Build.0 = Release|Any CPU
|
{C81E7637-D25A-4545-8E27-4D83D973F4DC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{C97C30F9-30F3-4BA2-9A02-CF8644DEB616}.Release|x64.ActiveCfg = Release|Any CPU
|
{C81E7637-D25A-4545-8E27-4D83D973F4DC}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
{C97C30F9-30F3-4BA2-9A02-CF8644DEB616}.Release|x64.Build.0 = Release|Any CPU
|
{C81E7637-D25A-4545-8E27-4D83D973F4DC}.Release|x64.Build.0 = Release|Any CPU
|
||||||
{C97C30F9-30F3-4BA2-9A02-CF8644DEB616}.Release|x86.ActiveCfg = Release|Any CPU
|
{C81E7637-D25A-4545-8E27-4D83D973F4DC}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{C97C30F9-30F3-4BA2-9A02-CF8644DEB616}.Release|x86.Build.0 = 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.ActiveCfg = Debug|Any CPU
|
||||||
{F2B84194-26EB-4227-B1C5-6602517E85AE}.Debug|Any CPU.Build.0 = 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
|
{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|x64.Build.0 = Release|Any CPU
|
||||||
{0BEB3088-B634-4289-AE17-CDF2D25D00D5}.Release|x86.ActiveCfg = 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
|
{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.ActiveCfg = Debug|Any CPU
|
||||||
{F8BDF57B-1571-4CD0-84B3-B422088D359A}.Debug|Any CPU.Build.0 = 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
|
{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|x64.Build.0 = Release|Any CPU
|
||||||
{F8BDF57B-1571-4CD0-84B3-B422088D359A}.Release|x86.ActiveCfg = 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
|
{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.ActiveCfg = Debug|Any CPU
|
||||||
{858398D1-7321-4763-8BAB-56BBFEC74E29}.Debug|Any CPU.Build.0 = 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
|
{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|x64.Build.0 = Release|Any CPU
|
||||||
{D571B8EF-903D-4353-BDD5-B834F9F029EF}.Release|x86.ActiveCfg = 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
|
{D571B8EF-903D-4353-BDD5-B834F9F029EF}.Release|x86.Build.0 = Release|Any CPU
|
||||||
{1E8EB4FB-C16D-437F-B54C-0026D32E9230}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{8F4AD79C-D5E5-44C4-9F03-B0DF4EE8BBA0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{1E8EB4FB-C16D-437F-B54C-0026D32E9230}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{8F4AD79C-D5E5-44C4-9F03-B0DF4EE8BBA0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{1E8EB4FB-C16D-437F-B54C-0026D32E9230}.Debug|x64.ActiveCfg = Debug|Any CPU
|
{8F4AD79C-D5E5-44C4-9F03-B0DF4EE8BBA0}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
{1E8EB4FB-C16D-437F-B54C-0026D32E9230}.Debug|x64.Build.0 = Debug|Any CPU
|
{8F4AD79C-D5E5-44C4-9F03-B0DF4EE8BBA0}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
{1E8EB4FB-C16D-437F-B54C-0026D32E9230}.Debug|x86.ActiveCfg = Debug|Any CPU
|
{8F4AD79C-D5E5-44C4-9F03-B0DF4EE8BBA0}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
{1E8EB4FB-C16D-437F-B54C-0026D32E9230}.Debug|x86.Build.0 = Debug|Any CPU
|
{8F4AD79C-D5E5-44C4-9F03-B0DF4EE8BBA0}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
{1E8EB4FB-C16D-437F-B54C-0026D32E9230}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{8F4AD79C-D5E5-44C4-9F03-B0DF4EE8BBA0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{1E8EB4FB-C16D-437F-B54C-0026D32E9230}.Release|Any CPU.Build.0 = Release|Any CPU
|
{8F4AD79C-D5E5-44C4-9F03-B0DF4EE8BBA0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{1E8EB4FB-C16D-437F-B54C-0026D32E9230}.Release|x64.ActiveCfg = Release|Any CPU
|
{8F4AD79C-D5E5-44C4-9F03-B0DF4EE8BBA0}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
{1E8EB4FB-C16D-437F-B54C-0026D32E9230}.Release|x64.Build.0 = Release|Any CPU
|
{8F4AD79C-D5E5-44C4-9F03-B0DF4EE8BBA0}.Release|x64.Build.0 = Release|Any CPU
|
||||||
{1E8EB4FB-C16D-437F-B54C-0026D32E9230}.Release|x86.ActiveCfg = Release|Any CPU
|
{8F4AD79C-D5E5-44C4-9F03-B0DF4EE8BBA0}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{1E8EB4FB-C16D-437F-B54C-0026D32E9230}.Release|x86.Build.0 = Release|Any CPU
|
{8F4AD79C-D5E5-44C4-9F03-B0DF4EE8BBA0}.Release|x86.Build.0 = Release|Any CPU
|
||||||
{6089CEBC-C88F-4A4C-8717-676F7CC427B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{ED8E11B7-786F-4EFF-9E4C-B937B7A2DE89}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{6089CEBC-C88F-4A4C-8717-676F7CC427B9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{ED8E11B7-786F-4EFF-9E4C-B937B7A2DE89}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{6089CEBC-C88F-4A4C-8717-676F7CC427B9}.Debug|x64.ActiveCfg = Debug|Any CPU
|
{ED8E11B7-786F-4EFF-9E4C-B937B7A2DE89}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
{6089CEBC-C88F-4A4C-8717-676F7CC427B9}.Debug|x64.Build.0 = Debug|Any CPU
|
{ED8E11B7-786F-4EFF-9E4C-B937B7A2DE89}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
{6089CEBC-C88F-4A4C-8717-676F7CC427B9}.Debug|x86.ActiveCfg = Debug|Any CPU
|
{ED8E11B7-786F-4EFF-9E4C-B937B7A2DE89}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
{6089CEBC-C88F-4A4C-8717-676F7CC427B9}.Debug|x86.Build.0 = Debug|Any CPU
|
{ED8E11B7-786F-4EFF-9E4C-B937B7A2DE89}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
{6089CEBC-C88F-4A4C-8717-676F7CC427B9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{ED8E11B7-786F-4EFF-9E4C-B937B7A2DE89}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{6089CEBC-C88F-4A4C-8717-676F7CC427B9}.Release|Any CPU.Build.0 = Release|Any CPU
|
{ED8E11B7-786F-4EFF-9E4C-B937B7A2DE89}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{6089CEBC-C88F-4A4C-8717-676F7CC427B9}.Release|x64.ActiveCfg = Release|Any CPU
|
{ED8E11B7-786F-4EFF-9E4C-B937B7A2DE89}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
{6089CEBC-C88F-4A4C-8717-676F7CC427B9}.Release|x64.Build.0 = Release|Any CPU
|
{ED8E11B7-786F-4EFF-9E4C-B937B7A2DE89}.Release|x64.Build.0 = Release|Any CPU
|
||||||
{6089CEBC-C88F-4A4C-8717-676F7CC427B9}.Release|x86.ActiveCfg = Release|Any CPU
|
{ED8E11B7-786F-4EFF-9E4C-B937B7A2DE89}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{6089CEBC-C88F-4A4C-8717-676F7CC427B9}.Release|x86.Build.0 = 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
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
|||||||
@@ -3,14 +3,17 @@ using NWaves.Filters.BiQuad;
|
|||||||
|
|
||||||
namespace RedBookPlayer
|
namespace RedBookPlayer
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Filter for applying de-emphasis to audio
|
||||||
|
/// </summary>
|
||||||
public class DeEmphasisFilter : BiQuadFilter
|
public class DeEmphasisFilter : BiQuadFilter
|
||||||
{
|
{
|
||||||
static readonly double B0;
|
private static readonly double B0;
|
||||||
static readonly double B1;
|
private static readonly double B1;
|
||||||
static readonly double B2;
|
private static readonly double B2;
|
||||||
static readonly double A0;
|
private static readonly double A0;
|
||||||
static readonly double A1;
|
private static readonly double A1;
|
||||||
static readonly double A2;
|
private static readonly double A2;
|
||||||
|
|
||||||
static DeEmphasisFilter()
|
static DeEmphasisFilter()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4,12 +4,15 @@ using System.Threading;
|
|||||||
|
|
||||||
namespace RedBookPlayer
|
namespace RedBookPlayer
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Recurring timer wrapper with a high degree of accuracy
|
||||||
|
/// </summary>
|
||||||
public class HiResTimer
|
public class HiResTimer
|
||||||
{
|
{
|
||||||
static readonly float tickFrequency = 1000f / Stopwatch.Frequency;
|
static readonly float tickFrequency = 1000f / Stopwatch.Frequency;
|
||||||
|
|
||||||
volatile float interval;
|
volatile float _interval;
|
||||||
volatile bool isRunning;
|
volatile bool _isRunning;
|
||||||
|
|
||||||
public HiResTimer() : this(1f) {}
|
public HiResTimer() : this(1f) {}
|
||||||
|
|
||||||
@@ -19,24 +22,25 @@ namespace RedBookPlayer
|
|||||||
float.IsNaN(interval))
|
float.IsNaN(interval))
|
||||||
throw new ArgumentOutOfRangeException(nameof(interval));
|
throw new ArgumentOutOfRangeException(nameof(interval));
|
||||||
|
|
||||||
this.interval = interval;
|
_interval = interval;
|
||||||
}
|
}
|
||||||
|
|
||||||
public float Interval
|
public float Interval
|
||||||
{
|
{
|
||||||
get => interval;
|
get => _interval;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if(value < 0f ||
|
if(value < 0f ||
|
||||||
float.IsNaN(value))
|
float.IsNaN(value))
|
||||||
throw new ArgumentOutOfRangeException(nameof(value));
|
throw new ArgumentOutOfRangeException(nameof(value));
|
||||||
|
|
||||||
interval = value;
|
_interval = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Enabled
|
public bool Enabled
|
||||||
{
|
{
|
||||||
|
get => _isRunning;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if(value)
|
if(value)
|
||||||
@@ -44,23 +48,22 @@ namespace RedBookPlayer
|
|||||||
else
|
else
|
||||||
Stop();
|
Stop();
|
||||||
}
|
}
|
||||||
get => isRunning;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public event EventHandler<HiResTimerElapsedEventArgs> Elapsed;
|
public event EventHandler<HiResTimerElapsedEventArgs> Elapsed;
|
||||||
|
|
||||||
public void Start()
|
public void Start()
|
||||||
{
|
{
|
||||||
if(isRunning)
|
if(_isRunning)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
isRunning = true;
|
_isRunning = true;
|
||||||
var thread = new Thread(ExecuteTimer);
|
var thread = new Thread(ExecuteTimer);
|
||||||
thread.Priority = ThreadPriority.Highest;
|
thread.Priority = ThreadPriority.Highest;
|
||||||
thread.Start();
|
thread.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Stop() => isRunning = false;
|
public void Stop() => _isRunning = false;
|
||||||
|
|
||||||
void ExecuteTimer()
|
void ExecuteTimer()
|
||||||
{
|
{
|
||||||
@@ -69,9 +72,9 @@ namespace RedBookPlayer
|
|||||||
var stopwatch = new Stopwatch();
|
var stopwatch = new Stopwatch();
|
||||||
stopwatch.Start();
|
stopwatch.Start();
|
||||||
|
|
||||||
while(isRunning)
|
while(_isRunning)
|
||||||
{
|
{
|
||||||
nextTrigger += interval;
|
nextTrigger += _interval;
|
||||||
float elapsed;
|
float elapsed;
|
||||||
|
|
||||||
while(true)
|
while(true)
|
||||||
@@ -91,7 +94,7 @@ namespace RedBookPlayer
|
|||||||
else
|
else
|
||||||
Thread.Sleep(10);
|
Thread.Sleep(10);
|
||||||
|
|
||||||
if(!isRunning)
|
if(!_isRunning)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,11 +113,4 @@ namespace RedBookPlayer
|
|||||||
|
|
||||||
static float ElapsedHiRes(Stopwatch stopwatch) => stopwatch.ElapsedTicks * tickFrequency;
|
static float ElapsedHiRes(Stopwatch stopwatch) => stopwatch.ElapsedTicks * tickFrequency;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class HiResTimerElapsedEventArgs : EventArgs
|
|
||||||
{
|
|
||||||
internal HiResTimerElapsedEventArgs(float delay) => Delay = delay;
|
|
||||||
|
|
||||||
public float Delay { get; }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
11
RedBookPlayer/HiResTimerElapsedEventArgs.cs
Normal file
11
RedBookPlayer/HiResTimerElapsedEventArgs.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace RedBookPlayer
|
||||||
|
{
|
||||||
|
public class HiResTimerElapsedEventArgs : EventArgs
|
||||||
|
{
|
||||||
|
internal HiResTimerElapsedEventArgs(float delay) => Delay = delay;
|
||||||
|
|
||||||
|
public float Delay { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,34 +19,37 @@ namespace RedBookPlayer
|
|||||||
InitializeComponent();
|
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)
|
public static void ApplyTheme(string theme)
|
||||||
{
|
{
|
||||||
if((theme ?? "") == "")
|
// If no theme path is provided, we can ignore
|
||||||
{
|
if(string.IsNullOrWhiteSpace(theme))
|
||||||
return;
|
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();
|
Instance.ContentControl.Content = new PlayerView();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
string themeDirectory = Directory.GetCurrentDirectory() + "/themes/" + theme;
|
string themeDirectory = $"{Directory.GetCurrentDirectory()}/themes/{theme}";
|
||||||
string xamlPath = themeDirectory + "/view.xaml";
|
string xamlPath = $"{themeDirectory}/view.xaml";
|
||||||
|
|
||||||
if(!File.Exists(xamlPath))
|
if(!File.Exists(xamlPath))
|
||||||
{
|
{
|
||||||
Console.WriteLine("Warning: specified theme doesn't exist, reverting to default");
|
Console.WriteLine("Warning: specified theme doesn't exist, reverting to default");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Instance.ContentControl.Content =
|
string xaml = File.ReadAllText(xamlPath);
|
||||||
new PlayerView(File.ReadAllText(xamlPath).
|
xaml = xaml.Replace("Source=\"", $"Source=\"file://{themeDirectory}/");
|
||||||
Replace("Source=\"", $"Source=\"file://{themeDirectory}/"));
|
Instance.ContentControl.Content = new PlayerView(xaml);
|
||||||
}
|
}
|
||||||
catch(XmlException ex)
|
catch(XmlException ex)
|
||||||
{
|
{
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
44
RedBookPlayer/PlayerSource.cs
Normal file
44
RedBookPlayer/PlayerSource.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@ using System.IO;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Timers;
|
using System.Timers;
|
||||||
using Aaru.CommonTypes.Interfaces;
|
using Aaru.CommonTypes.Enums;
|
||||||
using Aaru.DiscImages;
|
using Aaru.DiscImages;
|
||||||
using Aaru.Filters;
|
using Aaru.Filters;
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
@@ -14,60 +14,267 @@ using Avalonia.Markup.Xaml;
|
|||||||
using Avalonia.Media.Imaging;
|
using Avalonia.Media.Imaging;
|
||||||
using Avalonia.Platform;
|
using Avalonia.Platform;
|
||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
using ReactiveUI;
|
|
||||||
|
|
||||||
namespace RedBookPlayer
|
namespace RedBookPlayer
|
||||||
{
|
{
|
||||||
public class PlayerView : UserControl
|
public class PlayerView : UserControl
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Player representing the internal state and loaded image
|
||||||
|
/// </summary>
|
||||||
public static Player Player = new Player();
|
public static Player Player = new Player();
|
||||||
TextBlock currentTrack;
|
|
||||||
Image[] digits;
|
/// <summary>
|
||||||
Timer updateTimer;
|
/// 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() => InitializeComponent(null);
|
||||||
|
|
||||||
public PlayerView(string xaml) => InitializeComponent(xaml);
|
public PlayerView(string xaml) => InitializeComponent(xaml);
|
||||||
|
|
||||||
|
#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 { AllowMultiple = false };
|
||||||
|
List<string> knownExtensions = new AaruFormat().KnownExtensions.ToList();
|
||||||
|
dialog.Filters.Add(new FileDialogFilter()
|
||||||
|
{
|
||||||
|
Name = "Aaru Image Format (*" + string.Join(", *", knownExtensions) + ")",
|
||||||
|
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)
|
public async void LoadButton_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
string path = await GetPath();
|
string path = await GetPath();
|
||||||
|
|
||||||
if (path == null)
|
if (path == null)
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
await Task.Run(() =>
|
bool result = await Task.Run(() =>
|
||||||
{
|
{
|
||||||
var image = new AaruFormat();
|
var image = new AaruFormat();
|
||||||
IFilter filter = new ZZZNoFilter();
|
var filter = new ZZZNoFilter();
|
||||||
filter.Open(path);
|
filter.Open(path);
|
||||||
image.Open(filter);
|
image.Open(filter);
|
||||||
|
|
||||||
|
if (IsPlayableImage(image))
|
||||||
|
{
|
||||||
Player.Init(image, App.Settings.AutoPlay);
|
Player.Init(image, App.Settings.AutoPlay);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
await Dispatcher.UIThread.InvokeAsync(() =>
|
await Dispatcher.UIThread.InvokeAsync(() =>
|
||||||
{
|
{
|
||||||
MainWindow.Instance.Title = "RedBookPlayer - " + path.Split('/').Last().Split('\\').Last();
|
MainWindow.Instance.Title = "RedBookPlayer - " + path.Split('/').Last().Split('\\').Last();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<string> GetPath()
|
|
||||||
{
|
|
||||||
var dialog = new OpenFileDialog();
|
|
||||||
dialog.AllowMultiple = false;
|
|
||||||
|
|
||||||
List<string> knownExtensions = new AaruFormat().KnownExtensions.ToList();
|
|
||||||
|
|
||||||
dialog.Filters.Add(new FileDialogFilter
|
|
||||||
{
|
|
||||||
Name = "Aaru Image Format (*" + string.Join(", *", knownExtensions) + ")",
|
|
||||||
Extensions = knownExtensions.ConvertAll(e => e.Substring(1))
|
|
||||||
});
|
|
||||||
|
|
||||||
return (await dialog.ShowAsync((Window)Parent.Parent))?.FirstOrDefault();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PlayButton_Click(object sender, RoutedEventArgs e) => Player.Play();
|
public void PlayButton_Click(object sender, RoutedEventArgs e) => Player.Play();
|
||||||
@@ -80,208 +287,18 @@ namespace RedBookPlayer
|
|||||||
|
|
||||||
public void PreviousTrackButton_Click(object sender, RoutedEventArgs e) => Player.PreviousTrack();
|
public void PreviousTrackButton_Click(object sender, RoutedEventArgs e) => Player.PreviousTrack();
|
||||||
|
|
||||||
public void NextIndexButton_Click(object sender, RoutedEventArgs e) =>
|
public void NextIndexButton_Click(object sender, RoutedEventArgs e) => Player.NextIndex(App.Settings.IndexButtonChangeTrack);
|
||||||
Player.NextIndex(App.Settings.IndexButtonChangeTrack);
|
|
||||||
|
|
||||||
public void PreviousIndexButton_Click(object sender, RoutedEventArgs e) =>
|
public void PreviousIndexButton_Click(object sender, RoutedEventArgs e) => Player.PreviousIndex(App.Settings.IndexButtonChangeTrack);
|
||||||
Player.PreviousIndex(App.Settings.IndexButtonChangeTrack);
|
|
||||||
|
|
||||||
public void FastForwardButton_Click(object sender, RoutedEventArgs e) => Player.FastForward();
|
public void FastForwardButton_Click(object sender, RoutedEventArgs e) => Player.FastForward();
|
||||||
|
|
||||||
public void RewindButton_Click(object sender, RoutedEventArgs e) => Player.Rewind();
|
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)
|
#endregion
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
49
RedBookPlayer/PlayerViewModel.cs
Normal file
49
RedBookPlayer/PlayerViewModel.cs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,7 @@
|
|||||||
using Avalonia;
|
#if Windows
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
#endif
|
||||||
|
using Avalonia;
|
||||||
using Avalonia.Logging.Serilog;
|
using Avalonia.Logging.Serilog;
|
||||||
|
|
||||||
namespace RedBookPlayer
|
namespace RedBookPlayer
|
||||||
|
|||||||
@@ -6,18 +6,55 @@ namespace RedBookPlayer
|
|||||||
{
|
{
|
||||||
public class Settings
|
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() {}
|
||||||
|
|
||||||
public Settings(string filePath) => this.filePath = filePath;
|
public Settings(string filePath) => _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";
|
|
||||||
|
|
||||||
|
/// <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)
|
public static Settings Load(string filePath)
|
||||||
{
|
{
|
||||||
if(File.Exists(filePath))
|
if(File.Exists(filePath))
|
||||||
@@ -25,7 +62,7 @@ namespace RedBookPlayer
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
Settings settings = JsonSerializer.Deserialize<Settings>(File.ReadAllText(filePath));
|
Settings settings = JsonSerializer.Deserialize<Settings>(File.ReadAllText(filePath));
|
||||||
settings.filePath = filePath;
|
settings._filePath = filePath;
|
||||||
|
|
||||||
MainWindow.ApplyTheme(settings.SelectedTheme);
|
MainWindow.ApplyTheme(settings.SelectedTheme);
|
||||||
|
|
||||||
@@ -42,6 +79,9 @@ namespace RedBookPlayer
|
|||||||
return new Settings(filePath);
|
return new Settings(filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Save settings to a file
|
||||||
|
/// </summary>
|
||||||
public void Save()
|
public void Save()
|
||||||
{
|
{
|
||||||
var options = new JsonSerializerOptions
|
var options = new JsonSerializerOptions
|
||||||
@@ -50,7 +90,7 @@ namespace RedBookPlayer
|
|||||||
};
|
};
|
||||||
|
|
||||||
string json = JsonSerializer.Serialize(this, options);
|
string json = JsonSerializer.Serialize(this, options);
|
||||||
File.WriteAllText(filePath, json);
|
File.WriteAllText(_filePath, json);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -17,6 +17,14 @@
|
|||||||
<CheckBox IsChecked="{Binding AllowSkipHiddenTrack}" Margin="0,0,8,0" />
|
<CheckBox IsChecked="{Binding AllowSkipHiddenTrack}" Margin="0,0,8,0" />
|
||||||
<TextBlock VerticalAlignment="Center">Treat index 0 of track 1 as track 0 (hidden track)</TextBlock>
|
<TextBlock VerticalAlignment="Center">Treat index 0 of track 1 as track 0 (hidden track)</TextBlock>
|
||||||
</WrapPanel>
|
</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">
|
<DockPanel Margin="0,0,0,16">
|
||||||
<TextBlock VerticalAlignment="Center" Margin="0,0,8,0" DockPanel.Dock="Left">Volume</TextBlock>
|
<TextBlock VerticalAlignment="Center" Margin="0,0,8,0" DockPanel.Dock="Left">Volume</TextBlock>
|
||||||
<TextBlock VerticalAlignment="Center" DockPanel.Dock="Right" Text="%" />
|
<TextBlock VerticalAlignment="Center" DockPanel.Dock="Right" Text="%" />
|
||||||
|
|||||||
@@ -8,49 +8,47 @@ namespace RedBookPlayer
|
|||||||
{
|
{
|
||||||
public class SettingsWindow : Window
|
public class SettingsWindow : Window
|
||||||
{
|
{
|
||||||
readonly Settings settings;
|
private readonly Settings _settings;
|
||||||
string selectedTheme;
|
private string _selectedTheme;
|
||||||
ListBox themeList;
|
private ListBox _themeList;
|
||||||
|
|
||||||
public SettingsWindow() {}
|
public SettingsWindow() {}
|
||||||
|
|
||||||
public SettingsWindow(Settings settings)
|
public SettingsWindow(Settings settings)
|
||||||
{
|
{
|
||||||
DataContext = this.settings = settings;
|
DataContext = _settings = settings;
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ThemeList_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
public void ThemeList_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||||
{
|
{
|
||||||
if (e.AddedItems.Count == 0)
|
if (e.AddedItems.Count == 0)
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
selectedTheme = (string)e.AddedItems[0];
|
_selectedTheme = (string)e.AddedItems[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ApplySettings(object sender, RoutedEventArgs e)
|
public void ApplySettings(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
if((selectedTheme ?? "") != "")
|
if (!string.IsNullOrWhiteSpace(_selectedTheme))
|
||||||
{
|
{
|
||||||
settings.SelectedTheme = selectedTheme;
|
_settings.SelectedTheme = _selectedTheme;
|
||||||
MainWindow.ApplyTheme(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()
|
void InitializeComponent()
|
||||||
{
|
{
|
||||||
AvaloniaXamlLoader.Load(this);
|
AvaloniaXamlLoader.Load(this);
|
||||||
|
|
||||||
themeList = this.FindControl<ListBox>("ThemeList");
|
_themeList = this.FindControl<ListBox>("ThemeList");
|
||||||
themeList.SelectionChanged += ThemeList_SelectionChanged;
|
_themeList.SelectionChanged += ThemeList_SelectionChanged;
|
||||||
|
|
||||||
List<string> items = new List<string>();
|
List<string> items = new List<string>();
|
||||||
items.Add("default");
|
items.Add("default");
|
||||||
@@ -62,15 +60,13 @@ namespace RedBookPlayer
|
|||||||
string themeName = dir.Split('/')[1];
|
string themeName = dir.Split('/')[1];
|
||||||
|
|
||||||
if (!File.Exists($"themes/{themeName}/view.xaml"))
|
if (!File.Exists($"themes/{themeName}/view.xaml"))
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
items.Add(themeName);
|
items.Add(themeName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
themeList.Items = items;
|
_themeList.Items = items;
|
||||||
|
|
||||||
this.FindControl<Button>("ApplyButton").Click += ApplySettings;
|
this.FindControl<Button>("ApplyButton").Click += ApplySettings;
|
||||||
this.FindControl<Slider>("VolumeSlider").PropertyChanged += (s, e) => UpdateView();
|
this.FindControl<Slider>("VolumeSlider").PropertyChanged += (s, e) => UpdateView();
|
||||||
|
|||||||
Reference in New Issue
Block a user