├── .config
└── dotnet-tools.json
├── .gitattributes
├── .github
└── workflows
│ ├── build.yml
│ └── release.yml
├── .gitignore
├── .gitmodules
├── LICENSE
├── MiniPlugins
├── .config
│ └── dotnet-tools.json
├── MiniPluginInterface.cs
├── MiniPluginLayout.cs
├── MiniPlugins.cs
└── MiniPlugins.csproj
├── README.md
├── SrcTextures
├── .gitignore
├── ImageSources
│ ├── DialNumbered.knob
│ ├── PowerOn.xcf
│ └── PrefabText.xcf
├── Inter_18pt-Bold.ttf
├── OFL.txt
└── UserInterface
│ ├── .gitignore
│ ├── ButtonPressed.png
│ ├── ButtonUnpressed.png
│ ├── DialBackground.png
│ ├── DialPointer.png
│ ├── FileOpen.svg
│ ├── FxLoopChain.png
│ ├── HoverTextOutline.png
│ ├── InputChain.png
│ ├── LevelDisplay.png
│ ├── MoreButton.png
│ ├── OutputChain.png
│ ├── Play.png
│ ├── PluginBackground.png
│ ├── PopupBackground.png
│ ├── PowerOff.png
│ ├── PowerOn.png
│ ├── Record.png
│ ├── Restart.png
│ ├── SingleWhitePixel.png
│ ├── StompOutline.png
│ ├── StompboxLogo.png
│ ├── Stop.png
│ ├── TunerPoint.png
│ └── VerticalSlider.png
├── StompboxAndroid
├── .config
│ └── dotnet-tools.json
├── Activity1.cs
├── AndroidManifest.xml
├── Resources
│ ├── Values
│ │ ├── Strings.xml
│ │ └── ic_launcher_background.xml
│ ├── mipmap-anydpi-v26
│ │ ├── ic_launcher.xml
│ │ └── ic_launcher_round.xml
│ ├── mipmap-hdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ └── ic_launcher_round.png
│ ├── mipmap-ldpi
│ │ └── ic_launcher.png
│ ├── mipmap-mdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ └── ic_launcher_round.png
│ ├── mipmap-xhdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ └── ic_launcher_round.png
│ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ └── ic_launcher_round.png
│ └── mipmap-xxxhdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ └── ic_launcher_round.png
└── StompboxAndroid.csproj
├── StompboxClient
├── StompboxAPI
│ ├── APIClient.cs
│ ├── NativeAPI.cs
│ ├── StompboxAPI.csproj
│ ├── StompboxProcessor.cs
│ └── UnmanagedAudioPlugin.cs
├── StompboxAPIBase
│ ├── AudioPlugin.cs
│ ├── PluginFactory.cs
│ ├── StompboxAPIBase.projitems
│ ├── StompboxClient.cs
│ └── StompboxClientBase.shproj
├── StompboxAPITest
│ ├── Program.cs
│ └── StompboxAPITest.csproj
└── StompboxRemoteClient
│ ├── NetworkInterface.cs
│ ├── ProtocolClient.cs
│ ├── RemoteClient.cs
│ ├── RemotePlugin.cs
│ └── StompboxRemoteClient.csproj
├── StompboxContent
└── Content
│ └── Textures
│ ├── ImageManifest.xml
│ └── UISheet0.png
├── StompboxHost
├── Icon.ico
├── Program.cs
├── Properties
│ └── launchSettings.json
└── StompboxHost.csproj
├── StompboxImageProcessor
├── Program.cs
└── StompboxImageProcessor.csproj
├── StompboxPlugin
├── Properties
│ └── AssemblyInfo.cs
├── README.txt
├── StompboxPlugin.cs
├── StompboxPlugin.csproj
└── Troubleshooting.md
├── StompboxRemote
├── .config
│ └── dotnet-tools.json
├── Icon.ico
├── Program.cs
├── StompboxRemote.csproj
└── app.manifest
├── StompboxRemoteGL
├── .config
│ └── dotnet-tools.json
├── Icon.bmp
├── Icon.ico
├── Program.cs
├── StompboxRemoteGL.csproj
└── app.manifest
├── StompboxShared
├── Content
│ ├── Content.mgcb
│ └── Textures
│ │ └── .gitignore
├── Interface
│ ├── AudioFilePlayerInterface.cs
│ ├── AudioFileRecorderInterface.cs
│ ├── DAWInterface.cs
│ ├── InterfaceBase.cs
│ ├── MobileInterface.cs
│ ├── PedalboardInterface.cs
│ ├── PluginInterface.cs
│ ├── StompboxLayout.cs
│ └── TunerInterface.cs
├── NoteUtil.cs
├── StompboxShared.projitems
├── StompboxShared.shproj
└── SysExMapper.cs
├── StompboxUI.sln
└── WioSerialDisplay
├── Free_Fonts.h
└── WioSerialDisplay.ino
/.config/dotnet-tools.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": 1,
3 | "isRoot": true,
4 | "tools": {
5 | "dotnet-mgcb": {
6 | "version": "3.8.1.303",
7 | "commands": [
8 | "mgcb"
9 | ]
10 | },
11 | "dotnet-mgcb-editor": {
12 | "version": "3.8.1.303",
13 | "commands": [
14 | "mgcb-editor"
15 | ]
16 | },
17 | "dotnet-mgcb-editor-linux": {
18 | "version": "3.8.1.303",
19 | "commands": [
20 | "mgcb-editor-linux"
21 | ]
22 | },
23 | "dotnet-mgcb-editor-windows": {
24 | "version": "3.8.1.303",
25 | "commands": [
26 | "mgcb-editor-windows"
27 | ]
28 | },
29 | "dotnet-mgcb-editor-mac": {
30 | "version": "3.8.1.303",
31 | "commands": [
32 | "mgcb-editor-mac"
33 | ]
34 | }
35 | }
36 | }
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: Build
2 |
3 | on:
4 | [workflow_dispatch, push, pull_request]
5 |
6 | jobs:
7 | build-windows:
8 | name: Build Windows
9 | runs-on: windows-latest
10 | steps:
11 | - uses: actions/checkout@v4
12 | with:
13 | submodules: recursive
14 |
15 | - name: Configure stompbox
16 | working-directory: ${{github.workspace}}/Dependencies/stompbox/build
17 | run: |
18 | cmake.exe -G "Visual Studio 17 2022" -A x64 ..
19 |
20 | - name: Setup MSBuild and add to PATH
21 | uses: microsoft/setup-msbuild@v1.3.1
22 |
23 | - name: Restore NuGet Packages
24 | run:
25 | dotnet restore
26 |
27 | - name: Run Image Processor
28 | working-directory: ${{github.workspace}}
29 | run: |
30 | msbuild .\StompboxUI.sln /t:StompboxImageProcessor /p:Configuration="Release"
31 | cd StompboxImageProcessor\bin\Release\net8.0
32 | .\StompboxImageProcessor.exe
33 |
34 | - name: Run MSBuild for Plugin
35 | working-directory: ${{github.workspace}}
36 | run: msbuild .\StompboxUI.sln /t:StompboxPlugin /p:Configuration=Release
37 |
38 | - name: Create Plugin Artifact
39 | uses: actions/upload-artifact@v4
40 | with:
41 | name: StompboxVST3Plugin
42 | path: ${{github.workspace}}\StompboxPlugin\bin\Release\net8.0-windows
43 |
44 | - name: Run MSBuild for Windows Remote
45 | working-directory: ${{github.workspace}}
46 | run: msbuild .\StompboxUI.sln /t:StompboxRemote /p:Configuration=Release
47 |
48 | - name: Create Windows Remote Artifact
49 | uses: actions/upload-artifact@v4
50 | with:
51 | name: StompboxRemote
52 | path: ${{github.workspace}}\StompboxRemote\bin\Release\net8.0-windows
53 |
54 | - name: Setup Java
55 | uses: actions/setup-java@v3
56 | with:
57 | distribution: 'microsoft'
58 | java-version: '17'
59 |
60 | - name: run MSBuild for Android Remote
61 | run: |
62 | echo -n ${{ secrets.KEYSTORE }} | base64 --ignore-garbage --decode > ${{github.workspace}}\android.keystore
63 | msbuild .\StompboxAndroid\StompboxAndroid.csproj /p:Configuration=RELEASE /p:AndroidKeyStore=true /p:AndroidSigningKeyAlias=stompboxkeystore /p:AndroidSigningKeyStore="${{github.workspace}}\android.keystore" /p:AndroidSigningKeyPass="${{ secrets.KEYSTORE_PASS }}" /p:AndroidSigningStorePass="${{ secrets.KEYSTORE_PASS }}"
64 |
65 | - name: Create Android Remote Artifact
66 | uses: actions/upload-artifact@v4
67 | with:
68 | name: AndroidRemote
69 | path: ${{github.workspace}}\StompboxAndroid\bin\Release\net8.0-android\StompboxAndroid.StompboxAndroid-Signed.apk
70 |
71 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: Release
2 |
3 | on:
4 | workflow_dispatch:
5 |
6 | jobs:
7 | create_release:
8 | name: Create release
9 | runs-on: ubuntu-latest
10 | outputs:
11 | upload_url: ${{steps.create_release.outputs.upload_url}}
12 | steps:
13 | - name: Check out repository
14 | uses: actions/checkout@v4
15 | with:
16 | submodules: recursive
17 |
18 | - name: Create release
19 | id: create_release
20 | uses: actions/create-release@v1
21 | env:
22 | GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
23 | with:
24 | draft: true
25 | tag_name: ${{github.ref}}
26 | release_name: Release ${{github.ref}}
27 |
28 | build-windows:
29 | name: Build Windows
30 | needs: create_release
31 | runs-on: windows-latest
32 | steps:
33 | - uses: actions/checkout@v3.3.0
34 | with:
35 | submodules: recursive
36 |
37 | - name: Configure stompbox
38 | working-directory: ${{github.workspace}}/Dependencies/stompbox/build
39 | run: |
40 | cmake.exe -G "Visual Studio 17 2022" -A x64 ..
41 |
42 | - name: Setup MSBuild and add to PATH
43 | uses: microsoft/setup-msbuild@v1.3.1
44 |
45 | - name: Restore NuGet Packages
46 | run: dotnet restore
47 |
48 | - name: Run Image Processor
49 | working-directory: ${{github.workspace}}
50 | run: |
51 | msbuild .\StompboxUI.sln /t:StompboxImageProcessor /p:Configuration="Release"
52 | cd StompboxImageProcessor\bin\Release\net8.0
53 | .\StompboxImageProcessor.exe
54 |
55 | - name: Run MSBuild for VST Plugin
56 | working-directory: ${{github.workspace}}
57 | run: msbuild .\StompboxUI.sln /t:StompboxPlugin /p:Configuration=Release
58 |
59 | - name: Add Plugin Archive
60 | working-directory: ${{github.workspace}}
61 | run: |
62 | mkdir plugin-build
63 | move StompboxPlugin\bin\Release\net8.0-windows plugin-build\StompboxPlugin
64 | cp StompboxPlugin\README.txt plugin-build
65 | Compress-Archive -Path plugin-build\* -Destination StompboxVST3Plugin.zip
66 |
67 | - name: Upload Plugin Asset
68 | uses: actions/upload-release-asset@v1
69 | env:
70 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
71 | with:
72 | upload_url: ${{ needs.create_release.outputs.upload_url }}
73 | asset_path: ./StompboxVST3Plugin.zip
74 | asset_name: StompboxVST3Plugin.zip
75 | asset_content_type: application/zip
76 |
77 | - name: Run MSBuild for Windows Remote
78 | working-directory: ${{github.workspace}}
79 | run: msbuild .\StompboxUI.sln /t:StompboxRemote /p:Configuration=Release
80 |
81 | - name: Add Windows Remote Archive
82 | run: Compress-Archive -Path ${{github.workspace}}\StompboxRemote\bin\Release\net8.0-windows\* -Destination StompboxRemote.zip
83 |
84 | - name: Upload Windows Remote Asset
85 | uses: actions/upload-release-asset@v1
86 | env:
87 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
88 | with:
89 | upload_url: ${{ needs.create_release.outputs.upload_url }}
90 | asset_path: ./StompboxRemote.zip
91 | asset_name: StompboxRemote.zip
92 | asset_content_type: application/zip
93 |
94 | - name: Setup Java
95 | uses: actions/setup-java@v3
96 | with:
97 | distribution: 'microsoft'
98 | java-version: '17'
99 |
100 | - name: run MSBuild for Android Remote
101 | run: |
102 | echo -n ${{ secrets.KEYSTORE }} | base64 --ignore-garbage --decode > ${{github.workspace}}\android.keystore
103 | msbuild .\StompboxAndroid\StompboxAndroid.csproj /p:Configuration=RELEASE /p:AndroidKeyStore=true /p:AndroidSigningKeyAlias=stompboxkeystore /p:AndroidSigningKeyStore="${{github.workspace}}\android.keystore" /p:AndroidSigningKeyPass="${{ secrets.KEYSTORE_PASS }}" /p:AndroidSigningStorePass="${{ secrets.KEYSTORE_PASS }}"
104 |
105 | - name: Upload Android Remote Asset
106 | uses: actions/upload-release-asset@v1
107 | env:
108 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
109 | with:
110 | upload_url: ${{ needs.create_release.outputs.upload_url }}
111 | asset_path: ${{github.workspace}}\StompboxAndroid\bin\Release\net8.0-android\StompboxAndroid.StompboxAndroid-Signed.apk
112 | asset_name: StompboxAndroid.StompboxAndroid-Signed.apk
113 | asset_content_type: application/zip
114 |
115 | - name: Publish Linux-x64
116 | working-directory: ${{github.workspace}}
117 | run: dotnet publish .\StompboxRemoteGL\StompboxRemoteGL.csproj --runtime linux-x64 -p:PublishSingleFile=true --self-contained true
118 |
119 | - name: Add Linux-x64 Archive
120 | working-directory: ${{github.workspace}}
121 | run: |
122 | mkdir linux-x64-build
123 | move StompboxRemoteGL\bin\Release\net8.0\linux-x64\publish linux-x64-build\StompboxRemote
124 | Compress-Archive -Path linux-x64-build\* -Destination StompboxRemoteLinux-X64.zip
125 |
126 | - name: Upload Linux-x64 Asset
127 | uses: actions/upload-release-asset@v1
128 | env:
129 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
130 | with:
131 | upload_url: ${{ needs.create_release.outputs.upload_url }}
132 | asset_path: ./StompboxRemoteLinux-x64.zip
133 | asset_name: StompboxRemoteLinux-x64.zip
134 | asset_content_type: application/zip
135 |
136 | - name: Publish Linux-arm64
137 | working-directory: ${{github.workspace}}
138 | run: dotnet publish .\StompboxRemoteGL\StompboxRemoteGL.csproj --runtime linux-arm64 -p:PublishSingleFile=true --self-contained true
139 |
140 | - name: Add Linux-arm64 Archive
141 | working-directory: ${{github.workspace}}
142 | run: |
143 | mkdir linux-arm64-build
144 | move StompboxRemoteGL\bin\Release\net8.0\linux-arm64\publish linux-arm64-build\StompboxRemote
145 | Compress-Archive -Path linux-arm64-build\* -Destination StompboxRemoteLinux-Arm64.zip
146 |
147 | - name: Upload Linux-arm64 Asset
148 | uses: actions/upload-release-asset@v1
149 | env:
150 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
151 | with:
152 | upload_url: ${{ needs.create_release.outputs.upload_url }}
153 | asset_path: ./StompboxRemoteLinux-Arm64.zip
154 | asset_name: StompboxRemoteLinux-Arm64.zip
155 | asset_content_type: application/zip
156 |
157 | - name: Publish OSX-x64
158 | working-directory: ${{github.workspace}}
159 | run: dotnet publish .\StompboxRemoteGL\StompboxRemoteGL.csproj --runtime osx-x64 -p:PublishSingleFile=true --self-contained true
160 |
161 | - name: Add OSX-x64 Archive
162 | working-directory: ${{github.workspace}}
163 | run: |
164 | mkdir osx-x64-build
165 | move StompboxRemoteGL\bin\Release\net8.0\osx-x64\publish osx-x64-build\StompboxRemote
166 | Compress-Archive -Path osx-x64-build\* -Destination StompboxRemoteMac-X64.zip
167 |
168 | - name: Upload OSX-x64 Asset
169 | uses: actions/upload-release-asset@v1
170 | env:
171 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
172 | with:
173 | upload_url: ${{ needs.create_release.outputs.upload_url }}
174 | asset_path: ./StompboxRemoteMac-X64.zip
175 | asset_name: StompboxRemoteMac-X64.zip
176 | asset_content_type: application/zip
177 |
178 | - name: Publish OSX-arm64
179 | working-directory: ${{github.workspace}}
180 | run: dotnet publish .\StompboxRemoteGL\StompboxRemoteGL.csproj --runtime osx-arm64 -p:PublishSingleFile=true --self-contained true
181 |
182 | - name: Add OSX-arm64 Archive
183 | working-directory: ${{github.workspace}}
184 | run: |
185 | mkdir osx-arm64-build
186 | move StompboxRemoteGL\bin\Release\net8.0\osx-arm64\publish osx-arm64-build\StompboxRemote
187 | Compress-Archive -Path osx-arm64-build\* -Destination StompboxRemoteMac-Arm64.zip
188 |
189 | - name: Upload OSX-arm64 Asset
190 | uses: actions/upload-release-asset@v1
191 | env:
192 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
193 | with:
194 | upload_url: ${{ needs.create_release.outputs.upload_url }}
195 | asset_path: ./StompboxRemoteMac-Arm64.zip
196 | asset_name: StompboxRemoteMac-Arm64.zip
197 | asset_content_type: application/zip
198 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Mono auto generated files
17 | mono_crash.*
18 |
19 | # Build results
20 | [Dd]ebug/
21 | [Dd]ebugPublic/
22 | [Rr]elease/
23 | [Rr]eleases/
24 | x64/
25 | x86/
26 | [Ww][Ii][Nn]32/
27 | [Aa][Rr][Mm]/
28 | [Aa][Rr][Mm]64/
29 | bld/
30 | [Bb]in/
31 | [Oo]bj/
32 | [Oo]ut/
33 | [Ll]og/
34 | [Ll]ogs/
35 |
36 | # Visual Studio 2015/2017 cache/options directory
37 | .vs/
38 | # Uncomment if you have tasks that create the project's static files in wwwroot
39 | #wwwroot/
40 |
41 | # Visual Studio 2017 auto generated files
42 | Generated\ Files/
43 |
44 | # MSTest test Results
45 | [Tt]est[Rr]esult*/
46 | [Bb]uild[Ll]og.*
47 |
48 | # NUnit
49 | *.VisualState.xml
50 | TestResult.xml
51 | nunit-*.xml
52 |
53 | # Build Results of an ATL Project
54 | [Dd]ebugPS/
55 | [Rr]eleasePS/
56 | dlldata.c
57 |
58 | # Benchmark Results
59 | BenchmarkDotNet.Artifacts/
60 |
61 | # .NET Core
62 | project.lock.json
63 | project.fragment.lock.json
64 | artifacts/
65 |
66 | # ASP.NET Scaffolding
67 | ScaffoldingReadMe.txt
68 |
69 | # StyleCop
70 | StyleCopReport.xml
71 |
72 | # Files built by Visual Studio
73 | *_i.c
74 | *_p.c
75 | *_h.h
76 | *.ilk
77 | *.meta
78 | *.obj
79 | *.iobj
80 | *.pch
81 | *.pdb
82 | *.ipdb
83 | *.pgc
84 | *.pgd
85 | *.rsp
86 | *.sbr
87 | *.tlb
88 | *.tli
89 | *.tlh
90 | *.tmp
91 | *.tmp_proj
92 | *_wpftmp.csproj
93 | *.log
94 | *.vspscc
95 | *.vssscc
96 | .builds
97 | *.pidb
98 | *.svclog
99 | *.scc
100 |
101 | # Chutzpah Test files
102 | _Chutzpah*
103 |
104 | # Visual C++ cache files
105 | ipch/
106 | *.aps
107 | *.ncb
108 | *.opendb
109 | *.opensdf
110 | *.sdf
111 | *.cachefile
112 | *.VC.db
113 | *.VC.VC.opendb
114 |
115 | # Visual Studio profiler
116 | *.psess
117 | *.vsp
118 | *.vspx
119 | *.sap
120 |
121 | # Visual Studio Trace Files
122 | *.e2e
123 |
124 | # TFS 2012 Local Workspace
125 | $tf/
126 |
127 | # Guidance Automation Toolkit
128 | *.gpState
129 |
130 | # ReSharper is a .NET coding add-in
131 | _ReSharper*/
132 | *.[Rr]e[Ss]harper
133 | *.DotSettings.user
134 |
135 | # TeamCity is a build add-in
136 | _TeamCity*
137 |
138 | # DotCover is a Code Coverage Tool
139 | *.dotCover
140 |
141 | # AxoCover is a Code Coverage Tool
142 | .axoCover/*
143 | !.axoCover/settings.json
144 |
145 | # Coverlet is a free, cross platform Code Coverage Tool
146 | coverage*.json
147 | coverage*.xml
148 | coverage*.info
149 |
150 | # Visual Studio code coverage results
151 | *.coverage
152 | *.coveragexml
153 |
154 | # NCrunch
155 | _NCrunch_*
156 | .*crunch*.local.xml
157 | nCrunchTemp_*
158 |
159 | # MightyMoose
160 | *.mm.*
161 | AutoTest.Net/
162 |
163 | # Web workbench (sass)
164 | .sass-cache/
165 |
166 | # Installshield output folder
167 | [Ee]xpress/
168 |
169 | # DocProject is a documentation generator add-in
170 | DocProject/buildhelp/
171 | DocProject/Help/*.HxT
172 | DocProject/Help/*.HxC
173 | DocProject/Help/*.hhc
174 | DocProject/Help/*.hhk
175 | DocProject/Help/*.hhp
176 | DocProject/Help/Html2
177 | DocProject/Help/html
178 |
179 | # Click-Once directory
180 | publish/
181 |
182 | # Publish Web Output
183 | *.[Pp]ublish.xml
184 | *.azurePubxml
185 | # Note: Comment the next line if you want to checkin your web deploy settings,
186 | # but database connection strings (with potential passwords) will be unencrypted
187 | *.pubxml
188 | *.publishproj
189 |
190 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
191 | # checkin your Azure Web App publish settings, but sensitive information contained
192 | # in these scripts will be unencrypted
193 | PublishScripts/
194 |
195 | # NuGet Packages
196 | *.nupkg
197 | # NuGet Symbol Packages
198 | *.snupkg
199 | # The packages folder can be ignored because of Package Restore
200 | **/[Pp]ackages/*
201 | # except build/, which is used as an MSBuild target.
202 | !**/[Pp]ackages/build/
203 | # Uncomment if necessary however generally it will be regenerated when needed
204 | #!**/[Pp]ackages/repositories.config
205 | # NuGet v3's project.json files produces more ignorable files
206 | *.nuget.props
207 | *.nuget.targets
208 |
209 | # Microsoft Azure Build Output
210 | csx/
211 | *.build.csdef
212 |
213 | # Microsoft Azure Emulator
214 | ecf/
215 | rcf/
216 |
217 | # Windows Store app package directories and files
218 | AppPackages/
219 | BundleArtifacts/
220 | Package.StoreAssociation.xml
221 | _pkginfo.txt
222 | *.appx
223 | *.appxbundle
224 | *.appxupload
225 |
226 | # Visual Studio cache files
227 | # files ending in .cache can be ignored
228 | *.[Cc]ache
229 | # but keep track of directories ending in .cache
230 | !?*.[Cc]ache/
231 |
232 | # Others
233 | ClientBin/
234 | ~$*
235 | *~
236 | *.dbmdl
237 | *.dbproj.schemaview
238 | *.jfm
239 | *.pfx
240 | *.publishsettings
241 | orleans.codegen.cs
242 |
243 | # Including strong name files can present a security risk
244 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
245 | #*.snk
246 |
247 | # Since there are multiple workflows, uncomment next line to ignore bower_components
248 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
249 | #bower_components/
250 |
251 | # RIA/Silverlight projects
252 | Generated_Code/
253 |
254 | # Backup & report files from converting an old project file
255 | # to a newer Visual Studio version. Backup files are not needed,
256 | # because we have git ;-)
257 | _UpgradeReport_Files/
258 | Backup*/
259 | UpgradeLog*.XML
260 | UpgradeLog*.htm
261 | ServiceFabricBackup/
262 | *.rptproj.bak
263 |
264 | # SQL Server files
265 | *.mdf
266 | *.ldf
267 | *.ndf
268 |
269 | # Business Intelligence projects
270 | *.rdl.data
271 | *.bim.layout
272 | *.bim_*.settings
273 | *.rptproj.rsuser
274 | *- [Bb]ackup.rdl
275 | *- [Bb]ackup ([0-9]).rdl
276 | *- [Bb]ackup ([0-9][0-9]).rdl
277 |
278 | # Microsoft Fakes
279 | FakesAssemblies/
280 |
281 | # GhostDoc plugin setting file
282 | *.GhostDoc.xml
283 |
284 | # Node.js Tools for Visual Studio
285 | .ntvs_analysis.dat
286 | node_modules/
287 |
288 | # Visual Studio 6 build log
289 | *.plg
290 |
291 | # Visual Studio 6 workspace options file
292 | *.opt
293 |
294 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
295 | *.vbw
296 |
297 | # Visual Studio LightSwitch build output
298 | **/*.HTMLClient/GeneratedArtifacts
299 | **/*.DesktopClient/GeneratedArtifacts
300 | **/*.DesktopClient/ModelManifest.xml
301 | **/*.Server/GeneratedArtifacts
302 | **/*.Server/ModelManifest.xml
303 | _Pvt_Extensions
304 |
305 | # Paket dependency manager
306 | .paket/paket.exe
307 | paket-files/
308 |
309 | # FAKE - F# Make
310 | .fake/
311 |
312 | # CodeRush personal settings
313 | .cr/personal
314 |
315 | # Python Tools for Visual Studio (PTVS)
316 | __pycache__/
317 | *.pyc
318 |
319 | # Cake - Uncomment if you are using it
320 | # tools/**
321 | # !tools/packages.config
322 |
323 | # Tabs Studio
324 | *.tss
325 |
326 | # Telerik's JustMock configuration file
327 | *.jmconfig
328 |
329 | # BizTalk build output
330 | *.btp.cs
331 | *.btm.cs
332 | *.odx.cs
333 | *.xsd.cs
334 |
335 | # OpenCover UI analysis results
336 | OpenCover/
337 |
338 | # Azure Stream Analytics local run output
339 | ASALocalRun/
340 |
341 | # MSBuild Binary and Structured Log
342 | *.binlog
343 |
344 | # NVidia Nsight GPU debugger configuration file
345 | *.nvuser
346 |
347 | # MFractors (Xamarin productivity tool) working folder
348 | .mfractor/
349 |
350 | # Local History for Visual Studio
351 | .localhistory/
352 |
353 | # BeatPulse healthcheck temp database
354 | healthchecksdb
355 |
356 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
357 | MigrationBackup/
358 |
359 | # Ionide (cross platform F# VS Code tools) working folder
360 | .ionide/
361 |
362 | # Fody - auto-generated XML schema
363 | FodyWeavers.xsd
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "Dependencies/stompbox"]
2 | path = Dependencies/stompbox
3 | url = https://github.com/mikeoliphant/stompbox
4 | [submodule "Dependencies/UILayout"]
5 | path = Dependencies/UILayout
6 | url = https://github.com/mikeoliphant/UILayout
7 |
--------------------------------------------------------------------------------
/MiniPlugins/.config/dotnet-tools.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": 1,
3 | "isRoot": true,
4 | "tools": {
5 | "dotnet-mgcb": {
6 | "version": "3.8.1.303",
7 | "commands": [
8 | "mgcb"
9 | ]
10 | },
11 | "dotnet-mgcb-editor": {
12 | "version": "3.8.1.303",
13 | "commands": [
14 | "mgcb-editor"
15 | ]
16 | },
17 | "dotnet-mgcb-editor-linux": {
18 | "version": "3.8.1.303",
19 | "commands": [
20 | "mgcb-editor-linux"
21 | ]
22 | },
23 | "dotnet-mgcb-editor-windows": {
24 | "version": "3.8.1.303",
25 | "commands": [
26 | "mgcb-editor-windows"
27 | ]
28 | },
29 | "dotnet-mgcb-editor-mac": {
30 | "version": "3.8.1.303",
31 | "commands": [
32 | "mgcb-editor-mac"
33 | ]
34 | }
35 | }
36 | }
--------------------------------------------------------------------------------
/MiniPlugins/MiniPluginInterface.cs:
--------------------------------------------------------------------------------
1 | using Stompbox;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using UILayout;
8 |
9 | namespace MiniPlugins
10 | {
11 | public class MiniPluginInterface : Dock
12 | {
13 | HorizontalStack pluginStack;
14 |
15 | public MiniPluginInterface()
16 | {
17 | pluginStack = new HorizontalStack()
18 | {
19 | HorizontalAlignment = EHorizontalAlignment.Center,
20 | VerticalAlignment = EVerticalAlignment.Center
21 | };
22 | Children.Add(pluginStack);
23 |
24 | UpdateUI();
25 | }
26 |
27 | public void UpdateUI()
28 | {
29 | pluginStack.Children.Clear();
30 |
31 | string globalChain = StompboxClient.Instance.GetGlobalChain();
32 |
33 | string[] split = globalChain.Split(' ');
34 |
35 | int num = (split.Length / 2) * 2;
36 |
37 | for (int pos = 0; pos < num; pos+=2)
38 | {
39 | if ((split[pos] == "Slot") || (split[pos] == "MasterSlot"))
40 | {
41 | string slotName = split[pos + 1];
42 |
43 | AddPlugin(StompboxClient.Instance.PluginFactory.CreatePlugin(StompboxClient.Instance.GetSlotPlugin(split[pos + 1])), slotName);
44 | }
45 | else
46 | {
47 | foreach (IAudioPlugin plugin in StompboxClient.Instance.GetChain(split[pos]))
48 | {
49 | AddPlugin(plugin, null);
50 | }
51 | }
52 | }
53 | }
54 |
55 | void AddPlugin(IAudioPlugin plugin, string slotName)
56 | {
57 | if ((plugin.Name == "Input") || (plugin.Name == "Master"))
58 | {
59 | pluginStack.Children.Add(new GainPluginInterface(plugin) { VerticalAlignment = EVerticalAlignment.Stretch });
60 | }
61 | else
62 | {
63 | pluginStack.Children.Add(new PluginInterface(plugin, slotName) { VerticalAlignment = EVerticalAlignment.Stretch });
64 | }
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/MiniPlugins/MiniPluginLayout.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using UILayout;
3 | using Stompbox;
4 |
5 | namespace MiniPlugins
6 | {
7 | public class MiniPluginLayout : MonoGameLayout
8 | {
9 | public static MiniPluginLayout Instance { get; private set; }
10 | public static float BaseScale { get; set; } = 1.0f;
11 |
12 | bool clientConnected = true;
13 |
14 | public MiniPluginLayout()
15 | {
16 | Instance = this;
17 |
18 | Scale = BaseScale;
19 | }
20 |
21 | public override void SetHost(MonoGameHost host)
22 | {
23 | base.SetHost(host);
24 |
25 | Host.InactiveSleepTime = TimeSpan.Zero;
26 |
27 | host.Window.Title = "stompbox";
28 |
29 | LoadImageManifest("ImageManifest.xml");
30 |
31 | GraphicsContext.SingleWhitePixelImage = GetImage("SingleWhitePixel");
32 | GraphicsContext.SamplerState = new Microsoft.Xna.Framework.Graphics.SamplerState()
33 | {
34 | AddressU = Microsoft.Xna.Framework.Graphics.TextureAddressMode.Clamp,
35 | AddressV = Microsoft.Xna.Framework.Graphics.TextureAddressMode.Clamp,
36 | Filter = Microsoft.Xna.Framework.Graphics.TextureFilter.Anisotropic,
37 | MipMapLevelOfDetailBias = -0.8f
38 | };
39 |
40 | DefaultFont = GetFont("MainFont");
41 | DefaultFont.SpriteFont.Spacing = 1;
42 |
43 | GetFont("SmallFont").SpriteFont.Spacing = 0;
44 |
45 | DefaultForegroundColor = UIColor.White;
46 |
47 | DefaultOutlineNinePatch = GetImage("PopupBackground");
48 |
49 | DefaultPressedNinePatch = GetImage("ButtonPressed");
50 | DefaultUnpressedNinePatch = GetImage("ButtonUnpressed");
51 |
52 | DefaultDragImage = GetImage("ButtonPressed");
53 |
54 | Initialize();
55 |
56 | RootUIElement = new MiniPluginInterface();
57 | }
58 |
59 | void Initialize()
60 | {
61 | StompboxClient.Instance.SendCommand("SetGlobalChain MasterSlot InputGain Slot Amp Slot Tonestack Slot Cabinet MasterSlot MasterVolume");
62 |
63 | StompboxClient.Instance.UpdateProgram();
64 |
65 | StompboxClient.Instance.SendCommand("SetPluginSlot InputGain Input");
66 | StompboxClient.Instance.SendCommand("SetPluginSlot MasterVolume Master");
67 |
68 | StompboxClient.Instance.SetDefaultSlotPlugin("Amp", "NAM");
69 | StompboxClient.Instance.SetDefaultSlotPlugin("Tonestack", "EQ-7");
70 | StompboxClient.Instance.SetDefaultSlotPlugin("Cabint", "Cabinet");
71 | }
72 | }
73 | }
--------------------------------------------------------------------------------
/MiniPlugins/MiniPlugins.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using System.Threading;
4 | using AudioPlugSharp;
5 | using UILayout;
6 |
7 | namespace MiniPlugins
8 | {
9 | public unsafe class AmpPlugin : AudioPlugSharp.AudioPluginBase
10 | {
11 | public int CurrentProgram { get; private set; }
12 |
13 | public StompboxAPI.APIClient StompboxClient { get; private set; }
14 | public MonoGameHost GameHost { get; private set; } = null;
15 |
16 | FloatAudioIOPort monoInput;
17 | FloatAudioIOPort monoOutput;
18 | IntPtr bitConvertBuffer = IntPtr.Zero;
19 | uint bitConvertBufferSize = 0;
20 |
21 | public AmpPlugin()
22 | {
23 | Company = "Nostatic Software";
24 | Website = "nostatic.org";
25 | Contact = "contact@nostatic.org";
26 | PluginName = "SB-Amp";
27 | PluginCategory = "Fx";
28 | PluginVersion = "0.0.1";
29 |
30 | PluginID = 0x66D6F61F1DE14831;
31 |
32 | HasUserInterface = true;
33 |
34 | //Logger.ImmediateMode = true;
35 |
36 | //Logger.ImmediateMode = true;
37 | //Logger.WriteToStdErr = true;
38 | }
39 |
40 | public override void Initialize()
41 | {
42 | base.Initialize();
43 |
44 | Debug("Initialize");
45 |
46 | InputPorts = new AudioIOPort[] { monoInput = new FloatAudioIOPort("Mono Input", EAudioChannelConfiguration.Mono) };
47 | OutputPorts = new AudioIOPort[] { monoOutput = new FloatAudioIOPort("Mono Output", EAudioChannelConfiguration.Mono) };
48 |
49 | EditorWidth = 680;
50 | EditorHeight = 190;
51 |
52 | //GCSettings.LatencyMode = GCLatencyMode.LowLatency;// GCLatencyMode.Batch; // SustainedLowLatency;
53 |
54 | StompboxAPI.APIClient.DebugAction = Debug;
55 |
56 | StompboxClient = new StompboxAPI.APIClient();
57 |
58 | StompboxClient.MidiCallback = SendMidiCommand;
59 | }
60 |
61 | public override void Stop()
62 | {
63 | base.Stop();
64 |
65 | GC.Collect();
66 | }
67 |
68 | public void DisposeDevice()
69 | {
70 | }
71 |
72 | public void Debug(String debugStr)
73 | {
74 | Logger.Log(debugStr);
75 | }
76 |
77 |
78 | public void ReportDSPLoad(float maxDSPLoad, float minDSPLoad)
79 | {
80 | }
81 |
82 | public virtual void UpdateUI()
83 | {
84 | StompboxClient.UpdateUI();
85 | }
86 |
87 | IntPtr parentWindow;
88 |
89 | public override void ShowEditor(IntPtr parentWindow)
90 | {
91 | Logger.Log("Show Editor");
92 |
93 | this.parentWindow = parentWindow;
94 |
95 | if (parentWindow == IntPtr.Zero)
96 | {
97 | RunGame();
98 | }
99 | else
100 | {
101 | new Thread(new ThreadStart(RunGame)).Start();
102 | }
103 | }
104 |
105 | void RunGame()
106 | {
107 | Logger.Log("Start game");
108 |
109 | try
110 | {
111 | int screenWidth = (int)EditorWidth;
112 | int screenHeight = (int)EditorHeight;
113 |
114 | MiniPluginLayout layout = new MiniPluginLayout();
115 |
116 | layout.Scale = 0.35f;
117 |
118 | using (GameHost = new MonoGameHost(parentWindow, screenWidth, screenHeight, fullscreen: false))
119 | {
120 | GameHost.IsMouseVisible = true;
121 |
122 | GameHost.StartGame(layout);
123 |
124 | StompboxClient.NeedUIReload = true;
125 | }
126 |
127 | layout = null;
128 | }
129 | catch (Exception ex)
130 | {
131 | Logger.Log("Run game failed with: " + ex.ToString());
132 | }
133 | }
134 |
135 | public override void ResizeEditor(uint newWidth, uint newHeight)
136 | {
137 | base.ResizeEditor(newWidth, newHeight);
138 |
139 | if (GameHost != null)
140 | {
141 | GameHost.RequestResize((int)newWidth, (int)newHeight);
142 | }
143 | }
144 |
145 |
146 | public override void HideEditor()
147 | {
148 | base.HideEditor();
149 |
150 | GameHost.Exit();
151 | }
152 |
153 | public override void InitializeProcessing()
154 | {
155 | base.InitializeProcessing();
156 |
157 | Logger.Log("Sample rate is: " + Host.SampleRate);
158 |
159 | StompboxClient.Init((float)Host.SampleRate);
160 | }
161 |
162 | public override byte[] SaveState()
163 | {
164 | byte[] data = null;
165 |
166 | try
167 | {
168 | data = System.Text.Encoding.ASCII.GetBytes(StompboxClient.GetProgramState());
169 | }
170 | catch (Exception ex)
171 | {
172 | Logger.Log("Save state failed with: " + ex.ToString());
173 | }
174 |
175 | return data;
176 | }
177 |
178 | string[] lineSeparator = new string[] { "\r", "\n" };
179 |
180 | public override void RestoreState(byte[] stateData)
181 | {
182 | String programString = System.Text.Encoding.ASCII.GetString(stateData);
183 |
184 | string[] commands = programString.Split(lineSeparator, 0);
185 |
186 | foreach (string command in commands)
187 | {
188 | if (!string.IsNullOrWhiteSpace(command))
189 | {
190 | StompboxClient.SendCommand(command);
191 | }
192 | }
193 |
194 | UpdateUI();
195 | }
196 |
197 | Stopwatch processWatch = new Stopwatch();
198 |
199 | void SendMidiCommand(int midiCommand, int midiData1, int midiData2)
200 | {
201 | Logger.Log("Send midi: " + midiCommand + " " + midiData1 + " " + midiData2);
202 |
203 | switch (midiCommand)
204 | {
205 | case 0x80:
206 | Host.SendNoteOff(1, midiData1, (float)midiData2 / 127.0f, 0);
207 | break;
208 | case 0x90:
209 | Host.SendNoteOn(1, midiData1, (float)midiData2 / 127.0f, 0);
210 | break;
211 | }
212 | }
213 |
214 | public override void Process()
215 | {
216 | StompboxClient.Process(((float**)monoInput.GetAudioBufferPtrs())[0], ((float**)monoOutput.GetAudioBufferPtrs())[0], monoInput.CurrentBufferSize);
217 | }
218 | }
219 | }
220 |
--------------------------------------------------------------------------------
/MiniPlugins/MiniPlugins.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | Library
4 | net8.0-windows
5 | Major
6 | false
7 | false
8 | true
9 | true
10 | True
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # What is it?
2 |
3 | Stompbox is a guitar amplification and effects application, arranged as a digital version of a guitar pedalboard.
4 |
5 | This github repository is the front-end for the software (the core codebase is [stompbox](https://github.com/mikeoliphant/stompbox)), to be used either as a remote interface to an actual pedalboard implementation, or as a standalone VST plugin.
6 |
7 | This is what it looks like running a Windows/Linux remote or as a VST plugin:
8 |
9 | 
10 |
11 | This is what it looks like running as an Android remote:
12 |
13 | 
14 |
15 | # Features
16 |
17 | * Pedalboard-style layout (Amp/Cab with input chain and FX loop)
18 | * [Neural Amp Modeler](https://github.com/sdatkinson/neural-amp-modeler) and [RTNeural](https://github.com/jatinchowdhury18/RTNeural) model support
19 | * Cabinet impulse responses
20 | * Tonestack/EQ
21 | * Noise Gate
22 | * Drive (clean boost, tube screamer)
23 | * Time-based effects
24 | - Delay
25 | - Reverb (algorithmic and convolution)
26 | - Compressor
27 | - Chorus
28 | - Phaser
29 | - Flanger
30 | - Tremolo
31 | - Vibrato
32 | - Wah/Auto-Wah
33 | * Tuner
34 | * Audio file player
35 |
36 | # Platform Support
37 |
38 | Stompbox currently can be run in the following ways:
39 |
40 | * Headless on Linux (I use it on a [Raspberry Pi based pedalboard](https://www.youtube.com/watch?v=2I_bxxzQs2s))
41 | * Remote UI on Windows, Linux or Android
42 | * Standalone app on Windows
43 | * VST3 plugin on Windows
44 |
45 | # Installation
46 |
47 | To run it as a VST3, you can simply download it from [the releases section of this repo](https://github.com/mikeoliphant/StompboxUI/releases/latest).
48 |
49 | Simply extract the .zip file and copy the resulting folder to "C:\Program Files\Common Files\VST3".
50 |
51 | # User Data Location
52 |
53 | Files, such as NAM models, impulse responses, etc. go in your local user roaming AppData folder. Go to "%APPDATA%" in file explorer, and you should see a "stompbox" folder after the VST has been loaded at least once.
54 |
55 | # Building From Source
56 |
57 | Make sure you clone this github repo recursively:
58 |
59 | ```bash
60 | git clone --recurse-submodules https://github.com/mikeoliphant/StompboxUI
61 | ```
62 |
63 | Building should be straightforward using Visual Studio.
64 |
65 | **NOTE:** Build and run the "StompboxImageProcessor" project first - it creates texture assets that are required for the main build.
66 |
67 |
--------------------------------------------------------------------------------
/SrcTextures/.gitignore:
--------------------------------------------------------------------------------
1 | tmp/
--------------------------------------------------------------------------------
/SrcTextures/ImageSources/DialNumbered.knob:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikeoliphant/StompboxUI/8dc3bdc26e1513bb0ef88e4f925863b903655937/SrcTextures/ImageSources/DialNumbered.knob
--------------------------------------------------------------------------------
/SrcTextures/ImageSources/PowerOn.xcf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikeoliphant/StompboxUI/8dc3bdc26e1513bb0ef88e4f925863b903655937/SrcTextures/ImageSources/PowerOn.xcf
--------------------------------------------------------------------------------
/SrcTextures/ImageSources/PrefabText.xcf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikeoliphant/StompboxUI/8dc3bdc26e1513bb0ef88e4f925863b903655937/SrcTextures/ImageSources/PrefabText.xcf
--------------------------------------------------------------------------------
/SrcTextures/Inter_18pt-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikeoliphant/StompboxUI/8dc3bdc26e1513bb0ef88e4f925863b903655937/SrcTextures/Inter_18pt-Bold.ttf
--------------------------------------------------------------------------------
/SrcTextures/OFL.txt:
--------------------------------------------------------------------------------
1 | Copyright 2020 The Inter Project Authors (https://github.com/rsms/inter)
2 |
3 | This Font Software is licensed under the SIL Open Font License, Version 1.1.
4 | This license is copied below, and is also available with a FAQ at:
5 | https://openfontlicense.org
6 |
7 |
8 | -----------------------------------------------------------
9 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
10 | -----------------------------------------------------------
11 |
12 | PREAMBLE
13 | The goals of the Open Font License (OFL) are to stimulate worldwide
14 | development of collaborative font projects, to support the font creation
15 | efforts of academic and linguistic communities, and to provide a free and
16 | open framework in which fonts may be shared and improved in partnership
17 | with others.
18 |
19 | The OFL allows the licensed fonts to be used, studied, modified and
20 | redistributed freely as long as they are not sold by themselves. The
21 | fonts, including any derivative works, can be bundled, embedded,
22 | redistributed and/or sold with any software provided that any reserved
23 | names are not used by derivative works. The fonts and derivatives,
24 | however, cannot be released under any other type of license. The
25 | requirement for fonts to remain under this license does not apply
26 | to any document created using the fonts or their derivatives.
27 |
28 | DEFINITIONS
29 | "Font Software" refers to the set of files released by the Copyright
30 | Holder(s) under this license and clearly marked as such. This may
31 | include source files, build scripts and documentation.
32 |
33 | "Reserved Font Name" refers to any names specified as such after the
34 | copyright statement(s).
35 |
36 | "Original Version" refers to the collection of Font Software components as
37 | distributed by the Copyright Holder(s).
38 |
39 | "Modified Version" refers to any derivative made by adding to, deleting,
40 | or substituting -- in part or in whole -- any of the components of the
41 | Original Version, by changing formats or by porting the Font Software to a
42 | new environment.
43 |
44 | "Author" refers to any designer, engineer, programmer, technical
45 | writer or other person who contributed to the Font Software.
46 |
47 | PERMISSION & CONDITIONS
48 | Permission is hereby granted, free of charge, to any person obtaining
49 | a copy of the Font Software, to use, study, copy, merge, embed, modify,
50 | redistribute, and sell modified and unmodified copies of the Font
51 | Software, subject to the following conditions:
52 |
53 | 1) Neither the Font Software nor any of its individual components,
54 | in Original or Modified Versions, may be sold by itself.
55 |
56 | 2) Original or Modified Versions of the Font Software may be bundled,
57 | redistributed and/or sold with any software, provided that each copy
58 | contains the above copyright notice and this license. These can be
59 | included either as stand-alone text files, human-readable headers or
60 | in the appropriate machine-readable metadata fields within text or
61 | binary files as long as those fields can be easily viewed by the user.
62 |
63 | 3) No Modified Version of the Font Software may use the Reserved Font
64 | Name(s) unless explicit written permission is granted by the corresponding
65 | Copyright Holder. This restriction only applies to the primary font name as
66 | presented to the users.
67 |
68 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
69 | Software shall not be used to promote, endorse or advertise any
70 | Modified Version, except to acknowledge the contribution(s) of the
71 | Copyright Holder(s) and the Author(s) or with their explicit written
72 | permission.
73 |
74 | 5) The Font Software, modified or unmodified, in part or in whole,
75 | must be distributed entirely under this license, and must not be
76 | distributed under any other license. The requirement for fonts to
77 | remain under this license does not apply to any document created
78 | using the Font Software.
79 |
80 | TERMINATION
81 | This license becomes null and void if any of the above conditions are
82 | not met.
83 |
84 | DISCLAIMER
85 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
86 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
87 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
88 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
89 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
90 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
91 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
92 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
93 | OTHER DEALINGS IN THE FONT SOFTWARE.
94 |
--------------------------------------------------------------------------------
/SrcTextures/UserInterface/.gitignore:
--------------------------------------------------------------------------------
1 | DialPointerRotations.png
--------------------------------------------------------------------------------
/SrcTextures/UserInterface/ButtonPressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikeoliphant/StompboxUI/8dc3bdc26e1513bb0ef88e4f925863b903655937/SrcTextures/UserInterface/ButtonPressed.png
--------------------------------------------------------------------------------
/SrcTextures/UserInterface/ButtonUnpressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikeoliphant/StompboxUI/8dc3bdc26e1513bb0ef88e4f925863b903655937/SrcTextures/UserInterface/ButtonUnpressed.png
--------------------------------------------------------------------------------
/SrcTextures/UserInterface/DialBackground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikeoliphant/StompboxUI/8dc3bdc26e1513bb0ef88e4f925863b903655937/SrcTextures/UserInterface/DialBackground.png
--------------------------------------------------------------------------------
/SrcTextures/UserInterface/DialPointer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikeoliphant/StompboxUI/8dc3bdc26e1513bb0ef88e4f925863b903655937/SrcTextures/UserInterface/DialPointer.png
--------------------------------------------------------------------------------
/SrcTextures/UserInterface/FileOpen.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/SrcTextures/UserInterface/FxLoopChain.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikeoliphant/StompboxUI/8dc3bdc26e1513bb0ef88e4f925863b903655937/SrcTextures/UserInterface/FxLoopChain.png
--------------------------------------------------------------------------------
/SrcTextures/UserInterface/HoverTextOutline.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikeoliphant/StompboxUI/8dc3bdc26e1513bb0ef88e4f925863b903655937/SrcTextures/UserInterface/HoverTextOutline.png
--------------------------------------------------------------------------------
/SrcTextures/UserInterface/InputChain.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikeoliphant/StompboxUI/8dc3bdc26e1513bb0ef88e4f925863b903655937/SrcTextures/UserInterface/InputChain.png
--------------------------------------------------------------------------------
/SrcTextures/UserInterface/LevelDisplay.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikeoliphant/StompboxUI/8dc3bdc26e1513bb0ef88e4f925863b903655937/SrcTextures/UserInterface/LevelDisplay.png
--------------------------------------------------------------------------------
/SrcTextures/UserInterface/MoreButton.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikeoliphant/StompboxUI/8dc3bdc26e1513bb0ef88e4f925863b903655937/SrcTextures/UserInterface/MoreButton.png
--------------------------------------------------------------------------------
/SrcTextures/UserInterface/OutputChain.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikeoliphant/StompboxUI/8dc3bdc26e1513bb0ef88e4f925863b903655937/SrcTextures/UserInterface/OutputChain.png
--------------------------------------------------------------------------------
/SrcTextures/UserInterface/Play.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikeoliphant/StompboxUI/8dc3bdc26e1513bb0ef88e4f925863b903655937/SrcTextures/UserInterface/Play.png
--------------------------------------------------------------------------------
/SrcTextures/UserInterface/PluginBackground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikeoliphant/StompboxUI/8dc3bdc26e1513bb0ef88e4f925863b903655937/SrcTextures/UserInterface/PluginBackground.png
--------------------------------------------------------------------------------
/SrcTextures/UserInterface/PopupBackground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikeoliphant/StompboxUI/8dc3bdc26e1513bb0ef88e4f925863b903655937/SrcTextures/UserInterface/PopupBackground.png
--------------------------------------------------------------------------------
/SrcTextures/UserInterface/PowerOff.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikeoliphant/StompboxUI/8dc3bdc26e1513bb0ef88e4f925863b903655937/SrcTextures/UserInterface/PowerOff.png
--------------------------------------------------------------------------------
/SrcTextures/UserInterface/PowerOn.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikeoliphant/StompboxUI/8dc3bdc26e1513bb0ef88e4f925863b903655937/SrcTextures/UserInterface/PowerOn.png
--------------------------------------------------------------------------------
/SrcTextures/UserInterface/Record.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikeoliphant/StompboxUI/8dc3bdc26e1513bb0ef88e4f925863b903655937/SrcTextures/UserInterface/Record.png
--------------------------------------------------------------------------------
/SrcTextures/UserInterface/Restart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikeoliphant/StompboxUI/8dc3bdc26e1513bb0ef88e4f925863b903655937/SrcTextures/UserInterface/Restart.png
--------------------------------------------------------------------------------
/SrcTextures/UserInterface/SingleWhitePixel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikeoliphant/StompboxUI/8dc3bdc26e1513bb0ef88e4f925863b903655937/SrcTextures/UserInterface/SingleWhitePixel.png
--------------------------------------------------------------------------------
/SrcTextures/UserInterface/StompOutline.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikeoliphant/StompboxUI/8dc3bdc26e1513bb0ef88e4f925863b903655937/SrcTextures/UserInterface/StompOutline.png
--------------------------------------------------------------------------------
/SrcTextures/UserInterface/StompboxLogo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikeoliphant/StompboxUI/8dc3bdc26e1513bb0ef88e4f925863b903655937/SrcTextures/UserInterface/StompboxLogo.png
--------------------------------------------------------------------------------
/SrcTextures/UserInterface/Stop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikeoliphant/StompboxUI/8dc3bdc26e1513bb0ef88e4f925863b903655937/SrcTextures/UserInterface/Stop.png
--------------------------------------------------------------------------------
/SrcTextures/UserInterface/TunerPoint.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikeoliphant/StompboxUI/8dc3bdc26e1513bb0ef88e4f925863b903655937/SrcTextures/UserInterface/TunerPoint.png
--------------------------------------------------------------------------------
/SrcTextures/UserInterface/VerticalSlider.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikeoliphant/StompboxUI/8dc3bdc26e1513bb0ef88e4f925863b903655937/SrcTextures/UserInterface/VerticalSlider.png
--------------------------------------------------------------------------------
/StompboxAndroid/.config/dotnet-tools.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": 1,
3 | "isRoot": true,
4 | "tools": {
5 | "dotnet-mgcb": {
6 | "version": "3.8.1.303",
7 | "commands": [
8 | "mgcb"
9 | ]
10 | },
11 | "dotnet-mgcb-editor": {
12 | "version": "3.8.1.303",
13 | "commands": [
14 | "mgcb-editor"
15 | ]
16 | },
17 | "dotnet-mgcb-editor-linux": {
18 | "version": "3.8.1.303",
19 | "commands": [
20 | "mgcb-editor-linux"
21 | ]
22 | },
23 | "dotnet-mgcb-editor-windows": {
24 | "version": "3.8.1.303",
25 | "commands": [
26 | "mgcb-editor-windows"
27 | ]
28 | },
29 | "dotnet-mgcb-editor-mac": {
30 | "version": "3.8.1.303",
31 | "commands": [
32 | "mgcb-editor-mac"
33 | ]
34 | }
35 | }
36 | }
--------------------------------------------------------------------------------
/StompboxAndroid/Activity1.cs:
--------------------------------------------------------------------------------
1 | using Android.App;
2 | using Android.Content.PM;
3 | using Android.OS;
4 | using Android.Views;
5 | using Microsoft.Xna.Framework;
6 | using UILayout;
7 | using StompboxAPI;
8 | using Microsoft.Xna.Framework.Graphics;
9 | using Microsoft.Xna.Framework.Input;
10 |
11 | namespace Stompbox
12 | {
13 | [Activity(
14 | Label = "@string/app_name",
15 | MainLauncher = true,
16 | Icon = "@mipmap/ic_launcher",
17 | AlwaysRetainTaskState = true,
18 | LaunchMode = LaunchMode.SingleInstance,
19 | ScreenOrientation = ScreenOrientation.FullUser,
20 | ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.Keyboard | ConfigChanges.KeyboardHidden | ConfigChanges.ScreenSize
21 | )]
22 |
23 | public class Activity1 : AndroidGameActivity
24 | {
25 | public static Activity1 Instance { get; private set; }
26 |
27 | View view;
28 | RemoteClient guitarClient;
29 | MonoGameHost GameHost;
30 |
31 | protected override void OnCreate(Bundle bundle)
32 | {
33 | base.OnCreate(bundle);
34 |
35 | Instance = this;
36 |
37 | //StompboxLayout.DAWMode = false;
38 |
39 | guitarClient = new RemoteClient();
40 |
41 | InterfaceBase.InterfaceType = EStompboxInterfaceType.Mobile;
42 |
43 | StompboxLayout game = new StompboxLayout();
44 |
45 | //game.SetScreenScale(scale, resizeScreen: true);
46 |
47 | GameHost = new MonoGameHost(0, 0, fullscreen: true);
48 |
49 | GameHost.IsMouseVisible = true;
50 |
51 | view = GameHost.Services.GetService(typeof(View)) as View;
52 | view.KeepScreenOn = true;
53 |
54 | SetContentView(view);
55 |
56 | GameHost.StartGame(game);
57 | }
58 | }
59 |
60 | public class Game1 : Game
61 | {
62 | private GraphicsDeviceManager _graphics;
63 | private SpriteBatch _spriteBatch;
64 |
65 | public Game1()
66 | {
67 | _graphics = new GraphicsDeviceManager(this);
68 | Content.RootDirectory = "Content";
69 | IsMouseVisible = true;
70 | }
71 |
72 | protected override void Initialize()
73 | {
74 | // TODO: Add your initialization logic here
75 |
76 | base.Initialize();
77 | }
78 |
79 | protected override void LoadContent()
80 | {
81 | _spriteBatch = new SpriteBatch(GraphicsDevice);
82 |
83 | // TODO: use this.Content to load your game content here
84 | }
85 |
86 | protected override void Update(GameTime gameTime)
87 | {
88 | if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
89 | Exit();
90 |
91 | // TODO: Add your update logic here
92 |
93 | base.Update(gameTime);
94 | }
95 |
96 | protected override void Draw(GameTime gameTime)
97 | {
98 | GraphicsDevice.Clear(Color.CornflowerBlue);
99 |
100 | // TODO: Add your drawing code here
101 |
102 | base.Draw(gameTime);
103 | }
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/StompboxAndroid/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/StompboxAndroid/Resources/Values/Strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Stompbox Remote
4 |
5 |
--------------------------------------------------------------------------------
/StompboxAndroid/Resources/Values/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #000000
4 |
--------------------------------------------------------------------------------
/StompboxAndroid/Resources/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/StompboxAndroid/Resources/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/StompboxAndroid/Resources/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikeoliphant/StompboxUI/8dc3bdc26e1513bb0ef88e4f925863b903655937/StompboxAndroid/Resources/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/StompboxAndroid/Resources/mipmap-hdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikeoliphant/StompboxUI/8dc3bdc26e1513bb0ef88e4f925863b903655937/StompboxAndroid/Resources/mipmap-hdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/StompboxAndroid/Resources/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikeoliphant/StompboxUI/8dc3bdc26e1513bb0ef88e4f925863b903655937/StompboxAndroid/Resources/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/StompboxAndroid/Resources/mipmap-ldpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikeoliphant/StompboxUI/8dc3bdc26e1513bb0ef88e4f925863b903655937/StompboxAndroid/Resources/mipmap-ldpi/ic_launcher.png
--------------------------------------------------------------------------------
/StompboxAndroid/Resources/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikeoliphant/StompboxUI/8dc3bdc26e1513bb0ef88e4f925863b903655937/StompboxAndroid/Resources/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/StompboxAndroid/Resources/mipmap-mdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikeoliphant/StompboxUI/8dc3bdc26e1513bb0ef88e4f925863b903655937/StompboxAndroid/Resources/mipmap-mdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/StompboxAndroid/Resources/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikeoliphant/StompboxUI/8dc3bdc26e1513bb0ef88e4f925863b903655937/StompboxAndroid/Resources/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/StompboxAndroid/Resources/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikeoliphant/StompboxUI/8dc3bdc26e1513bb0ef88e4f925863b903655937/StompboxAndroid/Resources/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/StompboxAndroid/Resources/mipmap-xhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikeoliphant/StompboxUI/8dc3bdc26e1513bb0ef88e4f925863b903655937/StompboxAndroid/Resources/mipmap-xhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/StompboxAndroid/Resources/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikeoliphant/StompboxUI/8dc3bdc26e1513bb0ef88e4f925863b903655937/StompboxAndroid/Resources/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/StompboxAndroid/Resources/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikeoliphant/StompboxUI/8dc3bdc26e1513bb0ef88e4f925863b903655937/StompboxAndroid/Resources/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/StompboxAndroid/Resources/mipmap-xxhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikeoliphant/StompboxUI/8dc3bdc26e1513bb0ef88e4f925863b903655937/StompboxAndroid/Resources/mipmap-xxhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/StompboxAndroid/Resources/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikeoliphant/StompboxUI/8dc3bdc26e1513bb0ef88e4f925863b903655937/StompboxAndroid/Resources/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/StompboxAndroid/Resources/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikeoliphant/StompboxUI/8dc3bdc26e1513bb0ef88e4f925863b903655937/StompboxAndroid/Resources/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/StompboxAndroid/Resources/mipmap-xxxhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikeoliphant/StompboxUI/8dc3bdc26e1513bb0ef88e4f925863b903655937/StompboxAndroid/Resources/mipmap-xxxhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/StompboxAndroid/Resources/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikeoliphant/StompboxUI/8dc3bdc26e1513bb0ef88e4f925863b903655937/StompboxAndroid/Resources/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/StompboxAndroid/StompboxAndroid.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net8.0-android
4 | 23
5 | Exe
6 | com.companyname.StompboxAndroid
7 | 1
8 | 1.0
9 |
10 |
11 | $(DefineConstants);STOMPBOXREMOTE
12 | False
13 |
14 |
15 | $(DefineConstants);STOMPBOXREMOTE
16 | False
17 | apk
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/StompboxClient/StompboxAPI/APIClient.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.InteropServices;
3 | using Stompbox;
4 |
5 | namespace StompboxAPI
6 | {
7 | public class APIClient : StompboxClient
8 | {
9 | StompboxProcessor processor;
10 | bool needPresetLoad = false;
11 |
12 | public override bool NeedUIReload
13 | {
14 | get
15 | {
16 | if (needPresetLoad && !processor.IsPresetLoading)
17 | {
18 | UpdateProgram();
19 |
20 | needPresetLoad = false;
21 |
22 | return true;
23 | }
24 |
25 | return base.NeedUIReload;
26 | }
27 |
28 | set => base.NeedUIReload = value;
29 | }
30 |
31 | public override int CurrentPresetIndex
32 | {
33 | get => base.CurrentPresetIndex;
34 |
35 | set
36 | {
37 | base.CurrentPresetIndex = value;
38 |
39 | if (CurrentPresetIndex >= 0)
40 | {
41 | processor.LoadPreset(PresetNames[base.CurrentPresetIndex]);
42 |
43 | needPresetLoad = true;
44 | }
45 | }
46 | }
47 |
48 | public APIClient()
49 | : base()
50 | {
51 | if (!Directory.Exists(PluginPath))
52 | {
53 | Directory.CreateDirectory(PluginPath);
54 | }
55 |
56 | processor = new StompboxProcessor(PluginPath, dawMode: true);
57 |
58 | InClientMode = false;
59 |
60 | //processorWrapper.SetMidiCallback(HandleMidi);
61 |
62 | //UpdateProgram();
63 | }
64 |
65 | public void StartServer()
66 | {
67 | processor.StartServer();
68 | }
69 |
70 | public override void UpdatePresets()
71 | {
72 | needPresetLoad = false;
73 |
74 | base.UpdatePresets();
75 |
76 | SetPresetNames(processor.GetPresets());
77 |
78 | SetSelectedPreset(processor.GetCurrentPreset());
79 | }
80 |
81 | public override void UpdateProgram()
82 | {
83 | base.UpdateProgram();
84 |
85 | UpdateUI();
86 | }
87 |
88 | // FIXME: these should use direct commands
89 |
90 | public override void SaveCurrentPreset()
91 | {
92 | SendCommand("SavePreset " + PresetNames[CurrentPresetIndex]);
93 | }
94 |
95 | public override void SavePresetAs(string presetName)
96 | {
97 | SendCommand("SavePreset " + presetName);
98 | SendCommand("List Presets");
99 | UpdateProgram();
100 | }
101 |
102 | public override void DeleteCurrentPreset()
103 | {
104 | SendCommand("DeletePreset " + PresetNames[CurrentPresetIndex]);
105 |
106 | UpdateProgram();
107 | }
108 |
109 | public override string GetGlobalChain()
110 | {
111 | return processor.GetGlobalChain();
112 | }
113 |
114 | public override IEnumerable GetAllPluginNames()
115 | {
116 | return processor.GetAllPlugins();
117 | }
118 |
119 | public override IAudioPlugin GetPluginDefinition(string pluginName)
120 | {
121 | return PluginFactory.GetPluginDefinition(pluginName);
122 | }
123 |
124 | public override IAudioPlugin CreatePlugin(string pluginName, string pluginID)
125 | {
126 | return processor.CreatePlugin(pluginID);
127 | }
128 |
129 | public override void SendCommand(string command)
130 | {
131 | processor.HandleCommand(command);
132 | }
133 |
134 | public override List GetChain(string chainName)
135 | {
136 | List chain = new();
137 |
138 | chain.AddRange(processor.GetChainPlugins(chainName));
139 |
140 | foreach (IAudioPlugin plugin in chain)
141 | {
142 | PluginFactory.RegisterPlugin(plugin);
143 | }
144 |
145 | return chain;
146 | }
147 |
148 | public override string GetSlotPlugin(string slotName)
149 | {
150 | return processor.GetPluginSlot(slotName);
151 | }
152 |
153 | public override void SetSlotPlugin(string slotName, string pluginID)
154 | {
155 | processor.SetPluginSlot(slotName, pluginID);
156 | }
157 |
158 | public override void Init(float sampleRate)
159 | {
160 | processor.Init(sampleRate);
161 | }
162 |
163 | public String GetProgramState()
164 | {
165 | String settingsString = processor.DumpSettings();
166 | String programString = processor.DumpProgram();
167 |
168 | return settingsString + programString;
169 | }
170 |
171 | public unsafe void Process(float* input, float* output, uint bufferSize)
172 | {
173 | processor.Process(input, output, bufferSize);
174 | }
175 |
176 | long samplePos = 0;
177 |
178 | public unsafe void SimulateAudio()
179 | {
180 | int bufferSize = 1024;
181 | int sampleRate = 44100;
182 |
183 | int sleepMS = sampleRate / 1000;
184 |
185 | Init(sampleRate);
186 |
187 | float* inBuf = (float*)Marshal.AllocHGlobal(bufferSize * sizeof(float));
188 | float* outBuf = (float*)Marshal.AllocHGlobal(bufferSize * sizeof(float));
189 |
190 | while (true)
191 | {
192 | if (StopSimulateAudio)
193 | break;
194 |
195 | for (int i = 0; i < bufferSize; i++)
196 | {
197 | inBuf[i] = 0;
198 |
199 | inBuf[i] += (float)Math.Sin(((float)samplePos / (float)sampleRate) * 440 * Math.PI * 2) * 0.25f;
200 |
201 | samplePos++;
202 | }
203 |
204 | processor.Process(inBuf, outBuf, (uint)bufferSize);
205 |
206 | Thread.Sleep(sleepMS);
207 | }
208 | }
209 | }
210 | }
211 |
--------------------------------------------------------------------------------
/StompboxClient/StompboxAPI/NativeAPI.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Runtime.InteropServices;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace StompboxAPI
9 | {
10 | class NativeApi
11 | {
12 | public const string STOMPBOX_LIB_NAME = "stompbox-capi";
13 |
14 | [DllImport(STOMPBOX_LIB_NAME)]
15 | public static extern uint GetStringVectorSize(IntPtr strVec);
16 |
17 | [DllImport(STOMPBOX_LIB_NAME)]
18 | public static extern IntPtr GetStringVectorValue(IntPtr strVec, uint index);
19 |
20 | [DllImport(STOMPBOX_LIB_NAME)]
21 | public static extern IntPtr CreateProcessor([MarshalAs(UnmanagedType.LPWStr)] string dataPath, bool dawMode);
22 |
23 | [DllImport(STOMPBOX_LIB_NAME)]
24 | public static extern void DeleteProcessor(IntPtr processor);
25 |
26 | [DllImport(STOMPBOX_LIB_NAME)]
27 | public static extern void InitProcessor(IntPtr processor, float sampleRate);
28 |
29 | [DllImport(STOMPBOX_LIB_NAME)]
30 | public static extern void StartServer(IntPtr processor);
31 |
32 | [DllImport(STOMPBOX_LIB_NAME)]
33 | public static unsafe extern void Process(IntPtr processor, float* input, float* output, uint bufferSize);
34 |
35 | [DllImport(STOMPBOX_LIB_NAME)]
36 | [return: MarshalAs(UnmanagedType.I1)]
37 | public static extern bool IsPresetLoading(IntPtr processor);
38 |
39 | [DllImport(STOMPBOX_LIB_NAME)]
40 | public static extern void HandleCommand(IntPtr processor, [MarshalAs(UnmanagedType.LPStr)] string cmd);
41 |
42 | [DllImport(STOMPBOX_LIB_NAME)]
43 | [return: MarshalAs(UnmanagedType.I1)]
44 | public static extern bool HandleMidiCommand(IntPtr processor, int midiCommand, int midiData1, int midiData2);
45 |
46 | [DllImport(STOMPBOX_LIB_NAME)]
47 | [return: MarshalAs(UnmanagedType.LPWStr)]
48 | public static extern string GetDataPath(IntPtr processor);
49 |
50 | [DllImport(STOMPBOX_LIB_NAME)]
51 | public static extern IntPtr GetAllPlugins(IntPtr processor);
52 |
53 | [DllImport(STOMPBOX_LIB_NAME)]
54 | [return: MarshalAs(UnmanagedType.LPStr)]
55 | public static extern string GetGlobalChain(IntPtr processor);
56 |
57 | [DllImport(STOMPBOX_LIB_NAME)]
58 | public static extern IntPtr GetPluginSlot(IntPtr processor, [MarshalAs(UnmanagedType.LPStr)] string slotName);
59 |
60 | [DllImport(STOMPBOX_LIB_NAME)]
61 | public static extern void SetPluginSlot(IntPtr processor, [MarshalAs(UnmanagedType.LPStr)] string slotName, [MarshalAs(UnmanagedType.LPStr)] string pluginID);
62 |
63 | [DllImport(STOMPBOX_LIB_NAME)]
64 | public static extern uint GetPluginVectorSize(IntPtr plugVec);
65 |
66 | [DllImport(STOMPBOX_LIB_NAME)]
67 | public static extern IntPtr GetPluginVectorValue(IntPtr plugVec, uint index);
68 |
69 | [DllImport(STOMPBOX_LIB_NAME)]
70 | public static extern IntPtr GetChainPlugins(IntPtr processor, [MarshalAs(UnmanagedType.LPStr)] string chainName);
71 |
72 | [DllImport(STOMPBOX_LIB_NAME)]
73 | public static extern IntPtr CreatePlugin(IntPtr processor, [MarshalAs(UnmanagedType.LPStr)] string id);
74 |
75 | [DllImport(STOMPBOX_LIB_NAME)]
76 | public static extern IntPtr GetPresets(IntPtr processor);
77 |
78 | [DllImport(STOMPBOX_LIB_NAME)]
79 | public static extern IntPtr GetCurrentPreset(IntPtr processor);
80 |
81 | [DllImport(STOMPBOX_LIB_NAME)]
82 | public static extern void LoadPreset(IntPtr processor, [MarshalAs(UnmanagedType.LPStr)] string presetName);
83 |
84 | [DllImport(STOMPBOX_LIB_NAME)]
85 | [return: MarshalAs(UnmanagedType.LPStr)]
86 | public static extern string DumpSettings(IntPtr processor);
87 |
88 | [DllImport(STOMPBOX_LIB_NAME)]
89 | [return: MarshalAs(UnmanagedType.LPStr)]
90 | public static extern string DumpProgram(IntPtr processor);
91 |
92 | [DllImport(STOMPBOX_LIB_NAME)]
93 | public static extern IntPtr GetPluginName(IntPtr plugin);
94 |
95 | [DllImport(STOMPBOX_LIB_NAME)]
96 | public static extern IntPtr GetPluginID(IntPtr plugin);
97 |
98 | [DllImport(STOMPBOX_LIB_NAME)]
99 | public static extern IntPtr GetPluginDescription(IntPtr plugin);
100 |
101 | [DllImport(STOMPBOX_LIB_NAME)]
102 | public static extern IntPtr GetPluginBackgroundColor(IntPtr plugin);
103 |
104 | [DllImport(STOMPBOX_LIB_NAME)]
105 | public static extern IntPtr GetPluginForegroundColor(IntPtr plugin);
106 |
107 | [DllImport(STOMPBOX_LIB_NAME)]
108 | [return: MarshalAs(UnmanagedType.I1)]
109 | public static extern bool GetPluginIsUserSelectable(IntPtr plugin);
110 |
111 | [DllImport(STOMPBOX_LIB_NAME)]
112 | public static extern bool GetPluginEnabled(IntPtr plugin);
113 |
114 | [DllImport(STOMPBOX_LIB_NAME)]
115 | public static extern void SetPluginEnabled(IntPtr plugin, bool enabled);
116 |
117 | [DllImport(STOMPBOX_LIB_NAME)]
118 | public static extern float GetOutputValue(IntPtr plugin);
119 |
120 | [DllImport(STOMPBOX_LIB_NAME)]
121 | public static extern uint GetPluginNumParameters(IntPtr plugin);
122 |
123 | [DllImport(STOMPBOX_LIB_NAME)]
124 | public static extern IntPtr GetPluginParameter(IntPtr plugin, uint index);
125 |
126 | [DllImport(STOMPBOX_LIB_NAME)]
127 | public static extern float GetParameterValue(IntPtr parameter);
128 |
129 | [DllImport(STOMPBOX_LIB_NAME)]
130 | public static extern void SetParameterValue(IntPtr parameter, float value);
131 |
132 | [DllImport(STOMPBOX_LIB_NAME)]
133 | public static extern IntPtr GetParameterName(IntPtr parameter);
134 |
135 | [DllImport(STOMPBOX_LIB_NAME)]
136 | public static extern IntPtr GetParameterDescription(IntPtr parameter);
137 |
138 | [DllImport(STOMPBOX_LIB_NAME)]
139 | public static extern float GetParameterMinValue(IntPtr parameter);
140 |
141 | [DllImport(STOMPBOX_LIB_NAME)]
142 | public static extern float GetParameterMaxValue(IntPtr parameter);
143 |
144 | [DllImport(STOMPBOX_LIB_NAME)]
145 | public static extern float GetParameterDefaultValue(IntPtr parameter);
146 |
147 | [DllImport(STOMPBOX_LIB_NAME)]
148 | public static extern float GetParameterRangePower(IntPtr parameter);
149 |
150 | [DllImport(STOMPBOX_LIB_NAME)]
151 | public static extern int GetParameterType(IntPtr parameter);
152 |
153 | [DllImport(STOMPBOX_LIB_NAME)]
154 | public static extern IntPtr GetParameterEnumValues(IntPtr parameter);
155 |
156 | [DllImport(STOMPBOX_LIB_NAME)]
157 | [return: MarshalAs(UnmanagedType.I1)]
158 | public static extern bool GetParameterCanSyncToHostBPM(IntPtr parameter);
159 |
160 | [DllImport(STOMPBOX_LIB_NAME)]
161 | public static extern int GetParameterBPMSyncNumerator(IntPtr parameter);
162 |
163 | [DllImport(STOMPBOX_LIB_NAME)]
164 | public static extern int GetParameterBPMSyncDenominator(IntPtr parameter);
165 |
166 | [DllImport(STOMPBOX_LIB_NAME)]
167 | public static extern void SetParameterBPMSyncNumerator(IntPtr parameter, int numerator);
168 |
169 | [DllImport(STOMPBOX_LIB_NAME)]
170 | public static extern void SetParameterBPMSyncDenominator(IntPtr parameter, int denom);
171 |
172 | [DllImport(STOMPBOX_LIB_NAME)]
173 | [return: MarshalAs(UnmanagedType.I1)]
174 | public static extern bool GetParameterIsAdvanced(IntPtr parameter);
175 |
176 | [DllImport(STOMPBOX_LIB_NAME)]
177 | public static extern IntPtr GetParameterFilePath(IntPtr parameter);
178 |
179 | [DllImport(STOMPBOX_LIB_NAME)]
180 | public static extern IntPtr GetParameterDisplayFormat(IntPtr parameter);
181 |
182 |
183 |
184 | public static List GetListFromStringVector(IntPtr strVec)
185 | {
186 | if (strVec == IntPtr.Zero)
187 | return null;
188 |
189 | List list = new();
190 |
191 | uint size = NativeApi.GetStringVectorSize(strVec);
192 |
193 | for (uint i = 0; i < size; i++)
194 | {
195 | list.Add(Marshal.PtrToStringAnsi(NativeApi.GetStringVectorValue(strVec, i)));
196 | }
197 |
198 | return list;
199 | }
200 | }
201 | }
202 |
--------------------------------------------------------------------------------
/StompboxClient/StompboxAPI/StompboxAPI.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net8.0
5 | enable
6 | enable
7 | True
8 |
9 |
10 |
11 |
12 |
13 |
14 | PreserveNewest
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/StompboxClient/StompboxAPI/StompboxProcessor.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.InteropServices;
3 |
4 | namespace StompboxAPI
5 | {
6 | public class StompboxProcessor
7 | {
8 | IntPtr nativeProcessor;
9 |
10 | public string DataPath { get { return NativeApi.GetDataPath(nativeProcessor); } }
11 |
12 | public StompboxProcessor(string dataPath, bool dawMode)
13 | {
14 | nativeProcessor = NativeApi.CreateProcessor(dataPath, dawMode);
15 | }
16 |
17 | public void Init(float sampleRate)
18 | {
19 | NativeApi.InitProcessor(nativeProcessor, sampleRate);
20 | }
21 |
22 | public UnmanagedAudioPlugin CreatePlugin(string id)
23 | {
24 | return CreatePluginFromNative(NativeApi.CreatePlugin(nativeProcessor, id));
25 |
26 | }
27 |
28 | public bool IsPresetLoading { get { return NativeApi.IsPresetLoading(nativeProcessor); } }
29 |
30 | public void StartServer()
31 | {
32 | NativeApi.StartServer(nativeProcessor);
33 | }
34 |
35 | public void HandleCommand(string command)
36 | {
37 | NativeApi.HandleCommand(nativeProcessor, command);
38 | }
39 |
40 | public bool HandleMidiCommand(int midiCommand, int midiData1, int midiData2)
41 | {
42 | return NativeApi.HandleMidiCommand(nativeProcessor, midiCommand, midiData1, midiData2);
43 | }
44 |
45 | public List GetAllPlugins()
46 | {
47 | return NativeApi.GetListFromStringVector(NativeApi.GetAllPlugins(nativeProcessor));
48 | }
49 |
50 | public string GetGlobalChain()
51 | {
52 | return NativeApi.GetGlobalChain(nativeProcessor);
53 | }
54 |
55 | public string GetPluginSlot(string slotName)
56 | {
57 | return Marshal.PtrToStringAnsi(NativeApi.GetPluginSlot(nativeProcessor, slotName));
58 | }
59 |
60 | public void SetPluginSlot(string slotName, string pluginID)
61 | {
62 | NativeApi.SetPluginSlot(nativeProcessor, slotName, pluginID);
63 | }
64 |
65 | public List GetChainPlugins(string chainName)
66 | {
67 | return GetChainPlugins(NativeApi.GetChainPlugins(nativeProcessor, chainName));
68 | }
69 |
70 | public List GetPresets()
71 | {
72 | return NativeApi.GetListFromStringVector(NativeApi.GetPresets(nativeProcessor));
73 | }
74 |
75 | public string GetCurrentPreset()
76 | {
77 | IntPtr preset = NativeApi.GetCurrentPreset(nativeProcessor);
78 |
79 | if (preset == IntPtr.Zero)
80 | return null;
81 |
82 | return Marshal.PtrToStringAnsi(preset);
83 | }
84 |
85 | public void LoadPreset(string presetName)
86 | {
87 | NativeApi.LoadPreset(nativeProcessor, presetName);
88 | }
89 |
90 | public string DumpSettings()
91 | {
92 | return NativeApi.DumpSettings(nativeProcessor);
93 | }
94 |
95 | public string DumpProgram()
96 | {
97 | return NativeApi.DumpProgram(nativeProcessor);
98 | }
99 |
100 | public unsafe void Process(float* input, float* output, uint bufferSize)
101 | {
102 | NativeApi.Process(nativeProcessor, input, output, bufferSize);
103 | }
104 |
105 | UnmanagedAudioPlugin CreatePluginFromNative(IntPtr nativePtr)
106 | {
107 | if (nativePtr == IntPtr.Zero)
108 | return null;
109 |
110 | UnmanagedAudioPlugin newPlugin = new UnmanagedAudioPlugin();
111 |
112 | newPlugin.SetNativePlugin(nativePtr);
113 |
114 | return newPlugin;
115 | }
116 |
117 | List GetChainPlugins(IntPtr plugVec)
118 | {
119 | if (plugVec == IntPtr.Zero)
120 | return null;
121 |
122 | List list = new();
123 |
124 | uint size = NativeApi.GetPluginVectorSize(plugVec);
125 |
126 | for (uint i = 0; i < size; i++)
127 | {
128 | list.Add(CreatePluginFromNative(NativeApi.GetPluginVectorValue(plugVec, i)));
129 | }
130 |
131 | return list;
132 | }
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/StompboxClient/StompboxAPI/UnmanagedAudioPlugin.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Collections.ObjectModel;
4 | using System.Runtime.InteropServices;
5 | using Stompbox;
6 |
7 | namespace StompboxAPI
8 | {
9 | public class UnmanagedPluginParameter : PluginParameter
10 | {
11 | internal IntPtr nativeParameter;
12 |
13 | public override float Value
14 | {
15 | get
16 | {
17 | return NativeApi.GetParameterValue(nativeParameter);
18 | }
19 |
20 | set
21 | {
22 | if (SetValue != null)
23 | SetValue(value);
24 |
25 | NativeApi.SetParameterValue(nativeParameter, value);
26 | }
27 | }
28 |
29 | public IntPtr ParameterHandle { get; set; }
30 | }
31 |
32 | public class UnmanagedAudioPlugin : AudioPluginBase, IAudioPlugin
33 | {
34 | internal IntPtr nativePlugin;
35 |
36 | public override bool Enabled
37 | {
38 | get { return NativeApi.GetPluginEnabled(nativePlugin); }
39 | set { NativeApi.SetPluginEnabled(nativePlugin, value); }
40 | }
41 |
42 | public override float OutputValue
43 | {
44 | get
45 | {
46 | return NativeApi.GetOutputValue(nativePlugin);
47 | }
48 | }
49 |
50 | Dictionary cachedParameters = new Dictionary();
51 |
52 | internal void SetNativePlugin(IntPtr nativePlugin)
53 | {
54 | this.nativePlugin = nativePlugin;
55 |
56 | ID = Marshal.PtrToStringAnsi(NativeApi.GetPluginID(nativePlugin));
57 |
58 | foreach (PluginParameter parameter in Parameters)
59 | {
60 | cachedParameters[parameter.Name] = (parameter.Value - parameter.MinValue) / (parameter.MaxValue - parameter.MinValue);
61 | }
62 |
63 | ObservableCollection newParameters = new ObservableCollection();
64 |
65 | if (String.IsNullOrEmpty(Name))
66 | Name = Marshal.PtrToStringAnsi(NativeApi.GetPluginName(nativePlugin));
67 |
68 | Description = Marshal.PtrToStringAnsi(NativeApi.GetPluginDescription(nativePlugin));
69 |
70 | IsUserSelectable = NativeApi.GetPluginIsUserSelectable(nativePlugin);
71 |
72 | string backgroundColor = Marshal.PtrToStringAnsi(NativeApi.GetPluginBackgroundColor(nativePlugin));
73 |
74 | if (!string.IsNullOrEmpty(backgroundColor))
75 | {
76 | BackgroundColor = backgroundColor;
77 | //PaintColor = (System.Windows.Media.Color)System.Windows.Media.ColorConverter.ConvertFromString(backgroundColor);
78 | }
79 |
80 | string foregroundColor = Marshal.PtrToStringAnsi(NativeApi.GetPluginForegroundColor(nativePlugin));
81 |
82 | if (!string.IsNullOrEmpty(foregroundColor))
83 | {
84 | ForegroundColor = foregroundColor;
85 | }
86 |
87 | uint numParameters = NativeApi.GetPluginNumParameters(nativePlugin);
88 |
89 | for (uint i = 0; i < numParameters; i++)
90 | {
91 | IntPtr nativeParameter = NativeApi.GetPluginParameter(nativePlugin, i);
92 |
93 | string paramName = Marshal.PtrToStringAnsi(NativeApi.GetParameterName(nativeParameter));
94 | EParameterType paramType = (EParameterType)NativeApi.GetParameterType(nativeParameter);
95 |
96 | string filePath = null;
97 |
98 | if (paramType == EParameterType.File)
99 | {
100 | filePath = Marshal.PtrToStringAnsi(NativeApi.GetParameterFilePath(nativeParameter));
101 | }
102 |
103 | String[] enumValues = null;
104 |
105 | if ((paramType == EParameterType.Enum) || (paramType == EParameterType.File))
106 | {
107 | enumValues = NativeApi.GetListFromStringVector(NativeApi.GetParameterEnumValues(nativeParameter)).ToArray();
108 | }
109 |
110 | int[] intValues = null;
111 |
112 | if (paramType == EParameterType.Int)
113 | {
114 | int minVal = (int)NativeApi.GetParameterMinValue(nativeParameter);
115 | int maxVal = (int)NativeApi.GetParameterMaxValue(nativeParameter);
116 |
117 | if (minVal == maxVal)
118 | continue;
119 |
120 | intValues = new int[(maxVal - minVal) + 1];
121 |
122 | for (int intVal = 0; intVal < intValues.Length; intVal++)
123 | {
124 | intValues[intVal] = minVal + intVal;
125 | }
126 | }
127 |
128 | PluginParameter parameter = new UnmanagedPluginParameter
129 | {
130 | Plugin = this,
131 | nativeParameter = nativeParameter,
132 | Name = paramName,
133 | Description = Marshal.PtrToStringAnsi(NativeApi.GetParameterDescription(nativeParameter)),
134 | MinValue = NativeApi.GetParameterMinValue(nativeParameter),
135 | MaxValue = NativeApi.GetParameterMaxValue(nativeParameter),
136 | DefaultValue = NativeApi.GetParameterDefaultValue(nativeParameter),
137 | RangePower = NativeApi.GetParameterRangePower(nativeParameter),
138 | ParameterType = paramType,
139 | IsAdvanced = NativeApi.GetParameterIsAdvanced(nativeParameter),
140 | CanSyncToHostBPM = NativeApi.GetParameterCanSyncToHostBPM(nativeParameter),
141 | HostBPMSyncNumerator = NativeApi.GetParameterBPMSyncNumerator(nativeParameter),
142 | HostBPMSyncDenominator = NativeApi.GetParameterBPMSyncDenominator(nativeParameter),
143 | ValueFormat = Marshal.PtrToStringAnsi(NativeApi.GetParameterDisplayFormat(nativeParameter)),
144 | FilePath = filePath,
145 | EnumValues = enumValues,
146 | IntValues = intValues,
147 | GetValue = delegate
148 | {
149 | return NativeApi.GetParameterValue(nativeParameter);
150 | },
151 | };
152 |
153 | if (parameter.CanSyncToHostBPM)
154 | {
155 | parameter.UpdateBPMSync = delegate
156 | {
157 | NativeApi.SetParameterBPMSyncNumerator(nativeParameter, parameter.HostBPMSyncNumerator);
158 | NativeApi.SetParameterBPMSyncDenominator(nativeParameter, parameter.HostBPMSyncDenominator);
159 | };
160 | }
161 |
162 | if ((paramType == EParameterType.Enum) || (paramType == EParameterType.File))
163 | {
164 | EnumParameter = parameter;
165 | }
166 |
167 | if (cachedParameters.ContainsKey(parameter.Name))
168 | {
169 | parameter.Value = parameter.MinValue + ((parameter.MaxValue - parameter.MinValue) * cachedParameters[parameter.Name]);
170 |
171 | //Logger.Log("Set cached " + Name + "/" + unmanagedWrapper.GetParameterName(index) + " to " + parameter.Value );
172 | }
173 |
174 | newParameters.Add(parameter);
175 | }
176 |
177 | Parameters = newParameters;
178 |
179 | // Currently just for EQ-7...
180 | if (Parameters.Count > 6)
181 | {
182 | ParameterTextSize = 9;
183 | }
184 | }
185 | }
186 | }
187 |
--------------------------------------------------------------------------------
/StompboxClient/StompboxAPIBase/AudioPlugin.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.ObjectModel;
3 | using System.ComponentModel;
4 |
5 | namespace Stompbox
6 | {
7 | public enum EParameterType
8 | {
9 | Knob,
10 | Bool,
11 | Int,
12 | VSlider,
13 | Enum,
14 | File
15 | };
16 |
17 | public class BPMSync
18 | {
19 | public static List Timings;
20 |
21 | public string Name { get; set; }
22 | public int Numerator { get; set; }
23 | public int Denomenator { get; set; }
24 |
25 | static BPMSync()
26 | {
27 | Timings = new List
28 | {
29 | new BPMSync
30 | {
31 | Name = "Custom",
32 | Numerator = 0,
33 | Denomenator = 0
34 | },
35 | new BPMSync
36 | {
37 | Name = "Half Note",
38 | Numerator = 2,
39 | Denomenator = 1
40 | },
41 | new BPMSync
42 | {
43 | Name = "Dotted 1/4 Note",
44 | Numerator = 3,
45 | Denomenator = 2
46 | },
47 | new BPMSync
48 | {
49 | Name = "1/4 Note",
50 | Numerator = 1,
51 | Denomenator = 1
52 | },
53 | new BPMSync
54 | {
55 | Name = "Dotted 1/8th",
56 | Numerator = 3,
57 | Denomenator = 4
58 | },
59 | new BPMSync
60 | {
61 | Name = "Triplet of Half",
62 | Numerator = 2,
63 | Denomenator = 3
64 | },
65 | new BPMSync
66 | {
67 | Name = "1/8th Note",
68 | Numerator = 1,
69 | Denomenator = 2
70 | },
71 | new BPMSync
72 | {
73 | Name = "Dotted 1/16th",
74 | Numerator = 3,
75 | Denomenator = 8
76 | },
77 | new BPMSync
78 | {
79 | Name = "Triplet of Quarter",
80 | Numerator = 1,
81 | Denomenator = 3
82 | },
83 | new BPMSync
84 | {
85 | Name = "16th Note",
86 | Numerator = 1,
87 | Denomenator = 4
88 | }
89 | };
90 | }
91 | }
92 |
93 | public class PluginParameter
94 | {
95 | public IAudioPlugin Plugin { get; set; }
96 | public string Name { get; set; }
97 | public string Description { get; set; }
98 | public string ValueFormat { get; set; }
99 | public float MinValue { get; set; }
100 | public float MaxValue { get; set; }
101 | public float DefaultValue { get; set; }
102 | public float RangePower { get; set; } = 1;
103 | public EParameterType ParameterType { get; set; }
104 | public bool CanSyncToHostBPM { get; set; }
105 | public int HostBPMSyncNumerator { get; set; }
106 | public int HostBPMSyncDenominator { get; set; }
107 | public bool IsAdvanced { get; set; }
108 | public bool IsVisible { get; set; }
109 | public virtual float Value { get; set; }
110 | public float NormalizedValue
111 | {
112 | get
113 | {
114 | return GetNormalizedValue(Value);
115 | }
116 | set
117 | {
118 | Value = GetRangeValue(value);
119 | }
120 | }
121 | public string DisplayValue { get { return String.Format(ValueFormat, Value); } }
122 | public String FilePath { get; set; } = null;
123 | public String[] EnumValues { get; set; }
124 | public int[] IntValues { get; set; }
125 | public int IntValue
126 | {
127 | get
128 | {
129 | return (int)Value;
130 | }
131 | set
132 | {
133 | Value = value;
134 | }
135 | }
136 | public Func GetValue { get; set; }
137 | public Action SetValue { get; set; }
138 | public Action UpdateBPMSync { get; set; }
139 |
140 | double value;
141 |
142 | public PluginParameter()
143 | {
144 | IsVisible = true;
145 | ValueFormat = "{0:0.00}";
146 | }
147 |
148 | public float GetNormalizedValue(float value)
149 | {
150 | float val = (value - MinValue) / (MaxValue - MinValue);
151 |
152 | return (float)((RangePower < 0) ? (1 - (Math.Pow(1 - val, 1 / -RangePower))) : Math.Pow(val, 1 / RangePower));
153 | }
154 |
155 | public float GetRangeValue(float normalizedValue)
156 | {
157 | float val = (float)((RangePower < 0) ? (1 - Math.Pow(1 - normalizedValue, -RangePower)) : Math.Pow(normalizedValue, RangePower));
158 |
159 | return MinValue + ((MaxValue - MinValue) * val);
160 | }
161 |
162 | public override string ToString()
163 | {
164 | return Name + ": " + DisplayValue;
165 | }
166 |
167 | public PluginParameter ShallowCopy()
168 | {
169 | return (PluginParameter)this.MemberwiseClone();
170 | }
171 | }
172 |
173 | public interface IAudioPlugin
174 | {
175 | String Name { get; set; }
176 | String ID { get; }
177 | String Description { get; set; }
178 | bool Enabled { get; set; }
179 | float OutputValue { get; set; }
180 | bool EnabledIsSwitchable { get; set; }
181 | String BackgroundColor { get; set; }
182 | String ForegroundColor { get; set; }
183 | bool IsUserSelectable { get; set; }
184 | double ParameterTextSize { get; set; }
185 | string DialStyle { get; set; }
186 | ObservableCollection Parameters { get; set; }
187 | PluginParameter EnumParameter { get; set; }
188 | Action SetEnabled { get; set; }
189 | Action SetOutputValue { get; set; }
190 |
191 | PluginParameter GetParameter(string parameterName);
192 | }
193 |
194 | public class AudioPluginBase : IAudioPlugin
195 | {
196 | public String Name { get; set; }
197 | public String ID { get; set; }
198 | public String Description { get; set; }
199 | public virtual bool Enabled
200 | {
201 | get
202 | {
203 | return enabled;
204 | }
205 | set
206 | {
207 | enabled = value;
208 |
209 | if (SetEnabled != null)
210 | SetEnabled(enabled);
211 | }
212 | }
213 | public virtual float OutputValue
214 | {
215 | get
216 | {
217 | return outputValue;
218 | }
219 | set
220 | {
221 | outputValue = value;
222 |
223 | if (SetOutputValue != null)
224 | {
225 | SetOutputValue(value);
226 | }
227 | }
228 | }
229 | public String BackgroundColor { get; set; }
230 | public String ForegroundColor { get; set; }
231 | public bool IsUserSelectable { get; set; }
232 | public double ParameterTextSize { get; set; }
233 | public string DialStyle { get; set; }
234 | public bool EnabledIsSwitchable { get; set; }
235 | public ObservableCollection Parameters { get; set; }
236 | public PluginParameter EnumParameter { get; set; }
237 | public Action SetEnabled { get; set; }
238 | public Action SetOutputValue { get; set; }
239 |
240 | protected bool enabled;
241 | float outputValue;
242 |
243 | public event PropertyChangedEventHandler PropertyChanged;
244 | protected bool initialized = false;
245 |
246 | public AudioPluginBase()
247 | {
248 | EnabledIsSwitchable = true;
249 | Parameters = new ObservableCollection();
250 |
251 | ForegroundColor = "#000000";
252 | BackgroundColor = "#c9c9c9";
253 | ParameterTextSize = 11;
254 | }
255 |
256 | public override string ToString()
257 | {
258 | return ID;
259 | }
260 |
261 | public PluginParameter GetParameter(string parameterName)
262 | {
263 | foreach (PluginParameter parameter in Parameters)
264 | {
265 | if (parameter.Name == parameterName)
266 | return parameter;
267 | }
268 |
269 | return null;
270 | }
271 | }
272 | }
--------------------------------------------------------------------------------
/StompboxClient/StompboxAPIBase/PluginFactory.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace Stompbox
5 | {
6 | public class PluginFactory
7 | {
8 | Dictionary loadedPlugins = new Dictionary();
9 |
10 | StompboxClient StompboxClient;
11 |
12 | public PluginFactory(StompboxClient stompboxClient)
13 | {
14 | this.StompboxClient = stompboxClient;
15 | }
16 |
17 | public void ClearPlugins()
18 | {
19 | loadedPlugins.Clear();
20 | }
21 |
22 | public void RegisterPlugin(IAudioPlugin plugin)
23 | {
24 | loadedPlugins[plugin.ID] = plugin;
25 | }
26 |
27 | public IAudioPlugin GetPlugin(string id)
28 | {
29 | if (!loadedPlugins.ContainsKey(id))
30 | return null;
31 |
32 | return loadedPlugins[id];
33 | }
34 |
35 | public IAudioPlugin GetPluginDefinition(string name)
36 | {
37 | if (loadedPlugins.ContainsKey(name))
38 | return loadedPlugins[name];
39 |
40 | return StompboxClient.CreatePlugin(name, name);
41 | }
42 |
43 | public IAudioPlugin CreateNewPlugin(string name)
44 | {
45 | return CreatePlugin(name, null);
46 | }
47 |
48 | public IAudioPlugin CreatePlugin(string id)
49 | {
50 | if (id == null)
51 | return null;
52 |
53 | string name = id;
54 | string[] idName = id.Split('_');
55 |
56 | if (idName.Length > 1)
57 | {
58 | name = idName[0];
59 | }
60 |
61 | return CreatePlugin(name, id);
62 | }
63 |
64 | public IAudioPlugin CreatePlugin(string name, string id)
65 | {
66 | IAudioPlugin newPlugin = null;
67 |
68 | if (id == null)
69 | {
70 | id = name;
71 | int number = 1;
72 |
73 | while (loadedPlugins.ContainsKey(id))
74 | {
75 | number++;
76 |
77 | id = name + "_" + number;
78 | }
79 | }
80 | else
81 | {
82 | if (loadedPlugins.ContainsKey(id))
83 | return loadedPlugins[id];
84 | }
85 |
86 | newPlugin = StompboxClient.CreatePlugin(name, id);
87 |
88 | loadedPlugins[id] = newPlugin;
89 |
90 | if (newPlugin != null)
91 | {
92 | StompboxClient.Debug("New plugin: " + newPlugin.Name + "[" + newPlugin.ID + "]");
93 | }
94 |
95 | return newPlugin;
96 | }
97 |
98 | public void ReleasePlugin(IAudioPlugin plugin)
99 | {
100 | if (loadedPlugins.ContainsKey(plugin.ID))
101 | {
102 | loadedPlugins.Remove(plugin.ID);
103 | }
104 | }
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/StompboxClient/StompboxAPIBase/StompboxAPIBase.projitems:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | $(MSBuildAllProjects);$(MSBuildThisFileFullPath)
5 | true
6 | ef794465-7976-4ad3-b2cc-dea7a85a80ae
7 |
8 |
9 | StompboxAPIBase
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/StompboxClient/StompboxAPIBase/StompboxClient.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Runtime.InteropServices;
5 | using System.Security.Cryptography;
6 | using System.Threading;
7 | using System.Xml.Linq;
8 |
9 | namespace Stompbox
10 | {
11 | public class MidiCCMapEntry
12 | {
13 | public int CCNumber { get; set; }
14 | public string PluginName { get; set; }
15 | public string PluginParameter { get; set; }
16 | }
17 |
18 | public class StompboxClient
19 | {
20 | public static StompboxClient Instance { get; private set; }
21 |
22 | public static Action DebugAction { get; set; }
23 |
24 | public PluginFactory PluginFactory { get; set; }
25 | public Action MidiCallback { get; set; }
26 |
27 | public virtual bool Connected { get { return false; } }
28 | public float BPM { get; set; }
29 | public bool InClientMode { get; protected set; }
30 | public bool AllowMidiMapping { get; set; }
31 | public string PluginPath { get; set; }
32 | public float MaxDSPLoad { get; private set; }
33 | public float MinDSPLoad { get; private set; }
34 | public List MidiCCMap { get; private set; } = new List();
35 | public int MidiModeCC { get; set; } = -1;
36 | public Dictionary MidiStompCCMap { get; private set; } = new Dictionary();
37 | public bool StopSimulateAudio { get; set; }
38 | public List PresetNames { get; private set; }
39 |
40 | public IEnumerable AllActivePlugins
41 | {
42 | get
43 | {
44 | yield break;
45 | }
46 | }
47 |
48 | public virtual int CurrentPresetIndex { get; set; } = -1;
49 |
50 | public virtual bool NeedUIReload { get; set; }
51 |
52 | bool needUIReload = false;
53 |
54 | public StompboxClient()
55 | {
56 | Instance = this;
57 |
58 | Debug("Creating StompboxClient.");
59 |
60 | AllowMidiMapping = true;
61 | BPM = 120;
62 |
63 | PluginPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "stompbox");
64 |
65 | PluginFactory = new PluginFactory(this);
66 |
67 | PresetNames = new List();
68 | }
69 |
70 | public virtual void Connect(string serverName, int port, Action connectCallback)
71 | {
72 | }
73 |
74 | public virtual void UpdatePresets()
75 | {
76 | }
77 |
78 | public virtual void UpdateProgram()
79 | {
80 | UpdatePresets();
81 | }
82 |
83 | public virtual void SaveCurrentPreset()
84 | {
85 |
86 | }
87 |
88 | public virtual void SavePresetAs(string presetName)
89 | {
90 |
91 | }
92 |
93 | public virtual void DeleteCurrentPreset()
94 | {
95 |
96 | }
97 |
98 | public virtual string GetGlobalChain()
99 | {
100 | throw new NotImplementedException();
101 | }
102 |
103 | public virtual IEnumerable GetAllPluginNames()
104 | {
105 | return null;
106 | }
107 |
108 | public IEnumerable GetAllPluginDefinitions()
109 | {
110 | foreach (string name in GetAllPluginNames())
111 | {
112 | yield return GetPluginDefinition(name);
113 | }
114 | }
115 |
116 | public IEnumerable GetAllUserPluginDefinitions()
117 | {
118 | foreach (string name in GetAllPluginNames())
119 | {
120 | IAudioPlugin plugin = GetPluginDefinition(name);
121 |
122 | if (plugin.IsUserSelectable)
123 | yield return plugin;
124 | }
125 | }
126 |
127 | public virtual IAudioPlugin GetPluginDefinition(string pluginName)
128 | {
129 | return null;
130 | }
131 |
132 | public virtual IAudioPlugin CreatePlugin(string pluginName, string pluginID)
133 | {
134 | return null;
135 | }
136 |
137 | public virtual void SetChain(string name, List plugins)
138 | {
139 |
140 | }
141 |
142 | public virtual List GetChain(string name)
143 | {
144 | throw new NotImplementedException();
145 | }
146 |
147 | public virtual void SendCommand(string command)
148 | {
149 | }
150 |
151 | public void Debug(string debugStr)
152 | {
153 | if (DebugAction != null)
154 | DebugAction(debugStr);
155 | }
156 |
157 |
158 | public void ReportDSPLoad(float maxDSPLoad, float minDSPLoad)
159 | {
160 | MaxDSPLoad = maxDSPLoad;
161 | MinDSPLoad = minDSPLoad;
162 | }
163 |
164 | public void SetPresetNames(List presetNames)
165 | {
166 | PresetNames.Clear();
167 |
168 | foreach (string presetName in presetNames)
169 | {
170 | PresetNames.Add(presetName);
171 | }
172 | }
173 |
174 | public void SetSelectedPreset(string presetName)
175 | {
176 | Debug("Set selected preset: " + presetName);
177 |
178 | CurrentPresetIndex = PresetNames.IndexOf(presetName);
179 | }
180 |
181 | public virtual void UpdateUI()
182 | {
183 | Debug("*** Update UI");
184 |
185 | NeedUIReload = true;
186 | }
187 |
188 | protected virtual IAudioPlugin CreateSlotPlugin(string slotName, string defaultPlugin)
189 | {
190 | string pluginID = GetSlotPlugin(slotName);
191 |
192 | if (pluginID == null)
193 | {
194 | pluginID = defaultPlugin;
195 | }
196 |
197 | SetSlotPlugin(slotName, pluginID);
198 |
199 | return PluginFactory.CreatePlugin(pluginID);
200 | }
201 |
202 | public virtual void SetDefaultSlotPlugin(string slotName, string pluginID)
203 | {
204 | if (GetSlotPlugin(slotName) == null)
205 | SetSlotPlugin(slotName, pluginID);
206 |
207 | }
208 |
209 | public virtual void SetSlotPlugin(string slotName, string pluginID)
210 | {
211 |
212 | }
213 |
214 | public virtual string GetSlotPlugin(string slotName)
215 | {
216 | return null;
217 | }
218 |
219 | public virtual void UpdateChain(string chainName, List plugins)
220 | {
221 | string cmd = "SetChain " + chainName;
222 |
223 | foreach (IAudioPlugin plugin in plugins)
224 | {
225 | cmd += " " + plugin.ID;
226 | }
227 |
228 | StompboxClient.Instance.SendCommand(cmd);
229 | }
230 |
231 | public virtual void Init(float sampleRate)
232 | {
233 | }
234 |
235 | void HandleMidi(int midiCommand, int midiData1, int midiData2)
236 | {
237 | if (MidiCallback != null)
238 | MidiCallback(midiCommand, midiData1, midiData2);
239 | }
240 |
241 | }
242 | }
243 |
--------------------------------------------------------------------------------
/StompboxClient/StompboxAPIBase/StompboxClientBase.shproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | ef794465-7976-4ad3-b2cc-dea7a85a80ae
5 | 14.0
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/StompboxClient/StompboxAPITest/Program.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics;
2 | using System.Runtime.InteropServices;
3 | using System.Threading;
4 | using StompboxAPI;
5 |
6 | namespace StompboxAPITest
7 | {
8 | internal class Program
9 | {
10 | static void Main(string[] args)
11 | {
12 | APIClient client = new();
13 |
14 | client.Init(48000);
15 |
16 | Thread thread = new Thread(new ThreadStart(client.SimulateAudio));
17 | thread.Start();
18 |
19 | client.SetSelectedPreset("tmp");
20 |
21 | Thread.Sleep(1000);
22 |
23 | string state = client.GetProgramState();
24 |
25 | var tuner = client.PluginFactory.CreatePlugin("Tuner");
26 |
27 | tuner.Enabled = true;
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/StompboxClient/StompboxAPITest/StompboxAPITest.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net8.0
6 | enable
7 | enable
8 | True
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/StompboxClient/StompboxRemoteClient/NetworkInterface.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Net.Sockets;
4 | using System.Threading;
5 | using System.Threading.Tasks;
6 |
7 | namespace StompboxAPI
8 | {
9 | public class NetworkClient
10 | {
11 | public bool Running { get; private set; }
12 | public bool Connected { get; private set; }
13 | public string LastError { get; private set; }
14 |
15 | TcpClient client;
16 | NetworkStream stream;
17 | Thread runThread = null;
18 |
19 | public Action LineHandler { get; set; }
20 | public Action DebugAction { get; set; }
21 |
22 | Action resultCallback = null;
23 |
24 | public NetworkClient()
25 | {
26 | }
27 |
28 | public bool Start(string serverName, int port, Action resultCallback)
29 | {
30 | this.resultCallback = resultCallback;
31 |
32 | try
33 | {
34 | Debug("** Connecting to " + serverName + ":" + port);
35 |
36 | client = new TcpClient();
37 |
38 | var connectionTask = client.ConnectAsync(serverName, port).ContinueWith(task =>
39 | {
40 | return task.IsFaulted ? null : client;
41 | }, TaskContinuationOptions.ExecuteSynchronously);
42 | var timeoutTask = Task.Delay(5000)
43 | .ContinueWith(task => null, TaskContinuationOptions.ExecuteSynchronously);
44 | var resultTask = Task.WhenAny(connectionTask, timeoutTask).Unwrap();
45 |
46 | var resultTcpClient = resultTask.GetAwaiter().GetResult();
47 |
48 | if (client.Connected)
49 | {
50 | stream = client.GetStream();
51 |
52 | Connected = true;
53 |
54 | Debug("** Connected!");
55 |
56 | runThread = new Thread(RunServer);
57 | runThread.Start();
58 | }
59 |
60 | resultCallback(client.Connected);
61 |
62 | return client.Connected;
63 | }
64 | catch (Exception ex)
65 | {
66 | LastError = ex.ToString();
67 |
68 | Debug("** Connect failed with: " + LastError);
69 |
70 | resultCallback(false);
71 | }
72 |
73 | return false;
74 | }
75 |
76 | void Debug(string debugStr)
77 | {
78 | if (DebugAction != null)
79 | DebugAction(debugStr);
80 | }
81 |
82 | public void Stop()
83 | {
84 | client.Close();
85 |
86 | if (runThread != null)
87 | runThread.Join();
88 | }
89 |
90 | public void SendData(String data)
91 | {
92 | if (!Running)
93 | return;
94 |
95 | try
96 | {
97 | Byte[] byteData = System.Text.Encoding.ASCII.GetBytes(data);
98 |
99 | stream.Write(byteData, 0, data.Length);
100 | }
101 | catch
102 | {
103 | }
104 | }
105 |
106 | void RunServer()
107 | {
108 | try
109 | {
110 | using (StreamReader reader = new StreamReader(stream))
111 | {
112 | Running = true;
113 |
114 | resultCallback(true); // Do this here to make sure we don't send any messages before we are ready to get the response
115 |
116 | do
117 | {
118 | string line = reader.ReadLine();
119 |
120 | if (String.IsNullOrEmpty(line))
121 | {
122 | if (client.Client.Poll(0, SelectMode.SelectRead))
123 | {
124 | byte[] buff = new byte[1];
125 |
126 | if (client.Client.Receive(buff, SocketFlags.Peek) == 0)
127 | {
128 | break;
129 | }
130 | }
131 | }
132 | else
133 | {
134 | if (LineHandler != null)
135 | LineHandler(line);
136 | }
137 | }
138 | while (true);
139 | }
140 | }
141 | catch (Exception ex)
142 | {
143 | }
144 |
145 | Debug("** Connection ended");
146 |
147 | Running = false;
148 | Connected = false;
149 | }
150 | }
151 | }
152 |
--------------------------------------------------------------------------------
/StompboxClient/StompboxRemoteClient/RemoteClient.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using Stompbox;
5 |
6 | namespace StompboxAPI
7 | {
8 | public class RemoteClient : StompboxClient
9 | {
10 | public static new RemoteClient Instance { get { return StompboxClient.Instance as RemoteClient; } }
11 |
12 | public bool SuppressCommandUpdates { get; set; }
13 |
14 | Dictionary slotPlugins = new();
15 | Dictionary> chains = new();
16 |
17 | NetworkClient networkClient;
18 | ProtocolClient protocolClient;
19 |
20 | public override bool Connected
21 | {
22 | get
23 | {
24 | return networkClient.Connected;
25 | }
26 | }
27 |
28 | public override int CurrentPresetIndex
29 | {
30 | get => base.CurrentPresetIndex;
31 |
32 | set
33 | {
34 | base.CurrentPresetIndex = value;
35 |
36 | if ((CurrentPresetIndex >= 0) && !SuppressCommandUpdates)
37 | {
38 | SendCommand("LoadPreset " + PresetNames[base.CurrentPresetIndex]);
39 | }
40 | }
41 | }
42 |
43 | public RemoteClient()
44 | : base()
45 | {
46 | InClientMode = true;
47 |
48 | protocolClient = new ProtocolClient(this);
49 |
50 | networkClient = new NetworkClient();
51 | networkClient.LineHandler = HandleCommand;
52 | networkClient.DebugAction = delegate (string debug)
53 | {
54 | Debug(debug);
55 | };
56 | }
57 |
58 | Action connectCallback;
59 |
60 | public override void Connect(string serverName, int port, Action connectCallback)
61 | {
62 | if (InClientMode)
63 | {
64 | this.connectCallback = connectCallback;
65 |
66 | Debug("Connect to server: " + serverName);
67 |
68 | networkClient.Start(serverName, 24639, ConnectCallback);
69 | }
70 | }
71 |
72 | public void Disconnect()
73 | {
74 | if (InClientMode)
75 | {
76 | networkClient.Stop();
77 | }
78 | }
79 |
80 | void ConnectCallback(bool result)
81 | {
82 | if (result)
83 | {
84 | Debug("Connected");
85 |
86 | networkClient.LineHandler = HandleCommand;
87 |
88 | RequestConfigDump();
89 |
90 | connectCallback(true);
91 | }
92 | else
93 | {
94 | Debug("Connect failed");
95 |
96 | connectCallback(false);
97 | }
98 | }
99 |
100 | public override void UpdatePresets()
101 | {
102 | base.UpdatePresets();
103 |
104 | SendCommand("List Presets");
105 | }
106 |
107 | public override void UpdateProgram()
108 | {
109 | base.UpdateProgram();
110 |
111 | SendCommand("Dump Program");
112 | }
113 |
114 | public override void SaveCurrentPreset()
115 | {
116 | SendCommand("SavePreset " + PresetNames[CurrentPresetIndex]);
117 | }
118 |
119 | public override void SavePresetAs(string presetName)
120 | {
121 | SendCommand("SavePreset " + presetName);
122 | SendCommand("List Presets");
123 | UpdateProgram();
124 | }
125 |
126 | public override void DeleteCurrentPreset()
127 | {
128 | SendCommand("DeletePreset " + PresetNames[CurrentPresetIndex]);
129 |
130 | UpdateProgram();
131 | }
132 |
133 | public void RequestConfigDump()
134 | {
135 | //Thread.Sleep(500);
136 |
137 | SendCommand("Dump Config");
138 | SendCommand("List Presets");
139 |
140 | if (InClientMode)
141 | SendCommand("PluginOutputOn");
142 |
143 | UpdateProgram();
144 | }
145 |
146 | public override IEnumerable GetAllPluginNames()
147 | {
148 | return protocolClient.PluginNames;
149 | }
150 |
151 | public override IAudioPlugin GetPluginDefinition(string pluginName)
152 | {
153 | return protocolClient.GetPluginDefinition(pluginName);
154 | }
155 |
156 | public override IAudioPlugin CreatePlugin(string pluginName, string pluginID)
157 | {
158 | return protocolClient.CreateNewPlugin(pluginName, pluginID);
159 | }
160 |
161 | string[] lineSeparator = new string[] { "\r", "\n" };
162 |
163 | public void HandleCommand(string commandStr)
164 | {
165 | if (InClientMode)
166 | {
167 | string[] commands = commandStr.Split(lineSeparator, 0);
168 |
169 | foreach (string command in commands)
170 | {
171 | if (!string.IsNullOrWhiteSpace(command))
172 | {
173 | protocolClient.HandleCommand(command);
174 | }
175 | }
176 | }
177 | }
178 |
179 | public override void SendCommand(string command)
180 | {
181 | Debug("Send command: " + command);
182 |
183 | if (SuppressCommandUpdates)
184 | {
185 | Debug("*** Command suppressed");
186 | }
187 | else
188 | {
189 | if (networkClient != null)
190 | {
191 | if (!networkClient.Connected)
192 | {
193 | Debug("*** Network client not connected");
194 | }
195 | else
196 | {
197 | Debug("Actullay sending");
198 | networkClient.SendData(command + "\r\n");
199 | }
200 | }
201 | }
202 | }
203 |
204 | public override void SetSlotPlugin(string slotName, string pluginID)
205 | {
206 | slotPlugins[slotName] = pluginID;
207 |
208 | string cmd = "SetPluginSlot " + slotName + " " + pluginID;
209 |
210 | StompboxClient.Instance.SendCommand(cmd);
211 | }
212 |
213 | public override string GetSlotPlugin(string slotName)
214 | {
215 | string pluginID;
216 |
217 | if (slotPlugins.TryGetValue(slotName, out pluginID))
218 | {
219 | return pluginID;
220 | }
221 |
222 | return null;
223 | }
224 |
225 | public override void SetChain(string name, List plugins)
226 | {
227 | chains[name] = plugins;
228 | }
229 |
230 | public override List GetChain(string name)
231 | {
232 | if (chains.ContainsKey(name))
233 | {
234 | return chains[name];
235 | }
236 |
237 | return new List();
238 | }
239 | }
240 | }
241 |
--------------------------------------------------------------------------------
/StompboxClient/StompboxRemoteClient/RemotePlugin.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Stompbox;
3 |
4 | namespace StompboxAPI
5 | {
6 | public class RemoteParameter : PluginParameter
7 | {
8 | public override float Value
9 | {
10 | get => base.Value;
11 |
12 | set
13 | {
14 | if (SetValue != null)
15 | SetValue(value);
16 |
17 | base.Value = value;
18 |
19 | if (!RemoteClient.Instance.SuppressCommandUpdates)
20 | {
21 | if (CanSyncToHostBPM && (HostBPMSyncNumerator != 0) && (HostBPMSyncDenominator != 0))
22 | {
23 | RemoteClient.Instance.SendCommand("SetParam " + Plugin.ID + " " + Name + " " + HostBPMSyncNumerator + "/" + HostBPMSyncDenominator);
24 | }
25 | else
26 | {
27 | RemoteClient.Instance.SendCommand("SetParam " + Plugin.ID + " " + Name + " " +
28 | (((ParameterType == EParameterType.Enum) || (ParameterType == EParameterType.File)) ? ((EnumValues.Length > 0) ? EnumValues[(int)Value] : "") : Value.ToString()));
29 | }
30 | }
31 | }
32 | }
33 | }
34 |
35 | public class RemotePlugin : AudioPluginBase
36 | {
37 | public override bool Enabled
38 | {
39 | get => base.Enabled;
40 |
41 | set
42 | {
43 | base.Enabled = value;
44 |
45 | if (!RemoteClient.Instance.SuppressCommandUpdates)
46 | {
47 | RemoteClient.Instance.SendCommand("SetParam " + ID + " Enabled " + (enabled ? "1" : "0"));
48 | }
49 | }
50 | }
51 | }
52 | }
--------------------------------------------------------------------------------
/StompboxClient/StompboxRemoteClient/StompboxRemoteClient.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net8.0
5 | enable
6 | enable
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/StompboxContent/Content/Textures/UISheet0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikeoliphant/StompboxUI/8dc3bdc26e1513bb0ef88e4f925863b903655937/StompboxContent/Content/Textures/UISheet0.png
--------------------------------------------------------------------------------
/StompboxHost/Icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikeoliphant/StompboxUI/8dc3bdc26e1513bb0ef88e4f925863b903655937/StompboxHost/Icon.ico
--------------------------------------------------------------------------------
/StompboxHost/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using AudioPlugSharpHost;
3 |
4 | namespace Stompbox
5 | {
6 | class Program
7 | {
8 | [STAThread]
9 | static void Main(string[] args)
10 | {
11 | //StompboxPlugin plugin = new();
12 | //var host = new WindowsFormsHost(plugin);
13 |
14 | MiniPlugins.AmpPlugin plugin = new();
15 | var host = new WindowsFormsHost(plugin);
16 |
17 | host.Run();
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/StompboxHost/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "profiles": {
3 | "StompboxSimHost": {
4 | "commandName": "Project",
5 | "nativeDebugging": true
6 | }
7 | }
8 | }
--------------------------------------------------------------------------------
/StompboxHost/StompboxHost.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | WinExe
4 | net8.0-windows
5 | Icon.ico
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/StompboxImageProcessor/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Drawing;
3 | using System.IO;
4 | using System.Reflection;
5 |
6 | namespace StompboxImageProcessor
7 | {
8 | class StompboxImageProcessor : ImageSheetProcessor.ImageSheetProcessor
9 | {
10 | public void RenderImages(string destPath)
11 | {
12 | BeginRenderImages(destPath);
13 | Render();
14 |
15 | EndRenderImages();
16 | }
17 |
18 | public void Render()
19 | {
20 | MaxImageSheetSize = 2048;
21 |
22 | BeginSpriteSheetGroup("UISheet");
23 |
24 | string font = Path.Combine(SrcPath, "Inter_18pt-Bold.ttf");
25 |
26 | AddFont("MainFont", font, 36);
27 | AddFont("SmallFont", font, 26);
28 |
29 | PushDirectory("UserInterface");
30 |
31 | Add("SingleWhitePixel");
32 |
33 | //CreateRotations("DialPointer", "DialPointerRotations", 32);
34 |
35 | //DoSquaredSprites = true;
36 | //processor.Scale("DialPointerRotations", 128, 128);
37 | //processor.DoSquaredSprites = false;
38 |
39 | Add("StompboxLogo");
40 |
41 | Add("InputChain");
42 | Add("OutputChain");
43 | Add("FxLoopChain");
44 |
45 | AddWithShadow("HoverTextOutline");
46 |
47 | Add("DialBackground");
48 | Add("DialPointer");
49 |
50 | Add("PowerOff");
51 | Add("PowerOn");
52 |
53 | Add("PopupBackground");
54 | Add("PluginBackground");
55 | Add("ButtonPressed");
56 | Add("ButtonUnpressed");
57 |
58 | Add("LevelDisplay");
59 |
60 | Add("TunerPoint");
61 |
62 | Add("VerticalSlider");
63 |
64 | Add("MoreButton");
65 |
66 | Add("StompOutline");
67 |
68 | Add("Play");
69 | Add("Stop");
70 | Add("Restart");
71 | Add("Record");
72 |
73 | PopDirectory();
74 |
75 | EndSpriteSheetGroup();
76 | }
77 |
78 | void CreateRotations(string srcImage, string destImage, int numRotations)
79 | {
80 | string srcPath = GetSourcePath(srcImage);
81 | string destPath = GetSourcePath(destImage);
82 |
83 | Bitmap srcBitmap = (Bitmap)Bitmap.FromFile(srcPath);
84 | srcBitmap.SetResolution(96, 96);
85 |
86 | Bitmap destBitmap = new Bitmap(srcBitmap.Width * numRotations, srcBitmap.Height);
87 |
88 | Bitmap tmpBitmap = new Bitmap(srcBitmap.Width, srcBitmap.Height);
89 |
90 | for (int i = 0; i < numRotations; i++)
91 | {
92 | float angle = ((float)i / (float)numRotations) * 360f;
93 |
94 | Rectangle srcRect = new Rectangle(0, 0, srcBitmap.Width, srcBitmap.Height);
95 |
96 | using (Graphics gt = Graphics.FromImage(tmpBitmap))
97 | {
98 | using (Graphics g = Graphics.FromImage(destBitmap))
99 | {
100 | gt.Clear(Color.Transparent);
101 |
102 | //move rotation point to center of image
103 | gt.TranslateTransform((float)srcBitmap.Width / 2, (float)srcBitmap.Height / 2);
104 | //rotate
105 | gt.RotateTransform(angle);
106 | //move image back
107 | gt.TranslateTransform(-(float)srcBitmap.Width / 2, -(float)srcBitmap.Height / 2);
108 | //draw passed in image onto graphics object
109 | gt.DrawImage(srcBitmap, 0, 0, srcRect, GraphicsUnit.Pixel);
110 |
111 | g.DrawImage(tmpBitmap, i * srcBitmap.Width, 0, srcRect, GraphicsUnit.Pixel);
112 | }
113 | }
114 | }
115 |
116 | destBitmap.Save(destPath, System.Drawing.Imaging.ImageFormat.Png);
117 | }
118 | }
119 |
120 |
121 | class Program
122 | {
123 | static void Main(string[] args)
124 | {
125 | var processor = new StompboxImageProcessor();
126 |
127 | string path = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), @"..\..\..\..");
128 |
129 | processor.ForceRegen = false;
130 |
131 | processor.SrcPath = Path.Combine(path, "SrcTextures");
132 |
133 | processor.RenderImages(Path.Combine(path, @"StompboxShared\Content\Textures"));
134 | }
135 |
136 | }
137 | }
138 |
--------------------------------------------------------------------------------
/StompboxImageProcessor/StompboxImageProcessor.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net8.0
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/StompboxPlugin/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.InteropServices;
3 | using System.Windows;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("StompboxPlugin")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("StompboxPlugin")]
13 | [assembly: AssemblyCopyright("Copyright © 2020")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("7bc972c1-afea-4dfd-be4d-71dc5a544274")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/StompboxPlugin/README.txt:
--------------------------------------------------------------------------------
1 | Stompbox
2 |
3 | Copyright (c) 2024-2025 Mike Oliphant
4 |
5 | Source code and license information can be found here:
6 |
7 | https://github.com/mikeoliphant/StompboxUI
8 |
9 | This is a VST3 plugin, and as such must be run within a VST host such as
10 | a DAW (Digital Audio Workstation) application.
11 |
12 | For your host to see the plugin, the "Stompbox" folder must be copied to your
13 | VST3 path - usually "C:\Program Files\Common Files\VST3".
14 |
15 | **Important Note**: You must have .NET 8.0 or later installed:
16 |
17 | https://dotnet.microsoft.com/en-us/download/dotnet/8.0
18 |
19 | If you are still having trouble getting the plugin to work, please check out
20 | troubleshooting instructions here:
21 |
22 | https://github.com/mikeoliphant/StompboxUI/blob/master/StompboxPlugin/Troubleshooting.md
23 |
--------------------------------------------------------------------------------
/StompboxPlugin/StompboxPlugin.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using System.Threading;
4 | using AudioPlugSharp;
5 | using UILayout;
6 |
7 | namespace Stompbox
8 | {
9 | public unsafe class StompboxPlugin : AudioPlugSharp.AudioPluginBase
10 | {
11 | public int CurrentProgram { get; private set; }
12 |
13 | public StompboxAPI.APIClient StompboxClient { get; private set; }
14 | public MonoGameHost GameHost { get; private set; } = null;
15 |
16 | FloatAudioIOPort monoInput;
17 | FloatAudioIOPort monoOutput;
18 | IntPtr bitConvertBuffer = IntPtr.Zero;
19 | uint bitConvertBufferSize = 0;
20 |
21 | public StompboxPlugin()
22 | {
23 | Company = "Nostatic Software";
24 | Website = "nostatic.org";
25 | Contact = "contact@nostatic.org";
26 | PluginName = "stompbox";
27 | PluginCategory = "Fx";
28 | PluginVersion = "0.1.14";
29 |
30 | PluginID = 0x43D53D93648B49CA;
31 |
32 | HasUserInterface = true;
33 |
34 | //Logger.ImmediateMode = true;
35 |
36 | //Logger.ImmediateMode = true;
37 | //Logger.WriteToStdErr = true;
38 | }
39 |
40 | public override void Initialize()
41 | {
42 | base.Initialize();
43 |
44 | Debug("Initialize");
45 |
46 | InputPorts = new AudioIOPort[] { monoInput = new FloatAudioIOPort("Mono Input", EAudioChannelConfiguration.Mono) };
47 | OutputPorts = new AudioIOPort[] { monoOutput = new FloatAudioIOPort("Mono Output", EAudioChannelConfiguration.Mono) };
48 |
49 | EditorWidth = 1000;
50 | EditorHeight = 540;
51 |
52 | //GCSettings.LatencyMode = GCLatencyMode.LowLatency;// GCLatencyMode.Batch; // SustainedLowLatency;
53 |
54 | StompboxAPI.APIClient.DebugAction = Debug;
55 |
56 | StompboxClient = new StompboxAPI.APIClient();
57 |
58 | StompboxClient.MidiCallback = SendMidiCommand;
59 | }
60 |
61 | public override void Stop()
62 | {
63 | base.Stop();
64 |
65 | GC.Collect();
66 | }
67 |
68 | public void DisposeDevice()
69 | {
70 | }
71 |
72 | public void Debug(String debugStr)
73 | {
74 | Logger.Log(debugStr);
75 | }
76 |
77 |
78 | public void ReportDSPLoad(float maxDSPLoad, float minDSPLoad)
79 | {
80 | }
81 |
82 | public virtual void UpdateUI()
83 | {
84 | StompboxClient.UpdateUI();
85 | }
86 |
87 | IntPtr parentWindow;
88 |
89 | public override void ShowEditor(IntPtr parentWindow)
90 | {
91 | Logger.Log("Show Editor");
92 |
93 | this.parentWindow = parentWindow;
94 |
95 | if (parentWindow == IntPtr.Zero)
96 | {
97 | RunGame();
98 | }
99 | else
100 | {
101 | new Thread(new ThreadStart(RunGame)).Start();
102 | }
103 | }
104 |
105 | void RunGame()
106 | {
107 | Logger.Log("Start game");
108 |
109 | try
110 | {
111 | int screenWidth = (int)EditorWidth;
112 | int screenHeight = (int)EditorHeight;
113 |
114 | StompboxLayout game = new StompboxLayout();
115 |
116 | game.Scale = 0.35f;
117 |
118 | using (GameHost = new MonoGameHost(parentWindow, screenWidth, screenHeight, fullscreen: false))
119 | {
120 | GameHost.IsMouseVisible = true;
121 |
122 | GameHost.StartGame(game);
123 |
124 | StompboxClient.NeedUIReload = true;
125 | }
126 |
127 | game = null;
128 | }
129 | catch (Exception ex)
130 | {
131 | Logger.Log("Run game failed with: " + ex.ToString());
132 | }
133 | }
134 |
135 | public override void ResizeEditor(uint newWidth, uint newHeight)
136 | {
137 | base.ResizeEditor(newWidth, newHeight);
138 |
139 | if (GameHost != null)
140 | {
141 | GameHost.RequestResize((int)newWidth, (int)newHeight);
142 | }
143 | }
144 |
145 |
146 | public override void HideEditor()
147 | {
148 | base.HideEditor();
149 |
150 | GameHost.Exit();
151 | }
152 |
153 | public override void InitializeProcessing()
154 | {
155 | base.InitializeProcessing();
156 |
157 | Logger.Log("Sample rate is: " + Host.SampleRate);
158 |
159 | StompboxClient.Init((float)Host.SampleRate);
160 | }
161 |
162 | public override byte[] SaveState()
163 | {
164 | byte[] data = null;
165 |
166 | try
167 | {
168 | data = System.Text.Encoding.ASCII.GetBytes(StompboxClient.GetProgramState());
169 | }
170 | catch (Exception ex)
171 | {
172 | Logger.Log("Save state failed with: " + ex.ToString());
173 | }
174 |
175 | return data;
176 | }
177 |
178 | string[] lineSeparator = new string[] { "\r", "\n" };
179 |
180 | public override void RestoreState(byte[] stateData)
181 | {
182 | String programString = System.Text.Encoding.ASCII.GetString(stateData);
183 |
184 | string[] commands = programString.Split(lineSeparator, 0);
185 |
186 | foreach (string command in commands)
187 | {
188 | if (!string.IsNullOrWhiteSpace(command))
189 | {
190 | StompboxClient.SendCommand(command);
191 | }
192 | }
193 |
194 | UpdateUI();
195 | }
196 |
197 | Stopwatch processWatch = new Stopwatch();
198 |
199 | void SendMidiCommand(int midiCommand, int midiData1, int midiData2)
200 | {
201 | Logger.Log("Send midi: " + midiCommand + " " + midiData1 + " " + midiData2);
202 |
203 | switch (midiCommand)
204 | {
205 | case 0x80:
206 | Host.SendNoteOff(1, midiData1, (float)midiData2 / 127.0f, 0);
207 | break;
208 | case 0x90:
209 | Host.SendNoteOn(1, midiData1, (float)midiData2 / 127.0f, 0);
210 | break;
211 | }
212 | }
213 |
214 | public override void Process()
215 | {
216 | StompboxClient.Process(((float**)monoInput.GetAudioBufferPtrs())[0], ((float**)monoOutput.GetAudioBufferPtrs())[0], monoInput.CurrentBufferSize);
217 | }
218 | }
219 | }
220 |
--------------------------------------------------------------------------------
/StompboxPlugin/StompboxPlugin.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net8.0-windows
4 | Library
5 | false
6 | true
7 | true
8 | true
9 | AllDisabledByDefault
10 | AnyCPU
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | TRACE;XNA
29 |
30 |
31 | TRACE;XNA
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/StompboxPlugin/Troubleshooting.md:
--------------------------------------------------------------------------------
1 | # Troubleshooting
2 |
3 | ## Installing
4 |
5 | Make sure that the ChartPlayer folder is installed where your DAW looks for VST3 plugins. Normally this is "**C:\Program Files\Common Files\VST3**".
6 |
7 | Also ensure that you have .NET 8.0 installed on your system. You can get it here:
8 |
9 | https://dotnet.microsoft.com/en-us/download/dotnet/8.0
10 |
11 | ## Stompbox Plugin Doesn't Scan in DAW
12 |
13 | If your DAW isn't loading the plugin, first make sure that you had it re-scan plugins after installing .net 8.0
14 |
15 | If you are still having trouble, please check for log files here:
16 |
17 | "**%appdata%\AudioPlugSharp**"
18 |
19 | Error messages here can help track down the problem.
20 |
21 | ## Reporting Problems
22 |
23 | If you are having trouble, please get in touch. The best way is through opening an issue or a discussion here on GitHub.
24 |
--------------------------------------------------------------------------------
/StompboxRemote/.config/dotnet-tools.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": 1,
3 | "isRoot": true,
4 | "tools": {
5 | "dotnet-mgcb": {
6 | "version": "3.8.1.303",
7 | "commands": [
8 | "mgcb"
9 | ]
10 | },
11 | "dotnet-mgcb-editor": {
12 | "version": "3.8.1.303",
13 | "commands": [
14 | "mgcb-editor"
15 | ]
16 | },
17 | "dotnet-mgcb-editor-linux": {
18 | "version": "3.8.1.303",
19 | "commands": [
20 | "mgcb-editor-linux"
21 | ]
22 | },
23 | "dotnet-mgcb-editor-windows": {
24 | "version": "3.8.1.303",
25 | "commands": [
26 | "mgcb-editor-windows"
27 | ]
28 | },
29 | "dotnet-mgcb-editor-mac": {
30 | "version": "3.8.1.303",
31 | "commands": [
32 | "mgcb-editor-mac"
33 | ]
34 | }
35 | }
36 | }
--------------------------------------------------------------------------------
/StompboxRemote/Icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikeoliphant/StompboxUI/8dc3bdc26e1513bb0ef88e4f925863b903655937/StompboxRemote/Icon.ico
--------------------------------------------------------------------------------
/StompboxRemote/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Stompbox;
3 | using StompboxAPI;
4 | using UILayout;
5 |
6 | RemoteClient client = new();
7 |
8 | InterfaceBase.InterfaceType = EStompboxInterfaceType.DAW;
9 |
10 | StompboxLayout game = new StompboxLayout();
11 |
12 | int width = 1000;
13 | int height = 540;
14 |
15 | if (InterfaceBase.InterfaceType == EStompboxInterfaceType.Mobile)
16 | {
17 | width = 540;
18 | height = 960;
19 | }
20 | else if (InterfaceBase.InterfaceType == EStompboxInterfaceType.Pedalboard)
21 | {
22 | width = 960;
23 | height = 540;
24 | }
25 |
26 | using (MonoGameHost GameHost = new MonoGameHost(width, height, fullscreen: false))
27 | {
28 | GameHost.IsMouseVisible = true;
29 | GameHost.StartGame(game);
30 |
31 | client.Disconnect();
32 | }
33 |
34 |
--------------------------------------------------------------------------------
/StompboxRemote/StompboxRemote.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | WinExe
4 | net8.0-windows
5 | Major
6 | false
7 | false
8 | true
9 |
10 |
11 | app.manifest
12 | Icon.ico
13 | True
14 |
15 |
16 | $(DefineConstants);STOMPBOXREMOTE
17 |
18 |
19 | $(DefineConstants);STOMPBOXREMOTE
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/StompboxRemote/app.manifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 | true/pm
39 | permonitorv2,permonitor
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/StompboxRemoteGL/.config/dotnet-tools.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": 1,
3 | "isRoot": true,
4 | "tools": {
5 | "dotnet-mgcb": {
6 | "version": "3.8.1.303",
7 | "commands": [
8 | "mgcb"
9 | ]
10 | },
11 | "dotnet-mgcb-editor": {
12 | "version": "3.8.1.303",
13 | "commands": [
14 | "mgcb-editor"
15 | ]
16 | },
17 | "dotnet-mgcb-editor-linux": {
18 | "version": "3.8.1.303",
19 | "commands": [
20 | "mgcb-editor-linux"
21 | ]
22 | },
23 | "dotnet-mgcb-editor-windows": {
24 | "version": "3.8.1.303",
25 | "commands": [
26 | "mgcb-editor-windows"
27 | ]
28 | },
29 | "dotnet-mgcb-editor-mac": {
30 | "version": "3.8.1.303",
31 | "commands": [
32 | "mgcb-editor-mac"
33 | ]
34 | }
35 | }
36 | }
--------------------------------------------------------------------------------
/StompboxRemoteGL/Icon.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikeoliphant/StompboxUI/8dc3bdc26e1513bb0ef88e4f925863b903655937/StompboxRemoteGL/Icon.bmp
--------------------------------------------------------------------------------
/StompboxRemoteGL/Icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mikeoliphant/StompboxUI/8dc3bdc26e1513bb0ef88e4f925863b903655937/StompboxRemoteGL/Icon.ico
--------------------------------------------------------------------------------
/StompboxRemoteGL/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Stompbox;
3 | using StompboxAPI;
4 | using UILayout;
5 |
6 | RemoteClient client = new RemoteClient();
7 |
8 | //client.MidiCallback = SendMidiCommand;
9 |
10 | StompboxLayout game = new StompboxLayout();
11 |
12 | //game.SetScreenScale(scale, resizeScreen: true);
13 |
14 | //int width = 540;
15 | //int height = 960;
16 | int width = 1024;
17 | int height = 640;
18 |
19 | using (MonoGameHost GameHost = new MonoGameHost(width, height, fullscreen: false))
20 | {
21 | GameHost.IsMouseVisible = true;
22 | GameHost.StartGame(game);
23 |
24 | client.Disconnect();
25 | }
26 |
--------------------------------------------------------------------------------
/StompboxRemoteGL/StompboxRemoteGL.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | WinExe
4 | net8.0
5 | Major
6 | false
7 | false
8 |
9 |
10 | app.manifest
11 | Icon.ico
12 |
13 |
14 | $(DefineConstants);STOMPBOXREMOTE
15 |
16 |
17 | $(DefineConstants);STOMPBOXREMOTE
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/StompboxRemoteGL/app.manifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 | true/pm
39 | permonitorv2,permonitor
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/StompboxShared/Content/Content.mgcb:
--------------------------------------------------------------------------------
1 |
2 | #----------------------------- Global Properties ----------------------------#
3 |
4 | /outputDir:bin/$(Platform)
5 | /intermediateDir:obj/$(Platform)
6 | /platform:Windows
7 | /config:
8 | /profile:Reach
9 | /compress:False
10 |
11 | #-------------------------------- References --------------------------------#
12 |
13 |
14 | #---------------------------------- Content ---------------------------------#
15 |
16 | #begin Textures/ImageManifest.xml
17 | /copy:Textures/ImageManifest.xml
18 |
19 | #begin Textures/UISheet0.png
20 | /importer:TextureImporter
21 | /processor:TextureProcessor
22 | /processorParam:ColorKeyColor=255,0,255,255
23 | /processorParam:ColorKeyEnabled=True
24 | /processorParam:GenerateMipmaps=True
25 | /processorParam:PremultiplyAlpha=True
26 | /processorParam:ResizeToPowerOfTwo=False
27 | /processorParam:MakeSquare=False
28 | /processorParam:TextureFormat=Color
29 | /build:Textures/UISheet0.png
30 |
31 |
--------------------------------------------------------------------------------
/StompboxShared/Content/Textures/.gitignore:
--------------------------------------------------------------------------------
1 | # Ignore everything in this directory
2 | *
3 | # Except this file
4 | !.gitignore
--------------------------------------------------------------------------------
/StompboxShared/Interface/AudioFilePlayerInterface.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using UILayout;
3 | using Stompbox;
4 |
5 | namespace Stompbox
6 | {
7 | public class AudioFilePlayerInterface : PluginInterface
8 | {
9 | public AudioFilePlayerInterface(IAudioPlugin plugin)
10 | : base(plugin)
11 | {
12 |
13 | }
14 |
15 | protected override void AddControls(Dock dock)
16 | {
17 | VerticalStack vStack = new VerticalStack { HorizontalAlignment = EHorizontalAlignment.Stretch, VerticalAlignment = EVerticalAlignment.Stretch, ChildSpacing = 5 };
18 | dock.Children.Add(vStack);
19 |
20 | vStack.Children.Add(new TextBlock(Plugin.Name) { HorizontalAlignment = EHorizontalAlignment.Center, TextColor = foregroundColor });
21 |
22 | vStack.Children.Add(CreateFileControl(Plugin.Parameters[0]));
23 |
24 | UIElement levelControl = CreateControl(Plugin.Parameters[1]);
25 | levelControl.HorizontalAlignment = EHorizontalAlignment.Center;
26 |
27 | vStack.Children.Add(levelControl);
28 |
29 | HorizontalStack controlStack = new HorizontalStack { HorizontalAlignment = EHorizontalAlignment.Center, ChildSpacing = 5 };
30 | vStack.Children.Add(controlStack);
31 |
32 | ImageToggleButton playButton = new ImageToggleButton("Stop", "Play")
33 | {
34 | HorizontalAlignment = EHorizontalAlignment.Center,
35 | };
36 |
37 | playButton.PressAction = delegate
38 | {
39 | Plugin.Enabled = playButton.IsPressed;
40 | Plugin.GetParameter("Playing").Value = playButton.IsPressed ? 1 : 0;
41 | };
42 |
43 | playButton.SetPressed(Plugin.GetParameter("Playing").Value == 1);
44 |
45 | playButton.ImageColor = foregroundColor;
46 |
47 | controlStack.Children.Add(playButton);
48 |
49 | controlStack.Children.Add(new ImageButton("Restart")
50 | {
51 | ImageColor = foregroundColor,
52 | PressAction = delegate
53 | {
54 | StompboxClient.Instance.SendCommand("SetParam " + Plugin.ID + " Position 0");
55 | }
56 | });
57 |
58 | controlStack.Children.Add(new ImageButton("Record")
59 | {
60 | ImageColor = UIColor.Red,
61 | PressAction = delegate
62 | {
63 | StompboxClient.Instance.SendCommand("SendCommand " + Plugin.ID + " ArmRecord");
64 | }
65 | });
66 | }
67 | }
68 | }
--------------------------------------------------------------------------------
/StompboxShared/Interface/AudioFileRecorderInterface.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Timers;
3 | using UILayout;
4 | using Stompbox;
5 |
6 | namespace Stompbox
7 | {
8 | public class AudioFileRecorderInterface : PluginInterface
9 | {
10 | TextBlock recordTimeText;
11 | Timer recordTimer;
12 | DateTime startTime;
13 |
14 | public AudioFileRecorderInterface(IAudioPlugin plugin)
15 | : base(plugin)
16 | {
17 | recordTimer = new Timer(1000);
18 | recordTimer.Elapsed += RecordTimer_Elapsed;
19 | recordTimer.Start();
20 |
21 | startTime = DateTime.Now;
22 | }
23 |
24 | protected override void AddControls(Dock dock)
25 | {
26 | VerticalStack vStack = new VerticalStack { HorizontalAlignment = EHorizontalAlignment.Stretch, VerticalAlignment = EVerticalAlignment.Stretch, ChildSpacing = 5 };
27 | dock.Children.Add(vStack);
28 |
29 | vStack.Children.Add(new TextBlock(Plugin.Name) { HorizontalAlignment = EHorizontalAlignment.Center, TextColor = foregroundColor });
30 |
31 | recordTimeText = new TextBlock("-----") { HorizontalAlignment = EHorizontalAlignment.Center, VerticalAlignment = EVerticalAlignment.Stretch, TextColor = foregroundColor };
32 | vStack.Children.Add(recordTimeText);
33 |
34 | HorizontalStack controlStack = new HorizontalStack { HorizontalAlignment = EHorizontalAlignment.Center, VerticalAlignment = EVerticalAlignment.Stretch, ChildSpacing = 5 };
35 | vStack.Children.Add(controlStack);
36 |
37 | controlStack.Children.Add(new ImageButton("Record")
38 | {
39 | VerticalAlignment = EVerticalAlignment.Center,
40 | ImageColor = UIColor.Red,
41 | PressAction = delegate
42 | {
43 | StompboxClient.Instance.SendCommand("SendCommand " + Plugin.ID + " Save");
44 |
45 | startTime = DateTime.Now;
46 | }
47 | });
48 | }
49 |
50 | private void RecordTimer_Elapsed(object sender, ElapsedEventArgs e)
51 | {
52 | int recordSecondsElapsed = (int)(e.SignalTime - startTime).TotalSeconds;
53 |
54 | recordTimeText.Text = (recordSecondsElapsed / 60).ToString("00") + ":" + (recordSecondsElapsed % 60).ToString("00");
55 |
56 | UpdateContentLayout();
57 | }
58 | }
59 | }
--------------------------------------------------------------------------------
/StompboxShared/Interface/DAWInterface.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Configuration.Internal;
4 | using System.Threading;
5 | using System.Threading.Tasks;
6 | using UILayout;
7 |
8 | namespace Stompbox
9 | {
10 | public class DAWInterface : InterfaceBase
11 | {
12 | PluginChainDisplay inputChainDisplay;
13 | PluginChainDisplay fxLoopDisplay;
14 | PluginChainDisplay outputChainDisplay;
15 |
16 | HorizontalStack topUIStack;
17 | VerticalStack programStack;
18 | HorizontalStack ampStack;
19 | EnumInterface currentProgramInterface;
20 | TextToggleButton midiToggleButton;
21 | StringBuilderTextBlock dspLoadText;
22 | UIElementWrapper tunerWrapper;
23 | UIElementWrapper audioFilePlayerWrapper;
24 |
25 | public DAWInterface()
26 | {
27 | Padding = new LayoutPadding(5);
28 | BackgroundColor = new UIColor(60, 60, 60);
29 |
30 | VerticalStack vStack = new VerticalStack
31 | {
32 | ChildSpacing = 10,
33 | HorizontalAlignment = EHorizontalAlignment.Stretch,
34 | VerticalAlignment = EVerticalAlignment.Stretch
35 | };
36 | Children.Add(vStack);
37 |
38 | topUIStack = new HorizontalStack { HorizontalAlignment = EHorizontalAlignment.Stretch };
39 | vStack.Children.Add(topUIStack);
40 |
41 | programStack = new VerticalStack { HorizontalAlignment = EHorizontalAlignment.Stretch, VerticalAlignment = EVerticalAlignment.Center };
42 |
43 | programStack.Children.Add(new ImageElement("StompboxLogo")
44 | {
45 | HorizontalAlignment = EHorizontalAlignment.Center,
46 | VerticalAlignment = EVerticalAlignment.Center
47 | });
48 |
49 | HorizontalStack programHStack = new HorizontalStack() { ChildSpacing = 10, HorizontalAlignment = EHorizontalAlignment.Stretch };
50 | programStack.Children.Add(programHStack);
51 |
52 | currentProgramInterface = new EnumInterface(new List(), UIColor.Black)
53 | {
54 | NoSelectionText = "-- No Preset --",
55 | HorizontalAlignment = EHorizontalAlignment.Stretch,
56 | SelectionChangedAction = delegate (int index)
57 | {
58 | int currentPreset = currentProgramInterface.SelectedIndex;
59 |
60 | StompboxClient.Instance.CurrentPresetIndex = currentPreset;
61 |
62 | //if (currentPreset != -1)
63 | //{
64 | // StompboxClient.Instance.SendCommand("LoadPreset " + currentProgramInterface.EnumValues[currentPreset]);
65 |
66 | // StompboxClient.Instance.UpdateProgram();
67 | //}
68 | }
69 | };
70 | programHStack.Children.Add(currentProgramInterface);
71 |
72 | HorizontalStack programHStack2 = new HorizontalStack() { ChildSpacing = 10, HorizontalAlignment = EHorizontalAlignment.Center }; ;
73 | programStack.Children.Add(programHStack2);
74 |
75 | programHStack2.Children.Add(new TextButton("Save")
76 | {
77 | ClickAction = delegate
78 | {
79 | if (currentProgramInterface.SelectedIndex == -1)
80 | DoSavePresetAs();
81 | else
82 | StompboxClient.Instance.SaveCurrentPreset();
83 | }
84 | });
85 | programHStack2.Children.Add(new TextButton("Save As")
86 | {
87 | ClickAction = delegate
88 | {
89 | DoSavePresetAs();
90 | }
91 | });
92 | programHStack2.Children.Add(new TextButton("Delete")
93 | {
94 | ClickAction = delegate
95 | {
96 | if (currentProgramInterface.SelectedIndex != -1)
97 | {
98 | Layout.Current.ShowConfirmationPopup("Are you sure you want to\ndelete this preset?",
99 | delegate
100 | {
101 | StompboxClient.Instance.DeleteCurrentPreset();
102 | });
103 | }
104 | }
105 | });
106 |
107 | HorizontalStack programHStack3 = new HorizontalStack() { ChildSpacing = 10, HorizontalAlignment = EHorizontalAlignment.Center }; ;
108 | programStack.Children.Add(programHStack3);
109 |
110 | programHStack3.Children.Add(new TextButton("Save Settings")
111 | {
112 | ClickAction = delegate
113 | {
114 | StompboxClient.Instance.SendCommand("SaveSettings");
115 | }
116 | });
117 |
118 |
119 | HorizontalStack buttonStack = new HorizontalStack { HorizontalAlignment = EHorizontalAlignment.Center };
120 | programStack.Children.Add(buttonStack);
121 |
122 | midiToggleButton = new TextToggleButton("Midi On", "Midi Off")
123 | {
124 | PressAction = ToggleMidi
125 | };
126 |
127 | midiToggleButton.SetPressed(true);
128 |
129 | buttonStack.Children.Add(midiToggleButton);
130 |
131 |
132 | ampStack = new HorizontalStack { HorizontalAlignment = EHorizontalAlignment.Center }; //, BackgroundColor = UIColor.FromHex("#b5893c") };
133 |
134 | HorizontalStack row2Stack = new HorizontalStack { HorizontalAlignment = EHorizontalAlignment.Stretch };
135 | vStack.Children.Add(row2Stack);
136 |
137 | row2Stack.Children.Add(tunerWrapper = new UIElementWrapper());
138 |
139 | row2Stack.Children.Add(inputChainDisplay = new PluginChainDisplay("Input", miniMode: false) { HorizontalAlignment = EHorizontalAlignment.Center });
140 |
141 | HorizontalStack row3Stack = new HorizontalStack { HorizontalAlignment = EHorizontalAlignment.Stretch };
142 | vStack.Children.Add(row3Stack);
143 |
144 | row3Stack.Children.Add(audioFilePlayerWrapper = new UIElementWrapper());
145 |
146 | HorizontalStack loopOutputStack = new HorizontalStack { HorizontalAlignment = EHorizontalAlignment.Center, ChildSpacing = 50 };
147 | row3Stack.Children.Add(loopOutputStack);
148 |
149 | loopOutputStack.Children.Add(fxLoopDisplay = new PluginChainDisplay("FxLoop", miniMode: false) { HorizontalAlignment = EHorizontalAlignment.Left });
150 | loopOutputStack.Children.Add(outputChainDisplay = new PluginChainDisplay("Output", miniMode: false) { HorizontalAlignment = EHorizontalAlignment.Left });
151 |
152 | if (StompboxClient.Instance.InClientMode)
153 | {
154 | dspLoadText = new StringBuilderTextBlock("---") { HorizontalAlignment = EHorizontalAlignment.Left, VerticalAlignment = EVerticalAlignment.Bottom };
155 | Children.Add(dspLoadText);
156 |
157 | Children.Add(new ExtraOptionsButton(EStompboxInterfaceType.DAW)
158 | {
159 | HorizontalAlignment = EHorizontalAlignment.Right,
160 | VerticalAlignment = EVerticalAlignment.Bottom,
161 | });
162 | }
163 | }
164 |
165 | protected override void DrawContents()
166 | {
167 | base.DrawContents();
168 |
169 | float desiredScale = (Layout.Current as MonoGameLayout).UnscaledBounds.Height / 1600.0f;
170 |
171 | if (StompboxLayout.Instance.Scale != desiredScale)
172 | StompboxLayout.Instance.Scale = desiredScale;
173 |
174 | if (StompboxClient.Instance.NeedUIReload)
175 | {
176 | UpdateUI();
177 |
178 | StompboxClient.Instance.NeedUIReload = false;
179 | }
180 |
181 | if (StompboxClient.Instance.InClientMode)
182 | {
183 | UpdateDSPLoad(StompboxClient.Instance.MaxDSPLoad, StompboxClient.Instance.MinDSPLoad);
184 | }
185 | }
186 |
187 | void ToggleMidi()
188 | {
189 | StompboxClient.Instance.SendCommand("MidiLock" + (midiToggleButton.IsPressed ? "On" : "Off"));
190 | }
191 |
192 | public void UpdateUI()
193 | {
194 | ampStack.Children.Clear();
195 |
196 | AddAmpPlugin("Amp");
197 | AddAmpPlugin("Tonestack");
198 | AddAmpPlugin("Cabinet");
199 |
200 | topUIStack.Children.Clear();
201 |
202 | topUIStack.Children.Add(programStack);
203 |
204 | topUIStack.Children.Add(new GainPluginInterface(StompboxClient.Instance.PluginFactory.CreatePlugin("Input")));
205 |
206 | topUIStack.Children.Add(ampStack);
207 |
208 | topUIStack.Children.Add(new GainPluginInterface(StompboxClient.Instance.PluginFactory.CreatePlugin("Master")));
209 |
210 | tunerWrapper.Child = new TunerInterface(StompboxClient.Instance.PluginFactory.CreatePlugin("Tuner"));
211 | audioFilePlayerWrapper.Child = new AudioFilePlayerInterface(StompboxClient.Instance.PluginFactory.CreatePlugin("AudioFilePlayer"));
212 |
213 | inputChainDisplay.SetChain(StompboxClient.Instance.GetChain("Input"));
214 | fxLoopDisplay.SetChain(StompboxClient.Instance.GetChain("FxLoop"));
215 | outputChainDisplay.SetChain(StompboxClient.Instance.GetChain("Output"));
216 |
217 | currentProgramInterface.SetEnumValues(StompboxClient.Instance.PresetNames);
218 | currentProgramInterface.SetSelectedIndex(StompboxClient.Instance.CurrentPresetIndex);
219 |
220 | UpdateContentLayout();
221 | }
222 |
223 | void AddAmpPlugin(string slotName)
224 | {
225 | IAudioPlugin plugin = StompboxClient.Instance.PluginFactory.CreatePlugin(StompboxClient.Instance.GetSlotPlugin(slotName));
226 |
227 | if (plugin == null)
228 | return;
229 |
230 | ampStack.Children.Add(new PluginInterface(plugin, slotName) { VerticalAlignment = EVerticalAlignment.Stretch });
231 | }
232 |
233 | public void UpdateDSPLoad(float maxDSPLoad, float minDSPLoad)
234 | {
235 | maxDSPLoad *= 100;
236 | minDSPLoad *= 100;
237 |
238 | dspLoadText.StringBuilder.Clear();
239 |
240 | int maxInt = (int)maxDSPLoad;
241 |
242 | dspLoadText.StringBuilder.AppendNumber(maxInt);
243 | dspLoadText.StringBuilder.Append('.');
244 | dspLoadText.StringBuilder.AppendNumber((int)Math.Round((maxDSPLoad - (float)maxInt) * 10));
245 | dspLoadText.StringBuilder.Append("%/");
246 |
247 | int minInt = (int)minDSPLoad;
248 |
249 | dspLoadText.StringBuilder.AppendNumber(maxInt);
250 | dspLoadText.StringBuilder.Append('.');
251 | dspLoadText.StringBuilder.AppendNumber((int)Math.Round((minDSPLoad - (float)minInt) * 10));
252 | dspLoadText.StringBuilder.Append('%');
253 | }
254 | }
255 | }
256 |
--------------------------------------------------------------------------------
/StompboxShared/Interface/InterfaceBase.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using System.Threading.Tasks;
5 | using UILayout;
6 |
7 | namespace Stompbox
8 | {
9 | public enum EStompboxInterfaceType
10 | {
11 | DAW,
12 | Mobile,
13 | Pedalboard
14 | }
15 |
16 | public class InterfaceBase : Dock
17 | {
18 | public static EStompboxInterfaceType InterfaceType { get; set; } = EStompboxInterfaceType.DAW;
19 |
20 | protected void DoSavePresetAs()
21 | {
22 | Layout.Current.ShowTextInputPopup("File Name:", null, delegate (string presetName)
23 | {
24 | if (!string.IsNullOrEmpty(presetName))
25 | {
26 | StompboxClient.Instance.SavePresetAs(presetName);
27 | }
28 | });
29 | }
30 |
31 | public static InterfaceBase GetInterface()
32 | {
33 | switch (InterfaceType)
34 | {
35 | case EStompboxInterfaceType.DAW:
36 | return new DAWInterface();
37 | case EStompboxInterfaceType.Mobile:
38 | #if ANDROID
39 | Activity1.Instance.RequestedOrientation = Android.Content.PM.ScreenOrientation.UserPortrait;
40 | #endif
41 | return new MobileInterface();
42 | case EStompboxInterfaceType.Pedalboard:
43 | #if ANDROID
44 | Activity1.Instance.RequestedOrientation = Android.Content.PM.ScreenOrientation.UserLandscape;
45 | #endif
46 | return new PedalboardInterface();
47 | }
48 |
49 | throw new InvalidOperationException();
50 | }
51 |
52 | public static void SetInterfaceType(EStompboxInterfaceType interfaceType)
53 | {
54 | InterfaceType = interfaceType;
55 |
56 | StompboxLayout.Instance.RootUIElement = GetInterface();
57 | }
58 | }
59 |
60 | public class ExtraOptionsButton : ImageButton
61 | {
62 | public ExtraOptionsButton(EStompboxInterfaceType currentInterfaceType)
63 | : base("MoreButton")
64 | {
65 | ClickAction = delegate
66 | {
67 | Layout.Current.ShowPopup(new ExtraOptionsMenu(currentInterfaceType), ContentBounds.Center);
68 | };
69 | }
70 | }
71 |
72 | public class ExtraOptionsMenu : Menu
73 | {
74 | public ExtraOptionsMenu(EStompboxInterfaceType currentInterfaceType)
75 | {
76 | List