major update commit
This commit is contained in:
parent
0654b86aa9
commit
aef4eb4f37
6
.gitmodules
vendored
6
.gitmodules
vendored
@ -1,3 +1,9 @@
|
|||||||
[submodule "framework-dotnet"]
|
[submodule "framework-dotnet"]
|
||||||
path = framework-dotnet
|
path = framework-dotnet
|
||||||
url = git@gitea.azcona-becker.net:alcetech/framework-dotnet
|
url = git@gitea.azcona-becker.net:alcetech/framework-dotnet
|
||||||
|
[submodule "desktop-framework-dotnet"]
|
||||||
|
path = desktop-framework-dotnet
|
||||||
|
url = git@gitea.azcona-becker.net:alcetech/desktop-framework-dotnet
|
||||||
|
[submodule "web-framework-dotnet"]
|
||||||
|
path = web-framework-dotnet
|
||||||
|
url = git@gitea.azcona-becker.net:alcetech/web-framework-dotnet
|
||||||
|
|||||||
1
desktop-framework-dotnet
Submodule
1
desktop-framework-dotnet
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 57316e3557c1c3a566d1a24bd60675c02d1f8744
|
||||||
@ -14,8 +14,6 @@ EndProject
|
|||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MBS.Editor.UserInterface", "editor-dotnet\src\lib\MBS.Editor.UserInterface\MBS.Editor.UserInterface.csproj", "{C4316562-555A-4A79-9D71-15737976DF8B}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MBS.Editor.UserInterface", "editor-dotnet\src\lib\MBS.Editor.UserInterface\MBS.Editor.UserInterface.csproj", "{C4316562-555A-4A79-9D71-15737976DF8B}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "app", "app", "{4ED8C38B-47EF-4368-9965-CF627465B45A}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "app", "app", "{4ED8C38B-47EF-4368-9965-CF627465B45A}"
|
||||||
ProjectSection(SolutionItems) = preProject
|
|
||||||
EndProjectSection
|
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MBS.Editor", "editor-dotnet\src\app\MBS.Editor\MBS.Editor.csproj", "{A936C411-0184-43F8-A343-0DE8C3B7B42E}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MBS.Editor", "editor-dotnet\src\app\MBS.Editor\MBS.Editor.csproj", "{A936C411-0184-43F8-A343-0DE8C3B7B42E}"
|
||||||
EndProject
|
EndProject
|
||||||
@ -27,8 +25,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{BDC147D8-4D9
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "lib", "lib", "{80A728D5-7C00-4B59-A37E-321C54CC554F}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "lib", "lib", "{80A728D5-7C00-4B59-A37E-321C54CC554F}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MBS.Desktop", "framework-dotnet\framework-dotnet\src\lib\MBS.Desktop\MBS.Desktop.csproj", "{4F2B8AF8-E1A4-4114-B4DA-4789A3A21143}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MBS.Core", "framework-dotnet\framework-dotnet\src\lib\MBS.Core\MBS.Core.csproj", "{7565CFB4-9761-4064-B18F-5E2644730BC0}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MBS.Core", "framework-dotnet\framework-dotnet\src\lib\MBS.Core\MBS.Core.csproj", "{7565CFB4-9761-4064-B18F-5E2644730BC0}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "plugins", "plugins", "{451AD529-16B4-4049-9D0C-0C79B3DDFA52}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "plugins", "plugins", "{451AD529-16B4-4049-9D0C-0C79B3DDFA52}"
|
||||||
@ -45,6 +41,46 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MBS.Editor.Core.Tests", "ed
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MBS.Editor.Plugins.CRI.Tests", "editor-dotnet\src\tests\MBS.Editor.Plugins.CRI.Tests\MBS.Editor.Plugins.CRI.Tests.csproj", "{2747FFC9-55AA-4A76-B0E9-D8A839E94E47}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MBS.Editor.Plugins.CRI.Tests", "editor-dotnet\src\tests\MBS.Editor.Plugins.CRI.Tests\MBS.Editor.Plugins.CRI.Tests.csproj", "{2747FFC9-55AA-4A76-B0E9-D8A839E94E47}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "desktop-framework-dotnet", "desktop-framework-dotnet", "{1BEBE6E9-D723-4A76-8210-D470DEB8C9C7}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "desktop-framework-dotnet", "desktop-framework-dotnet", "{68FC9B7D-A168-47CE-9106-A2501F5E4814}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{9C1544A0-92FF-46F3-A8F3-93A6EB599EDD}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "lib", "lib", "{418A36B7-1856-4945-AB9D-D66956A6A549}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MBS.Desktop", "desktop-framework-dotnet\desktop-framework-dotnet\src\lib\MBS.Desktop\MBS.Desktop.csproj", "{11862DE3-B214-42C5-9CFE-72FFE7F29F09}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "engines", "engines", "{C91C4319-D6B5-448C-BC28-3F5F65EC4EB7}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MBS.Desktop.Engines.GTK3", "desktop-framework-dotnet\desktop-framework-dotnet\src\engines\MBS.Desktop.Engines.GTK3\MBS.Desktop.Engines.GTK3.csproj", "{A738CB41-831D-4BB3-A7F5-87DB19FAD87B}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MBS.Editor.Plugins.Mekada", "editor-dotnet\src\plugins\MBS.Editor.Plugins.Mekada\MBS.Editor.Plugins.Mekada.csproj", "{9D1F7A94-B165-4581-B68D-4E2CF9F83D30}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MBS.Editor.Plugins.Mekada.Tests", "editor-dotnet\src\tests\MBS.Editor.Plugins.Mekada.Tests\MBS.Editor.Plugins.Mekada.Tests.csproj", "{55865BF2-E3C3-4823-A295-C85F6D98901F}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MBS.Editor.Testing", "editor-dotnet\src\lib\MBS.Editor.Testing\MBS.Editor.Testing.csproj", "{93A3D49C-A6EC-4F19-A410-F222DE1C9358}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MBS.Editor.Plugins.Kronosaur", "editor-dotnet\src\plugins\MBS.Editor.Plugins.Kronosaur\MBS.Editor.Plugins.Kronosaur.csproj", "{5D627852-158F-460D-9E5F-56F80BDB9A0B}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{D5423E32-5CD5-4207-8B56-235D470E7BBB}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MBS.Core.Tests", "framework-dotnet\framework-dotnet\src\tests\MBS.Core.Tests\MBS.Core.Tests.csproj", "{13F3D325-9EB8-4479-BB3F-1D663F924A8D}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MBS.Editor.Plugins.Multimedia.Tests", "editor-dotnet\src\tests\MBS.Editor.Plugins.Multimedia.Tests\MBS.Editor.Plugins.Multimedia.Tests.csproj", "{BDE1CD42-771E-4902-93DB-5B17C616C172}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MBS.Editor.Web.Server", "editor-dotnet\src\app\MBS.Editor.Web.Server\MBS.Editor.Web.Server.csproj", "{A74A8939-9E5A-4811-9D03-7B53E164A979}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "web-framework-dotnet", "web-framework-dotnet", "{B24A3EC9-CAC1-4162-A71F-4E085E828DAD}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{5A57B76D-C7E1-48A4-AB10-23E804590287}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "lib", "lib", "{91E8E5EA-8098-4929-9E87-6C2D55F35A02}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MBS.Web", "web-framework-dotnet\src\lib\MBS.Web\MBS.Web.csproj", "{09CD7984-6CB9-42BC-9A9E-31FA1C21697F}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MBS.Editor.Web", "editor-dotnet\src\lib\MBS.Editor.Web\MBS.Editor.Web.csproj", "{C40F7294-C2FD-4642-A35E-6AEE7DE9F2A1}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@ -63,10 +99,6 @@ Global
|
|||||||
{A936C411-0184-43F8-A343-0DE8C3B7B42E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{A936C411-0184-43F8-A343-0DE8C3B7B42E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{A936C411-0184-43F8-A343-0DE8C3B7B42E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{A936C411-0184-43F8-A343-0DE8C3B7B42E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{A936C411-0184-43F8-A343-0DE8C3B7B42E}.Release|Any CPU.Build.0 = Release|Any CPU
|
{A936C411-0184-43F8-A343-0DE8C3B7B42E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{4F2B8AF8-E1A4-4114-B4DA-4789A3A21143}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{4F2B8AF8-E1A4-4114-B4DA-4789A3A21143}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{4F2B8AF8-E1A4-4114-B4DA-4789A3A21143}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{4F2B8AF8-E1A4-4114-B4DA-4789A3A21143}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{7565CFB4-9761-4064-B18F-5E2644730BC0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{7565CFB4-9761-4064-B18F-5E2644730BC0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{7565CFB4-9761-4064-B18F-5E2644730BC0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{7565CFB4-9761-4064-B18F-5E2644730BC0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{7565CFB4-9761-4064-B18F-5E2644730BC0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{7565CFB4-9761-4064-B18F-5E2644730BC0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
@ -91,13 +123,55 @@ Global
|
|||||||
{2747FFC9-55AA-4A76-B0E9-D8A839E94E47}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{2747FFC9-55AA-4A76-B0E9-D8A839E94E47}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{2747FFC9-55AA-4A76-B0E9-D8A839E94E47}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{2747FFC9-55AA-4A76-B0E9-D8A839E94E47}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{2747FFC9-55AA-4A76-B0E9-D8A839E94E47}.Release|Any CPU.Build.0 = Release|Any CPU
|
{2747FFC9-55AA-4A76-B0E9-D8A839E94E47}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{11862DE3-B214-42C5-9CFE-72FFE7F29F09}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{11862DE3-B214-42C5-9CFE-72FFE7F29F09}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{11862DE3-B214-42C5-9CFE-72FFE7F29F09}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{11862DE3-B214-42C5-9CFE-72FFE7F29F09}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{A738CB41-831D-4BB3-A7F5-87DB19FAD87B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{A738CB41-831D-4BB3-A7F5-87DB19FAD87B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{A738CB41-831D-4BB3-A7F5-87DB19FAD87B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{A738CB41-831D-4BB3-A7F5-87DB19FAD87B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{9D1F7A94-B165-4581-B68D-4E2CF9F83D30}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{9D1F7A94-B165-4581-B68D-4E2CF9F83D30}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{9D1F7A94-B165-4581-B68D-4E2CF9F83D30}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{9D1F7A94-B165-4581-B68D-4E2CF9F83D30}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{55865BF2-E3C3-4823-A295-C85F6D98901F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{55865BF2-E3C3-4823-A295-C85F6D98901F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{55865BF2-E3C3-4823-A295-C85F6D98901F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{55865BF2-E3C3-4823-A295-C85F6D98901F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{93A3D49C-A6EC-4F19-A410-F222DE1C9358}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{93A3D49C-A6EC-4F19-A410-F222DE1C9358}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{93A3D49C-A6EC-4F19-A410-F222DE1C9358}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{93A3D49C-A6EC-4F19-A410-F222DE1C9358}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{5D627852-158F-460D-9E5F-56F80BDB9A0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{5D627852-158F-460D-9E5F-56F80BDB9A0B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{5D627852-158F-460D-9E5F-56F80BDB9A0B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{5D627852-158F-460D-9E5F-56F80BDB9A0B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{13F3D325-9EB8-4479-BB3F-1D663F924A8D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{13F3D325-9EB8-4479-BB3F-1D663F924A8D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{13F3D325-9EB8-4479-BB3F-1D663F924A8D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{13F3D325-9EB8-4479-BB3F-1D663F924A8D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{BDE1CD42-771E-4902-93DB-5B17C616C172}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{BDE1CD42-771E-4902-93DB-5B17C616C172}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{BDE1CD42-771E-4902-93DB-5B17C616C172}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{BDE1CD42-771E-4902-93DB-5B17C616C172}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{A74A8939-9E5A-4811-9D03-7B53E164A979}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{A74A8939-9E5A-4811-9D03-7B53E164A979}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{A74A8939-9E5A-4811-9D03-7B53E164A979}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{A74A8939-9E5A-4811-9D03-7B53E164A979}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{09CD7984-6CB9-42BC-9A9E-31FA1C21697F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{09CD7984-6CB9-42BC-9A9E-31FA1C21697F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{09CD7984-6CB9-42BC-9A9E-31FA1C21697F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{09CD7984-6CB9-42BC-9A9E-31FA1C21697F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{C40F7294-C2FD-4642-A35E-6AEE7DE9F2A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{C40F7294-C2FD-4642-A35E-6AEE7DE9F2A1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{C40F7294-C2FD-4642-A35E-6AEE7DE9F2A1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{C40F7294-C2FD-4642-A35E-6AEE7DE9F2A1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(NestedProjects) = preSolution
|
GlobalSection(NestedProjects) = preSolution
|
||||||
{74AD8C3F-B0B8-472F-A847-1FFFB1667B34} = {F05001E1-6FFB-48AE-BF7F-7F39A24D3B70}
|
|
||||||
{451AD529-16B4-4049-9D0C-0C79B3DDFA52} = {F05001E1-6FFB-48AE-BF7F-7F39A24D3B70}
|
|
||||||
{F05001E1-6FFB-48AE-BF7F-7F39A24D3B70} = {75210F45-D690-4A61-9CD8-96B09E5DAAC5}
|
{F05001E1-6FFB-48AE-BF7F-7F39A24D3B70} = {75210F45-D690-4A61-9CD8-96B09E5DAAC5}
|
||||||
{C86F60F9-BBC1-4554-A3B0-D553F9C157A8} = {F05001E1-6FFB-48AE-BF7F-7F39A24D3B70}
|
{C86F60F9-BBC1-4554-A3B0-D553F9C157A8} = {F05001E1-6FFB-48AE-BF7F-7F39A24D3B70}
|
||||||
{8FFB417A-2CDC-429F-ABE0-19B3015530D3} = {C86F60F9-BBC1-4554-A3B0-D553F9C157A8}
|
{8FFB417A-2CDC-429F-ABE0-19B3015530D3} = {C86F60F9-BBC1-4554-A3B0-D553F9C157A8}
|
||||||
@ -107,13 +181,32 @@ Global
|
|||||||
{B9747AFE-160D-4807-B989-B3F0ACCA3634} = {CC86007D-8193-4EAA-932D-A96B5F09847E}
|
{B9747AFE-160D-4807-B989-B3F0ACCA3634} = {CC86007D-8193-4EAA-932D-A96B5F09847E}
|
||||||
{BDC147D8-4D97-4663-9408-BC822E1E0B3C} = {B9747AFE-160D-4807-B989-B3F0ACCA3634}
|
{BDC147D8-4D97-4663-9408-BC822E1E0B3C} = {B9747AFE-160D-4807-B989-B3F0ACCA3634}
|
||||||
{80A728D5-7C00-4B59-A37E-321C54CC554F} = {BDC147D8-4D97-4663-9408-BC822E1E0B3C}
|
{80A728D5-7C00-4B59-A37E-321C54CC554F} = {BDC147D8-4D97-4663-9408-BC822E1E0B3C}
|
||||||
{4F2B8AF8-E1A4-4114-B4DA-4789A3A21143} = {80A728D5-7C00-4B59-A37E-321C54CC554F}
|
|
||||||
{7565CFB4-9761-4064-B18F-5E2644730BC0} = {80A728D5-7C00-4B59-A37E-321C54CC554F}
|
{7565CFB4-9761-4064-B18F-5E2644730BC0} = {80A728D5-7C00-4B59-A37E-321C54CC554F}
|
||||||
|
{451AD529-16B4-4049-9D0C-0C79B3DDFA52} = {F05001E1-6FFB-48AE-BF7F-7F39A24D3B70}
|
||||||
{5978938E-19F6-42AE-B588-7719A65ABCA7} = {451AD529-16B4-4049-9D0C-0C79B3DDFA52}
|
{5978938E-19F6-42AE-B588-7719A65ABCA7} = {451AD529-16B4-4049-9D0C-0C79B3DDFA52}
|
||||||
{CDA151F8-5BA7-47DB-883D-CBC2DD94F0DF} = {4ED8C38B-47EF-4368-9965-CF627465B45A}
|
{CDA151F8-5BA7-47DB-883D-CBC2DD94F0DF} = {4ED8C38B-47EF-4368-9965-CF627465B45A}
|
||||||
{78B11A3E-1371-48D8-9B8E-AE6ED2380A50} = {451AD529-16B4-4049-9D0C-0C79B3DDFA52}
|
{78B11A3E-1371-48D8-9B8E-AE6ED2380A50} = {451AD529-16B4-4049-9D0C-0C79B3DDFA52}
|
||||||
|
{74AD8C3F-B0B8-472F-A847-1FFFB1667B34} = {F05001E1-6FFB-48AE-BF7F-7F39A24D3B70}
|
||||||
{7A349FC6-BCE7-465D-ADBC-7A21242E2C78} = {74AD8C3F-B0B8-472F-A847-1FFFB1667B34}
|
{7A349FC6-BCE7-465D-ADBC-7A21242E2C78} = {74AD8C3F-B0B8-472F-A847-1FFFB1667B34}
|
||||||
{2747FFC9-55AA-4A76-B0E9-D8A839E94E47} = {74AD8C3F-B0B8-472F-A847-1FFFB1667B34}
|
{2747FFC9-55AA-4A76-B0E9-D8A839E94E47} = {74AD8C3F-B0B8-472F-A847-1FFFB1667B34}
|
||||||
|
{68FC9B7D-A168-47CE-9106-A2501F5E4814} = {1BEBE6E9-D723-4A76-8210-D470DEB8C9C7}
|
||||||
|
{9C1544A0-92FF-46F3-A8F3-93A6EB599EDD} = {68FC9B7D-A168-47CE-9106-A2501F5E4814}
|
||||||
|
{418A36B7-1856-4945-AB9D-D66956A6A549} = {9C1544A0-92FF-46F3-A8F3-93A6EB599EDD}
|
||||||
|
{11862DE3-B214-42C5-9CFE-72FFE7F29F09} = {418A36B7-1856-4945-AB9D-D66956A6A549}
|
||||||
|
{C91C4319-D6B5-448C-BC28-3F5F65EC4EB7} = {9C1544A0-92FF-46F3-A8F3-93A6EB599EDD}
|
||||||
|
{A738CB41-831D-4BB3-A7F5-87DB19FAD87B} = {C91C4319-D6B5-448C-BC28-3F5F65EC4EB7}
|
||||||
|
{9D1F7A94-B165-4581-B68D-4E2CF9F83D30} = {451AD529-16B4-4049-9D0C-0C79B3DDFA52}
|
||||||
|
{55865BF2-E3C3-4823-A295-C85F6D98901F} = {74AD8C3F-B0B8-472F-A847-1FFFB1667B34}
|
||||||
|
{93A3D49C-A6EC-4F19-A410-F222DE1C9358} = {C86F60F9-BBC1-4554-A3B0-D553F9C157A8}
|
||||||
|
{5D627852-158F-460D-9E5F-56F80BDB9A0B} = {451AD529-16B4-4049-9D0C-0C79B3DDFA52}
|
||||||
|
{D5423E32-5CD5-4207-8B56-235D470E7BBB} = {BDC147D8-4D97-4663-9408-BC822E1E0B3C}
|
||||||
|
{13F3D325-9EB8-4479-BB3F-1D663F924A8D} = {D5423E32-5CD5-4207-8B56-235D470E7BBB}
|
||||||
|
{BDE1CD42-771E-4902-93DB-5B17C616C172} = {74AD8C3F-B0B8-472F-A847-1FFFB1667B34}
|
||||||
|
{A74A8939-9E5A-4811-9D03-7B53E164A979} = {4ED8C38B-47EF-4368-9965-CF627465B45A}
|
||||||
|
{5A57B76D-C7E1-48A4-AB10-23E804590287} = {B24A3EC9-CAC1-4162-A71F-4E085E828DAD}
|
||||||
|
{91E8E5EA-8098-4929-9E87-6C2D55F35A02} = {5A57B76D-C7E1-48A4-AB10-23E804590287}
|
||||||
|
{09CD7984-6CB9-42BC-9A9E-31FA1C21697F} = {91E8E5EA-8098-4929-9E87-6C2D55F35A02}
|
||||||
|
{C40F7294-C2FD-4642-A35E-6AEE7DE9F2A1} = {C86F60F9-BBC1-4554-A3B0-D553F9C157A8}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {4D0B64EB-14E9-4013-AA33-33716704909B}
|
SolutionGuid = {4D0B64EB-14E9-4013-AA33-33716704909B}
|
||||||
|
|||||||
@ -0,0 +1,15 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="../../../../web-framework-dotnet/src/lib/MBS.Web/MBS.Web.csproj" />
|
||||||
|
<ProjectReference Include="../../lib/MBS.Editor.Web/MBS.Editor.Web.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
102
editor-dotnet/src/app/MBS.Editor.Web.Server/Program.cs
Normal file
102
editor-dotnet/src/app/MBS.Editor.Web.Server/Program.cs
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
using System.Text.Json.Nodes;
|
||||||
|
using System.Xml;
|
||||||
|
using MBS.Core;
|
||||||
|
using MBS.Editor.Web.Pages;
|
||||||
|
using MBS.Web;
|
||||||
|
|
||||||
|
public class Program : WebApplication
|
||||||
|
{
|
||||||
|
protected override int DefaultPort => 54920;
|
||||||
|
|
||||||
|
public Program()
|
||||||
|
{
|
||||||
|
Commands.Add(new Command("File", "_File", new CommandItem[]
|
||||||
|
{
|
||||||
|
new CommandReferenceCommandItem("FileOpen")
|
||||||
|
}));
|
||||||
|
Commands.Add(new Command("FileOpen", "_Open"));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override WebServer CreateWebServer()
|
||||||
|
{
|
||||||
|
WebServer ws = base.CreateWebServer();
|
||||||
|
ws.Routes.Add(new WebRoute("/", new WebHandler(delegate(WebContext ctx)
|
||||||
|
{
|
||||||
|
ctx.Response.ContentType = "application/xhtml+xml";
|
||||||
|
|
||||||
|
MainPage page = new MainPage();
|
||||||
|
page.Title = "MBS Editor";
|
||||||
|
|
||||||
|
MBS.Web.UI.WebControls.CommandBar toolbar = new MBS.Web.UI.WebControls.CommandBar();
|
||||||
|
toolbar.Items.Add(new CommandReferenceCommandItem("FileOpen"));
|
||||||
|
page.Controls.Add(toolbar);
|
||||||
|
|
||||||
|
XmlWriter sw = XmlWriter.Create(ctx.Response.Stream);
|
||||||
|
page.Render(sw);
|
||||||
|
sw.Close();
|
||||||
|
})));
|
||||||
|
ws.Routes.Add(new WebRoute("/api/local/browse", new WebHandler(delegate(WebContext ctx)
|
||||||
|
{
|
||||||
|
StreamWriter sw = new StreamWriter(ctx.Response.Stream);
|
||||||
|
|
||||||
|
string relativePath = "";
|
||||||
|
if (ctx.Request.Query.ContainsKey("path"))
|
||||||
|
{
|
||||||
|
List<string> oPath = ctx.Request.Query["path"];
|
||||||
|
if (oPath.Count > 0)
|
||||||
|
{
|
||||||
|
relativePath = oPath[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonObject json = new JsonObject();
|
||||||
|
|
||||||
|
string homeDirectory = "/home/beckermj/Documents";
|
||||||
|
string absolutePath = String.Join("/", new string[] { homeDirectory, relativePath });
|
||||||
|
if (!System.IO.Directory.Exists(absolutePath))
|
||||||
|
{
|
||||||
|
json.Add("result", "failure");
|
||||||
|
json.Add("message", "path not found");
|
||||||
|
|
||||||
|
sw.Write(json.ToJsonString());
|
||||||
|
sw.Close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
json.Add("result", "success");
|
||||||
|
|
||||||
|
JsonArray ary = new JsonArray();
|
||||||
|
string[] files = System.IO.Directory.GetFiles(absolutePath, "*", SearchOption.TopDirectoryOnly);
|
||||||
|
string[] folders = System.IO.Directory.GetDirectories(absolutePath, "*", SearchOption.TopDirectoryOnly);
|
||||||
|
foreach (string file in folders)
|
||||||
|
{
|
||||||
|
JsonObject o = new JsonObject();
|
||||||
|
string title = System.IO.Path.GetFileName(file);
|
||||||
|
o.Add("title", title);
|
||||||
|
o.Add("type", "folder");
|
||||||
|
o.Add("path", file);
|
||||||
|
ary.Add(o);
|
||||||
|
}
|
||||||
|
foreach (string file in files)
|
||||||
|
{
|
||||||
|
JsonObject o = new JsonObject();
|
||||||
|
string title = System.IO.Path.GetFileName(file);
|
||||||
|
o.Add("title", title);
|
||||||
|
o.Add("type", "file");
|
||||||
|
o.Add("path", file);
|
||||||
|
ary.Add(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
json.Add("items", ary);
|
||||||
|
|
||||||
|
sw.Write(json.ToJsonString());
|
||||||
|
sw.Close();
|
||||||
|
})));
|
||||||
|
return ws;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Main(string[] args)
|
||||||
|
{
|
||||||
|
(new Program()).Start();
|
||||||
|
}
|
||||||
|
}
|
||||||
12
editor-dotnet/src/app/MBS.Editor.Web.Server/TODO.txt
Normal file
12
editor-dotnet/src/app/MBS.Editor.Web.Server/TODO.txt
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
This is MBS Editor Web Server.
|
||||||
|
|
||||||
|
example URL:
|
||||||
|
|
||||||
|
Edit existing registered Document:
|
||||||
|
https://localhost:54920/doc/61b30ad3c7754ae2bc7abf949ee83289/edit
|
||||||
|
|
||||||
|
Create document and register it:
|
||||||
|
https://localhost:54920/doc/new
|
||||||
|
|
||||||
|
- redirects to /doc/.../edit when document is created
|
||||||
|
|
||||||
@ -3,8 +3,8 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\lib\MBS.Editor.Core\MBS.Editor.Core.csproj" />
|
<ProjectReference Include="..\..\lib\MBS.Editor.Core\MBS.Editor.Core.csproj" />
|
||||||
<ProjectReference Include="..\..\lib\MBS.Editor.UserInterface\MBS.Editor.UserInterface.csproj" />
|
<ProjectReference Include="..\..\lib\MBS.Editor.UserInterface\MBS.Editor.UserInterface.csproj" />
|
||||||
<ProjectReference Include="..\..\..\..\framework-dotnet\framework-dotnet\src\lib\MBS.Desktop\MBS.Desktop.csproj" />
|
|
||||||
<ProjectReference Include="..\..\..\..\framework-dotnet\framework-dotnet\src\lib\MBS.Core\MBS.Core.csproj" />
|
<ProjectReference Include="..\..\..\..\framework-dotnet\framework-dotnet\src\lib\MBS.Core\MBS.Core.csproj" />
|
||||||
|
<ProjectReference Include="..\..\..\..\desktop-framework-dotnet\desktop-framework-dotnet\src\lib\MBS.Desktop\MBS.Desktop.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
|
|||||||
23
editor-dotnet/src/install-engines.sh
Executable file
23
editor-dotnet/src/install-engines.sh
Executable file
@ -0,0 +1,23 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
CONFIDENCE=Debug
|
||||||
|
NET_VERSION=net8.0
|
||||||
|
|
||||||
|
if [ ! -d app/MBS.Editor/bin/$CONFIDENCE/$NET_VERSION/engines ]; then
|
||||||
|
|
||||||
|
mkdir app/MBS.Editor/bin/$CONFIDENCE/$NET_VERSION/engines
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
for dir in ../../desktop-framework-dotnet/desktop-framework-dotnet/src/engines/* ; do
|
||||||
|
|
||||||
|
echo "Building $dir"
|
||||||
|
|
||||||
|
pushd $dir
|
||||||
|
dotnet build
|
||||||
|
popd
|
||||||
|
|
||||||
|
echo "Copying $dir"
|
||||||
|
cp $dir/bin/$CONFIDENCE/$NET_VERSION/*.dll app/MBS.Editor/bin/$CONFIDENCE/$NET_VERSION/engines
|
||||||
|
|
||||||
|
done
|
||||||
@ -1,22 +1,73 @@
|
|||||||
|
//
|
||||||
|
// DataFormat.cs - translates ObjectModel to serialized data in a particular format
|
||||||
|
//
|
||||||
|
// Author:
|
||||||
|
// Michael Becker <alcexhim@gmail.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2011-2024 Mike Becker's Software
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
namespace MBS.Editor.Core;
|
namespace MBS.Editor.Core;
|
||||||
|
|
||||||
public abstract class DataFormat
|
public abstract class DataFormat
|
||||||
{
|
{
|
||||||
|
protected virtual void BeforeLoadInternal(Stack<ObjectModel> objectModels)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
protected virtual void AfterLoadInternal(Stack<ObjectModel> objectModels)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
public void Load(ObjectModel objectModel, Stream stream)
|
public void Load(ObjectModel objectModel, Stream stream)
|
||||||
{
|
{
|
||||||
LoadInternal(objectModel, stream);
|
Stack<ObjectModel> stack = new Stack<ObjectModel>();
|
||||||
|
stack.Push(objectModel);
|
||||||
|
BeforeLoadInternal(stack);
|
||||||
|
|
||||||
|
ObjectModel omb = stack.Pop();
|
||||||
|
|
||||||
|
LoadInternal(omb, stream);
|
||||||
|
|
||||||
|
stack.Push(omb);
|
||||||
|
AfterLoadInternal(stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void LoadInternal(ObjectModel objectModel, Stream stream);
|
protected abstract void LoadInternal(ObjectModel objectModel, Stream stream);
|
||||||
|
|
||||||
|
protected virtual void BeforeSaveInternal(Stack<ObjectModel> objectModels)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
protected virtual void AfterSaveInternal(Stack<ObjectModel> objectModels)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
public void Save(ObjectModel objectModel, Stream stream)
|
public void Save(ObjectModel objectModel, Stream stream)
|
||||||
{
|
{
|
||||||
SaveInternal(objectModel, stream);
|
Stack<ObjectModel> stack = new Stack<ObjectModel>();
|
||||||
|
stack.Push(objectModel);
|
||||||
|
BeforeSaveInternal(stack);
|
||||||
|
|
||||||
|
ObjectModel omb = stack.Pop();
|
||||||
|
|
||||||
|
SaveInternal(omb, stream);
|
||||||
|
|
||||||
|
stack.Push(omb);
|
||||||
|
AfterSaveInternal(stack);
|
||||||
}
|
}
|
||||||
protected abstract void SaveInternal(ObjectModel objectModel, Stream stream);
|
protected abstract void SaveInternal(ObjectModel objectModel, Stream stream);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static T FromType<T>() where T : DataFormat, new()
|
public static T FromType<T>() where T : DataFormat, new()
|
||||||
{
|
{
|
||||||
T objectModel = new T();
|
T objectModel = new T();
|
||||||
|
|||||||
@ -0,0 +1,142 @@
|
|||||||
|
// Copyright (C) 2024 Michael Becker <alcexhim@gmail.com>
|
||||||
|
//
|
||||||
|
// This file is part of editor-dotnet.
|
||||||
|
//
|
||||||
|
// editor-dotnet is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// editor-dotnet is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with editor-dotnet. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
using MBS.Core;
|
||||||
|
using MBS.Editor.Core.IO;
|
||||||
|
using MBS.Editor.Core.ObjectModels.Chunked;
|
||||||
|
using MBS.Editor.Core.ObjectModels.FileSystem.FileSources;
|
||||||
|
|
||||||
|
namespace MBS.Editor.Core.DataFormats.FileSystem.Chunked;
|
||||||
|
|
||||||
|
public class ChunkedDataFormat : DataFormat
|
||||||
|
{
|
||||||
|
protected virtual int KeyLength { get; } = 4;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the endianness of multibyte values. For IFF and AIFF, set to
|
||||||
|
/// <see cref="Endianness.BigEndian" />. For RIFF, set to <see cref="Endianness.LittleEndian" />.
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
public Endianness Endianness { get; set; } = Endianness.LittleEndian;
|
||||||
|
|
||||||
|
protected virtual int ChunkAlignment { get; } = 0;
|
||||||
|
protected virtual bool IsGroupChunk(string name)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ReadChunk(Reader reader, IChunkContainer parent)
|
||||||
|
{
|
||||||
|
string chunkName = reader.ReadFixedLengthString(4);
|
||||||
|
int chunkLength = reader.ReadInt32();
|
||||||
|
|
||||||
|
if (IsGroupChunk(chunkName))
|
||||||
|
{
|
||||||
|
string typeName = reader.ReadFixedLengthString(4);
|
||||||
|
|
||||||
|
// is group chunk
|
||||||
|
GroupChunk folder = new GroupChunk(chunkName, typeName);
|
||||||
|
|
||||||
|
while (!reader.BaseStream.EndOfStream())
|
||||||
|
{
|
||||||
|
ReadChunk(reader, folder);
|
||||||
|
}
|
||||||
|
|
||||||
|
parent.Chunks.Add(folder);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
long offset = reader.BaseStream.Position;
|
||||||
|
|
||||||
|
DataChunk file = new DataChunk(chunkName);
|
||||||
|
file.Source = new EmbeddedFileSource(reader.BaseStream, offset, chunkLength);
|
||||||
|
parent.Chunks.Add(file);
|
||||||
|
|
||||||
|
// CMAP=color map, 768 bytes, 3x256 colors, rgb
|
||||||
|
|
||||||
|
reader.BaseStream.Seek(chunkLength, SeekOrigin.Current);
|
||||||
|
reader.Align(ChunkAlignment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void LoadInternal(ObjectModel objectModel, Stream stream)
|
||||||
|
{
|
||||||
|
ChunkedObjectModel chunked = ObjectModel.CastOrThrow<ChunkedObjectModel>(objectModel);
|
||||||
|
|
||||||
|
Reader reader = new Reader(stream);
|
||||||
|
reader.Endianness = Endianness;
|
||||||
|
while (!reader.BaseStream.EndOfStream())
|
||||||
|
{
|
||||||
|
ReadChunk(reader, chunked);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
protected override void SaveInternal(ObjectModel objectModel, Stream stream)
|
||||||
|
{
|
||||||
|
ChunkedObjectModel chunked = ObjectModel.CastOrThrow<ChunkedObjectModel>(objectModel);
|
||||||
|
|
||||||
|
Writer writer = new Writer(stream);
|
||||||
|
writer.Endianness = Endianness;
|
||||||
|
foreach (Chunk chunk in chunked.Chunks)
|
||||||
|
{
|
||||||
|
WriteChunk(writer, chunk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WriteChunk(Writer writer, Chunk chunk)
|
||||||
|
{
|
||||||
|
writer.WriteFixedLengthString(chunk.Name, KeyLength);
|
||||||
|
writer.WriteInt32(CalculateChunkSize(chunk));
|
||||||
|
|
||||||
|
if (chunk is GroupChunk g)
|
||||||
|
{
|
||||||
|
writer.WriteFixedLengthString(g.TypeName, KeyLength);
|
||||||
|
foreach (Chunk chunk2 in g.Chunks)
|
||||||
|
{
|
||||||
|
WriteChunk(writer, chunk2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (chunk is DataChunk d)
|
||||||
|
{
|
||||||
|
if (d.Source != null)
|
||||||
|
{
|
||||||
|
writer.WriteBytes(d.Source.GetData());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int CalculateChunkSize(Chunk chunk)
|
||||||
|
{
|
||||||
|
int sz = 0;
|
||||||
|
if (chunk is GroupChunk g)
|
||||||
|
{
|
||||||
|
sz += 4;
|
||||||
|
foreach (Chunk c in g.Chunks)
|
||||||
|
{
|
||||||
|
sz += CalculateChunkSize(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (chunk is DataChunk d)
|
||||||
|
{
|
||||||
|
sz = 0;
|
||||||
|
if (d.Source != null)
|
||||||
|
{
|
||||||
|
sz = (int)d.Source.Length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sz;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,45 @@
|
|||||||
|
// Copyright (C) 2024 Michael Becker <alcexhim@gmail.com>
|
||||||
|
//
|
||||||
|
// This file is part of editor-dotnet.
|
||||||
|
//
|
||||||
|
// editor-dotnet is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// editor-dotnet is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with editor-dotnet. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
using MBS.Core;
|
||||||
|
using MBS.Editor.Core.DataFormats.FileSystem.Chunked;
|
||||||
|
using MBS.Editor.Core.IO;
|
||||||
|
using MBS.Editor.Core.ObjectModels.Chunked;
|
||||||
|
using MBS.Editor.Core.ObjectModels.FileSystem;
|
||||||
|
using MBS.Editor.Core.ObjectModels.FileSystem.FileSources;
|
||||||
|
|
||||||
|
namespace MBS.Editor.Core.DataFormats.FileSystem.IFF;
|
||||||
|
|
||||||
|
public class IFFDataFormat : ChunkedDataFormat
|
||||||
|
{
|
||||||
|
public List<string> GroupChunkNames { get; } = new List<string>();
|
||||||
|
public IFFDataFormat()
|
||||||
|
{
|
||||||
|
Endianness = Endianness.BigEndian;
|
||||||
|
GroupChunkNames.Add("FORM");
|
||||||
|
GroupChunkNames.Add("LIST");
|
||||||
|
GroupChunkNames.Add("CAT");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool IsGroupChunk(string name)
|
||||||
|
{
|
||||||
|
return GroupChunkNames.Contains(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override int ChunkAlignment => 2;
|
||||||
|
}
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
// Copyright (C) 2024 Michael Becker <alcexhim@gmail.com>
|
||||||
|
//
|
||||||
|
// This file is part of editor-dotnet.
|
||||||
|
//
|
||||||
|
// editor-dotnet is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// editor-dotnet is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with editor-dotnet. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
namespace MBS.Editor.Core.DataFormats.FileSystem.IFF;
|
||||||
|
|
||||||
|
public class RIFFDataFormat : IFFDataFormat
|
||||||
|
{
|
||||||
|
public RIFFDataFormat()
|
||||||
|
{
|
||||||
|
GroupChunkNames.Add("RIFF");
|
||||||
|
Endianness = IO.Endianness.LittleEndian;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,205 @@
|
|||||||
|
|
||||||
|
using System.Formats.Asn1;
|
||||||
|
using System.Runtime.InteropServices.Marshalling;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using MBS.Core.Settings;
|
||||||
|
|
||||||
|
namespace MBS.Editor.Core;
|
||||||
|
|
||||||
|
public class INIDataFormat : DataFormat
|
||||||
|
{
|
||||||
|
public char CommentPrefix { get; set; } = ';';
|
||||||
|
|
||||||
|
private static DataFormatMetadata? _dfr = null;
|
||||||
|
public static DataFormatMetadata Metadata
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_dfr == null)
|
||||||
|
{
|
||||||
|
_dfr = new DataFormatMetadata();
|
||||||
|
|
||||||
|
SettingsGroup sg = new SettingsGroup("General", new Setting[]
|
||||||
|
{
|
||||||
|
new TextSetting("CommentPrefix", "Comment Prefix", ";")
|
||||||
|
});
|
||||||
|
_dfr.ExportSettings.SettingsGroups.Add(sg);
|
||||||
|
}
|
||||||
|
return _dfr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void LoadInternal(ObjectModel objectModel, Stream stream)
|
||||||
|
{
|
||||||
|
PropertyListObjectModel? plom = objectModel as PropertyListObjectModel;
|
||||||
|
if (plom == null)
|
||||||
|
throw new ObjectModelNotSupportedException(typeof(PropertyListObjectModel), objectModel?.GetType());
|
||||||
|
|
||||||
|
IPropertyListContainer currentGroup = plom;
|
||||||
|
INIDataFormatToken insideToken = INIDataFormatToken.None;
|
||||||
|
StringBuilder currentString = new StringBuilder();
|
||||||
|
bool escaped = false;
|
||||||
|
|
||||||
|
string currentPropertyName = "";
|
||||||
|
string currentGroupName = "";
|
||||||
|
|
||||||
|
StreamReader sr = new StreamReader(stream);
|
||||||
|
while (!sr.EndOfStream)
|
||||||
|
{
|
||||||
|
int val = sr.Read();
|
||||||
|
if (val == -1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
char c = (char)val;
|
||||||
|
if (insideToken == INIDataFormatToken.Group)
|
||||||
|
{
|
||||||
|
if (c == ']')
|
||||||
|
{
|
||||||
|
insideToken = INIDataFormatToken.None;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
currentGroupName += c;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c == CommentPrefix)
|
||||||
|
{
|
||||||
|
if (insideToken == INIDataFormatToken.None)
|
||||||
|
{
|
||||||
|
insideToken = INIDataFormatToken.Comment;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
currentString.Append(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (c == '"')
|
||||||
|
{
|
||||||
|
if (insideToken == INIDataFormatToken.None)
|
||||||
|
{
|
||||||
|
insideToken = INIDataFormatToken.String;
|
||||||
|
}
|
||||||
|
else if (insideToken == INIDataFormatToken.String && !escaped)
|
||||||
|
{
|
||||||
|
insideToken = INIDataFormatToken.None;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
currentString.Append(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (c == '\\')
|
||||||
|
{
|
||||||
|
if (insideToken == INIDataFormatToken.None || insideToken == INIDataFormatToken.Comment)
|
||||||
|
{
|
||||||
|
currentString.Append(c);
|
||||||
|
}
|
||||||
|
else if (insideToken == INIDataFormatToken.String)
|
||||||
|
{
|
||||||
|
if (!escaped)
|
||||||
|
{
|
||||||
|
escaped = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
currentString.Append(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (c == '\n')
|
||||||
|
{
|
||||||
|
if (currentGroupName != "")
|
||||||
|
{
|
||||||
|
PropertyListGroup group = new PropertyListGroup(currentGroupName);
|
||||||
|
currentGroupName = "";
|
||||||
|
|
||||||
|
plom.Items.Add(group);
|
||||||
|
currentGroup = group;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PropertyListProperty property = new PropertyListProperty(currentPropertyName, currentString.ToString());
|
||||||
|
currentString.Clear();
|
||||||
|
|
||||||
|
currentGroup.Items.Add(property);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (c == '=')
|
||||||
|
{
|
||||||
|
if (insideToken == INIDataFormatToken.None)
|
||||||
|
{
|
||||||
|
currentPropertyName = currentString.ToString();
|
||||||
|
currentString.Clear();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
currentString.Append(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (c == '[')
|
||||||
|
{
|
||||||
|
if (insideToken == INIDataFormatToken.None)
|
||||||
|
{
|
||||||
|
insideToken = INIDataFormatToken.Group;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
currentString.Append(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (c == ']')
|
||||||
|
{
|
||||||
|
if (insideToken != INIDataFormatToken.None)
|
||||||
|
{
|
||||||
|
currentString.Append(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
currentString.Append(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WriteItem(StreamWriter sw, PropertyListItem item)
|
||||||
|
{
|
||||||
|
if (item is PropertyListProperty p)
|
||||||
|
{
|
||||||
|
sw.WriteLine(String.Format("{0}={1}", p.Name, p.Value));
|
||||||
|
}
|
||||||
|
else if (item is PropertyListGroup g)
|
||||||
|
{
|
||||||
|
sw.WriteLine(String.Format("[{0}]", g.Name));
|
||||||
|
foreach (PropertyListItem item2 in g.Items)
|
||||||
|
{
|
||||||
|
WriteItem(sw, item2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (item is PropertyListComment c)
|
||||||
|
{
|
||||||
|
string[] lines = c.Value.Split(System.Environment.NewLine);
|
||||||
|
foreach (string line in lines)
|
||||||
|
{
|
||||||
|
sw.WriteLine(String.Format("{0} {1}", CommentPrefix, line));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void SaveInternal(ObjectModel objectModel, Stream stream)
|
||||||
|
{
|
||||||
|
PropertyListObjectModel? plom = objectModel as PropertyListObjectModel;
|
||||||
|
if (plom == null)
|
||||||
|
throw new ObjectModelNotSupportedException(typeof(PropertyListObjectModel), objectModel?.GetType());
|
||||||
|
|
||||||
|
StreamWriter sw = new StreamWriter(stream);
|
||||||
|
foreach (PropertyListItem item in plom.Items)
|
||||||
|
{
|
||||||
|
WriteItem(sw, item);
|
||||||
|
}
|
||||||
|
sw.Flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
namespace MBS.Editor.Core;
|
||||||
|
|
||||||
|
public enum INIDataFormatToken
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
Comment,
|
||||||
|
String,
|
||||||
|
Group
|
||||||
|
}
|
||||||
@ -609,7 +609,7 @@ public class Reader : ReaderWriterBase
|
|||||||
public int ReadInt24()
|
public int ReadInt24()
|
||||||
{
|
{
|
||||||
byte[] buffer = ReadBytes((uint)3);
|
byte[] buffer = ReadBytes((uint)3);
|
||||||
byte[] _buffer = new byte[3];
|
byte[] _buffer = new byte[4];
|
||||||
if (base.Endianness == Endianness.LittleEndian)
|
if (base.Endianness == Endianness.LittleEndian)
|
||||||
{
|
{
|
||||||
_buffer[0] = buffer[0];
|
_buffer[0] = buffer[0];
|
||||||
@ -1798,31 +1798,6 @@ public class Reader : ReaderWriterBase
|
|||||||
return line;
|
return line;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Closes the current stream and releases any resources (such as sockets and file handles) associated with the current stream.
|
|
||||||
/// </summary>
|
|
||||||
public void Close()
|
|
||||||
{
|
|
||||||
BaseStream.Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Aligns the <see cref="Reader" /> to the specified number of bytes. If the current
|
|
||||||
/// position of the <see cref="Reader" /> is not a multiple of the specified number of bytes,
|
|
||||||
/// the position will be increased by the amount of bytes necessary to bring it to the
|
|
||||||
/// aligned position.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="alignTo">The number of bytes on which to align the <see cref="Reader"/>.</param>
|
|
||||||
/// <param name="extraPadding">Any additional padding bytes that should be included after aligning to the specified boundary.</param>
|
|
||||||
public void Align(int alignTo, int extraPadding = 0)
|
|
||||||
{
|
|
||||||
long paddingCount = ((alignTo - (BaseStream.Position % alignTo)) % alignTo);
|
|
||||||
paddingCount += extraPadding;
|
|
||||||
|
|
||||||
if (BaseStream.Position + paddingCount < BaseStream.Length)
|
|
||||||
BaseStream.Position += paddingCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string ReadStringUntilAny(char[] anyOf)
|
public string ReadStringUntilAny(char[] anyOf)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -66,14 +66,25 @@ public class ReaderWriterBase
|
|||||||
long paddingCount = ((alignTo - (_st.Position % alignTo)) % alignTo);
|
long paddingCount = ((alignTo - (_st.Position % alignTo)) % alignTo);
|
||||||
paddingCount += extraPadding;
|
paddingCount += extraPadding;
|
||||||
|
|
||||||
if (_st.Position == _st.Length)
|
if (paddingCount > 0)
|
||||||
{
|
{
|
||||||
byte[] buffer = new byte[paddingCount];
|
if (_st.Position == _st.Length)
|
||||||
_st.Write(buffer, 0, buffer.Length);
|
{
|
||||||
}
|
byte[] buffer = new byte[paddingCount];
|
||||||
else
|
_st.Write(buffer, 0, buffer.Length);
|
||||||
{
|
}
|
||||||
_st.Position += paddingCount;
|
else
|
||||||
|
{
|
||||||
|
_st.Position += paddingCount;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Closes the current stream and releases any resources (such as sockets and file handles) associated with the current stream.
|
||||||
|
/// </summary>
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
BaseStream.Close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,5 +32,14 @@ public class ObjectModel
|
|||||||
}
|
}
|
||||||
return objectModel;
|
return objectModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static T CastOrThrow<T>(ObjectModel? objectModel) where T : ObjectModel
|
||||||
|
{
|
||||||
|
T om = objectModel as T;
|
||||||
|
if (om == null)
|
||||||
|
{
|
||||||
|
throw new ObjectModelNotSupportedException(typeof(T), objectModel?.GetType());
|
||||||
|
}
|
||||||
|
return om;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
using MBS.Core;
|
||||||
|
|
||||||
namespace MBS.Editor.Core;
|
namespace MBS.Editor.Core;
|
||||||
|
|
||||||
public class ObjectModelNotSupportedException : Exception
|
public class ObjectModelNotSupportedException : Exception
|
||||||
@ -29,9 +31,19 @@ public class ObjectModelNotSupportedException : Exception
|
|||||||
public Type? ExpectedObjectModelType { get; }
|
public Type? ExpectedObjectModelType { get; }
|
||||||
public Type? ActualObjectModelType { get; }
|
public Type? ActualObjectModelType { get; }
|
||||||
|
|
||||||
public ObjectModelNotSupportedException(string? message, Type expectedObjectModelType, Type actualObjectModelType)
|
private static Dictionary<string, string> __c1(Type expected, Type actual)
|
||||||
{
|
{
|
||||||
|
Dictionary<string, string> dict = new Dictionary<string, string>();
|
||||||
|
dict["expected"] = expected.FullName;
|
||||||
|
dict["actual"] = actual.FullName;
|
||||||
|
return dict;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObjectModelNotSupportedException(Type expectedObjectModelType, Type? actualObjectModelType) : this("The object model is not supported (expected $(expected), got $(actual))", expectedObjectModelType, actualObjectModelType) { }
|
||||||
|
public ObjectModelNotSupportedException(string? message, Type expectedObjectModelType, Type? actualObjectModelType) : base(StringExtensions.Format(message, __c1(expectedObjectModelType, actualObjectModelType)))
|
||||||
|
{
|
||||||
|
ExpectedObjectModelType = expectedObjectModelType;
|
||||||
|
ActualObjectModelType = actualObjectModelType;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -0,0 +1,63 @@
|
|||||||
|
// Copyright (C) 2024 Michael Becker <alcexhim@gmail.com>
|
||||||
|
//
|
||||||
|
// This file is part of editor-dotnet.
|
||||||
|
//
|
||||||
|
// editor-dotnet is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// editor-dotnet is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with editor-dotnet. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
namespace MBS.Editor.Core.ObjectModels.Chunked;
|
||||||
|
|
||||||
|
public abstract class Chunk
|
||||||
|
{
|
||||||
|
public class ChunkCollection
|
||||||
|
: System.Collections.ObjectModel.Collection<Chunk>
|
||||||
|
{
|
||||||
|
|
||||||
|
public Chunk? this[string name]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
foreach (Chunk item in this)
|
||||||
|
{
|
||||||
|
if (item.Name == name)
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Chunk? this[string name, string typeName]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
foreach (Chunk item in this)
|
||||||
|
{
|
||||||
|
if (item is GroupChunk g)
|
||||||
|
{
|
||||||
|
if (g.Name == name && g.TypeName == typeName)
|
||||||
|
return g;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Chunk(string name)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
}
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
// Copyright (C) 2024 Michael Becker <alcexhim@gmail.com>
|
||||||
|
//
|
||||||
|
// This file is part of editor-dotnet.
|
||||||
|
//
|
||||||
|
// editor-dotnet is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// editor-dotnet is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with editor-dotnet. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
namespace MBS.Editor.Core.ObjectModels.Chunked;
|
||||||
|
|
||||||
|
public class ChunkedObjectModel : ObjectModel, IChunkContainer
|
||||||
|
{
|
||||||
|
public Chunk.ChunkCollection Chunks { get; } = new Chunk.ChunkCollection();
|
||||||
|
}
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
// Copyright (C) 2024 Michael Becker <alcexhim@gmail.com>
|
||||||
|
//
|
||||||
|
// This file is part of editor-dotnet.
|
||||||
|
//
|
||||||
|
// editor-dotnet is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// editor-dotnet is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with editor-dotnet. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
using MBS.Editor.Core.ObjectModels.FileSystem;
|
||||||
|
|
||||||
|
namespace MBS.Editor.Core.ObjectModels.Chunked;
|
||||||
|
|
||||||
|
public class DataChunk : Chunk
|
||||||
|
{
|
||||||
|
public DataChunk(string name) : base(name)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
public FileSource? Source { get; set; } = null;
|
||||||
|
}
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
// Copyright (C) 2024 Michael Becker <alcexhim@gmail.com>
|
||||||
|
//
|
||||||
|
// This file is part of editor-dotnet.
|
||||||
|
//
|
||||||
|
// editor-dotnet is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// editor-dotnet is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with editor-dotnet. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
namespace MBS.Editor.Core.ObjectModels.Chunked;
|
||||||
|
|
||||||
|
public class GroupChunk : Chunk, IChunkContainer
|
||||||
|
{
|
||||||
|
public GroupChunk(string name, string typeName) : base(name)
|
||||||
|
{
|
||||||
|
TypeName = typeName;
|
||||||
|
}
|
||||||
|
public string TypeName { get; set; }
|
||||||
|
|
||||||
|
public Chunk.ChunkCollection Chunks { get; } = new Chunk.ChunkCollection();
|
||||||
|
}
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
// Copyright (C) 2024 Michael Becker <alcexhim@gmail.com>
|
||||||
|
//
|
||||||
|
// This file is part of editor-dotnet.
|
||||||
|
//
|
||||||
|
// editor-dotnet is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// editor-dotnet is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with editor-dotnet. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
namespace MBS.Editor.Core.ObjectModels.Chunked;
|
||||||
|
|
||||||
|
public interface IChunkContainer
|
||||||
|
{
|
||||||
|
Chunk.ChunkCollection Chunks { get; }
|
||||||
|
}
|
||||||
@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
namespace MBS.Editor.Core.ObjectModels.FileSystem;
|
namespace MBS.Editor.Core.ObjectModels.FileSystem;
|
||||||
|
|
||||||
public abstract class FileSource
|
public abstract class FileSource
|
||||||
@ -22,4 +23,11 @@ public abstract class FileSource
|
|||||||
*/
|
*/
|
||||||
return msInput.ToArray();
|
return msInput.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Stream GetStream()
|
||||||
|
{
|
||||||
|
byte[] data = GetData();
|
||||||
|
MemoryStream msInput = new MemoryStream(data);
|
||||||
|
return msInput;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -13,7 +13,7 @@ public class EmbeddedFileSource : FileSource
|
|||||||
}
|
}
|
||||||
protected override byte[] GetDataInternal(long offset, long length)
|
protected override byte[] GetDataInternal(long offset, long length)
|
||||||
{
|
{
|
||||||
if (Offset + offset + length >= Stream.Length)
|
if (Offset + offset + length > Stream.Length)
|
||||||
{
|
{
|
||||||
throw new ArgumentOutOfRangeException("embedded file offset + requested offset + requested length extends past the actual length of the underlying stream");
|
throw new ArgumentOutOfRangeException("embedded file offset + requested offset + requested length extends past the actual length of the underlying stream");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -178,4 +178,14 @@ public class FileSystemItemCollection
|
|||||||
}
|
}
|
||||||
return list.ToArray();
|
return list.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public T? GetChild<T>(string v) where T : FileSystemItem
|
||||||
|
{
|
||||||
|
FileSystemItem? item = this[v];
|
||||||
|
if (item is T)
|
||||||
|
{
|
||||||
|
return (T)item;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,9 @@
|
|||||||
|
namespace MBS.Editor.Core;
|
||||||
|
|
||||||
|
public interface IPropertyListContainer
|
||||||
|
{
|
||||||
|
|
||||||
|
PropertyListItem.PropertyListItemCollection Items { get; }
|
||||||
|
IPropertyListContainer? Parent { get; }
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
namespace MBS.Editor.Core;
|
||||||
|
|
||||||
|
public class PropertyListComment : PropertyListItem
|
||||||
|
{
|
||||||
|
public string Value { get; set; } = "";
|
||||||
|
}
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
namespace MBS.Editor.Core;
|
||||||
|
|
||||||
|
public class PropertyListGroup : PropertyListItem, IPropertyListContainer
|
||||||
|
{
|
||||||
|
|
||||||
|
public PropertyListItem.PropertyListItemCollection Items { get; }
|
||||||
|
|
||||||
|
public PropertyListGroup(string name)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
Items = new PropertyListItemCollection(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,58 @@
|
|||||||
|
namespace MBS.Editor.Core;
|
||||||
|
|
||||||
|
public abstract class PropertyListItem
|
||||||
|
{
|
||||||
|
|
||||||
|
public class PropertyListItemCollection
|
||||||
|
: System.Collections.ObjectModel.Collection<PropertyListItem>
|
||||||
|
{
|
||||||
|
private IPropertyListContainer _Parent = null;
|
||||||
|
|
||||||
|
public PropertyListItemCollection(IPropertyListContainer parent)
|
||||||
|
{
|
||||||
|
_Parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void ClearItems()
|
||||||
|
{
|
||||||
|
foreach (PropertyListItem item in this)
|
||||||
|
{
|
||||||
|
item.Parent = null;
|
||||||
|
}
|
||||||
|
base.ClearItems();
|
||||||
|
}
|
||||||
|
protected override void InsertItem(int index, PropertyListItem item)
|
||||||
|
{
|
||||||
|
base.InsertItem(index, item);
|
||||||
|
item.Parent = _Parent;
|
||||||
|
}
|
||||||
|
protected override void RemoveItem(int index)
|
||||||
|
{
|
||||||
|
this[index].Parent = null;
|
||||||
|
base.RemoveItem(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name { get; set; } = "";
|
||||||
|
public IPropertyListContainer? Parent { get; internal set; }
|
||||||
|
|
||||||
|
public PropertyListObjectModel? ParentObjectModel
|
||||||
|
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
IPropertyListContainer? parent = Parent;
|
||||||
|
while (parent != null)
|
||||||
|
{
|
||||||
|
if (parent is PropertyListObjectModel)
|
||||||
|
{
|
||||||
|
return (parent as PropertyListObjectModel);
|
||||||
|
}
|
||||||
|
parent = parent.Parent;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
using MBS.Editor.Core.ObjectModels.PropertyList.Schema;
|
||||||
|
|
||||||
|
namespace MBS.Editor.Core;
|
||||||
|
|
||||||
|
public class PropertyListObjectModel : ObjectModel, IPropertyListContainer
|
||||||
|
{
|
||||||
|
|
||||||
|
public PropertyListItem.PropertyListItemCollection Items { get; }
|
||||||
|
public PropertyListSchema? Schema { get; set; } = null;
|
||||||
|
|
||||||
|
public IPropertyListContainer? Parent => null;
|
||||||
|
|
||||||
|
public PropertyListObjectModel()
|
||||||
|
{
|
||||||
|
Items = new PropertyListItem.PropertyListItemCollection(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,41 @@
|
|||||||
|
using MBS.Editor.Core.ObjectModels.PropertyList.Schema;
|
||||||
|
|
||||||
|
namespace MBS.Editor.Core;
|
||||||
|
|
||||||
|
public class PropertyListProperty : PropertyListItem
|
||||||
|
{
|
||||||
|
|
||||||
|
private object? _Value = null;
|
||||||
|
public object? Value
|
||||||
|
{
|
||||||
|
get { return _Value; }
|
||||||
|
set { _Value = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public T? GetValueAs<T>()
|
||||||
|
{
|
||||||
|
PropertyListObjectModel? plom = ParentObjectModel;
|
||||||
|
if (plom != null)
|
||||||
|
{
|
||||||
|
PropertyListSchema? schema = plom.Schema;
|
||||||
|
if (schema != null)
|
||||||
|
{
|
||||||
|
foreach (PropertyDefinition def in schema.PropertyDefinitions)
|
||||||
|
{
|
||||||
|
if (def.PropertyName == Name)
|
||||||
|
{
|
||||||
|
//return def.ConvertTo<T>(def.DataType, Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return default(T);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PropertyListProperty(string name, object value)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
Value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
namespace MBS.Editor.Core.ObjectModels.PropertyList.Schema;
|
||||||
|
|
||||||
|
public class PropertyValueConverter
|
||||||
|
{
|
||||||
|
public class PropertyValueConverterCollection
|
||||||
|
: System.Collections.ObjectModel.Collection<PropertyValueConverter>
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public class PropertyValueConverter<TInput, TOutput> : PropertyValueConverter
|
||||||
|
{
|
||||||
|
private Func<TInput, TOutput> __convertTo = null;
|
||||||
|
private Func<TOutput, TInput> __convertFrom = null;
|
||||||
|
public PropertyValueConverter(Func<TInput, TOutput> convertTo, Func<TOutput, TInput> convertFrom)
|
||||||
|
{
|
||||||
|
__convertTo = convertTo;
|
||||||
|
__convertFrom = convertFrom;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TOutput? ConvertTo(TInput value)
|
||||||
|
{
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,41 @@
|
|||||||
|
|
||||||
|
using System.Diagnostics.Contracts;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using MBS.Core.Collections.Generic;
|
||||||
|
|
||||||
|
namespace MBS.Editor.Core.ObjectModels.PropertyList.Schema;
|
||||||
|
|
||||||
|
public class PropertyDefinition
|
||||||
|
{
|
||||||
|
public class PropertyDefinitionCollection
|
||||||
|
: System.Collections.ObjectModel.Collection<PropertyDefinition>
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public string PropertyName { get; }
|
||||||
|
public Type DataType { get; }
|
||||||
|
public PropertyValueConverter.PropertyValueConverterCollection Converters { get; } = new PropertyValueConverter.PropertyValueConverterCollection();
|
||||||
|
|
||||||
|
public PropertyDefinition(string propertyName, string displayTitle, Type dataType, PropertyValueConverter[]? valueConverters = null)
|
||||||
|
{
|
||||||
|
PropertyName = propertyName;
|
||||||
|
DataType = dataType;
|
||||||
|
if (valueConverters != null)
|
||||||
|
{
|
||||||
|
Converters.AddRange(valueConverters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public TTo ConvertTo<TFrom, TTo>(TFrom value)
|
||||||
|
{
|
||||||
|
foreach (PropertyValueConverter converter in Converters)
|
||||||
|
{
|
||||||
|
if (converter is PropertyValueConverter<TFrom, TTo> cvt)
|
||||||
|
{
|
||||||
|
return cvt.ConvertTo(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
using MBS.Core.Collections.Generic;
|
||||||
|
|
||||||
|
namespace MBS.Editor.Core.ObjectModels.PropertyList.Schema;
|
||||||
|
|
||||||
|
public class PropertyListSchema
|
||||||
|
{
|
||||||
|
public PropertyDefinition.PropertyDefinitionCollection PropertyDefinitions { get; } = new PropertyDefinition.PropertyDefinitionCollection();
|
||||||
|
|
||||||
|
public PropertyListSchema(PropertyDefinition[] propertyDefinitions)
|
||||||
|
{
|
||||||
|
PropertyDefinitions.AddRange(propertyDefinitions);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,65 @@
|
|||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace MBS.Editor.Testing;
|
||||||
|
|
||||||
|
public class EmbeddedResourceTest
|
||||||
|
{
|
||||||
|
private System.Collections.Generic.Dictionary<string, System.IO.Stream> testDataStreams = new System.Collections.Generic.Dictionary<string, System.IO.Stream>();
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void SetUp()
|
||||||
|
{
|
||||||
|
InitializeResources();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void InitializeResources()
|
||||||
|
{
|
||||||
|
MBS.Core.Reflection.ManifestResourceStream[] strms = MBS.Core.Reflection.ManifestResourceStream.GetManifestResourceStreamsForAssembly(this.GetType().Assembly);
|
||||||
|
for (int i = 0; i < strms.Length; i++)
|
||||||
|
{
|
||||||
|
testDataStreams[strms[i].Name] = strms[i].Stream;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Stream? CreateResourceStream(string name)
|
||||||
|
{
|
||||||
|
if (TryCreateResourceStream(name, out Stream? st))
|
||||||
|
{
|
||||||
|
return st;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected bool TryCreateResourceStream(string name, out System.IO.Stream? st)
|
||||||
|
{
|
||||||
|
st = null;
|
||||||
|
if (testDataStreams.ContainsKey(name))
|
||||||
|
{
|
||||||
|
System.IO.Stream TEST_STREAM = testDataStreams[name];
|
||||||
|
st = TEST_STREAM;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.Error.WriteLine("test data stream not found: '{0}'", name);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void SampleStreamTest(string streamName)
|
||||||
|
{
|
||||||
|
if (TryCreateResourceStream(streamName, out System.IO.Stream? st))
|
||||||
|
{
|
||||||
|
SampleStreamTest(st);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Assert.Ignore();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void SampleStreamTest(Stream st)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="NUnit" Version="3.13.3" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\..\..\framework-dotnet\framework-dotnet\src\lib\MBS.Core\MBS.Core.csproj" />
|
||||||
|
<ProjectReference Include="..\MBS.Editor.Core\MBS.Editor.Core.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
<IsTestProject>false</IsTestProject>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@ -1,14 +1,38 @@
|
|||||||
namespace MBS.Editor.UserInterface;
|
namespace MBS.Editor.UserInterface;
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using MBS.Core;
|
||||||
using MBS.Desktop;
|
using MBS.Desktop;
|
||||||
|
using MBS.Desktop.Controls;
|
||||||
|
|
||||||
public class EditorApplication : DesktopApplication
|
public class EditorApplication : DesktopApplication
|
||||||
{
|
{
|
||||||
|
protected override void OnStartup(EventArgs e)
|
||||||
|
{
|
||||||
|
base.OnStartup(e);
|
||||||
|
|
||||||
protected override int StartInternal()
|
Console.WriteLine("editor: OnStartup");
|
||||||
{
|
|
||||||
return 0;
|
this.Commands.Add(new Command("FileExit", "E_xit"));
|
||||||
}
|
this.Commands.Add(new Command("File", "_File", new CommandItem[]
|
||||||
|
{
|
||||||
|
new CommandReferenceCommandItem("FileExit")
|
||||||
|
}));
|
||||||
|
|
||||||
|
this.AttachCommandEventHandler("FileExit", delegate (object sender, CommandEventArgs e)
|
||||||
|
{
|
||||||
|
this.Stop();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnActivated(ApplicationActivatedEventArgs e)
|
||||||
|
{
|
||||||
|
base.OnActivated(e);
|
||||||
|
|
||||||
|
Console.WriteLine("editor: OnActivated");
|
||||||
|
|
||||||
|
EditorWindow window = new EditorWindow();
|
||||||
|
window.Show();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,20 @@
|
|||||||
|
namespace MBS.Editor.UserInterface;
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using MBS.Core;
|
||||||
|
using MBS.Desktop;
|
||||||
|
using MBS.Desktop.Controls;
|
||||||
|
|
||||||
|
// [ContainerLayout(typeof(EditorWindow), "MBS.Editor.UserInterface.EditorWindow.glade")]
|
||||||
|
public class EditorWindow : MainWindow
|
||||||
|
{
|
||||||
|
|
||||||
|
public EditorWindow()
|
||||||
|
{
|
||||||
|
Title = "MBS Editor";
|
||||||
|
DefaultSize = new Core.Drawing.Dimension2D(1000, 700);
|
||||||
|
|
||||||
|
Controls.Add(new Label("<b>Strong Bad!</b>") { UseMarkup = true });
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\..\..\framework-dotnet\framework-dotnet\src\lib\MBS.Core\MBS.Core.csproj" />
|
<ProjectReference Include="..\..\..\..\framework-dotnet\framework-dotnet\src\lib\MBS.Core\MBS.Core.csproj" />
|
||||||
<ProjectReference Include="..\..\..\..\framework-dotnet\framework-dotnet\src\lib\MBS.Desktop\MBS.Desktop.csproj" />
|
<ProjectReference Include="..\..\..\..\desktop-framework-dotnet\desktop-framework-dotnet\src\lib\MBS.Desktop\MBS.Desktop.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
|
|||||||
31
editor-dotnet/src/lib/MBS.Editor.Web/Controls/PageHeader.cs
Normal file
31
editor-dotnet/src/lib/MBS.Editor.Web/Controls/PageHeader.cs
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// Copyright (C) 2024 Michael Becker <alcexhim@gmail.com>
|
||||||
|
//
|
||||||
|
// This file is part of editor-dotnet.
|
||||||
|
//
|
||||||
|
// editor-dotnet is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// editor-dotnet is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with editor-dotnet. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
using MBS.Web.UI;
|
||||||
|
|
||||||
|
namespace MBS.Editor.Web.Controls;
|
||||||
|
|
||||||
|
public class PageHeader : WebControl
|
||||||
|
{
|
||||||
|
protected override string TagName => "div";
|
||||||
|
protected override IEnumerable<string> GetStyleClasses()
|
||||||
|
{
|
||||||
|
return new string[] { "uwt-page-header" };
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
14
editor-dotnet/src/lib/MBS.Editor.Web/MBS.Editor.Web.csproj
Normal file
14
editor-dotnet/src/lib/MBS.Editor.Web/MBS.Editor.Web.csproj
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="../../../../framework-dotnet/framework-dotnet/src/lib/MBS.Core/MBS.Core.csproj" />
|
||||||
|
<ProjectReference Include="../../../../web-framework-dotnet/src/lib/MBS.Web/MBS.Web.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
123
editor-dotnet/src/lib/MBS.Editor.Web/Pages/MainPage.cs
Normal file
123
editor-dotnet/src/lib/MBS.Editor.Web/Pages/MainPage.cs
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
// Copyright (C) 2024 Michael Becker <alcexhim@gmail.com>
|
||||||
|
//
|
||||||
|
// This file is part of editor-dotnet.
|
||||||
|
//
|
||||||
|
// editor-dotnet is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// editor-dotnet is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with editor-dotnet. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
using MBS.Web;
|
||||||
|
using MBS.Web.UI;
|
||||||
|
|
||||||
|
using MBS.Editor.Web.Controls;
|
||||||
|
using MBS.Web.UI.HtmlControls;
|
||||||
|
using System.Text;
|
||||||
|
using MBS.Core.Drawing;
|
||||||
|
using MBS.Web.UI.WebControls;
|
||||||
|
using MBS.Core;
|
||||||
|
|
||||||
|
namespace MBS.Editor.Web.Pages;
|
||||||
|
|
||||||
|
public class MainPage : WebPage
|
||||||
|
{
|
||||||
|
private class WebStyleSheet2
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public MainPage()
|
||||||
|
{
|
||||||
|
Dictionary<string, Dictionary<string, object>> dict = new Dictionary<string, Dictionary<string, object>>();
|
||||||
|
/*
|
||||||
|
WebStyleSheet2 wss = new WebStyleSheet2();
|
||||||
|
|
||||||
|
WebStyleSheetSelector selector = WebStyleSheetSelector.Parse("div.uwt-page-header");
|
||||||
|
|
||||||
|
wss.Selectors.Add("div", "uwt-page-header");
|
||||||
|
*/
|
||||||
|
|
||||||
|
dict["div.uwt-page-header"] = new Dictionary<string, object>();
|
||||||
|
dict["div.uwt-page-header"]["border-bottom"] = new object[] { Measurement.Parse("1px"), "solid", Color.FromString("#E0E0E0") };
|
||||||
|
|
||||||
|
StyleSheets.Add(WebStyleSheet.FromContent("text/css", FormatCss(dict)));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override IEnumerable<Control> GetHeaderControls()
|
||||||
|
{
|
||||||
|
return new Control[]
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private string FormatCss(Dictionary<string, Dictionary<string, object>> dict)
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
foreach (KeyValuePair<string, Dictionary<string, object>> kvp in dict)
|
||||||
|
{
|
||||||
|
sb.Append(kvp.Key);
|
||||||
|
sb.Append(" { ");
|
||||||
|
foreach (KeyValuePair<string, object> kvp2 in kvp.Value)
|
||||||
|
{
|
||||||
|
sb.Append(kvp2.Key);
|
||||||
|
sb.Append(": ");
|
||||||
|
|
||||||
|
if (kvp2.Value is Color)
|
||||||
|
{
|
||||||
|
sb.Append(((Color)kvp2.Value).ToHexadecimalHTML());
|
||||||
|
}
|
||||||
|
else if (kvp2.Value is string)
|
||||||
|
{
|
||||||
|
sb.Append("\"");
|
||||||
|
sb.Append(kvp2.Value);
|
||||||
|
sb.Append("\"");
|
||||||
|
}
|
||||||
|
else if (kvp2.Value is object[])
|
||||||
|
{
|
||||||
|
object[] objs = (object[])kvp2.Value;
|
||||||
|
for (int i = 0; i < objs.Length; i++)
|
||||||
|
{
|
||||||
|
sb.Append(objs[i]);
|
||||||
|
if (i < objs.Length - 1)
|
||||||
|
{
|
||||||
|
sb.Append(' ');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sb.Append(kvp2.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sb.Append(" } ");
|
||||||
|
}
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override IEnumerable<Control> GetBodyControls()
|
||||||
|
{
|
||||||
|
CommandBar cb = new CommandBar();
|
||||||
|
cb.ClientId = "mainToolbar";
|
||||||
|
cb.Items.Add(new CommandReferenceCommandItem("FileOpen"));
|
||||||
|
|
||||||
|
return new Control[]
|
||||||
|
{
|
||||||
|
new PageHeader(),
|
||||||
|
cb
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
namespace MBS.Editor.Plugins.Kronosaur;
|
||||||
|
|
||||||
|
public class Class1
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@ -0,0 +1,70 @@
|
|||||||
|
using MBS.Editor.Core;
|
||||||
|
using MBS.Editor.Core.ObjectModels.PropertyList.Schema;
|
||||||
|
using MBS.Editor.Plugins.Mekada.DataFormats.PropertyList;
|
||||||
|
|
||||||
|
namespace MBS.Editor.Plugins.Mekada.DataFormats.Mechanic;
|
||||||
|
|
||||||
|
public class MEKDataFormat : MEKBaseDataFormat
|
||||||
|
{
|
||||||
|
protected override void BeforeLoadInternal(Stack<ObjectModel> objectModels)
|
||||||
|
{
|
||||||
|
base.BeforeLoadInternal(objectModels);
|
||||||
|
|
||||||
|
PropertyListObjectModel plom = new PropertyListObjectModel();
|
||||||
|
plom.Schema = new PropertyListSchema(new PropertyDefinition[]
|
||||||
|
{
|
||||||
|
new PropertyDefinition("1403", "Money", typeof(float)),
|
||||||
|
new PropertyDefinition("1405", "Total Time Played", typeof(int), new PropertyValueConverter[]
|
||||||
|
{
|
||||||
|
new PropertyValueConverter<int, TimeSpan>(delegate (int value)
|
||||||
|
{
|
||||||
|
TimeSpan ts = new TimeSpan(0, 0, value);
|
||||||
|
return ts;
|
||||||
|
},
|
||||||
|
delegate (TimeSpan value)
|
||||||
|
{
|
||||||
|
int seconds = (value.Hours * 3600) + (value.Minutes * 60) + (value.Seconds);
|
||||||
|
return seconds;
|
||||||
|
})
|
||||||
|
})
|
||||||
|
});
|
||||||
|
objectModels.Push(plom);
|
||||||
|
}
|
||||||
|
protected override void AfterLoadInternal(Stack<ObjectModel> objectModels)
|
||||||
|
{
|
||||||
|
base.AfterLoadInternal(objectModels);
|
||||||
|
|
||||||
|
PropertyListObjectModel? plom = objectModels.Pop() as PropertyListObjectModel;
|
||||||
|
if (plom == null)
|
||||||
|
throw new ObjectModelNotSupportedException(typeof(PropertyListObjectModel), plom?.GetType());
|
||||||
|
|
||||||
|
Console.WriteLine("{ ");
|
||||||
|
foreach (PropertyListItem item in plom.Items)
|
||||||
|
{
|
||||||
|
RenderItem(item);
|
||||||
|
}
|
||||||
|
Console.WriteLine(" }");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RenderItem(PropertyListItem item)
|
||||||
|
{
|
||||||
|
if (item is PropertyListGroup grp)
|
||||||
|
{
|
||||||
|
Console.WriteLine("\"" + grp.Name + "\": { ");
|
||||||
|
foreach (PropertyListItem item2 in grp.Items)
|
||||||
|
{
|
||||||
|
RenderItem(item2);
|
||||||
|
if (grp.Items.IndexOf(item2) < grp.Items.Count - 1)
|
||||||
|
{
|
||||||
|
Console.Write(", ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Console.WriteLine(" }");
|
||||||
|
}
|
||||||
|
else if (item is PropertyListProperty prop)
|
||||||
|
{
|
||||||
|
Console.Write("\"" + item.Name + "\": \"" + prop.Value.ToString() + "\"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,92 @@
|
|||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using MBS.Editor.Core;
|
||||||
|
using MBS.Editor.Core.IO;
|
||||||
|
|
||||||
|
namespace MBS.Editor.Plugins.Mekada.DataFormats.PropertyList;
|
||||||
|
|
||||||
|
public class MEKBaseDataFormat : DataFormat
|
||||||
|
{
|
||||||
|
protected override void LoadInternal(ObjectModel objectModel, Stream stream)
|
||||||
|
{
|
||||||
|
PropertyListObjectModel? plom = objectModel as PropertyListObjectModel;
|
||||||
|
if (plom == null)
|
||||||
|
throw new ObjectModelNotSupportedException(typeof(PropertyListObjectModel), objectModel?.GetType());
|
||||||
|
|
||||||
|
Reader r = new Reader(stream);
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
PropertyListItem item = ReadItem(r, plom);
|
||||||
|
if (item == null)
|
||||||
|
break;
|
||||||
|
|
||||||
|
plom.Items.Add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private PropertyListItem? ReadItem(Reader r, IPropertyListContainer parent)
|
||||||
|
{
|
||||||
|
long start = r.BaseStream.Position;
|
||||||
|
|
||||||
|
ushort index = r.ReadUInt16();
|
||||||
|
MEKPropertyType type = (MEKPropertyType) r.ReadUInt16();
|
||||||
|
int length = r.ReadInt32();
|
||||||
|
if (index == 0 && type == MEKPropertyType.None && length == 0)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (type == MEKPropertyType.Group)
|
||||||
|
{
|
||||||
|
PropertyListGroup group = new PropertyListGroup(index.ToString());
|
||||||
|
|
||||||
|
while (r.BaseStream.Position < length + start)
|
||||||
|
{
|
||||||
|
PropertyListItem? item = ReadItem(r, group);
|
||||||
|
if (item != null)
|
||||||
|
{
|
||||||
|
group.Items.Add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
else if (type == MEKPropertyType.Float)
|
||||||
|
{
|
||||||
|
if (length == 4)
|
||||||
|
{
|
||||||
|
float value = r.ReadSingle();
|
||||||
|
return new PropertyListProperty(index.ToString(), value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (type == MEKPropertyType.Int32)
|
||||||
|
{
|
||||||
|
if (length == 4)
|
||||||
|
{
|
||||||
|
int value = r.ReadInt32();
|
||||||
|
return new PropertyListProperty(index.ToString(), value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (type == MEKPropertyType.String)
|
||||||
|
{
|
||||||
|
string value = r.ReadFixedLengthString(length);
|
||||||
|
return new PropertyListProperty(index.ToString(), value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
byte[] data = r.ReadBytes(length);
|
||||||
|
return new PropertyListProperty(index.ToString(), data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void SaveInternal(ObjectModel objectModel, Stream stream)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
namespace MBS.Editor.Plugins.Mekada;
|
||||||
|
|
||||||
|
public enum MEKPropertyType : ushort
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
Int32 = 8192,
|
||||||
|
Float = 16384,
|
||||||
|
String = 24576,
|
||||||
|
Group = 32768
|
||||||
|
}
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\lib\MBS.Editor.Core\MBS.Editor.Core.csproj" />
|
||||||
|
<ProjectReference Include="..\..\..\..\framework-dotnet\framework-dotnet\src\lib\MBS.Core\MBS.Core.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
using MBS.Editor.Core;
|
||||||
|
|
||||||
|
namespace MBS.Editor.Plugins.Mekada;
|
||||||
|
|
||||||
|
public class MechanicObjectModel : ObjectModel
|
||||||
|
{
|
||||||
|
public string Name { get; set; } = "";
|
||||||
|
|
||||||
|
public float Money { get; set; } = 0.0f;
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,143 @@
|
|||||||
|
//
|
||||||
|
// MIDICommand.cs - represents a command in a MIDI synthesized audio file
|
||||||
|
//
|
||||||
|
// Author:
|
||||||
|
// Michael Becker <alcexhim@gmail.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2019-2020 Mike Becker's Software
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
namespace MBS.Editor.Plugins.Multimedia.DataFormats.Audio.Synthesized.MIDI;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a command in a MIDI synthesized audio file.
|
||||||
|
/// </summary>
|
||||||
|
public class MIDICommand
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the type of the <see cref="MIDICommand" /> to send.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The type of the <see cref="MIDICommand" /> to send.</value>
|
||||||
|
public MIDICommandType CommandType
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
MIDICommandType result;
|
||||||
|
switch (Command)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
{
|
||||||
|
result = MIDICommandType.None;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
case 8:
|
||||||
|
{
|
||||||
|
result = MIDICommandType.NoteOff;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
case 9:
|
||||||
|
{
|
||||||
|
result = MIDICommandType.NoteOn;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
case 10:
|
||||||
|
{
|
||||||
|
result = MIDICommandType.KeyAfterTouch;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
case 11:
|
||||||
|
{
|
||||||
|
result = MIDICommandType.ControlChange;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
case 12:
|
||||||
|
{
|
||||||
|
result = MIDICommandType.ProgramChange;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
case 13:
|
||||||
|
{
|
||||||
|
result = MIDICommandType.ChannelAfterTouch;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
case 14:
|
||||||
|
{
|
||||||
|
result = MIDICommandType.PitchWheelChange;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = MIDICommandType.Unknown;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
switch (value)
|
||||||
|
{
|
||||||
|
case MIDICommandType.None:
|
||||||
|
{
|
||||||
|
Command = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case MIDICommandType.NoteOff:
|
||||||
|
{
|
||||||
|
Command = 8;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case MIDICommandType.NoteOn:
|
||||||
|
{
|
||||||
|
Command = 9;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case MIDICommandType.KeyAfterTouch:
|
||||||
|
{
|
||||||
|
Command = 10;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case MIDICommandType.ControlChange:
|
||||||
|
{
|
||||||
|
Command = 11;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case MIDICommandType.ProgramChange:
|
||||||
|
{
|
||||||
|
Command = 12;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case MIDICommandType.ChannelAfterTouch:
|
||||||
|
{
|
||||||
|
Command = 13;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case MIDICommandType.PitchWheelChange:
|
||||||
|
{
|
||||||
|
Command = 14;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Command = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the channel on which to send this <see cref="MIDICommand" />.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The channel on which to send this <see cref="MIDICommand" />.</value>
|
||||||
|
public byte Channel { get; set; } = 0;
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the value of the <see cref="MIDICommand" /> to send.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The value of the <see cref="MIDICommand" /> to send.</value>
|
||||||
|
public byte Command { get; set; } = 0;
|
||||||
|
}
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
//
|
||||||
|
// MIDICommandType.cs - indicates the type of MIDI command
|
||||||
|
//
|
||||||
|
// Author:
|
||||||
|
// Michael Becker <alcexhim@gmail.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2019-2020 Mike Becker's Software
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
namespace MBS.Editor.Plugins.Multimedia.DataFormats.Audio.Synthesized.MIDI;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates the type of MIDI command.
|
||||||
|
/// </summary>
|
||||||
|
public enum MIDICommandType
|
||||||
|
{
|
||||||
|
Unknown = -1,
|
||||||
|
None,
|
||||||
|
NoteOff = 8,
|
||||||
|
NoteOn,
|
||||||
|
KeyAfterTouch,
|
||||||
|
ControlChange,
|
||||||
|
ProgramChange,
|
||||||
|
ChannelAfterTouch,
|
||||||
|
PitchWheelChange
|
||||||
|
}
|
||||||
@ -0,0 +1,353 @@
|
|||||||
|
// Copyright (C) 2024 Michael Becker <alcexhim@gmail.com>
|
||||||
|
//
|
||||||
|
// This file is part of editor-dotnet.
|
||||||
|
//
|
||||||
|
// editor-dotnet is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// editor-dotnet is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with editor-dotnet. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Reflection;
|
||||||
|
using MBS.Core;
|
||||||
|
using MBS.Editor.Core;
|
||||||
|
using MBS.Editor.Core.DataFormats.FileSystem.Chunked;
|
||||||
|
using MBS.Editor.Core.IO;
|
||||||
|
using MBS.Editor.Core.ObjectModels.Chunked;
|
||||||
|
using MBS.Editor.Core.ObjectModels.FileSystem;
|
||||||
|
using MBS.Editor.Core.ObjectModels.FileSystem.FileSources;
|
||||||
|
using MBS.Editor.Plugins.Multimedia.ObjectModels.Audio;
|
||||||
|
using MBS.Editor.Plugins.Multimedia.ObjectModels.Audio.Synthesized;
|
||||||
|
|
||||||
|
namespace MBS.Editor.Plugins.Multimedia.DataFormats.Audio.Synthesized.MIDI;
|
||||||
|
|
||||||
|
public class MIDIDataFormat : ChunkedDataFormat
|
||||||
|
{
|
||||||
|
public MIDIDataFormat()
|
||||||
|
{
|
||||||
|
Endianness = Endianness.BigEndian;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void BeforeLoadInternal(Stack<ObjectModel> objectModels)
|
||||||
|
{
|
||||||
|
base.BeforeLoadInternal(objectModels);
|
||||||
|
objectModels.Push(new ChunkedObjectModel());
|
||||||
|
}
|
||||||
|
protected override void AfterLoadInternal(Stack<ObjectModel> objectModels)
|
||||||
|
{
|
||||||
|
base.AfterLoadInternal(objectModels);
|
||||||
|
|
||||||
|
ChunkedObjectModel chunked = ObjectModel.CastOrThrow<ChunkedObjectModel>(objectModels.Pop());
|
||||||
|
SynthesizedAudioObjectModel audio = ObjectModel.CastOrThrow<SynthesizedAudioObjectModel>(objectModels.Pop());
|
||||||
|
|
||||||
|
System.Collections.Generic.Dictionary<int, SynthesizedAudioCommandNote> notesForNoteNumber = new System.Collections.Generic.Dictionary<int, SynthesizedAudioCommandNote>();
|
||||||
|
foreach (Chunk c in chunked.Chunks)
|
||||||
|
{
|
||||||
|
if (c.Name == "MThd")
|
||||||
|
{
|
||||||
|
Stream s = ((DataChunk)c).Source.GetStream();
|
||||||
|
Reader r = new Reader(s);
|
||||||
|
r.Endianness = Endianness.BigEndian;
|
||||||
|
|
||||||
|
ushort format = r.ReadUInt16();
|
||||||
|
ushort trackCount = r.ReadUInt16();
|
||||||
|
ushort tickdiv = r.ReadUInt16();
|
||||||
|
}
|
||||||
|
else if (c.Name == "MTrk")
|
||||||
|
{
|
||||||
|
int ofs = 0;
|
||||||
|
Stream s = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
s = ((DataChunk)c).Source.GetStream();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Reader r = new Reader(s);
|
||||||
|
r.Endianness = Endianness.BigEndian;
|
||||||
|
|
||||||
|
SynthesizedAudioTrack track = new SynthesizedAudioTrack();
|
||||||
|
|
||||||
|
while (!r.BaseStream.EndOfStream())
|
||||||
|
{
|
||||||
|
int deltaTime = r.ReadVariableLengthInt32();
|
||||||
|
MIDIEventType commandAndChannel = (MIDIEventType) r.ReadByte();
|
||||||
|
byte channel = (byte)((byte)commandAndChannel & (byte)MIDIEventType.MIDIChannelMask);
|
||||||
|
MIDIEventType command = (MIDIEventType)((byte)commandAndChannel >> 4);
|
||||||
|
|
||||||
|
if (commandAndChannel == MIDIEventType.Meta)
|
||||||
|
{
|
||||||
|
// this is special cased because it does not include a channel number
|
||||||
|
MIDIMetaEventType metaEventType = (MIDIMetaEventType)r.ReadByte();
|
||||||
|
int length = r.ReadVariableLengthInt32();
|
||||||
|
switch (metaEventType)
|
||||||
|
{
|
||||||
|
case MIDIMetaEventType.Text:
|
||||||
|
{
|
||||||
|
string text = r.ReadFixedLengthString(length).TrimNull();
|
||||||
|
track.Commands.Add(new SynthesizedAudioCommandText(text));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MIDIMetaEventType.CopyrightNotice:
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MIDIMetaEventType.SequenceName:
|
||||||
|
{
|
||||||
|
string text = r.ReadFixedLengthString(length).TrimNull();
|
||||||
|
track.Name = text;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MIDIMetaEventType.ProgramName:
|
||||||
|
{
|
||||||
|
string text = r.ReadFixedLengthString(length).TrimNull();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MIDIMetaEventType.DeviceName:
|
||||||
|
{
|
||||||
|
string text = r.ReadFixedLengthString(length).TrimNull();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MIDIMetaEventType.EndOfTrack:
|
||||||
|
{
|
||||||
|
audio.Tracks.Add(track);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MIDIMetaEventType.TimeSignature:
|
||||||
|
{
|
||||||
|
byte numerator = r.ReadByte();
|
||||||
|
byte denominatorPower = r.ReadByte();
|
||||||
|
byte denominator = (byte)Math.Pow(2.0, denominatorPower);
|
||||||
|
byte ticksPerMetronomeClick = r.ReadByte();
|
||||||
|
byte numberOf32ndNotesPerQuarterNote = r.ReadByte();
|
||||||
|
track.Commands.Add(new SynthesizedAudioCommandTimeSignature(numerator, denominator, ticksPerMetronomeClick, numberOf32ndNotesPerQuarterNote));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MIDIMetaEventType.SetTempo:
|
||||||
|
{
|
||||||
|
int tempo = (int)r.ReadInt24();
|
||||||
|
track.Commands.Add(new SynthesizedAudioCommandTempo((double)tempo));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MIDIMetaEventType.KeySignature:
|
||||||
|
{
|
||||||
|
byte sf = r.ReadByte(); // -7 = 7 flats, -1 = 1 flat, 0 = none (key of C), 1 =
|
||||||
|
bool minorKey = r.ReadBoolean();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
Console.WriteLine("ue: MIDI: warning: meta event type {0} ({1}) [{2} bytes] unhandled", metaEventType, (byte)metaEventType, length);
|
||||||
|
r.BaseStream.Seek(length, SeekOrigin.Current);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (command)
|
||||||
|
{
|
||||||
|
case MIDIEventType.ProgramChange:
|
||||||
|
{
|
||||||
|
byte programNumber = r.ReadByte();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MIDIEventType.NoteOn:
|
||||||
|
{
|
||||||
|
byte noteNumber = r.ReadByte();
|
||||||
|
byte velocity = r.ReadByte();
|
||||||
|
|
||||||
|
if (!notesForNoteNumber.ContainsKey(noteNumber))
|
||||||
|
{
|
||||||
|
notesForNoteNumber[noteNumber] = new SynthesizedAudioCommandNote();
|
||||||
|
}
|
||||||
|
SynthesizedAudioCommandNote note = notesForNoteNumber[noteNumber];
|
||||||
|
note.Frequency = noteNumber;
|
||||||
|
note.Position = deltaTime + ofs;
|
||||||
|
note.Intensity = velocity;
|
||||||
|
ofs += deltaTime;
|
||||||
|
track.Commands.Add(note);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MIDIEventType.NoteOff:
|
||||||
|
{
|
||||||
|
byte noteNumber = r.ReadByte();
|
||||||
|
byte velocity = r.ReadByte();
|
||||||
|
|
||||||
|
if (notesForNoteNumber.ContainsKey(noteNumber))
|
||||||
|
{
|
||||||
|
notesForNoteNumber[noteNumber].Length = deltaTime;
|
||||||
|
notesForNoteNumber.Remove(noteNumber);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MIDIEventType.ControlChange:
|
||||||
|
{
|
||||||
|
byte controllerNumber = r.ReadByte();
|
||||||
|
byte value = r.ReadByte();
|
||||||
|
// track.Commands.Add(new SynthesizedAudioCommandControlChange(controllerNumber, value));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MIDIEventType.PolyphonicKeyPressureAftertouch:
|
||||||
|
{
|
||||||
|
byte noteNumber = r.ReadByte();
|
||||||
|
byte pressure = r.ReadByte();
|
||||||
|
// track.Commands.Add(new SynthesizedAudioCommandPolyphonicKeyPressureAftertouch(controllerNumber, value));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MIDIEventType.ChannelPressureAftertouch:
|
||||||
|
{
|
||||||
|
byte pressure = r.ReadByte();
|
||||||
|
// track.Commands.Add(new SynthesizedAudioCommandChannelPressureAftertouch(controllerNumber, value));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MIDIEventType.PitchWheelChange:
|
||||||
|
{
|
||||||
|
short value = r.ReadInt16();
|
||||||
|
// track.Commands.Add(new SynthesizedAudioCommandPitchWheel(value));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WriteMIDIMetaEvent(Writer w, int deltaTime, MIDIMetaEventType metaType)
|
||||||
|
{
|
||||||
|
WriteMIDIMetaEvent(w, deltaTime, metaType, (Action<Writer>?)null);
|
||||||
|
}
|
||||||
|
private void WriteMIDIMetaEvent(Writer w, int deltaTime, MIDIMetaEventType metaType, string data)
|
||||||
|
{
|
||||||
|
WriteMIDIMetaEvent(w, deltaTime, metaType, delegate (Writer w2)
|
||||||
|
{
|
||||||
|
w2.WriteFixedLengthString(data);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
private void WriteMIDIMetaEvent(Writer w, int deltaTime, MIDIMetaEventType metaType, Action<Writer>? dataFunc = null)
|
||||||
|
{
|
||||||
|
byte[] data;
|
||||||
|
if (dataFunc == null)
|
||||||
|
{
|
||||||
|
data = new byte[0];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MemoryStream ms = new MemoryStream();
|
||||||
|
Writer w2 = new Writer(ms);
|
||||||
|
|
||||||
|
dataFunc(w2);
|
||||||
|
|
||||||
|
ms.Close();
|
||||||
|
data = ms.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
w.WriteVariableLengthInt32(deltaTime);
|
||||||
|
w.WriteByte((byte)MIDIEventType.Meta);
|
||||||
|
w.WriteByte((byte)metaType);
|
||||||
|
w.WriteVariableLengthInt32(data.Length);
|
||||||
|
w.WriteBytes(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void BeforeSaveInternal(Stack<ObjectModel> objectModels)
|
||||||
|
{
|
||||||
|
base.BeforeSaveInternal(objectModels);
|
||||||
|
|
||||||
|
SynthesizedAudioObjectModel audio = ObjectModel.CastOrThrow<SynthesizedAudioObjectModel>(objectModels.Pop());
|
||||||
|
|
||||||
|
ChunkedObjectModel chunked = new ChunkedObjectModel();
|
||||||
|
|
||||||
|
DataChunk MThd = new DataChunk("MThd");
|
||||||
|
chunked.Chunks.Add(MThd);
|
||||||
|
|
||||||
|
foreach (SynthesizedAudioTrack track in audio.Tracks)
|
||||||
|
{
|
||||||
|
DataChunk MTrk = new DataChunk("MTrk");
|
||||||
|
|
||||||
|
MemoryStream ms = new MemoryStream();
|
||||||
|
Writer w = new Writer(ms);
|
||||||
|
|
||||||
|
if (track.Name != null)
|
||||||
|
{
|
||||||
|
WriteMIDIMetaEvent(w, 0, MIDIMetaEventType.SequenceName, track.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (SynthesizedAudioCommand command in track.Commands)
|
||||||
|
{
|
||||||
|
WriteCommand(w, command);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
WriteMIDIMetaEvent(w, 0, MIDIMetaEventType.EndOfTrack);
|
||||||
|
|
||||||
|
ms.Close();
|
||||||
|
|
||||||
|
MTrk.Source = new ByteArrayFileSource(ms.ToArray());
|
||||||
|
chunked.Chunks.Add(MTrk);
|
||||||
|
}
|
||||||
|
|
||||||
|
objectModels.Push(chunked);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WriteCommand(Writer w, SynthesizedAudioCommand command)
|
||||||
|
{
|
||||||
|
if (command is SynthesizedAudioCommandNote note)
|
||||||
|
{
|
||||||
|
WriteMIDIEvent(w, 0, MIDIEventType.NoteOn, delegate(Writer w)
|
||||||
|
{
|
||||||
|
byte noteNumber = (byte)(note.Frequency);
|
||||||
|
byte velocity = 0;
|
||||||
|
w.WriteByte(noteNumber);
|
||||||
|
w.WriteByte(velocity);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if (command is SynthesizedAudioCommandTempo tempo)
|
||||||
|
{
|
||||||
|
WriteMIDIMetaEvent(w, 0, MIDIMetaEventType.SetTempo, delegate (Writer w)
|
||||||
|
{
|
||||||
|
w.WriteInt24((int)(tempo.Tempo));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if (command is SynthesizedAudioCommandTimeSignature ts)
|
||||||
|
{
|
||||||
|
WriteMIDIMetaEvent(w, 0, MIDIMetaEventType.TimeSignature, delegate (Writer w)
|
||||||
|
{
|
||||||
|
byte numerator = (byte)ts.Numerator;
|
||||||
|
w.WriteByte(numerator);
|
||||||
|
|
||||||
|
byte denominatorPower = (byte)Math.Log2((byte)ts.Denominator);
|
||||||
|
w.WriteByte(denominatorPower);
|
||||||
|
|
||||||
|
byte ticksPerMetronomeClick = (byte)ts.TicksPerMetronomeClick;
|
||||||
|
w.WriteByte(ticksPerMetronomeClick);
|
||||||
|
|
||||||
|
byte numberOf32ndNotesPerQuarterNote = (byte)ts.NumberOf32ndNotesPerQuarterNote;
|
||||||
|
w.WriteByte(numberOf32ndNotesPerQuarterNote);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WriteMIDIEvent(Writer w, int deltaTime, MIDIEventType eventType, Action<Writer> func)
|
||||||
|
{
|
||||||
|
w.WriteVariableLengthInt32(deltaTime);
|
||||||
|
|
||||||
|
byte channel = 0;
|
||||||
|
MIDIEventType type = MIDIEventType.NoteOn;
|
||||||
|
byte commandAndChannel = (byte)type;
|
||||||
|
w.WriteByte(commandAndChannel);
|
||||||
|
|
||||||
|
func(w);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,46 @@
|
|||||||
|
//
|
||||||
|
// MIDIEventType.cs - indicates the type of MIDI event
|
||||||
|
//
|
||||||
|
// Author:
|
||||||
|
// Michael Becker <alcexhim@gmail.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2019 Mike Becker's Software
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
namespace MBS.Editor.Plugins.Multimedia.DataFormats.Audio.Synthesized.MIDI;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates the type of MIDI event.
|
||||||
|
/// </summary>
|
||||||
|
public enum MIDIEventType : byte
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
|
||||||
|
MIDIChannelMask = 0x0F,
|
||||||
|
MIDIEventMask = 0xF0,
|
||||||
|
|
||||||
|
NoteOff = 0x8,
|
||||||
|
NoteOn = 0x9,
|
||||||
|
PolyphonicKeyPressureAftertouch = 0xA,
|
||||||
|
ControlChange = 0xB,
|
||||||
|
ProgramChange = 0xC,
|
||||||
|
ChannelPressureAftertouch = 0xD,
|
||||||
|
PitchWheelChange = 0xE,
|
||||||
|
|
||||||
|
|
||||||
|
SysEx = 0xF0,
|
||||||
|
Escape = 0xF7,
|
||||||
|
Meta = 0xFF
|
||||||
|
}
|
||||||
@ -0,0 +1,46 @@
|
|||||||
|
//
|
||||||
|
// MIDIFileFormatType.cs - indicates the type of MIDI file format
|
||||||
|
//
|
||||||
|
// Author:
|
||||||
|
// Michael Becker <alcexhim@gmail.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2019-2020 Mike Becker's Software
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
namespace MBS.Editor.Plugins.Multimedia.DataFormats.Audio.Synthesized.MIDI;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates the type of MIDI file format.
|
||||||
|
/// </summary>
|
||||||
|
public enum MIDIFileFormatType : short
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Single track (format 0). Consists of a header-chunk and a single track-chunk. The single track chunk will contain all the
|
||||||
|
/// note and tempo information.
|
||||||
|
/// </summary>
|
||||||
|
SingleTrack = 0,
|
||||||
|
/// <summary>
|
||||||
|
/// Simultaneous multi-track (format 1). Consists of a header-chunk and one or more track-chunks, with all tracks being played
|
||||||
|
/// simultaneously. The first track of a Format 1 file is special, and is also known as the 'Tempo Map'. It should contain all
|
||||||
|
/// meta-events of the types Time Signature, and Set Tempo. The meta-events Sequence/Track Name, Sequence Number, Marker, and
|
||||||
|
/// SMTPE Offset. should also be on the first track of a Format 1 file.
|
||||||
|
/// </summary>
|
||||||
|
SimultaneousMultitrack = 1,
|
||||||
|
/// <summary>
|
||||||
|
/// Independent multi-track (format 2). Consists of a header-chunk and one or more track-chunks, where each track represents an
|
||||||
|
/// independent sequence.
|
||||||
|
/// </summary>
|
||||||
|
IndependentMultitrack = 2
|
||||||
|
}
|
||||||
@ -0,0 +1,46 @@
|
|||||||
|
//
|
||||||
|
// MIDIMetaEventType.cs - indicates the type of MIDI meta event
|
||||||
|
//
|
||||||
|
// Author:
|
||||||
|
// Michael Becker <alcexhim@gmail.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2019 Mike Becker's Software
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
namespace MBS.Editor.Plugins.Multimedia.DataFormats.Audio.Synthesized.MIDI;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates the type of MIDI meta event.
|
||||||
|
/// </summary>
|
||||||
|
public enum MIDIMetaEventType : byte
|
||||||
|
{
|
||||||
|
SequenceNumber = 0x00,
|
||||||
|
Text = 0x01,
|
||||||
|
CopyrightNotice = 0x02,
|
||||||
|
SequenceName = 0x03,
|
||||||
|
InstrumentName = 0x04,
|
||||||
|
Lyric = 0x05,
|
||||||
|
Marker = 0x06,
|
||||||
|
CuePoint = 0x07,
|
||||||
|
ProgramName = 0x08,
|
||||||
|
DeviceName = 0x09,
|
||||||
|
ChannelPrefix = 0x20,
|
||||||
|
EndOfTrack = 0x2F,
|
||||||
|
SetTempo = 0x51,
|
||||||
|
SMPTEOffset = 0x54,
|
||||||
|
TimeSignature = 0x58,
|
||||||
|
KeySignature = 0x59,
|
||||||
|
SequencerSpecific = 0x7F
|
||||||
|
}
|
||||||
@ -0,0 +1,114 @@
|
|||||||
|
// Copyright (C) 2024 Michael Becker <alcexhim@gmail.com>
|
||||||
|
//
|
||||||
|
// This file is part of editor-dotnet.
|
||||||
|
//
|
||||||
|
// editor-dotnet is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// editor-dotnet is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with editor-dotnet. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
using MBS.Core;
|
||||||
|
using MBS.Editor.Core;
|
||||||
|
using MBS.Editor.Core.DataFormats.FileSystem.IFF;
|
||||||
|
using MBS.Editor.Core.ObjectModels.Chunked;
|
||||||
|
using MBS.Editor.Core.ObjectModels.FileSystem;
|
||||||
|
using MBS.Editor.Core.ObjectModels.FileSystem.FileSources;
|
||||||
|
using MBS.Editor.Plugins.Multimedia.DataFormats.Audio.Synthesized.MIDI;
|
||||||
|
using MBS.Editor.Plugins.Multimedia.ObjectModels.Audio.Synthesized;
|
||||||
|
|
||||||
|
namespace MBS.Editor.Plugins.Multimedia.DataFormats.Audio.Synthesized.RMI;
|
||||||
|
|
||||||
|
public class RMIDataFormat : RIFFDataFormat
|
||||||
|
{
|
||||||
|
|
||||||
|
protected override void BeforeLoadInternal(Stack<ObjectModel> objectModels)
|
||||||
|
{
|
||||||
|
base.BeforeLoadInternal(objectModels);
|
||||||
|
objectModels.Push(new ChunkedObjectModel());
|
||||||
|
}
|
||||||
|
// f8ffdcb7-e2ec-40b1-aa8a-beeb5076c1c9
|
||||||
|
protected override void AfterLoadInternal(Stack<ObjectModel> objectModels)
|
||||||
|
{
|
||||||
|
base.AfterLoadInternal(objectModels);
|
||||||
|
|
||||||
|
ChunkedObjectModel chunked = ObjectModel.CastOrThrow<ChunkedObjectModel>(objectModels.Pop());
|
||||||
|
SynthesizedAudioObjectModel audio = ObjectModel.CastOrThrow<SynthesizedAudioObjectModel>(objectModels.Pop());
|
||||||
|
|
||||||
|
if (chunked.Chunks.Count == 0)
|
||||||
|
{
|
||||||
|
throw new InvalidDataFormatException("RIFF-MIDI document does not contain any RIFF chunks");
|
||||||
|
}
|
||||||
|
|
||||||
|
GroupChunk? root = chunked.Chunks["RIFF", "RMID"] as GroupChunk;
|
||||||
|
if (root == null)
|
||||||
|
{
|
||||||
|
throw new InvalidDataFormatException("RIFF-MIDI document does not contain an RIFF-RMID group chunk");
|
||||||
|
}
|
||||||
|
|
||||||
|
DataChunk? filData = root.Chunks["data"] as DataChunk;
|
||||||
|
if (filData != null)
|
||||||
|
{
|
||||||
|
byte[]? data = filData.Source?.GetData();
|
||||||
|
if (data != null)
|
||||||
|
{
|
||||||
|
MIDIDataFormat mid = new MIDIDataFormat();
|
||||||
|
Document.Load(audio, mid, filData.Source?.GetStream());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GroupChunk info = (GroupChunk)root.Chunks["LIST", "INFO"];
|
||||||
|
if (info != null)
|
||||||
|
{
|
||||||
|
DataChunk? filIART = info.Chunks["IART"] as DataChunk;
|
||||||
|
if (filIART != null)
|
||||||
|
{
|
||||||
|
byte[]? data = filIART.Source?.GetData();
|
||||||
|
if (data != null)
|
||||||
|
{
|
||||||
|
string artist = System.Text.Encoding.UTF8.GetString(data).TrimNull();
|
||||||
|
audio.Metadata.Artist = artist;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DataChunk? filICOP = info.Chunks["ICOP"] as DataChunk;
|
||||||
|
if (filICOP != null)
|
||||||
|
{
|
||||||
|
byte[]? data = filICOP.Source?.GetData();
|
||||||
|
if (data != null)
|
||||||
|
{
|
||||||
|
string copyright = System.Text.Encoding.UTF8.GetString(data).TrimNull();
|
||||||
|
audio.Metadata.Copyright = copyright;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void BeforeSaveInternal(Stack<ObjectModel> objectModels)
|
||||||
|
{
|
||||||
|
base.BeforeSaveInternal(objectModels);
|
||||||
|
|
||||||
|
SynthesizedAudioObjectModel audio = ObjectModel.CastOrThrow<SynthesizedAudioObjectModel>(objectModels.Pop());
|
||||||
|
ChunkedObjectModel chunked = new ChunkedObjectModel();
|
||||||
|
|
||||||
|
GroupChunk rmid = new GroupChunk("RIFF", "RMID");
|
||||||
|
|
||||||
|
MemoryStream ms = new MemoryStream();
|
||||||
|
MIDIDataFormat mid = new MIDIDataFormat();
|
||||||
|
Document.Save(audio, mid, ms);
|
||||||
|
|
||||||
|
DataChunk data = new DataChunk("data");
|
||||||
|
data.Source = new StreamFileSource(ms);
|
||||||
|
rmid.Chunks.Add(data);
|
||||||
|
|
||||||
|
chunked.Chunks.Add(rmid);
|
||||||
|
objectModels.Push(chunked);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
// Copyright (C) 2024 Michael Becker <alcexhim@gmail.com>
|
||||||
|
//
|
||||||
|
// This file is part of editor-dotnet.
|
||||||
|
//
|
||||||
|
// editor-dotnet is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// editor-dotnet is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with editor-dotnet. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
namespace MBS.Editor.Plugins.Multimedia.DataFormats.Picture.ILBM;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Choice of compression algorithm applied to the rows of all source and mask planes.
|
||||||
|
/// </summary>
|
||||||
|
public enum ILBMCompression : byte
|
||||||
|
{
|
||||||
|
None = 0x00,
|
||||||
|
ByteRun1 = 0x01
|
||||||
|
}
|
||||||
@ -0,0 +1,164 @@
|
|||||||
|
// Copyright (C) 2024 Michael Becker <alcexhim@gmail.com>
|
||||||
|
//
|
||||||
|
// This file is part of editor-dotnet.
|
||||||
|
//
|
||||||
|
// editor-dotnet is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// editor-dotnet is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with editor-dotnet. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
using MBS.Core.Drawing;
|
||||||
|
using MBS.Editor.Core;
|
||||||
|
using MBS.Editor.Core.DataFormats.FileSystem.IFF;
|
||||||
|
using MBS.Editor.Core.IO;
|
||||||
|
using MBS.Editor.Core.ObjectModels.Chunked;
|
||||||
|
using MBS.Editor.Core.ObjectModels.FileSystem;
|
||||||
|
using MBS.Editor.Plugins.Multimedia.ObjectModels.Palette;
|
||||||
|
using MBS.Editor.Plugins.Multimedia.ObjectModels.Picture;
|
||||||
|
|
||||||
|
namespace MBS.Editor.Plugins.Multimedia.DataFormats.Picture.ILBM;
|
||||||
|
|
||||||
|
public class ILBMDataFormat : IFFDataFormat
|
||||||
|
{
|
||||||
|
public ILBMMasking Masking { get; set; } = ILBMMasking.None;
|
||||||
|
public ILBMCompression Compression { get; set; } = ILBMCompression.None;
|
||||||
|
protected override void BeforeLoadInternal(Stack<ObjectModel> objectModels)
|
||||||
|
{
|
||||||
|
base.BeforeLoadInternal(objectModels);
|
||||||
|
objectModels.Push(new ChunkedObjectModel());
|
||||||
|
}
|
||||||
|
protected override void AfterLoadInternal(Stack<ObjectModel> objectModels)
|
||||||
|
{
|
||||||
|
base.AfterLoadInternal(objectModels);
|
||||||
|
|
||||||
|
ObjectModel om = objectModels.Pop();
|
||||||
|
ChunkedObjectModel? fsom = om as ChunkedObjectModel;
|
||||||
|
if (fsom == null)
|
||||||
|
throw new ObjectModelNotSupportedException(typeof(ChunkedObjectModel), om.GetType());
|
||||||
|
|
||||||
|
om = objectModels.Pop();
|
||||||
|
PictureObjectModel? pic = om as PictureObjectModel;
|
||||||
|
if (pic == null)
|
||||||
|
throw new ObjectModelNotSupportedException(typeof(PictureObjectModel), om.GetType());
|
||||||
|
|
||||||
|
|
||||||
|
GroupChunk? fldFORM = fsom.Chunks[0] as GroupChunk;
|
||||||
|
if (fldFORM?.Name != "FORM" || fldFORM?.TypeName != "ILBM")
|
||||||
|
throw new InvalidDataFormatException();
|
||||||
|
|
||||||
|
#region BMHD
|
||||||
|
{
|
||||||
|
DataChunk? filBMHD = fldFORM.Chunks[0] as DataChunk;
|
||||||
|
if (filBMHD?.Name != "BMHD" || filBMHD?.Source == null)
|
||||||
|
throw new InvalidDataFormatException();
|
||||||
|
|
||||||
|
MemoryStream ms = new MemoryStream(filBMHD.Source.GetData());
|
||||||
|
Reader reader = new Reader(ms);
|
||||||
|
reader.Endianness = Endianness.BigEndian;
|
||||||
|
|
||||||
|
// thanks http://etwright.org/lwsdk/docs/filefmts/ilbm.html
|
||||||
|
|
||||||
|
// raster width & height in pixels
|
||||||
|
ushort width = reader.ReadUInt16();
|
||||||
|
ushort height = reader.ReadUInt16();
|
||||||
|
pic.Width = width;
|
||||||
|
pic.Height = height;
|
||||||
|
|
||||||
|
// pixel position for this image
|
||||||
|
ushort x = reader.ReadUInt16();
|
||||||
|
ushort y = reader.ReadUInt16();
|
||||||
|
|
||||||
|
byte nPlanes = reader.ReadByte();
|
||||||
|
ILBMMasking masking = (ILBMMasking)reader.ReadByte();
|
||||||
|
ILBMCompression compression = (ILBMCompression)reader.ReadByte();
|
||||||
|
byte pad1 = reader.ReadByte(); // should be 0
|
||||||
|
ushort transparentColor = reader.ReadUInt16();
|
||||||
|
byte xAspect = reader.ReadByte();
|
||||||
|
byte yAspect = reader.ReadByte();
|
||||||
|
ushort pageWidth = reader.ReadUInt16();
|
||||||
|
ushort pageHeight = reader.ReadUInt16();
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
#region CMAP
|
||||||
|
{
|
||||||
|
DataChunk? filCMAP = fldFORM.Chunks["CMAP"] as DataChunk;
|
||||||
|
if (filCMAP != null)
|
||||||
|
{
|
||||||
|
byte[]? data = filCMAP.Source?.GetData();
|
||||||
|
if (data != null)
|
||||||
|
{
|
||||||
|
pic.Palette = new PaletteObjectModel();
|
||||||
|
for (int i = 0; i < data.Length; i += 3)
|
||||||
|
{
|
||||||
|
byte r = data[i];
|
||||||
|
byte g = data[i + 1];
|
||||||
|
byte b = data[i + 2];
|
||||||
|
|
||||||
|
Color color = Color.FromRGBAByte(r, g, b);
|
||||||
|
pic.Palette.Entries.Add(color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region BODY
|
||||||
|
{
|
||||||
|
|
||||||
|
System.IO.MemoryStream ms = new MemoryStream();
|
||||||
|
Writer w = new Writer(ms);
|
||||||
|
|
||||||
|
DataChunk? filBODY = fldFORM.Chunks["BODY"] as DataChunk;
|
||||||
|
if (filBODY != null)
|
||||||
|
{
|
||||||
|
byte[]? data = filBODY.Source?.GetData();
|
||||||
|
if (data != null)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < data.Length; i += 3)
|
||||||
|
{
|
||||||
|
sbyte n = (sbyte) data[i];
|
||||||
|
if (n >= 0 && n <= 127)
|
||||||
|
{
|
||||||
|
int count = n + 1;
|
||||||
|
for (int j = 0; j < count; j++)
|
||||||
|
{
|
||||||
|
byte next = data[i + 1];
|
||||||
|
w.WriteByte(next);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (n == -128)
|
||||||
|
{
|
||||||
|
// nop
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int count = -n;
|
||||||
|
byte next = data[i + 1];
|
||||||
|
for (int j = 0; j < count; j++)
|
||||||
|
{
|
||||||
|
w.WriteByte(next);
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void BeforeSaveInternal(Stack<ObjectModel> objectModels)
|
||||||
|
{
|
||||||
|
base.BeforeSaveInternal(objectModels);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,46 @@
|
|||||||
|
// Copyright (C) 2024 Michael Becker <alcexhim@gmail.com>
|
||||||
|
//
|
||||||
|
// This file is part of editor-dotnet.
|
||||||
|
//
|
||||||
|
// editor-dotnet is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// editor-dotnet is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with editor-dotnet. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
namespace MBS.Editor.Plugins.Multimedia.DataFormats.Picture.ILBM;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Choice of masking technique.
|
||||||
|
/// </summary>
|
||||||
|
public enum ILBMMasking : byte
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Designates an opaque rectangular image.
|
||||||
|
/// </summary>
|
||||||
|
None = 0x00,
|
||||||
|
/// <summary>
|
||||||
|
/// Mask plane is interleaved with the bitplanes in the BODY chunk.
|
||||||
|
/// </summary>
|
||||||
|
Mask = 0x01,
|
||||||
|
/// <summary>
|
||||||
|
/// Pixels in the source planes matching transparentColor are to be considered "transparent."
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// transparentColor isn't a "color number" since it's matched with numbers formed by the source bitmap rather than the possibly
|
||||||
|
/// deeper destination bitmap. Note that having a transparent color implies ignoring one of the color registers.
|
||||||
|
/// </remarks>
|
||||||
|
TransparentColor = 0x02,
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates the reader may construct a mask by lassoing the image as in MacPaint. To do this, put a 1 pixel border of
|
||||||
|
/// transparentColor around the image rectangle. Then do a seed fill from this border. Filled pixels are to be transparent.
|
||||||
|
/// </summary>
|
||||||
|
Lasso = 0x03
|
||||||
|
}
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
// Copyright (C) 2024 Michael Becker <alcexhim@gmail.com>
|
||||||
|
//
|
||||||
|
// This file is part of editor-dotnet.
|
||||||
|
//
|
||||||
|
// editor-dotnet is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// editor-dotnet is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with editor-dotnet. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
namespace MBS.Editor.Plugins.Multimedia.ObjectModels.Audio;
|
||||||
|
|
||||||
|
public class AudioMetadata
|
||||||
|
{
|
||||||
|
public string Title { get; set; } = "";
|
||||||
|
public string Artist { get; set; } = "";
|
||||||
|
public string Copyright { get; set; } = "";
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
// Copyright (C) 2024 Michael Becker <alcexhim@gmail.com>
|
||||||
|
//
|
||||||
|
// This file is part of editor-dotnet.
|
||||||
|
//
|
||||||
|
// editor-dotnet is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// editor-dotnet is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with editor-dotnet. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
using MBS.Editor.Core;
|
||||||
|
|
||||||
|
namespace MBS.Editor.Plugins.Multimedia.ObjectModels.Audio;
|
||||||
|
|
||||||
|
public abstract class AudioObjectModelBase : ObjectModel
|
||||||
|
{
|
||||||
|
public AudioMetadata Metadata { get; set; } = new AudioMetadata();
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,114 @@
|
|||||||
|
//
|
||||||
|
// SynthesizedAudioCommand.cs - represents a command (e.g. note, control change) in a synthesized audio file
|
||||||
|
//
|
||||||
|
// Author:
|
||||||
|
// Michael Becker <alcexhim@gmail.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2011-2020 Mike Becker's Software
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using MBS.Core;
|
||||||
|
|
||||||
|
namespace MBS.Editor.Plugins.Multimedia.ObjectModels.Audio.Synthesized;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a command (e.g. note, control change) in a synthesized audio file.
|
||||||
|
/// </summary>
|
||||||
|
public class SynthesizedAudioCommand : ICloneable
|
||||||
|
{
|
||||||
|
public class SynthesizedAudioCommandCollection : Collection<SynthesizedAudioCommand>
|
||||||
|
{
|
||||||
|
public SynthesizedAudioCommandRest Add(double length)
|
||||||
|
{
|
||||||
|
SynthesizedAudioCommandRest rest = new SynthesizedAudioCommandRest();
|
||||||
|
rest.Length = length;
|
||||||
|
|
||||||
|
base.Add(rest);
|
||||||
|
return rest;
|
||||||
|
}
|
||||||
|
public SynthesizedAudioCommandNote Add(SynthesizedAudioPredefinedNote note, double length, int octave, float volume)
|
||||||
|
{
|
||||||
|
SynthesizedAudioCommandNote command = new SynthesizedAudioCommandNote();
|
||||||
|
command.Length = length;
|
||||||
|
command.Frequency = SynthesizedAudioPredefinedNoteConverter.GetFrequency(note, octave);
|
||||||
|
|
||||||
|
base.Add(command);
|
||||||
|
return command;
|
||||||
|
}
|
||||||
|
|
||||||
|
public event EventHandler ItemsChanged;
|
||||||
|
protected virtual void OnItemsChanged(EventArgs e)
|
||||||
|
{
|
||||||
|
ItemsChanged?.Invoke(this, e);
|
||||||
|
}
|
||||||
|
protected override void InsertItem(int index, SynthesizedAudioCommand item)
|
||||||
|
{
|
||||||
|
base.InsertItem(index, item);
|
||||||
|
OnItemsChanged(EventArgs.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void RemoveItem(int index)
|
||||||
|
{
|
||||||
|
base.RemoveItem(index);
|
||||||
|
OnItemsChanged(EventArgs.Empty);
|
||||||
|
}
|
||||||
|
protected override void ClearItems()
|
||||||
|
{
|
||||||
|
base.ClearItems();
|
||||||
|
OnItemsChanged(EventArgs.Empty);
|
||||||
|
}
|
||||||
|
protected override void SetItem(int index, SynthesizedAudioCommand item)
|
||||||
|
{
|
||||||
|
base.SetItem(index, item);
|
||||||
|
OnItemsChanged(EventArgs.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
public T NextOfType<T>(T item, SeekDirection direction = SeekDirection.Forward) where T : SynthesizedAudioCommand
|
||||||
|
{
|
||||||
|
int index = IndexOf(item);
|
||||||
|
if (index < 0) index = 0;
|
||||||
|
if (index > Count - 1) index = 0;
|
||||||
|
|
||||||
|
if (direction == SeekDirection.Backward)
|
||||||
|
{
|
||||||
|
if (index < 0) index = Count - 1;
|
||||||
|
if (index > Count - 1) index = Count - 1;
|
||||||
|
|
||||||
|
for (int i = index - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
if (this[i] is T)
|
||||||
|
return (T)this[i];
|
||||||
|
}
|
||||||
|
return (T)this[Count - 1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int i = index + 1; i < Count; i++)
|
||||||
|
{
|
||||||
|
if (this[i] is T)
|
||||||
|
return (T)this[i];
|
||||||
|
}
|
||||||
|
return (T)this[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual object Clone()
|
||||||
|
{
|
||||||
|
return base.MemberwiseClone();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,82 @@
|
|||||||
|
//
|
||||||
|
// SynthesizedAudioCommandNote.cs - represents a note command in a synthesized audio file
|
||||||
|
//
|
||||||
|
// Author:
|
||||||
|
// Michael Becker <alcexhim@gmail.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2011-2020 Mike Becker's Software
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace MBS.Editor.Plugins.Multimedia.ObjectModels.Audio.Synthesized;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a note command in a synthesized audio file.
|
||||||
|
/// </summary>
|
||||||
|
public class SynthesizedAudioCommandNote : SynthesizedAudioCommand
|
||||||
|
{
|
||||||
|
public bool Protected { get; set; } = false;
|
||||||
|
public int Position { get; set; } = 0;
|
||||||
|
public double Length { get; set; } = 0;
|
||||||
|
public string Phoneme { get; set; } = null;
|
||||||
|
public string Lyric { get; set; } = null;
|
||||||
|
public double Frequency { get; set; } = 0;
|
||||||
|
public int PreUtterance { get; set; } = 0;
|
||||||
|
public int VoiceOverlap { get; set; } = 0;
|
||||||
|
public int Intensity { get; set; } = 0;
|
||||||
|
public int Modulation { get; set; } = 0;
|
||||||
|
public int PBType { get; set; } = 0;
|
||||||
|
public double[] Pitches { get; set; } = new double[0];
|
||||||
|
public string[] Envelope { get; set; } = new string[0];
|
||||||
|
public double[] VBR { get; set; } = new double[0];
|
||||||
|
public int Accent { get; set; } = 50;
|
||||||
|
public int PitchBendDepth { get; set; } = 8;
|
||||||
|
public int PitchBendLength { get; set; } = 0;
|
||||||
|
public int Decay { get; set; } = 50;
|
||||||
|
public bool PortamentoFalling { get; set; } = false;
|
||||||
|
public int Opening { get; set; } = 127;
|
||||||
|
public bool PortamentoRising { get; set; } = false;
|
||||||
|
public int VibratoLength { get; set; } = 0;
|
||||||
|
public SynthesizedAudioVibratoType VibratoType { get; set; } = SynthesizedAudioVibratoType.None;
|
||||||
|
|
||||||
|
public override object Clone()
|
||||||
|
{
|
||||||
|
return new SynthesizedAudioCommandNote
|
||||||
|
{
|
||||||
|
Envelope = this.Envelope.Clone() as string[],
|
||||||
|
Intensity = this.Intensity,
|
||||||
|
Length = this.Length,
|
||||||
|
Lyric = this.Lyric,
|
||||||
|
Modulation = this.Modulation,
|
||||||
|
PBType = this.PBType,
|
||||||
|
Phoneme = this.Phoneme,
|
||||||
|
Pitches = this.Pitches.Clone() as double[],
|
||||||
|
PortamentoFalling = this.PortamentoFalling,
|
||||||
|
PortamentoRising = this.PortamentoRising,
|
||||||
|
PreUtterance = this.PreUtterance,
|
||||||
|
Protected = this.Protected,
|
||||||
|
Position = this.Position,
|
||||||
|
Frequency = this.Frequency,
|
||||||
|
VBR = this.VBR.Clone() as double[],
|
||||||
|
VoiceOverlap = this.VoiceOverlap
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return String.Format("{0} [{1}] <{2}, {3}>", Lyric, Phoneme, Position, Length);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
//
|
||||||
|
// SynthesizedAudioCommandRest.cs - represents a rest in a synthesized audio file
|
||||||
|
//
|
||||||
|
// Author:
|
||||||
|
// Michael Becker <alcexhim@gmail.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2011-2020 Mike Becker's Software
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
namespace MBS.Editor.Plugins.Multimedia.ObjectModels.Audio.Synthesized;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a rest in a synthesized audio file.
|
||||||
|
/// </summary>
|
||||||
|
public class SynthesizedAudioCommandRest : SynthesizedAudioCommandNote
|
||||||
|
{
|
||||||
|
}
|
||||||
@ -0,0 +1,49 @@
|
|||||||
|
//
|
||||||
|
// SynthesizedAudioCommandTempo.cs - represents a tempo change command in a synthesized audio file
|
||||||
|
//
|
||||||
|
// Author:
|
||||||
|
// Michael Becker <alcexhim@gmail.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2011-2020 Mike Becker's Software
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
namespace MBS.Editor.Plugins.Multimedia.ObjectModels.Audio.Synthesized;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a tempo change command in a synthesized audio file.
|
||||||
|
/// </summary>
|
||||||
|
public class SynthesizedAudioCommandTempo : SynthesizedAudioCommand
|
||||||
|
{
|
||||||
|
public double Tempo { get; set; } = 0.0;
|
||||||
|
|
||||||
|
public SynthesizedAudioCommandTempo()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
public SynthesizedAudioCommandTempo(double tempo)
|
||||||
|
{
|
||||||
|
this.Tempo = tempo;
|
||||||
|
}
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return "MM = " + this.Tempo.ToString() + " BPM";
|
||||||
|
}
|
||||||
|
public override object Clone()
|
||||||
|
{
|
||||||
|
return new SynthesizedAudioCommandTempo
|
||||||
|
{
|
||||||
|
Tempo = this.Tempo
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,48 @@
|
|||||||
|
//
|
||||||
|
// SynthesizedAudioCommandText.cs - represents a text command in a synthesized audio file
|
||||||
|
//
|
||||||
|
// Author:
|
||||||
|
// Michael Becker <alcexhim@gmail.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2011-2020 Mike Becker's Software
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
namespace MBS.Editor.Plugins.Multimedia.ObjectModels.Audio.Synthesized;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a text command in a synthesized audio file.
|
||||||
|
/// </summary>
|
||||||
|
public class SynthesizedAudioCommandText : SynthesizedAudioCommand
|
||||||
|
{
|
||||||
|
public string Text { get; set; } = string.Empty;
|
||||||
|
public SynthesizedAudioCommandText()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
public SynthesizedAudioCommandText(string text)
|
||||||
|
{
|
||||||
|
this.Text = text;
|
||||||
|
}
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return "\"" + this.Text + "\"";
|
||||||
|
}
|
||||||
|
public override object Clone()
|
||||||
|
{
|
||||||
|
return new SynthesizedAudioCommandText
|
||||||
|
{
|
||||||
|
Text = this.Text.Clone() as string
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,66 @@
|
|||||||
|
//
|
||||||
|
// SynthesizedAudioCommandTimeSignature.cs - represents a time signature change command in a synthesized audio file
|
||||||
|
//
|
||||||
|
// Author:
|
||||||
|
// Michael Becker <alcexhim@gmail.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2011-2020 Mike Becker's Software
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
namespace MBS.Editor.Plugins.Multimedia.ObjectModels.Audio.Synthesized;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a time signature change command in a synthesized audio file.
|
||||||
|
/// </summary>
|
||||||
|
public class SynthesizedAudioCommandTimeSignature : SynthesizedAudioCommand
|
||||||
|
{
|
||||||
|
public byte Numerator { get; set; } = 0;
|
||||||
|
public byte Denominator { get; set; } = 0;
|
||||||
|
public byte TicksPerMetronomeClick { get; set; } = 0;
|
||||||
|
public byte NumberOf32ndNotesPerQuarterNote { get; set; } = 0;
|
||||||
|
|
||||||
|
public SynthesizedAudioCommandTimeSignature()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
public SynthesizedAudioCommandTimeSignature(byte numerator, byte denominator, byte ticksPerMetronomeClick, byte numberOf32ndNotesPerQuarterNote)
|
||||||
|
{
|
||||||
|
this.Numerator = numerator;
|
||||||
|
this.Denominator = denominator;
|
||||||
|
this.TicksPerMetronomeClick = ticksPerMetronomeClick;
|
||||||
|
this.NumberOf32ndNotesPerQuarterNote = numberOf32ndNotesPerQuarterNote;
|
||||||
|
}
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return string.Concat(new string[]
|
||||||
|
{
|
||||||
|
"TS = ",
|
||||||
|
this.Numerator.ToString(),
|
||||||
|
"/",
|
||||||
|
this.Denominator.ToString(),
|
||||||
|
"; ♪ = ",
|
||||||
|
this.NumberOf32ndNotesPerQuarterNote.ToString()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
public override object Clone()
|
||||||
|
{
|
||||||
|
return new SynthesizedAudioCommandTimeSignature
|
||||||
|
{
|
||||||
|
Denominator = this.Denominator,
|
||||||
|
NumberOf32ndNotesPerQuarterNote = this.NumberOf32ndNotesPerQuarterNote,
|
||||||
|
Numerator = this.Numerator,
|
||||||
|
TicksPerMetronomeClick = this.TicksPerMetronomeClick
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,109 @@
|
|||||||
|
//
|
||||||
|
// SynthesizedAudioObjectModel.cs - provides an ObjectModel for manipulating synthesized audio files (e.g. MIDI, VSQ, etc.)
|
||||||
|
//
|
||||||
|
// Author:
|
||||||
|
// Michael Becker <alcexhim@gmail.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2011-2020 Mike Becker's Software
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using MBS.Editor.Core;
|
||||||
|
// using MBS.Editor.Plugins.Multimedia.ObjectModels.Audio.Voicebank;
|
||||||
|
|
||||||
|
namespace MBS.Editor.Plugins.Multimedia.ObjectModels.Audio.Synthesized;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Provides an <see cref="ObjectModel" /> for manipulating synthesized audio files (e.g. MIDI, VSQ, etc.).
|
||||||
|
/// </summary>
|
||||||
|
public class SynthesizedAudioObjectModel : AudioObjectModelBase
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
private static ObjectModelReference _omr = null;
|
||||||
|
protected override ObjectModelReference MakeReferenceInternal()
|
||||||
|
{
|
||||||
|
if (_omr == null)
|
||||||
|
{
|
||||||
|
_omr = base.MakeReferenceInternal();
|
||||||
|
_omr.Path = new string[] { "Multimedia", "Audio", "Synthesized Audio" };
|
||||||
|
}
|
||||||
|
return _omr;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
public short ChannelCount { get; set; } = 2;
|
||||||
|
|
||||||
|
public string Name { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
public double Tempo { get; set; } = 120.0;
|
||||||
|
|
||||||
|
public SynthesizedAudioTrack.SynthesizedAudioTrackCollection Tracks { get; } = new SynthesizedAudioTrack.SynthesizedAudioTrackCollection();
|
||||||
|
// public VoicebankObjectModel.VoicebankObjectModelCollection Voices { get; } = new VoicebankObjectModel.VoicebankObjectModelCollection();
|
||||||
|
|
||||||
|
/*
|
||||||
|
private CriteriaObject[] _CriteriaObjects = null;
|
||||||
|
|
||||||
|
private CriteriaProperty PROPERTY_LYRIC = new CriteriaProperty("Lyric", typeof(string));
|
||||||
|
protected override CriteriaObject[] GetCriteriaObjectsInternal()
|
||||||
|
{
|
||||||
|
if (_CriteriaObjects == null)
|
||||||
|
{
|
||||||
|
_CriteriaObjects = new CriteriaObject[]
|
||||||
|
{
|
||||||
|
new CriteriaObject("Note", new CriteriaProperty[]
|
||||||
|
{
|
||||||
|
PROPERTY_LYRIC
|
||||||
|
})
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return _CriteriaObjects;
|
||||||
|
}
|
||||||
|
protected override CriteriaResult[] FindInternal(CriteriaQuery query)
|
||||||
|
{
|
||||||
|
List<CriteriaResult> list = new List<CriteriaResult>();
|
||||||
|
for (int i = 0; i < Tracks.Count; i++)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < Tracks[i].Commands.Count; j++)
|
||||||
|
{
|
||||||
|
if (Tracks[i].Commands[j] is SynthesizedAudioCommandNote)
|
||||||
|
{
|
||||||
|
if (query.Check(PROPERTY_LYRIC, (Tracks[i].Commands[j] as SynthesizedAudioCommandNote).Lyric))
|
||||||
|
{
|
||||||
|
list.Add(new CriteriaResult(Tracks[i].Commands[j]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list.ToArray();
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
public override void CopyTo(ObjectModel destination)
|
||||||
|
{
|
||||||
|
SynthesizedAudioObjectModel clone = destination as SynthesizedAudioObjectModel;
|
||||||
|
clone.Name = (this.Name.Clone() as string);
|
||||||
|
clone.Tempo = this.Tempo;
|
||||||
|
foreach (SynthesizedAudioTrack track in this.Tracks)
|
||||||
|
{
|
||||||
|
clone.Tracks.Add(track.Clone() as SynthesizedAudioTrack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override void Clear()
|
||||||
|
{
|
||||||
|
this.Name = string.Empty;
|
||||||
|
this.Tempo = 120.0;
|
||||||
|
this.Tracks.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,98 @@
|
|||||||
|
//
|
||||||
|
// SynthesizedAudioPredefinedNote.cs - defines various commonly-used note pitches for synthesized audio files
|
||||||
|
//
|
||||||
|
// Author:
|
||||||
|
// Michael Becker <alcexhim@gmail.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2011-2020 Mike Becker's Software
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace MBS.Editor.Plugins.Multimedia.ObjectModels.Audio.Synthesized;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Defines various commonly-used note pitches for synthesized audio files.
|
||||||
|
/// </summary>
|
||||||
|
public enum SynthesizedAudioPredefinedNote
|
||||||
|
{
|
||||||
|
A = 0,
|
||||||
|
ASharp,
|
||||||
|
BFlat = ASharp,
|
||||||
|
B,
|
||||||
|
C,
|
||||||
|
CSharp,
|
||||||
|
DFlat = CSharp,
|
||||||
|
D,
|
||||||
|
DSharp,
|
||||||
|
EFlat = DSharp,
|
||||||
|
E,
|
||||||
|
F,
|
||||||
|
FSharp,
|
||||||
|
GFlat = FSharp,
|
||||||
|
G,
|
||||||
|
GSharp,
|
||||||
|
AFlat = GSharp
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Converts to and from <see cref="SynthesizedAudioPredefinedNote" /> values and their associated frequencies.
|
||||||
|
/// </summary>
|
||||||
|
public static class SynthesizedAudioPredefinedNoteConverter
|
||||||
|
{
|
||||||
|
public static double GetFrequency(SynthesizedAudioPredefinedNote note, int octave)
|
||||||
|
{
|
||||||
|
return GetFrequency((int)note, octave);
|
||||||
|
}
|
||||||
|
public static double GetFrequency(int note, int octave)
|
||||||
|
{
|
||||||
|
return GetFrequency(note + ((octave - 4) * 12));
|
||||||
|
}
|
||||||
|
public static double GetFrequency(int note)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
C5 = the C an octave above middle C. This is 3 half steps above A4 and so the frequency is
|
||||||
|
f3 = 440 * (1.059463..)^3 = 523.3 Hz
|
||||||
|
If your calculator does not have the ability to raise to powers, then use the fact that
|
||||||
|
(1.059463..)^3 = (1.059463..)*(1.059463..)*(1.059463..)
|
||||||
|
That is, you multiply it by itself 3 times.
|
||||||
|
|
||||||
|
Middle C is 9 half steps below A4 and the frequency is:
|
||||||
|
f -9 = 440 * (1.059463..)^(-9) = 261.6 Hz
|
||||||
|
If you don't have powers on your calculator, remember that the negative sign on the power means you divide instead of multiply. For this example, you divide by (1.059463..) 9 times.
|
||||||
|
*/
|
||||||
|
|
||||||
|
double d = Math.Pow(2, (double)1 / 12);
|
||||||
|
int halfSteps = note;
|
||||||
|
double value = 440 * Math.Pow(d, halfSteps);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int GetNote(double frequency)
|
||||||
|
{
|
||||||
|
double d = Math.Pow(2, (double)1 / 12);
|
||||||
|
double halfSteps = Math.Pow(frequency / 440, (1 / d));
|
||||||
|
int note = (int)Math.Round((halfSteps - 1) * 12) + 1;
|
||||||
|
return note;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double ChangeFrequency(double oldFrequency, int detuneBy)
|
||||||
|
{
|
||||||
|
if (detuneBy == 0) return oldFrequency;
|
||||||
|
|
||||||
|
int note = GetNote(oldFrequency);
|
||||||
|
double freq = GetFrequency(note + detuneBy);
|
||||||
|
return freq;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,63 @@
|
|||||||
|
//
|
||||||
|
// SynthesizedAudioStylePlugin.cs
|
||||||
|
//
|
||||||
|
// Author:
|
||||||
|
// Michael Becker <alcexhim@gmail.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2011-2020 Mike Becker's Software
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
namespace MBS.Editor.Plugins.Multimedia.ObjectModels.Audio.Synthesized;
|
||||||
|
|
||||||
|
public class SynthesizedAudioStylePlugin
|
||||||
|
{
|
||||||
|
private Guid mvarID = Guid.Empty;
|
||||||
|
private string mvarName = string.Empty;
|
||||||
|
private Version mvarVersion = new Version(1, 0);
|
||||||
|
public Guid ID
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return this.mvarID;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
this.mvarID = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return this.mvarName;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
this.mvarName = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public Version Version
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return this.mvarVersion;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
this.mvarVersion = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,101 @@
|
|||||||
|
//
|
||||||
|
// SynthesizedAudioTrack.cs - represents a track in a synthesized audio file
|
||||||
|
//
|
||||||
|
// Author:
|
||||||
|
// Michael Becker <alcexhim@gmail.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2011-2020 Mike Becker's Software
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
|
||||||
|
using MBS.Core.Drawing;
|
||||||
|
|
||||||
|
// using MBS.Editor.Plugins.Multimedia.ObjectModels.Audio.Voicebank;
|
||||||
|
|
||||||
|
namespace MBS.Editor.Plugins.Multimedia.ObjectModels.Audio.Synthesized;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a track in a synthesized audio file.
|
||||||
|
/// </summary>
|
||||||
|
public class SynthesizedAudioTrack : ICloneable
|
||||||
|
{
|
||||||
|
public class SynthesizedAudioTrackCollection : Collection<SynthesizedAudioTrack>
|
||||||
|
{
|
||||||
|
private Dictionary<string, SynthesizedAudioTrack> tracksByID = new Dictionary<string, SynthesizedAudioTrack>();
|
||||||
|
public SynthesizedAudioTrack this[string ID]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
SynthesizedAudioTrack result;
|
||||||
|
if (this.tracksByID.ContainsKey(ID))
|
||||||
|
{
|
||||||
|
result = this.tracksByID[ID];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = null;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void InsertItem(int index, SynthesizedAudioTrack item)
|
||||||
|
{
|
||||||
|
base.InsertItem(index, item);
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(item.ID))
|
||||||
|
tracksByID[item.ID] = item;
|
||||||
|
}
|
||||||
|
protected override void RemoveItem(int index)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(this[index].ID))
|
||||||
|
tracksByID.Remove(this[index].ID);
|
||||||
|
|
||||||
|
base.RemoveItem(index);
|
||||||
|
}
|
||||||
|
protected override void ClearItems()
|
||||||
|
{
|
||||||
|
base.ClearItems();
|
||||||
|
tracksByID.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ID { get; set; } = string.Empty;
|
||||||
|
public string Name { get; set; } = string.Empty;
|
||||||
|
public string Comment { get; set; } = string.Empty;
|
||||||
|
public SynthesizedAudioCommand.SynthesizedAudioCommandCollection Commands { get; } = new SynthesizedAudioCommand.SynthesizedAudioCommandCollection();
|
||||||
|
// public VoicebankObjectModel Synthesizer { get; set; } = null;
|
||||||
|
public bool IsMuted { get; set; } = false;
|
||||||
|
public bool IsSolo { get; set; } = false;
|
||||||
|
public byte Panpot { get; set; } = 64;
|
||||||
|
public byte Volume { get; set; } = 0;
|
||||||
|
public object Clone()
|
||||||
|
{
|
||||||
|
SynthesizedAudioTrack clone = new SynthesizedAudioTrack();
|
||||||
|
foreach (SynthesizedAudioCommand command in this.Commands)
|
||||||
|
{
|
||||||
|
clone.Commands.Add(command.Clone() as SynthesizedAudioCommand);
|
||||||
|
}
|
||||||
|
clone.ID = (this.ID.Clone() as string);
|
||||||
|
clone.Name = (this.Name.Clone() as string);
|
||||||
|
return clone;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double Tempo { get; set; } = 120;
|
||||||
|
public Color Color { get; set; } = Color.Empty;
|
||||||
|
}
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
//
|
||||||
|
// SynthesizedAudioVibratoType.cs - indicates the type of vibrato applied to a note in a synthesized audio file
|
||||||
|
//
|
||||||
|
// Author:
|
||||||
|
// Michael Becker <alcexhim@gmail.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2011-2020 Mike Becker's Software
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
namespace MBS.Editor.Plugins.Multimedia.ObjectModels.Audio.Synthesized;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates the type of vibrato applied to a note in a synthesized audio file.
|
||||||
|
/// </summary>
|
||||||
|
public enum SynthesizedAudioVibratoType
|
||||||
|
{
|
||||||
|
None
|
||||||
|
}
|
||||||
@ -0,0 +1,71 @@
|
|||||||
|
//
|
||||||
|
// PaletteEntry.cs - represents a color entry in a palette
|
||||||
|
//
|
||||||
|
// Author:
|
||||||
|
// Michael Becker <alcexhim@gmail.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2011-2020 Mike Becker's Software
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using MBS.Core.Drawing;
|
||||||
|
|
||||||
|
namespace MBS.Editor.Plugins.Multimedia.ObjectModels.Palette
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a color entry in a palette.
|
||||||
|
/// </summary>
|
||||||
|
public class PaletteEntry : ICloneable
|
||||||
|
{
|
||||||
|
public class PaletteEntryCollection
|
||||||
|
: System.Collections.ObjectModel.Collection<PaletteEntry>
|
||||||
|
{
|
||||||
|
public PaletteEntry Add(Color color, string colorName = "")
|
||||||
|
{
|
||||||
|
PaletteEntry entry = new PaletteEntry();
|
||||||
|
entry.Name = colorName;
|
||||||
|
entry.Color = color;
|
||||||
|
|
||||||
|
Add(entry);
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public PaletteEntry(Color color = default(Color), string name = "")
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
Color = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the name of this <see cref="PaletteEntry" />.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The name of this <see cref="PaletteEntry" />.</value>
|
||||||
|
public string Name { get; set; } = String.Empty;
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the color of this <see cref="PaletteEntry" />.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The color of this <see cref="PaletteEntry" />.</value>
|
||||||
|
public Color Color { get; set; } = Color.Empty;
|
||||||
|
|
||||||
|
public object Clone()
|
||||||
|
{
|
||||||
|
PaletteEntry clone = new PaletteEntry();
|
||||||
|
clone.Name = Name;
|
||||||
|
clone.Color = Color;
|
||||||
|
return clone;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,85 @@
|
|||||||
|
//
|
||||||
|
// PaletteObjectModel.cs - provides an ObjectModel for manipulating color palettes
|
||||||
|
//
|
||||||
|
// Author:
|
||||||
|
// Michael Becker <alcexhim@gmail.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2011-2020 Mike Becker's Software
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using MBS.Editor.Core;
|
||||||
|
|
||||||
|
namespace MBS.Editor.Plugins.Multimedia.ObjectModels.Palette
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides an <see cref="ObjectModel" /> for manipulating color palettes.
|
||||||
|
/// </summary>
|
||||||
|
public class PaletteObjectModel : ObjectModel
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
private static ObjectModelReference _omr = null;
|
||||||
|
protected override ObjectModelReference MakeReferenceInternal()
|
||||||
|
{
|
||||||
|
if (_omr == null)
|
||||||
|
{
|
||||||
|
_omr = new ObjectModelReference(GetType(), new Guid("{c852b1d7-d034-43b4-b850-00e583e47fef}"));
|
||||||
|
_omr.Path = new string[] { "Multimedia", "Color palette" };
|
||||||
|
}
|
||||||
|
return _omr;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
public PaletteObjectModel()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
public PaletteObjectModel(PaletteEntry[] entries)
|
||||||
|
{
|
||||||
|
if (entries != null)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < entries.Length; i++)
|
||||||
|
{
|
||||||
|
Entries.Add(entries[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Clear()
|
||||||
|
{
|
||||||
|
Entries.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void CopyTo(ObjectModel where)
|
||||||
|
{
|
||||||
|
PaletteObjectModel clone = (where as PaletteObjectModel);
|
||||||
|
clone.Name = (Name.Clone() as string);
|
||||||
|
for (int i = 0; i < Entries.Count; i++)
|
||||||
|
{
|
||||||
|
clone.Entries.Add(Entries[i].Clone() as PaletteEntry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the name of this palette.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The name of this palette.</value>
|
||||||
|
public string Name { get; set; } = String.Empty;
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a collection of <see cref="PaletteEntry" /> instances representing the color entries in this palette.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The color entries in this palette.</value>
|
||||||
|
public PaletteEntry.PaletteEntryCollection Entries { get; } = new PaletteEntry.PaletteEntryCollection();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,55 @@
|
|||||||
|
//
|
||||||
|
// Copyright (C) 2024 Michael Becker <alcexhim@gmail.com>
|
||||||
|
//
|
||||||
|
// This file is part of editor-dotnet.
|
||||||
|
//
|
||||||
|
// editor-dotnet is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// editor-dotnet is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with editor-dotnet. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System.Numerics;
|
||||||
|
using MBS.Core.Drawing;
|
||||||
|
using MBS.Editor.Core;
|
||||||
|
using MBS.Editor.Plugins.Multimedia.ObjectModels.Palette;
|
||||||
|
|
||||||
|
namespace MBS.Editor.Plugins.Multimedia.ObjectModels.Picture;
|
||||||
|
|
||||||
|
public class PictureObjectModel : ObjectModel
|
||||||
|
{
|
||||||
|
private Dictionary<Vector2D, Color> pixels = new Dictionary<Vector2D, Color>();
|
||||||
|
|
||||||
|
public PaletteObjectModel? Palette { get; set; } = null;
|
||||||
|
|
||||||
|
public int Width { get; set; }
|
||||||
|
public int Height { get; set; }
|
||||||
|
|
||||||
|
public IEnumerable<KeyValuePair<Vector2D, Color>> GetPixels()
|
||||||
|
{
|
||||||
|
return pixels;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color GetPixel(int x, int y)
|
||||||
|
{
|
||||||
|
Vector2D key = new Vector2D(x, y);
|
||||||
|
if (pixels.ContainsKey(key))
|
||||||
|
{
|
||||||
|
return pixels[key];
|
||||||
|
}
|
||||||
|
return Color.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetPixel(int x, int y, Color color)
|
||||||
|
{
|
||||||
|
pixels[new Vector2D(x, y)] = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,49 @@
|
|||||||
|
// Copyright (C) 2024 Michael Becker <alcexhim@gmail.com>
|
||||||
|
//
|
||||||
|
// This file is part of editor-dotnet.
|
||||||
|
//
|
||||||
|
// editor-dotnet is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// editor-dotnet is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with editor-dotnet. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
using MBS.Editor.Core.DataFormats.FileSystem.IFF;
|
||||||
|
using MBS.Editor.Core.ObjectModels.Chunked;
|
||||||
|
using MBS.Editor.Core.ObjectModels.FileSystem;
|
||||||
|
using MBS.Editor.Testing;
|
||||||
|
|
||||||
|
namespace MBS.Editor.Core.Tests.DataFormats.FileSystem.IFF;
|
||||||
|
|
||||||
|
[TestFixture]
|
||||||
|
public class IFFDataFormatTests : EmbeddedResourceTest
|
||||||
|
{
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void CheckVenusTotalSize()
|
||||||
|
{
|
||||||
|
if (TryCreateResourceStream("MBS.Editor.Core.Tests.Resources.TestData.DataFormats.FileSystem.IFF.VENUS.IFF", out Stream? st))
|
||||||
|
{
|
||||||
|
if (st == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ChunkedObjectModel fsom = new ChunkedObjectModel();
|
||||||
|
|
||||||
|
|
||||||
|
IFFDataFormat iff = new IFFDataFormat();
|
||||||
|
Document.Load(fsom, iff, st);
|
||||||
|
|
||||||
|
Assert.That(fsom.Chunks.Count, Is.EqualTo(1));
|
||||||
|
Assert.That((fsom.Chunks[0] as GroupChunk).Chunks.Count, Is.EqualTo(3));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -6,6 +6,10 @@
|
|||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
<IsTestProject>true</IsTestProject>
|
<IsTestProject>true</IsTestProject>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Include="Resources/TestData/DataFormats/FileSystem/IFF/VENUS.IFF" />
|
||||||
|
<EmbeddedResource Include="Resources/TestData/ObjectModels/PropertyList/INI/CompleteTest.ini" />
|
||||||
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.0" />
|
||||||
<PackageReference Include="NUnit" Version="3.13.3" />
|
<PackageReference Include="NUnit" Version="3.13.3" />
|
||||||
@ -15,5 +19,6 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\lib\MBS.Editor.Core\MBS.Editor.Core.csproj" />
|
<ProjectReference Include="..\..\lib\MBS.Editor.Core\MBS.Editor.Core.csproj" />
|
||||||
|
<ProjectReference Include="..\..\lib\MBS.Editor.Testing\MBS.Editor.Testing.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
@ -5,7 +5,7 @@ namespace MBS.Editor.Core.Tests.ObjectModels.FileSystem;
|
|||||||
|
|
||||||
public class FileSystemItemCollectionTests
|
public class FileSystemItemCollectionTests
|
||||||
{
|
{
|
||||||
[ Test()]
|
[Test()]
|
||||||
public static void AddFolderWithEmptyNameTest()
|
public static void AddFolderWithEmptyNameTest()
|
||||||
{
|
{
|
||||||
// the reason this test exists
|
// the reason this test exists
|
||||||
|
|||||||
@ -0,0 +1,80 @@
|
|||||||
|
namespace MBS.Editor.Core.Tests.ObjectModels.PropertyList;
|
||||||
|
|
||||||
|
using System.Text;
|
||||||
|
using MBS.Editor.Core.ObjectModels.PropertyList;
|
||||||
|
using MBS.Editor.Testing;
|
||||||
|
|
||||||
|
public class INIDataFormatTests : EmbeddedResourceTest
|
||||||
|
{
|
||||||
|
private PropertyListObjectModel CreateSimplePropertyListWithSections()
|
||||||
|
{
|
||||||
|
PropertyListObjectModel plom = new PropertyListObjectModel();
|
||||||
|
|
||||||
|
PropertyListProperty prop = new PropertyListProperty("Test 1", 3127);
|
||||||
|
plom.Items.Add(prop);
|
||||||
|
|
||||||
|
prop = new PropertyListProperty("String Property", "This is a Test");
|
||||||
|
plom.Items.Add(prop);
|
||||||
|
|
||||||
|
PropertyListGroup group = new PropertyListGroup("Section 2");
|
||||||
|
group.Items.Add(new PropertyListProperty("Property 2", 923.1072));
|
||||||
|
plom.Items.Add(group);
|
||||||
|
|
||||||
|
return plom;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test()]
|
||||||
|
public void INIDataFormatTest()
|
||||||
|
{
|
||||||
|
PropertyListObjectModel plom = CreateSimplePropertyListWithSections();
|
||||||
|
INIDataFormat ini = new INIDataFormat();
|
||||||
|
|
||||||
|
int old_count = plom.Items.Count;
|
||||||
|
|
||||||
|
MemoryStream ms = new MemoryStream();
|
||||||
|
Document.Save(plom, ini, ms);
|
||||||
|
ms.Flush();
|
||||||
|
|
||||||
|
byte[] data = ms.ToArray();
|
||||||
|
ms = new MemoryStream(data);
|
||||||
|
|
||||||
|
plom = new PropertyListObjectModel();
|
||||||
|
ini = new INIDataFormat();
|
||||||
|
|
||||||
|
Document.Load(plom, ini, ms);
|
||||||
|
|
||||||
|
Assert.That(plom.Items.Count, Is.EqualTo(old_count));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test()]
|
||||||
|
public void ReallyBadINIDataFormatTest()
|
||||||
|
{
|
||||||
|
if (TryCreateResourceStream("Resources.TestData.ObjectModels.PropertyList.INI.CompleteTest.ini", out Stream? st))
|
||||||
|
{
|
||||||
|
if (st == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
PropertyListObjectModel plom = new PropertyListObjectModel();
|
||||||
|
INIDataFormat ini = new INIDataFormat();
|
||||||
|
Document.Load(plom, ini, st);
|
||||||
|
|
||||||
|
Assert.That(plom.Items.Count == 4); // comments are included by default
|
||||||
|
Assert.That(plom.Items[0], Is.InstanceOf<PropertyListComment>());
|
||||||
|
|
||||||
|
Assert.That(plom.Items[1], Is.InstanceOf<PropertyListGroup>());
|
||||||
|
|
||||||
|
PropertyListGroup? g = plom.Items[1] as PropertyListGroup;
|
||||||
|
if (g != null)
|
||||||
|
{
|
||||||
|
Assert.That(g.Items.Count, Is.EqualTo(3));
|
||||||
|
Assert.That(g.Items[0].Name, Is.EqualTo("Property1"));
|
||||||
|
|
||||||
|
PropertyListProperty? prop = g.Items[1] as PropertyListProperty;
|
||||||
|
Assert.That(prop, Is.Not.Null);
|
||||||
|
Assert.That(prop.Value, Is.Not.Null);
|
||||||
|
Assert.That(prop.Value, Is.EqualTo("This is a property with quotes."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Binary file not shown.
@ -0,0 +1,16 @@
|
|||||||
|
; this is a really bad INI file which should be able
|
||||||
|
; to be completely parsed by MBS Editor
|
||||||
|
|
||||||
|
[Section1]
|
||||||
|
Property1=Value2
|
||||||
|
PropertyWithQuotes="This is a property with quotes."
|
||||||
|
PropertyWithoutQuotes=Quotes really do not matter in INI files.
|
||||||
|
|
||||||
|
[Section with a space in its name]
|
||||||
|
; this should work, and this comment should be included
|
||||||
|
; in the PropertyListObjectModel
|
||||||
|
Property Key with Space=Another unquoted value
|
||||||
|
What happens when=there are multiple equal=values it should be=just the first one
|
||||||
|
|
||||||
|
[This is [probably a [really bad] Idea]]
|
||||||
|
Version=1.0.50726.42
|
||||||
@ -5,22 +5,17 @@ using MBS.Editor.Core;
|
|||||||
using MBS.Editor.Core.ObjectModels.FileSystem;
|
using MBS.Editor.Core.ObjectModels.FileSystem;
|
||||||
using MBS.Editor.Core.ObjectModels.FileSystem.FileSources;
|
using MBS.Editor.Core.ObjectModels.FileSystem.FileSources;
|
||||||
using MBS.Editor.Plugins.CRI.DataFormats.FileSystem.CPK;
|
using MBS.Editor.Plugins.CRI.DataFormats.FileSystem.CPK;
|
||||||
|
using MBS.Editor.Testing;
|
||||||
using NUnit.Framework.Internal;
|
using NUnit.Framework.Internal;
|
||||||
|
|
||||||
namespace MBS.Editor.Plugins.CRI.Tests.DataFormats.CPK;
|
namespace MBS.Editor.Plugins.CRI.Tests.DataFormats.CPK;
|
||||||
|
|
||||||
public class CPKDataFormatTests
|
public class CPKDataFormatTests : EmbeddedResourceTest
|
||||||
{
|
{
|
||||||
private System.Collections.Generic.Dictionary<string, System.IO.Stream> testDataStreams = new System.Collections.Generic.Dictionary<string, System.IO.Stream>();
|
|
||||||
|
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void Setup()
|
public void Setup()
|
||||||
{
|
{
|
||||||
MBS.Core.Reflection.ManifestResourceStream[] strms = MBS.Core.Reflection.ManifestResourceStream.GetManifestResourceStreamsForAssembly(System.Reflection.Assembly.GetExecutingAssembly());
|
InitializeResources();
|
||||||
for (int i = 0; i < strms.Length; i++)
|
|
||||||
{
|
|
||||||
testDataStreams[strms[i].Name] = strms[i].Stream;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test(Description = "Ensures the CPKDataFormat can store exactly one file, uncompressed, with no filename masking.")]
|
[Test(Description = "Ensures the CPKDataFormat can store exactly one file, uncompressed, with no filename masking.")]
|
||||||
@ -57,20 +52,6 @@ public class CPKDataFormatTests
|
|||||||
|
|
||||||
Assert.That(System_dat.Source.GetData(2, 1)[0], Is.EqualTo(0xBA));
|
Assert.That(System_dat.Source.GetData(2, 1)[0], Is.EqualTo(0xBA));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SampleStreamTest(string streamName)
|
|
||||||
{
|
|
||||||
if (testDataStreams.ContainsKey(streamName))
|
|
||||||
{
|
|
||||||
System.IO.Stream TEST_STREAM = testDataStreams[streamName];
|
|
||||||
SampleStreamTest(TEST_STREAM);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Console.Error.WriteLine("test data stream not found: '" + streamName + "'");
|
|
||||||
Assert.Ignore();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private void SampleStreamTest(System.IO.Stream stream)
|
private void SampleStreamTest(System.IO.Stream stream)
|
||||||
{
|
{
|
||||||
stream.Seek(0, System.IO.SeekOrigin.Begin);
|
stream.Seek(0, System.IO.SeekOrigin.Begin);
|
||||||
|
|||||||
@ -0,0 +1,8 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace MBS.Editor.Plugins.CRI.Tests.DataFormats.Database.UTF;
|
||||||
|
|
||||||
|
public class UTFDataFormatTests
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@ -16,6 +16,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\lib\MBS.Editor.Core\MBS.Editor.Core.csproj" />
|
<ProjectReference Include="..\..\lib\MBS.Editor.Core\MBS.Editor.Core.csproj" />
|
||||||
<ProjectReference Include="..\..\plugins\MBS.Editor.Plugins.CRI\MBS.Editor.Plugins.CRI.csproj" />
|
<ProjectReference Include="..\..\plugins\MBS.Editor.Plugins.CRI\MBS.Editor.Plugins.CRI.csproj" />
|
||||||
|
<ProjectReference Include="..\..\lib\MBS.Editor.Testing\MBS.Editor.Testing.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<EmbeddedResource Include="Resources\TestData\sample_data_uncompressed_unmasked.cpk" />
|
<EmbeddedResource Include="Resources\TestData\sample_data_uncompressed_unmasked.cpk" />
|
||||||
|
|||||||
@ -0,0 +1,59 @@
|
|||||||
|
using MBS.Editor.Core;
|
||||||
|
using MBS.Editor.Plugins.Mekada.DataFormats.Mechanic;
|
||||||
|
using MBS.Editor.Testing;
|
||||||
|
|
||||||
|
namespace MBS.Editor.Plugins.Mekada.Tests;
|
||||||
|
|
||||||
|
public class MEKDataFormatTests : EmbeddedResourceTest
|
||||||
|
{
|
||||||
|
[SetUp]
|
||||||
|
public void Setup()
|
||||||
|
{
|
||||||
|
InitializeResources();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Test1()
|
||||||
|
{
|
||||||
|
if (TryCreateResourceStream("MBS.Editor.Plugins.Mekada.Tests.Resources.TestData.Mechanics.0.mek", out Stream? st))
|
||||||
|
{
|
||||||
|
MechanicObjectModel mekom = new MechanicObjectModel();
|
||||||
|
MEKDataFormat mekdf = new MEKDataFormat();
|
||||||
|
Document.Load(mekom, mekdf, st);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Assert.Ignore();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Test2()
|
||||||
|
{
|
||||||
|
if (TryCreateResourceStream("MBS.Editor.Plugins.Mekada.Tests.Resources.TestData.Mechanics.1.mek", out Stream? st))
|
||||||
|
{
|
||||||
|
MechanicObjectModel mekom = new MechanicObjectModel();
|
||||||
|
MEKDataFormat mekdf = new MEKDataFormat();
|
||||||
|
Document.Load(mekom, mekdf, st);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Assert.Ignore();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void WithCarInLot()
|
||||||
|
{
|
||||||
|
if (TryCreateResourceStream("MBS.Editor.Plugins.Mekada.Tests.Resources.TestData.Mechanics.WithCarInLot.mek", out Stream? st))
|
||||||
|
{
|
||||||
|
MechanicObjectModel mekom = new MechanicObjectModel();
|
||||||
|
MEKDataFormat mekdf = new MEKDataFormat();
|
||||||
|
Document.Load(mekom, mekdf, st);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Assert.Ignore();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1 @@
|
|||||||
|
global using NUnit.Framework;
|
||||||
@ -0,0 +1,39 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
<IsTestProject>true</IsTestProject>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.0" />
|
||||||
|
<PackageReference Include="NUnit" Version="3.13.3" />
|
||||||
|
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />
|
||||||
|
<PackageReference Include="NUnit.Analyzers" Version="3.6.1" />
|
||||||
|
<PackageReference Include="coverlet.collector" Version="6.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="Resources/" />
|
||||||
|
<Folder Include="Resources/TestData/" />
|
||||||
|
<Folder Include="Resources/TestData/Mechanics/" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Include="Resources/TestData/Mechanics/0.mek" />
|
||||||
|
<EmbeddedResource Include="Resources/TestData/Mechanics/1.mek" />
|
||||||
|
<EmbeddedResource Include="Resources/TestData/Mechanics/WithCarInLot.mek" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\..\..\framework-dotnet\framework-dotnet\src\lib\MBS.Core\MBS.Core.csproj" />
|
||||||
|
<ProjectReference Include="..\..\lib\MBS.Editor.Core\MBS.Editor.Core.csproj" />
|
||||||
|
<ProjectReference Include="..\..\plugins\MBS.Editor.Plugins.Mekada\MBS.Editor.Plugins.Mekada.csproj" />
|
||||||
|
<ProjectReference Include="..\..\lib\MBS.Editor.Testing\MBS.Editor.Testing.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,117 @@
|
|||||||
|
// Copyright (C) 2024 Michael Becker <alcexhim@gmail.com>
|
||||||
|
//
|
||||||
|
// This file is part of editor-dotnet.
|
||||||
|
//
|
||||||
|
// editor-dotnet is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// editor-dotnet is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with editor-dotnet. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
using MBS.Editor.Core;
|
||||||
|
using MBS.Editor.Plugins.Multimedia.DataFormats.Audio.Synthesized.RMI;
|
||||||
|
using MBS.Editor.Plugins.Multimedia.ObjectModels.Audio.Synthesized;
|
||||||
|
using MBS.Editor.Testing;
|
||||||
|
|
||||||
|
namespace MBS.Editor.Plugins.Multimedia.Tests.DataFormats.Audio.Synthesized.RMI;
|
||||||
|
|
||||||
|
public class RMIDataFormatTests : EmbeddedResourceTest
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void LoadMetadataTest()
|
||||||
|
{
|
||||||
|
if (TryCreateResourceStream("MBS.Editor.Plugins.Multimedia.Tests.Resources.TestData.DataFormats.Audio.Synthesized.RMI.Mountain.rmi", out Stream? st) && st != null)
|
||||||
|
{
|
||||||
|
SynthesizedAudioObjectModel audio = new SynthesizedAudioObjectModel();
|
||||||
|
RMIDataFormat rmi = new RMIDataFormat();
|
||||||
|
|
||||||
|
Document.Load(audio, rmi, st);
|
||||||
|
|
||||||
|
Assert.That(audio.Metadata.Artist, Is.EqualTo("Edvard Grieg"));
|
||||||
|
Assert.That(audio.Metadata.Copyright, Is.EqualTo("1995 Midisoft Corporation"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Assert.Ignore();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void LoadTrackMetadataTest()
|
||||||
|
{
|
||||||
|
if (TryCreateResourceStream("MBS.Editor.Plugins.Multimedia.Tests.Resources.TestData.DataFormats.Audio.Synthesized.RMI.Mountain.rmi", out Stream? st) && st != null)
|
||||||
|
{
|
||||||
|
SynthesizedAudioObjectModel audio = new SynthesizedAudioObjectModel();
|
||||||
|
RMIDataFormat rmi = new RMIDataFormat();
|
||||||
|
|
||||||
|
Document.Load(audio, rmi, st);
|
||||||
|
|
||||||
|
Assert.That(audio.Tracks.Count, Is.EqualTo(12));
|
||||||
|
Assert.That(audio.Tracks[1].Name, Is.EqualTo("High Strings"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Assert.Ignore();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void SaveTrackMetadataTest()
|
||||||
|
{
|
||||||
|
if (TryCreateResourceStream("MBS.Editor.Plugins.Multimedia.Tests.Resources.TestData.DataFormats.Audio.Synthesized.RMI.Mountain.rmi", out Stream? st) && st != null)
|
||||||
|
{
|
||||||
|
SynthesizedAudioObjectModel audio = new SynthesizedAudioObjectModel();
|
||||||
|
RMIDataFormat rmi = new RMIDataFormat();
|
||||||
|
|
||||||
|
Document.Load(audio, rmi, st);
|
||||||
|
|
||||||
|
MemoryStream ms = new MemoryStream();
|
||||||
|
Document.Save(audio, rmi, ms);
|
||||||
|
|
||||||
|
audio = new SynthesizedAudioObjectModel();
|
||||||
|
ms.Seek(0, SeekOrigin.Begin);
|
||||||
|
Document.Load(audio, rmi, ms);
|
||||||
|
|
||||||
|
Assert.That(audio.Tracks.Count, Is.EqualTo(12));
|
||||||
|
Assert.That(audio.Tracks[1].Name, Is.EqualTo("High Strings"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Assert.Ignore();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void SaveTrackCommandsTest()
|
||||||
|
{
|
||||||
|
if (TryCreateResourceStream("MBS.Editor.Plugins.Multimedia.Tests.Resources.TestData.DataFormats.Audio.Synthesized.RMI.Mountain.rmi", out Stream? st) && st != null)
|
||||||
|
{
|
||||||
|
SynthesizedAudioObjectModel audio = new SynthesizedAudioObjectModel();
|
||||||
|
RMIDataFormat rmi = new RMIDataFormat();
|
||||||
|
|
||||||
|
Document.Load(audio, rmi, st);
|
||||||
|
|
||||||
|
MemoryStream ms = new MemoryStream();
|
||||||
|
Document.Save(audio, rmi, ms);
|
||||||
|
|
||||||
|
int cc = audio.Tracks[1].Commands.Count;
|
||||||
|
|
||||||
|
audio = new SynthesizedAudioObjectModel();
|
||||||
|
ms.Seek(0, SeekOrigin.Begin);
|
||||||
|
Document.Load(audio, rmi, ms);
|
||||||
|
|
||||||
|
Assert.That(audio.Tracks[1].Commands.Count, Is.EqualTo(cc));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Assert.Ignore();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,62 @@
|
|||||||
|
using MBS.Core.Drawing;
|
||||||
|
using MBS.Editor.Core;
|
||||||
|
using MBS.Editor.Plugins.Multimedia.DataFormats.Picture.ILBM;
|
||||||
|
using MBS.Editor.Plugins.Multimedia.ObjectModels.Picture;
|
||||||
|
using MBS.Editor.Testing;
|
||||||
|
|
||||||
|
namespace MBS.Editor.Plugins.Multimedia.Tests.DataFormats.Picture.ILBM;
|
||||||
|
|
||||||
|
public class ILBMDataFormatTests : EmbeddedResourceTest
|
||||||
|
{
|
||||||
|
[SetUp]
|
||||||
|
public void Setup()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Venus_Size_EqualTo_300x150()
|
||||||
|
{
|
||||||
|
if (!TryCreateResourceStream("MBS.Editor.Plugins.Multimedia.Tests.Resources.TestData.DataFormats.Picture.ILBM.VENUS.IFF", out Stream? st))
|
||||||
|
{
|
||||||
|
Assert.Ignore();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (st == null)
|
||||||
|
{
|
||||||
|
Assert.Ignore();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PictureObjectModel pic = new PictureObjectModel();
|
||||||
|
|
||||||
|
ILBMDataFormat iff = new ILBMDataFormat();
|
||||||
|
Document.Load(pic, iff, st);
|
||||||
|
|
||||||
|
Assert.That(pic.Width, Is.EqualTo(300));
|
||||||
|
Assert.That(pic.Height, Is.EqualTo(150));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Venus_Palettte_Contains_ColorMap()
|
||||||
|
{
|
||||||
|
if (!TryCreateResourceStream("MBS.Editor.Plugins.Multimedia.Tests.Resources.TestData.DataFormats.Picture.ILBM.VENUS.IFF", out Stream? st))
|
||||||
|
{
|
||||||
|
Assert.Ignore();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (st == null)
|
||||||
|
{
|
||||||
|
Assert.Ignore();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PictureObjectModel pic = new PictureObjectModel();
|
||||||
|
|
||||||
|
ILBMDataFormat iff = new ILBMDataFormat();
|
||||||
|
Document.Load(pic, iff, st);
|
||||||
|
|
||||||
|
Assert.That(pic.Palette, Is.Not.Null);
|
||||||
|
Assert.That(pic.Palette.Entries.Count, Is.EqualTo(256));
|
||||||
|
Assert.That(pic.Palette.Entries[1].Color, Is.EqualTo(Color.FromString("#FFAF17")));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1 @@
|
|||||||
|
global using NUnit.Framework;
|
||||||
@ -0,0 +1,42 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
<IsTestProject>true</IsTestProject>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.0" />
|
||||||
|
<PackageReference Include="NUnit" Version="3.13.3" />
|
||||||
|
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />
|
||||||
|
<PackageReference Include="NUnit.Analyzers" Version="3.6.1" />
|
||||||
|
<PackageReference Include="coverlet.collector" Version="6.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Include="Resources/TestData/DataFormats/Picture/ILBM/VENUS.IFF" />
|
||||||
|
<EmbeddedResource Include="Resources/TestData/DataFormats/Picture/ILBM/BLK.IFF" />
|
||||||
|
|
||||||
|
<EmbeddedResource Include="Resources/TestData/DataFormats/Audio/Synthesized/RMI/Mountain.rmi" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="../../../../framework-dotnet/framework-dotnet/src/lib/MBS.Core/MBS.Core.csproj" />
|
||||||
|
<ProjectReference Include="../../lib/MBS.Editor.Core/MBS.Editor.Core.csproj" />
|
||||||
|
<ProjectReference Include="../../lib/MBS.Editor.Testing/MBS.Editor.Testing.csproj" />
|
||||||
|
<ProjectReference Include="../../plugins/MBS.Editor.Plugins.Multimedia/MBS.Editor.Plugins.Multimedia.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="Resources/" />
|
||||||
|
<Folder Include="Resources/TestData/" />
|
||||||
|
<Folder Include="Resources/TestData/DataFormats/" />
|
||||||
|
<Folder Include="Resources/TestData/DataFormats/Picture/" />
|
||||||
|
<Folder Include="Resources/TestData/DataFormats/Picture/ILBM/" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1 +1 @@
|
|||||||
Subproject commit a24ae26d5775be4387a58f61a3dc26057e0c1171
|
Subproject commit 223c34c734ee60b4f4738b48181afb7221e18c39
|
||||||
1
web-framework-dotnet
Submodule
1
web-framework-dotnet
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 732daae00ebeb6bb31454bd954bdd8174ef1fd0e
|
||||||
Loading…
x
Reference in New Issue
Block a user