release: midi2_cpp v0.2.0 - external midi2 dependency#1
Conversation
- Tagline: zero-allocation -> static-by-default - What-you-get: "no malloc, no new" -> hot path is allocation-free, init-time new only inside m2bridge slot tables - First mention of midi2 now linked to its repo - Install snippets: drop nonexistent v0.1.0 tag, point at main with a note about pinning by hash until releases ship - Architecture: ASCII layer diagram replaced by architecture.png - Logo regenerated to reflect the same tagline shift and reference "Built on c99 core"
m2bridge is the only midi2_cpp class that allocates state on the heap (BridgeState plus one ByteStreamConverter per slot). 11 sub-tests exercise: - construct/begin/destruct heap balance (50x cycle stress) - topology setters honour bounds and lock after begin() - begin() no-ops without downstream/upstream write fns - group rewrite formula base + (in_group % groupsPerSlot) on slots 0/1/3 - feedHostRx ignores out-of-range slot indices - feedHostMidi1Bytes uplifts USB-MIDI 1.0 packets to MT 0x2 UMPs in the slot's first group All seven test executables (the new bridge suite plus device, scaling, flex, conversion, ci, host) compile and run clean under -fsanitize=address,undefined -fno-sanitize-recover=all.
library.properties gains depends=midi2 (>=0.3.2) so the Arduino
Library Manager auto-installs the midi2 C99 core when a sketch
includes midi2_cpp. library.json mirrors the contract for
PlatformIO via dependencies."sauloverissimo/midi2": "^0.3.2".
paragraph reworded to drop comparisons with other libraries and
focus on what midi2_cpp itself ships, plus the embedded board
families that have been validated.
This is the manifest-side declaration. The follow-up commits will
remove the vendored src/midi2.{h,c} and migrate the recipes to
pull midi2 externally so the Arduino IDE no longer compiles two
copies of the C99 core.
Adds a three-layer fallback at the top of CMakeLists.txt:
1. parent project's target (when midi2_cpp is consumed via
add_subdirectory or FetchContent of a parent that already
pulled midi2)
2. find_package(midi2 0.3.2 CONFIG) -- system / vcpkg / conan
3. FetchContent_Declare(midi2 GIT_TAG v0.3.2) -- the default
src/midi2.c is still part of the midi2_cpp library target for now so
the host tests, arduino-cli compile job, and standalone CMake build
all keep their single-translation-unit guarantee. The follow-up
commits migrate each build system under examples/ to depend on
midi2::midi2 directly; the final commit removes the vendored
src/midi2.{h,c} and links midi2_cpp against the external target.
Verified: cmake configure pulls midi2 v0.3.2, the host suite (7
executables) builds and runs clean.
Drop the local midi2_cpp / midi2_c99 helper libraries that re-listed
${MIDI2_CPP_ROOT}/src/midi2.c as a source. Each Pico SDK recipe now
declares the same FetchContent block (NOT TARGET midi2 -> v0.3.2 from
GitHub by default; -DMIDI2_LOCAL_PATH overrides for offline builds)
and links midi2::midi2 directly.
Recipes touched:
- rp2040-midi2
- waveshare-rp2040-midi2
- sparkfun-promicro-rp2350-midi2
- waveshare-rp2350-usb-a-midi2
- rp2040-promicro-ump-test-bench
- adafruit-feather-rp2040-host-midi2 (keeps midi2_host.cpp local)
- adafruit-feather-rp2040-bridge-midi2 (was midi2_c99-only)
- waveshare-rp2350-usb-a-bridge-midi2 (was midi2_c99-only)
The vendored src/midi2.{h,c} stays in the tree until the remaining
build systems (TinyUSB native CMake, ESP-IDF, PlatformIO) follow.
… FetchContent
Mirror of the Pico SDK migration for the two TinyUSB native CMake
recipes. Drop ${MIDI2_CPP_ROOT}/src/midi2.c from the local
midi2_cpp helper library and link midi2::midi2 instead. The
FetchContent block is identical so all CMake recipes share the
same MIDI2_LOCAL_PATH override semantics.
Drop the dist/midi2.c entry that every recipe re-listed in SRCS
under ${MIDI2_CPP_ROOT}. Each recipe now declares midi2 as a
managed dependency and lists midi2 in REQUIRES so <midi2.h> resolves
through the imported component:
# idf/main/idf_component.yml
dependencies:
idf: ">=5.4"
midi2:
git: https://github.com/sauloverissimo/midi2.git
version: ">=0.3.3"
The Component Manager clones midi2 into managed_components/midi2;
ESP-IDF processes it as a regular component because midi2's top-level
CMakeLists detects ESP_PLATFORM and routes to idf_component_register
(see midi2 v0.3.3).
Recipes touched:
- arduino-nano-esp32-midi2
- esp32-s3-devkitc-usb-midi2
- esp32-p4-devkit-usb-midi2
- esp32-p4-devkit-host-midi2
- esp32-p4-devkit-bridge-midi2
- esp32-p4-devkit-bridge2-midi2
- t-display-s3-midi2
The other midi2_cpp source files (midi2_device.cpp, midi2_ci.cpp,
midi2_host.cpp, midi2_bridge.cpp) keep being compiled inline from
the parent tree until the host helper library shape is finalised.
Each PlatformIO recipe (ESP32_Host_MIDI-based, no Pico SDK) now
pulls midi2 from the PlatformIO Registry through lib_deps:
lib_deps =
sauloverissimo/midi2 @ ^0.3.3
...other deps...
Recipes touched:
- esp32-c6-devkitc-multi-midi2 (BLE + ESP-NOW, ESP32_Host_MIDI v6.0.1)
- esp32-s3-devkitc-host-midi2 (USB Host, ESP32_Host_MIDI v6.0.0)
- t-display-s3-shield-host-midi2 (USB Host + ST7789 piano, ESP32_Host_MIDI local)
These recipes already pulled midi2_cpp via lib_extra_dirs from the
parent tree; nothing about that path changes. midi2_cpp's own
src/midi2.{h,c} keeps the recipes building today and will go away in
the final cleanup commit, at which point lib_extra_dirs gives them
midi2_cpp source files only and lib_deps gives them midi2.
This is the final step of the depends=midi2 migration. Every recipe
under examples/ has been migrated to pull midi2 externally (Pico SDK
+ TinyUSB CMake via FetchContent, ESP-IDF via Component Manager,
PlatformIO via lib_deps), so the duplicated copy of dist/midi2.{h,c}
that lived under src/ no longer has any consumer.
Removes:
- src/midi2.h
- src/midi2.c
Updates the root CMakeLists.txt:
- find_package + FetchContent now ask for midi2 0.3.3 (matches the
ESP-IDF idiom and the Library Manager constraint).
- midi2_cpp library target drops src/midi2.c from its source list.
- target_link_libraries(midi2_cpp PUBLIC midi2::midi2) exposes the
C99 core to downstream link consumers transitively.
Bumps the manifest declarations in lockstep:
- library.properties: depends=midi2 (>=0.3.3)
- library.json: sauloverissimo/midi2: ^0.3.3
Verified locally: cmake configure pulls midi2 v0.3.3 via
FetchContent, the host suite (7 executables, including the m2bridge
ASan + UBSan smoke) builds and runs clean.
Bumps library.properties / library.json / CMakeLists.txt to 0.2.0 and
publishes the CHANGELOG entry that consolidates the depends=midi2
migration: vendored src/midi2.{h,c} removed, every example/ recipe
migrated to pull midi2 externally (Pico SDK + TinyUSB CMake via
FetchContent, ESP-IDF via Component Manager, PlatformIO via lib_deps),
m2bridge class extracted with a host-side ASan + UBSan suite, and the
honest tagline shift from "zero-allocation" to "static-by-default".
This is a breaking release. Pre-v0.2 consumers that vendored
midi2_cpp/src/midi2.{h,c} will break; the README "Manual vendor"
section now explains the new two-repo layout, and the in-tree recipes
demonstrate the four supported package-manager paths.
Touches:
- library.properties / library.json / CMakeLists.txt: VERSION 0.2.0
- README.md "Manual vendor": rewritten to point at midi2/dist/
- esp32-c6 platformio.ini comment: midi2_cpp/src/midi2.h
reference replaced with the lib_deps midi2 entry it now relies on
- CHANGELOG.md: [Unreleased] promoted to [0.2.0] with the full
Breaking / Added / Changed / Examples sections
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: aabd99d8e9
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| else() | ||
| FetchContent_Declare(midi2 | ||
| GIT_REPOSITORY https://github.com/sauloverissimo/midi2.git | ||
| GIT_TAG v0.3.2 |
There was a problem hiding this comment.
Pin examples to the declared midi2 release
When a user builds this Pico/TinyUSB recipe from a fresh checkout, it fetches midi2 v0.3.2 even though the top-level CMake, Arduino/PlatformIO/ESP-IDF metadata, and changelog all moved the release to >=0.3.3. That leaves the examples building and shipping against a different C core than the library is tested and advertised with, so any v0.3.3 fixes or API/packaging changes are silently missed; please update this and the sibling example GIT_TAG pins to v0.3.3.
Useful? React with 👍 / 👎.
…ecipes Codex review on PR #1 caught that the Pico SDK and TinyUSB native CMake recipes still pinned `FetchContent_Declare(midi2 GIT_TAG v0.3.2)` after the rest of the v0.2.0 release (root CMakeLists, library.properties, library.json, CHANGELOG, ESP-IDF / PlatformIO recipes) moved to midi2 v0.3.3. That left those recipes building against v0.3.2 silently, out of sync with the C core the library is tested and advertised with. Touches the 10 affected CMakeLists.txt: - rp2040-midi2 - waveshare-rp2040-midi2 - sparkfun-promicro-rp2350-midi2 - waveshare-rp2350-usb-a-midi2 - waveshare-rp2350-usb-a-bridge-midi2 - adafruit-feather-rp2040-host-midi2 - adafruit-feather-rp2040-bridge-midi2 - rp2040-promicro-ump-test-bench - xiao-samd21-midi2 - nrf52840-promicro-midi2 Each one now matches the version advertised everywhere else in the repo. Ref Codex review on PR #1.
Summary
Single source of truth for the MIDI 2.0 stack: midi2_cpp no longer vendors the C99 core. midi2 v0.3.3 is now declared as an explicit dependency across every package manager surface (Arduino Library Manager, PlatformIO Registry, ESP-IDF Component Manager, CMake
find_package/FetchContent).This is a breaking release. Pre-v0.2 consumers that vendored
midi2_cpp/src/midi2.{h,c}directly will break; the new path is documented inCHANGELOG.mdand the per-build-system patterns inexamples/.What changed
zero-allocation(false for the wrapper —m2bridge::beginallocates slot tables) and becomesstatic-by-default. The C99 core stays strictly zero-allocation.midi2::Bridge(aliasm2bridge) class composes Device + CI + Host with multi-FB topology, slot table, group rewrite, dynamic FB names, and USB-MIDI 1.0 byte-stream uplift.tests/test_midi2_bridge.cpp: 11 host-side sub-tests covering m2bridge under ASan + UBSan.library.propertiesdeclaresdepends=midi2 (>=0.3.3).library.jsondeclaresdependencies."sauloverissimo/midi2": "^0.3.3".CMakeLists.txtexposes a three-layer fallback: parent target ->find_package(midi2 0.3.3 CONFIG)->FetchContent_Declare(midi2 GIT_TAG v0.3.3). midi2_cpp linksPUBLIC midi2::midi2.src/midi2.{h,c}removed (5155 lines).examples/migrated to pull midi2 externally.Recipes migrated
FetchContent_Declare(midi2 GIT_TAG v0.3.3)+target_link_libraries midi2::midi2idf_component.ymldeclaresmidi2 git: ..., version: ">=0.3.3";idf_component_registerlistsmidi2inREQUIRESlib_deps += sauloverissimo/midi2 @ ^0.3.3Test plan
.inoin examples/, expected compiled=0)Commits
10 atomic commits, one per build system + final cleanup:
5e65b93docs(readme,logo): replace zero-allocation claimddf05b1test(bridge): host-side ASan + UBSan suitec52b007build(library): declare midi2 as Arduino + PlatformIO dependency945f041build(cmake): expose midi2 externally at root572a01fbuild(pico-sdk): 8 recipes pull midi2 via FetchContent4d01c0abuild(tinyusb-cmake): xiao-samd21 + nrf52840 via FetchContentb33e017build(esp-idf): 7 recipes via Component Manager05b97ddbuild(platformio): 3 recipes via lib_depsd13a62abuild: drop vendored midi2.{h,c} + link midi2_cpp PUBLIC midi2::midi2aabd99drelease: v0.2.0