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"]
|
||||
path = 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}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "app", "app", "{4ED8C38B-47EF-4368-9965-CF627465B45A}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MBS.Editor", "editor-dotnet\src\app\MBS.Editor\MBS.Editor.csproj", "{A936C411-0184-43F8-A343-0DE8C3B7B42E}"
|
||||
EndProject
|
||||
@ -27,8 +25,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{BDC147D8-4D9
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "lib", "lib", "{80A728D5-7C00-4B59-A37E-321C54CC554F}"
|
||||
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}"
|
||||
EndProject
|
||||
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
|
||||
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
|
||||
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
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
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}.Release|Any CPU.ActiveCfg = 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.Build.0 = Debug|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}.Release|Any CPU.ActiveCfg = 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
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
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}
|
||||
{C86F60F9-BBC1-4554-A3B0-D553F9C157A8} = {F05001E1-6FFB-48AE-BF7F-7F39A24D3B70}
|
||||
{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}
|
||||
{BDC147D8-4D97-4663-9408-BC822E1E0B3C} = {B9747AFE-160D-4807-B989-B3F0ACCA3634}
|
||||
{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}
|
||||
{451AD529-16B4-4049-9D0C-0C79B3DDFA52} = {F05001E1-6FFB-48AE-BF7F-7F39A24D3B70}
|
||||
{5978938E-19F6-42AE-B588-7719A65ABCA7} = {451AD529-16B4-4049-9D0C-0C79B3DDFA52}
|
||||
{CDA151F8-5BA7-47DB-883D-CBC2DD94F0DF} = {4ED8C38B-47EF-4368-9965-CF627465B45A}
|
||||
{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}
|
||||
{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
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
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>
|
||||
<ProjectReference Include="..\..\lib\MBS.Editor.Core\MBS.Editor.Core.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="..\..\..\..\desktop-framework-dotnet\desktop-framework-dotnet\src\lib\MBS.Desktop\MBS.Desktop.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<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;
|
||||
|
||||
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)
|
||||
{
|
||||
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 virtual void BeforeSaveInternal(Stack<ObjectModel> objectModels)
|
||||
{
|
||||
}
|
||||
protected virtual void AfterSaveInternal(Stack<ObjectModel> objectModels)
|
||||
{
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
|
||||
|
||||
public static T FromType<T>() where T : DataFormat, new()
|
||||
{
|
||||
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()
|
||||
{
|
||||
byte[] buffer = ReadBytes((uint)3);
|
||||
byte[] _buffer = new byte[3];
|
||||
byte[] _buffer = new byte[4];
|
||||
if (base.Endianness == Endianness.LittleEndian)
|
||||
{
|
||||
_buffer[0] = buffer[0];
|
||||
@ -1799,31 +1799,6 @@ public class Reader : ReaderWriterBase
|
||||
}
|
||||
}
|
||||
|
||||
/// <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)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
@ -66,6 +66,8 @@ public class ReaderWriterBase
|
||||
long paddingCount = ((alignTo - (_st.Position % alignTo)) % alignTo);
|
||||
paddingCount += extraPadding;
|
||||
|
||||
if (paddingCount > 0)
|
||||
{
|
||||
if (_st.Position == _st.Length)
|
||||
{
|
||||
byte[] buffer = new byte[paddingCount];
|
||||
@ -76,4 +78,13 @@ public class ReaderWriterBase
|
||||
_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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -33,4 +33,13 @@ public class 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;
|
||||
|
||||
public class ObjectModelNotSupportedException : Exception
|
||||
@ -29,9 +31,19 @@ public class ObjectModelNotSupportedException : Exception
|
||||
public Type? ExpectedObjectModelType { 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;
|
||||
|
||||
public abstract class FileSource
|
||||
@ -22,4 +23,11 @@ public abstract class FileSource
|
||||
*/
|
||||
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)
|
||||
{
|
||||
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");
|
||||
}
|
||||
|
||||
@ -178,4 +178,14 @@ public class FileSystemItemCollection
|
||||
}
|
||||
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;
|
||||
|
||||
using System;
|
||||
using MBS.Core;
|
||||
using MBS.Desktop;
|
||||
using MBS.Desktop.Controls;
|
||||
|
||||
public class EditorApplication : DesktopApplication
|
||||
{
|
||||
|
||||
protected override int StartInternal()
|
||||
protected override void OnStartup(EventArgs e)
|
||||
{
|
||||
return 0;
|
||||
base.OnStartup(e);
|
||||
|
||||
Console.WriteLine("editor: OnStartup");
|
||||
|
||||
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>
|
||||
<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>
|
||||
|
||||
<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>
|
||||
<IsTestProject>true</IsTestProject>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Resources/TestData/DataFormats/FileSystem/IFF/VENUS.IFF" />
|
||||
<EmbeddedResource Include="Resources/TestData/ObjectModels/PropertyList/INI/CompleteTest.ini" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.0" />
|
||||
<PackageReference Include="NUnit" Version="3.13.3" />
|
||||
@ -15,5 +19,6 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\lib\MBS.Editor.Core\MBS.Editor.Core.csproj" />
|
||||
<ProjectReference Include="..\..\lib\MBS.Editor.Testing\MBS.Editor.Testing.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@ -5,7 +5,7 @@ namespace MBS.Editor.Core.Tests.ObjectModels.FileSystem;
|
||||
|
||||
public class FileSystemItemCollectionTests
|
||||
{
|
||||
[ Test()]
|
||||
[Test()]
|
||||
public static void AddFolderWithEmptyNameTest()
|
||||
{
|
||||
// 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.FileSources;
|
||||
using MBS.Editor.Plugins.CRI.DataFormats.FileSystem.CPK;
|
||||
using MBS.Editor.Testing;
|
||||
using NUnit.Framework.Internal;
|
||||
|
||||
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]
|
||||
public void Setup()
|
||||
{
|
||||
MBS.Core.Reflection.ManifestResourceStream[] strms = MBS.Core.Reflection.ManifestResourceStream.GetManifestResourceStreamsForAssembly(System.Reflection.Assembly.GetExecutingAssembly());
|
||||
for (int i = 0; i < strms.Length; i++)
|
||||
{
|
||||
testDataStreams[strms[i].Name] = strms[i].Stream;
|
||||
}
|
||||
InitializeResources();
|
||||
}
|
||||
|
||||
[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));
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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>
|
||||
<ProjectReference Include="..\..\lib\MBS.Editor.Core\MBS.Editor.Core.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>
|
||||
<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