Skip to content

Commit fc9f9ec

Browse files
committed
Merge branch 'master' into synths/korg_triton
2 parents e5f832d + 783f4a9 commit fc9f9ec

77 files changed

Lines changed: 5111 additions & 244 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.dockerignore

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
.builds/
2+
.pytest_cache/
3+
.vscode/
4+
Builds/
5+
build/
6+
builds/
7+
node_modules/
8+
public/
9+
venv/
10+
venv*/
11+
12+
*.aps
13+
*.dmg
14+
*.exe
15+
*.msi
16+
Screenshot*.png
17+
youtube-screenshot.PNG
18+
*.tar.gz
19+
*.zip
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json
2+
3+
name: Arch Linux Docker Build
4+
5+
on:
6+
push:
7+
pull_request:
8+
9+
jobs:
10+
build-archlinux-docker:
11+
runs-on: ubuntu-24.04
12+
timeout-minutes: 90
13+
steps:
14+
- name: Checkout repository with tags and submodules
15+
uses: actions/checkout@v4
16+
with:
17+
fetch-depth: 0
18+
submodules: recursive
19+
20+
- name: Build Arch Linux Docker image
21+
run: docker build --pull -f docker/archlinux/Dockerfile -t knobkraft-orm-arch .
22+
23+
- name: Verify executable can be copied from the image
24+
run: |
25+
container_id=$(docker create knobkraft-orm-arch)
26+
docker cp "$container_id:/KnobKraft-orm/builds/The-Orm/KnobKraftOrm" ./KnobKraftOrm-arch
27+
docker rm "$container_id"
28+
test -s ./KnobKraftOrm-arch

.github/workflows/builds-windows.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ jobs:
9797
- name: Prepare update key and generate code signature
9898
if: startsWith(github.ref, 'refs/tags/')
9999
run: |
100-
builds\_deps\winsparkle-src\bin\sign_update.bat Builds/The-Orm/knobkraft_orm_setup_${{env.ORM_VERSION}}.exe ${{ steps.extract_pem.outputs.SECRET_FILE }} > update.sig
100+
.\builds\_deps\winsparkle-src\bin\legacy_sign_update.bat Builds/The-Orm/knobkraft_orm_setup_${{env.ORM_VERSION}}.exe ${{ steps.extract_pem.outputs.SECRET_FILE }} > update.sig
101101
type update.sig
102102
103103
- name: Update appcast.xml to add the new release

CMakeLists.txt

Lines changed: 78 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ IF (WIN32)
7979
include(FetchContent REQUIRED)
8080

8181
FetchContent_Declare(
82-
icu URL https://github.com/unicode-org/icu/releases/download/release-74-2/icu4c-74_2-Win64-MSVC2019.zip
82+
icu URL https://github.com/unicode-org/icu/releases/download/release-78.3/icu4c-78.3-Win64-MSVC2022.zip
8383
)
8484
FetchContent_MakeAvailable(icu)
8585

@@ -110,7 +110,7 @@ IF (WIN32)
110110

111111
FetchContent_Declare(
112112
winsparkle
113-
URL https://github.com/vslavik/winsparkle/releases/download/v0.7.0/WinSparkle-0.7.0.zip
113+
URL https://github.com/vslavik/winsparkle/releases/download/v0.9.2/WinSparkle-0.9.2.zip
114114
)
115115
FetchContent_MakeAvailable(winsparkle)
116116
set(WINSPARKLE_INCLUDE "${CMAKE_CURRENT_BINARY_DIR}/_deps/winsparkle-src/include")
@@ -165,7 +165,73 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
165165
set(MANUALLY_RAPID_JSON "${CMAKE_CURRENT_LIST_DIR}/third_party/rapidjson/include")
166166

167167
# Setup pybind11
168-
set(PYTHON_EXECUTABLE "python3" CACHE STRING "Specify the Python executable location to be used. This must match the PYTHON_VERSION_TO_USE option. Default is just python3 expecting it on the path")
168+
# Try to find Python executable with fallback from python3 to python
169+
if(NOT PYTHON_EXECUTABLE)
170+
# Try python3 first
171+
find_program(PYTHON3_EXECUTABLE python3)
172+
if(PYTHON3_EXECUTABLE)
173+
execute_process(
174+
COMMAND ${PYTHON3_EXECUTABLE} --version
175+
RESULT_VARIABLE PYTHON3_CHECK_RESULT
176+
OUTPUT_VARIABLE PYTHON3_VERSION_OUTPUT
177+
ERROR_VARIABLE PYTHON3_VERSION_ERROR
178+
)
179+
if(NOT PYTHON3_CHECK_RESULT)
180+
# Check if it's Python 3.12+
181+
set(PYTHON3_VERSION_STRING "${PYTHON3_VERSION_OUTPUT}${PYTHON3_VERSION_ERROR}")
182+
if(PYTHON3_VERSION_STRING MATCHES "Python ([0-9]+)\\.([0-9]+)")
183+
set(PYTHON3_DETECTED_MAJOR ${CMAKE_MATCH_1})
184+
set(PYTHON3_DETECTED_MINOR ${CMAKE_MATCH_2})
185+
set(PYTHON3_DETECTED_VERSION "${PYTHON3_DETECTED_MAJOR}.${PYTHON3_DETECTED_MINOR}")
186+
if(PYTHON3_DETECTED_MAJOR EQUAL 3 AND PYTHON3_DETECTED_VERSION VERSION_GREATER_EQUAL "3.12")
187+
set(PYTHON_EXECUTABLE "${PYTHON3_EXECUTABLE}" CACHE STRING "Specify the Python executable location to be used. This must match the PYTHON_VERSION_TO_EMBED option.")
188+
else()
189+
message(WARNING "Found 'python3' but it is version ${PYTHON3_DETECTED_VERSION}, which is less than the required 3.12. Will try 'python' as fallback.")
190+
endif()
191+
else()
192+
message(WARNING "Found 'python3' but could not determine its version. Will try 'python' as fallback.")
193+
endif()
194+
endif()
195+
unset(PYTHON3_EXECUTABLE CACHE)
196+
endif()
197+
198+
# If python3 didn't work, try python (but verify it's Python 3, not Python 2)
199+
if(NOT PYTHON_EXECUTABLE)
200+
find_program(PYTHON_EXECUTABLE_CANDIDATE python)
201+
if(PYTHON_EXECUTABLE_CANDIDATE)
202+
execute_process(
203+
COMMAND ${PYTHON_EXECUTABLE_CANDIDATE} --version
204+
RESULT_VARIABLE PYTHON_CHECK_RESULT
205+
OUTPUT_VARIABLE PYTHON_VERSION_OUTPUT
206+
ERROR_VARIABLE PYTHON_VERSION_ERROR
207+
)
208+
if(NOT PYTHON_CHECK_RESULT)
209+
# Check if it's Python 3.12+ (not Python 2 or older Python 3)
210+
set(PYTHON_VERSION_STRING "${PYTHON_VERSION_OUTPUT}${PYTHON_VERSION_ERROR}")
211+
if(PYTHON_VERSION_STRING MATCHES "Python ([0-9]+)\\.([0-9]+)")
212+
set(PYTHON_DETECTED_MAJOR ${CMAKE_MATCH_1})
213+
set(PYTHON_DETECTED_MINOR ${CMAKE_MATCH_2})
214+
set(PYTHON_DETECTED_VERSION "${PYTHON_DETECTED_MAJOR}.${PYTHON_DETECTED_MINOR}")
215+
if(PYTHON_DETECTED_MAJOR EQUAL 3 AND PYTHON_DETECTED_VERSION VERSION_GREATER_EQUAL "3.12")
216+
set(PYTHON_EXECUTABLE "${PYTHON_EXECUTABLE_CANDIDATE}" CACHE STRING "Specify the Python executable location to be used. This must match the PYTHON_VERSION_TO_EMBED option. Fallback to python as python3 was not found.")
217+
else()
218+
# python points to Python 2 or Python 3 < 3.12, reject it
219+
message(WARNING "Found 'python' but it is version ${PYTHON_DETECTED_VERSION}, which is less than the required 3.12. Please install Python 3.12 or later and ensure 'python3' is available.")
220+
endif()
221+
else()
222+
# Could not parse version, reject it
223+
message(WARNING "Found 'python' but could not determine its version. Please install Python 3.12 or later and ensure 'python3' is available.")
224+
endif()
225+
endif()
226+
unset(PYTHON_EXECUTABLE_CANDIDATE CACHE)
227+
endif()
228+
endif()
229+
230+
# If still not found, provide helpful error
231+
if(NOT PYTHON_EXECUTABLE)
232+
message(FATAL_ERROR "Could not find a working Python executable (tried python3 and python). Please install Python 3.12 or later and ensure it is in your PATH.")
233+
endif()
234+
endif()
169235
IF(WIN32)
170236
message("USING PYTHON ${PYTHON_EXECUTABLE}")
171237
ELSE()
@@ -201,10 +267,10 @@ ENDIF()
201267
# CPack installer on macOS.
202268
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/third_party/SQLiteCpp EXCLUDE_FROM_ALL)
203269

204-
# Adding JUCE 6.0
270+
# Adding JUCE
205271
add_subdirectory("third_party/JUCE" EXCLUDE_FROM_ALL)
206272

207-
# Adding JUCE modules
273+
# Adding more third party modules
208274
add_subdirectory("third_party/")
209275

210276
# Build a static library from juce
@@ -293,7 +359,13 @@ add_subdirectory(The-Orm)
293359

294360
option(BUILD_PATCH_DATABASE_TESTS "Build the PatchDatabase doctest binary" OFF)
295361
if(BUILD_PATCH_DATABASE_TESTS)
296-
add_executable(patch_database_migration_test tests/patch_database_migration_test.cpp)
362+
add_executable(patch_database_migration_test
363+
tests/patch_database_migration_test.cpp
364+
tests/patch_list_fill_test.cpp
365+
tests/patch_database_search_test.cpp
366+
tests/user_bank_save_test.cpp
367+
tests/test_helpers.h
368+
The-Orm/UserBankFactory.cpp)
297369
target_include_directories(patch_database_migration_test PRIVATE
298370
${CMAKE_CURRENT_LIST_DIR}
299371
${CMAKE_CURRENT_LIST_DIR}/MidiKraft
@@ -303,5 +375,3 @@ if(BUILD_PATCH_DATABASE_TESTS)
303375
${CMAKE_CURRENT_LIST_DIR}/third_party/SQLiteCpp/include)
304376
target_link_libraries(patch_database_migration_test PRIVATE midikraft-database SQLiteCpp)
305377
endif()
306-
307-

README.md

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,15 @@ Questions and help with implementing new synths wanted! Or if you have found a b
4343
| Kawai | K1/K1m/K1r | beta | adaptation | |
4444
| Kawai | K3/K3m | works | native | |
4545
| Kawai | K4 | alpha | adaptation | |
46+
| Kawai | K5000 | beta | adaptation | Heroic effort by @markusschlosser! Most complex! |
4647
| Korg | 03R/W | works | adaptation | Thanks to Philippe! |
4748
| Korg | DW-6000 | works | adaptation | |
4849
| Korg | DW-8000/EX-8000 | works | adaptation | |
4950
| Korg | M1 | works | adaptation | Thanks to Jentusalentu at YT for giving the nudge |
5051
| Korg | microKORG S | works | adaptation | Thanks to @ilantz! |
5152
| Korg | Minilogue XD | works | adaptation | Thanks to @andy2no|
5253
| Korg | MS2000/microKORG | works | adaptation | Thanks to @windo|
54+
| Korg | R3 | alpha | adaptation | 100% AI generated |
5355
| Line 6 | POD Series | works | adaptation | Thanks to @milnak! |
5456
| Moog | Voyager | works | adaptation | Thanks to @troach242 for the nudge and test! |
5557
| Novation | AStation/KStation | beta | adaptation | Thanks to @thechildofroth |
@@ -66,11 +68,14 @@ Questions and help with implementing new synths wanted! Or if you have found a b
6668
| Roland | JX-8P | alpha | adaptation | |
6769
| Roland | Juno-DS | works | adaptation | contributed by @mslinn! Thank you! |
6870
| Roland | D-50 | works | adaptation | Shout out to @summersetter for testing! |
71+
| Roland | JD-Xi | alpha | adaptation | 100% AI generated |
6972
| Roland | JV-80/880/90/1000 | beta | adaptation | |
7073
| Roland | JV-1080/2080 | beta | adaptation | |
7174
| Roland | MKS-50 | alpha | native | |
7275
| Roland | MKS-70 (Vecoven) | beta | adaptation | Thanks to @markusschloesser!|
7376
| Roland | MKS-80 | works | native | |
77+
| Roland | SE-02 | beta | adaptation | Thanks to @MammaScan! |
78+
| Roland | U-20/U-220 | alpha | adaptation | 100% AI generated. Thanks to @Casuallynoted for testing! |
7479
| Roland | V-Drums TD-07 | alpha | adaptation | |
7580
| Roland | XV-3080/5080/5050 | works | adaptation | |
7681
| Sequential| Pro 3 | works | adaptation | |
@@ -174,7 +179,7 @@ This will produce the executable in the path `builds\The-Orm\Release`, namely a
174179

175180
## Building on Linux
176181

177-
See the azure-pipelines.yml file for some hints how the Ubuntu server is doing it. Mainly, you need to install a long list of prerequisites and development libraries:
182+
See the GitHub Actions workflow files for some hints how the Ubuntu server is doing it. Mainly, you need to install a long list of prerequisites and development libraries:
178183

179184
sudo apt-get -y update && sudo apt-get install -y libcurl4-openssl-dev pkg-config libtbb-dev libasound2-dev libboost-dev libgtk-3-dev libwebkit2gtk-4.0-dev libglew-dev libjack-dev libicu-dev libpython3-all-dev
180185

@@ -187,6 +192,25 @@ This will produce a single executable `builds/The-Orm/KnobKraftOrm` that you can
187192

188193
The LDFLAGS is required for a certain combination of gcc version/pybind11, else you will run into internal compiler errors. See issue #6 for a discussion.
189194

195+
## Building on Arch Linux with Docker
196+
197+
If you are running Arch Linux (or an Arch derivative) and the release binary fails due to library mismatches, you can build an Arch-linked binary in Docker using `docker/archlinux/Dockerfile`. This is based on the setup contributed in issue #319.
198+
199+
Clone the repository with submodules and build the Docker image from the repository root:
200+
201+
git clone --recurse-submodules https://github.com/christofmuc/KnobKraft-orm
202+
cd KnobKraft-orm
203+
docker build -f docker/archlinux/Dockerfile -t knobkraft-orm-arch .
204+
205+
The Docker build compiles KnobKraft Orm and runs the PatchDatabase doctest binary. The resulting `KnobKraftOrm` executable is linked against Arch Linux libraries and is expected to run on Arch or Arch-derivative hosts only; for Debian, Ubuntu, Fedora, or other distributions, use the native Linux build instructions above or create a matching distro-specific Docker build instead. To copy the compiled application out of the image:
206+
207+
container_id=$(docker create knobkraft-orm-arch)
208+
docker cp "$container_id:/KnobKraft-orm/builds/The-Orm" ./The-Orm-arch
209+
docker rm "$container_id"
210+
./The-Orm-arch/KnobKraftOrm
211+
212+
The same Dockerfile is built by the `Arch Linux Docker Build` GitHub Action so the documented Arch build path is checked regularly.
213+
190214
## Building on macOS
191215

192216
If you are inclined to build on Mac, you know what you're doing. I'd recommend to install the build requisites via homebrew like this

The-Orm/CMakeLists.txt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ set(SOURCES
9393
SimplePatchGrid.cpp SimplePatchGrid.h
9494
SynthBankPanel.cpp SynthBankPanel.h
9595
UIModel.cpp UIModel.h
96+
UserBankFactory.cpp UserBankFactory.h
9697
VerticalPatchButtonList.cpp VerticalPatchButtonList.h
9798
win_resources.rc
9899
version.cpp.in
@@ -246,7 +247,7 @@ IF(WIN32)
246247
add_custom_command(
247248
TARGET KnobKraftOrm POST_BUILD
248249
COMMAND ${CMAKE_COMMAND} -E copy
249-
"${icu_SOURCE_DIR}/bin64/icuuc74.dll" "${icu_SOURCE_DIR}/bin64/icudt74.dll"
250+
"${icu_SOURCE_DIR}/bin64/icuuc78.dll" "${icu_SOURCE_DIR}/bin64/icudt78.dll"
250251
${SENTRY_DISTRIBUTION_FILES} ${WINSPARKLE_DISTRIBUTION_FILES}
251252
${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>)
252253
add_custom_command(
@@ -269,6 +270,12 @@ add_custom_command(TARGET KnobKraftOrm POST_BUILD
269270
-DNO_PYCACHE_DEST_DIR=$<TARGET_FILE_DIR:KnobKraftOrm>/roland
270271
-P ${CMAKE_SOURCE_DIR}/cmake/copy_without_pycache.cmake
271272
)
273+
add_custom_command(TARGET KnobKraftOrm POST_BUILD
274+
COMMAND ${CMAKE_COMMAND}
275+
-DNO_PYCACHE_SOURCE_DIR=${CMAKE_SOURCE_DIR}/adaptations/korg
276+
-DNO_PYCACHE_DEST_DIR=$<TARGET_FILE_DIR:KnobKraftOrm>/korg
277+
-P ${CMAKE_SOURCE_DIR}/cmake/copy_without_pycache.cmake
278+
)
272279
add_custom_command(TARGET KnobKraftOrm POST_BUILD
273280
COMMAND ${CMAKE_COMMAND}
274281
-DNO_PYCACHE_SOURCE_DIR=${CMAKE_SOURCE_DIR}/adaptations/knobkraft

The-Orm/CreateListDialog.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include "LayoutConstants.h"
1010
#include "SynthBank.h"
11+
#include "UserBankFactory.h"
1112

1213
#include "Capability.h"
1314
#include "HasBanksCapability.h"
@@ -205,7 +206,7 @@ void CreateListDialog::notifyResult()
205206
if (isBank_) {
206207
int bankSelected = bankValue_.getValue();
207208
bank_ = MidiBankNumber::fromZeroBase(bankSelected, midikraft::SynthBank::numberOfPatchesInBank(synth_, bankSelected));
208-
list_ = std::make_shared<midikraft::SynthBank>(name.toStdString(), synth_, bank_);
209+
list_ = knobkraft::createUserBank(synth_, bankSelected, name.toStdString());
209210
}
210211
else {
211212
list_ = std::make_shared<midikraft::PatchList>(name.toStdString());

The-Orm/MainComponent.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1110,7 +1110,7 @@ int MainComponent::findIndexOfTabWithNameEnding(TabbedComponent* mainTabs, Strin
11101110

11111111
void MainComponent::aboutBox()
11121112
{
1113-
String message = "This software is copyright 2020-2024 by Christof Ruch\n\n"
1113+
String message = "This software is copyright 2020-2026 by Christof Ruch\n\n"
11141114
"Released under dual license, by default under AGPL-3.0, but an MIT licensed version is available on request by the author\n"
11151115
"\n"
11161116
"The homepage of the project is https://github.com/christofmuc/KnobKraft-orm\n"

The-Orm/PatchButtonPanel.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,36 @@ void PatchButtonPanel::setPatches(std::vector<midikraft::PatchHolder> const &pat
246246
setupPageButtons();
247247
}
248248

249+
bool PatchButtonPanel::updateVisiblePatch(midikraft::PatchHolder const& patch)
250+
{
251+
for (size_t i = 0; i < patches_.size(); ++i) {
252+
auto& visiblePatch = patches_[i];
253+
bool sameMd5 = visiblePatch.md5() == patch.md5();
254+
bool sameSynth = (!visiblePatch.synth() || !patch.synth() || visiblePatch.synth()->getName() == patch.synth()->getName());
255+
if (sameMd5 && sameSynth) {
256+
visiblePatch = patch;
257+
258+
if (i < patchButtons_->size() && visiblePatch.patch() && visiblePatch.synth()) {
259+
auto displayMode = PatchHolderButton::getCurrentInfoForSynth(visiblePatch.synth()->getName());
260+
if (UIModel::instance()->multiMode_.multiSynthMode()) {
261+
displayMode = static_cast<PatchButtonInfo>(
262+
static_cast<int>(PatchButtonInfo::SubtitleSynth) | (static_cast<int>(displayMode) & static_cast<int>(PatchButtonInfo::CenterMask))
263+
);
264+
}
265+
patchButtons_->buttonWithIndex((int)i)->setPatchHolder(&visiblePatch, displayMode);
266+
refreshThumbnail((int)i);
267+
}
268+
else {
269+
// Fallback safety for incomplete data
270+
refresh(false);
271+
}
272+
return true;
273+
}
274+
}
275+
276+
return false;
277+
}
278+
249279
String PatchButtonPanel::createNameOfThubnailCacheFile(midikraft::PatchHolder const &patch) {
250280
File thumbnailCache = UIModel::getThumbnailDirectory().getChildFile(patch.md5() + ".kkc");
251281
return thumbnailCache.getFullPathName();

0 commit comments

Comments
 (0)