Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
082c776
feat: Linux support — fix LVGL filesystem, add AppImage packaging
matixan Apr 8, 2026
f8f8edb
feat: app manager + migrate apps to submodules
matixan Apr 8, 2026
c6e1386
feat: add app-registry.json to .gitignore
matixan Apr 8, 2026
adde703
feat: smart run script — auto-build if stale or missing
matixan Apr 8, 2026
d4e3d08
feat: add VSCode toolbar config (CP Tools + Run buttons)
matixan Apr 8, 2026
474bdb0
refactor: move crosspad-core and crosspad-gui to lib/
matixan Apr 8, 2026
39edb82
feat: App Store as separate repo + app management docs
matixan Apr 8, 2026
f8d7da0
fix: update crosspad-appstore — remove LVGL group freeze bug
matixan Apr 8, 2026
43ee040
feat: App Store dev-only + pending changes + build button
matixan Apr 8, 2026
d6be4c4
fix: make mixer optional — conditional compilation with __has_include
matixan Apr 8, 2026
993aaff
fix: update crosspad-appstore — MSVC _popen/_pclose/_execl
matixan Apr 8, 2026
eb36131
feat: add BLE MIDI support — scan, connect, bidirectional MIDI
matixan Apr 10, 2026
ccd0794
feat: Linux updater support + release app management info
matixan Apr 10, 2026
9c4f7e3
fix: update crosspad-appstore — hide self from app list
matixan Apr 10, 2026
983b059
fix: update crosspad-core submodule — rebase IBleMidi onto latest main
matixan Apr 10, 2026
f9b4bd8
fix: CI build — suppress SimpleBLE warnings on MSVC, add named app re…
matixan Apr 10, 2026
013449e
fix: also disable /WX for SimpleBLE on MSVC CI
matixan Apr 10, 2026
5239eb4
fix: exclude PortableKitLoader on MSVC — uses POSIX dirent.h
matixan Apr 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ jobs:
uses: actions/cache@v4
with:
path: build
key: cmake-build-${{ runner.os }}-${{ hashFiles('CMakeLists.txt', 'cmake/**', 'crosspad-core', 'crosspad-gui') }}
key: cmake-build-${{ runner.os }}-${{ hashFiles('CMakeLists.txt', 'cmake/**', 'lib/crosspad-core', 'lib/crosspad-gui') }}
restore-keys: cmake-build-${{ runner.os }}-

- name: Configure
Expand Down
45 changes: 36 additions & 9 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ jobs:
# Copy SDL2.dll from vcpkg installed dir
cp "$RUNVCPKG_VCPKG_ROOT/installed/x64-windows/bin/SDL2.dll" dist/CrossPad/
# Copy assets
cp -r crosspad-gui/assets dist/CrossPad/assets
cp -r lib/crosspad-gui/assets dist/CrossPad/assets

- name: Upload artifact
uses: actions/upload-artifact@v4
Expand Down Expand Up @@ -120,18 +120,44 @@ jobs:
- name: Build
run: cmake --build build

- name: Package
- name: Create AppImage icon
run: |
mkdir -p dist/CrossPad
cp bin/CrossPad dist/CrossPad/CrossPad
chmod +x dist/CrossPad/CrossPad
cp -r crosspad-gui/assets dist/CrossPad/assets
python3 -c "
from PIL import Image
img = Image.open('logo.png')
img.thumbnail((256, 256), Image.LANCZOS)
new_img = Image.new('RGBA', (256, 256), (0, 0, 0, 0))
x = (256 - img.width) // 2
y = (256 - img.height) // 2
new_img.paste(img, (x, y))
new_img.save('CrossPad.png')
"
Comment on lines +123 to +134

Copilot AI Apr 8, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The workflow uses from PIL import Image to generate CrossPad.png, but Pillow isn’t installed anywhere in the Linux job. On ubuntu-latest this will typically fail with ModuleNotFoundError: No module named 'PIL'. Install Pillow explicitly (e.g., sudo apt-get install -y python3-pil or python3 -m pip install --user pillow) before this step, or replace this with a tool that’s already installed on the runner.

Copilot uses AI. Check for mistakes.

- name: Build AppImage
run: |
# Download linuxdeploy
wget -q https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage
Comment on lines +138 to +139

Copilot AI Apr 8, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The release workflow downloads and executes linuxdeploy-x86_64.AppImage from the moving continuous URL without any pinning or checksum/signature verification. Since this job produces release artifacts, this is a supply-chain risk and also makes builds non-reproducible. Pin to a specific linuxdeploy release version and verify its SHA256 (or use a GitHub Action/release asset with integrity checking) before executing it.

Suggested change
# Download linuxdeploy
wget -q https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage
# Download pinned linuxdeploy release and verify integrity
LINUXDEPLOY_VERSION=1-alpha-20250213-2
LINUXDEPLOY_SHA256=YOUR_LINUXDEPLOY_SHA256_HERE
wget -q "https://github.com/linuxdeploy/linuxdeploy/releases/download/${LINUXDEPLOY_VERSION}/linuxdeploy-x86_64.AppImage"
echo "${LINUXDEPLOY_SHA256} linuxdeploy-x86_64.AppImage" | sha256sum -c -

Copilot uses AI. Check for mistakes.
chmod +x linuxdeploy-x86_64.AppImage

# Prepare AppDir
mkdir -p AppDir/usr/bin
cp bin/CrossPad AppDir/usr/bin/CrossPad
chmod +x AppDir/usr/bin/CrossPad
cp -r lib/crosspad-gui/assets AppDir/usr/bin/assets

# Build AppImage
export OUTPUT=CrossPad-Linux-x86_64.AppImage
./linuxdeploy-x86_64.AppImage \
--appdir=AppDir \
--desktop-file=CrossPad.desktop \
--icon-file=CrossPad.png \
--output=appimage

- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: CrossPad-Linux-x64
path: dist/CrossPad
path: CrossPad-Linux-x86_64.AppImage

release:
needs: [build-windows, build-linux]
Expand All @@ -149,11 +175,12 @@ jobs:
with:
name: CrossPad-Linux-x64
path: CrossPad-Linux-x64
merge-multiple: true

- name: Create archives
run: |
cd CrossPad-Windows-x64 && zip -r ../CrossPad-Windows-x64.zip . && cd ..
tar -czf CrossPad-Linux-x64.tar.gz -C CrossPad-Linux-x64 .
cp CrossPad-Linux-x64/CrossPad-Linux-x86_64.AppImage .

- name: Checkout (for changelog generation)
uses: actions/checkout@v4
Expand Down Expand Up @@ -209,7 +236,7 @@ jobs:
prerelease: ${{ steps.tag.outputs.prerelease == 'true' }}
files: |
CrossPad-Windows-x64.zip
CrossPad-Linux-x64.tar.gz
CrossPad-Linux-x86_64.AppImage

- name: Detect release type
id: release_type
Expand Down
8 changes: 6 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ bin/
.*/
!.github/

# VSCode
.vscode
# VSCode — ignore all except shared config
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json

# MacOS file
.DS_Store
Expand All @@ -23,3 +25,5 @@ _build_*.bat

# Screenshots (dev/test artifacts)
screenshots/
app-registry.json
apps.json
19 changes: 17 additions & 2 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,23 @@
path = FreeRTOS
url = https://github.com/FreeRTOS/FreeRTOS-Kernel.git
[submodule "crosspad-core"]
path = crosspad-core
path = lib/crosspad-core
url = https://github.com/CrossPad/crosspad-core.git
[submodule "crosspad-gui"]
path = crosspad-gui
path = lib/crosspad-gui
url = https://github.com/CrossPad/crosspad-gui.git
[submodule "src/apps/crosspad-piano"]
path = src/apps/crosspad-piano
url = https://github.com/CrossPad/crosspad-piano.git
[submodule "src/apps/crosspad-instructions"]
path = src/apps/crosspad-instructions
url = https://github.com/CrossPad/crosspad-instructions.git
[submodule "src/apps/crosspad-appstore"]
path = src/apps/crosspad-appstore
url = https://github.com/CrossPad/crosspad-appstore.git
[submodule "src/apps/crosspad-serial-monitor"]
path = src/apps/crosspad-serial-monitor
url = https://github.com/CrossPad/crosspad-serial-monitor.git
[submodule "src/apps/crosspad-mixer"]
path = src/apps/crosspad-mixer
url = https://github.com/CrossPad/crosspad-mixer.git
13 changes: 13 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"VsCodeTaskButtons.showCounter": false,
"VsCodeTaskButtons.tasks": [
{
"label": "$(package) CP Tools",
"task": "CrossPad: App Manager"
},
{
"label": "$(zap) Run",
"task": "CrossPad: Run"
}
]
}
28 changes: 28 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "CrossPad: App Manager",
"type": "shell",
"command": "python3",
"args": ["${workspaceFolder}/scripts/app_manager.py"],
"presentation": {
"reveal": "always",
"panel": "dedicated",
"focus": true
},
"problemMatcher": []
},
{
"label": "CrossPad: Run",
"type": "shell",
"command": "${workspaceFolder}/scripts/run.sh",
"presentation": {
"reveal": "always",
"panel": "dedicated",
"focus": true
},
"problemMatcher": []
}
]
}
41 changes: 40 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,15 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co

## Default Tools

**Always prefer CrossPad MCP tools** (`crosspad_build`, `crosspad_run`, `crosspad_screenshot`, `crosspad_log`, `crosspad_test`, etc.) over manual bash commands for building, running, testing, and interacting with the simulator. The MCP server handles MSVC environment setup, paths, and simulator communication automatically.
**Always prefer CrossPad MCP tools** over manual bash commands for building, running, testing, and interacting with the simulator. The MCP server handles MSVC/GCC environment setup, paths, and simulator communication automatically.

Key tools:
- `crosspad_build` — build/run/check simulator (`action: pc/pc_run/pc_check/pc_log`) and ESP-IDF firmware (`action: idf`)
- `crosspad_test` — run Catch2 tests (`action: run/scaffold`)
- `crosspad_sim` — screenshots, input, stats, settings (`action: screenshot/input/stats/settings_get/settings_set`)
- `crosspad_repo` — git status and submodule diffs (`action: status/diff`)
- `crosspad_code` — search symbols, query interfaces, list apps, scaffold (`action: search/interfaces/apps/scaffold`)
- `crosspad_apps` — app package manager (`action: list/install/remove/update/sync`)

## Project Overview

Expand Down Expand Up @@ -85,16 +93,47 @@ src/
PcApp.cpp — lightweight App class for launcher (no sequencer/CLI)
pc_platform.h — public API: pc_platform_init(), set_midi/audio/synth
lib/ml_synth/ — vendored ML_SynthTools FM synth engine
lib/crosspad-core/ — submodule: portable C++ library
lib/crosspad-gui/ — submodule: shared LVGL UI components
scripts/
app_manager.py — Python app manager (wrapper for crosspad-apps core)
run.sh — Smart build+run script
tools/mcp-server/ — MCP development server (TypeScript, 16 tools)
```

### Submodules

**Shared libraries** (in `lib/`):

- **crosspad-core**: Portable C++ library — AppRegistry, IEventBus, PadManager, PadLedController, CrosspadSettings (IKeyValueStore), Stm32MessageHandler, platform interfaces (IClock, IMidiOutput, ILedStrip, IAudioOutput, ISynthEngine). Originally an ESP-IDF component; sources are listed manually in CMakeLists.txt.
- **crosspad-gui**: LVGL UI components — theme, styles, launcher, status bar, widgets (keypad buttons, spinbox, radial menu, VU meter, file explorer, DFU panel, modals/toasts). Originally an ESP-IDF component; sources listed manually.
- **lvgl**: LVGL v9.x graphics library
- **FreeRTOS**: FreeRTOS Kernel (MSVC-MingW port on Windows, GCC POSIX on Linux/Mac)

**Installable apps** (in `src/apps/crosspad-*/`, managed by app manager):

- **crosspad-appstore**: Built-in App Store (cannot be removed)
- **crosspad-mixer**, **crosspad-piano**, **crosspad-instructions**, **crosspad-serial-monitor**: Installable via `python3 scripts/app_manager.py install <name>` or via the App Store UI

### App Management

Apps are installed as git submodules in `src/apps/crosspad-*/`. CMake auto-discovers them via `file(GLOB)`. The app manager (`scripts/app_manager.py`) wraps the shared [crosspad-apps](https://github.com/CrossPad/crosspad-apps) core.

**CLI commands:**

```bash
python3 scripts/app_manager.py list # List available apps
python3 scripts/app_manager.py install mixer # Install an app
python3 scripts/app_manager.py remove mixer # Remove an app
python3 scripts/app_manager.py update --all # Update all installed apps
python3 scripts/app_manager.py sync # Sync manifest with disk
python3 scripts/app_manager.py # Launch interactive TUI
```

**After install/remove:** `cmake -B build -G Ninja && cmake --build build` (CMake reconfigure picks up new sources).

**Creating a new app:** See the [crosspad-appstore README](https://github.com/CrossPad/crosspad-appstore#creating-a-crosspad-app) for the app repo structure, `crosspad-app.json` format, and registration pattern.

### Platform Abstraction Pattern

crosspad-core defines portable interfaces; this repo provides PC implementations:
Expand Down
Loading
Loading