Skip to content

release: midi2_cpp v0.2.0 - external midi2 dependency#1

Merged
sauloverissimo merged 10 commits into
mainfrom
chore/honest-allocation-claims
May 9, 2026
Merged

release: midi2_cpp v0.2.0 - external midi2 dependency#1
sauloverissimo merged 10 commits into
mainfrom
chore/honest-allocation-claims

Conversation

@sauloverissimo
Copy link
Copy Markdown
Owner

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 in CHANGELOG.md and the per-build-system patterns in examples/.

What changed

  • Tagline drops zero-allocation (false for the wrapper — m2bridge::begin allocates slot tables) and becomes static-by-default. The C99 core stays strictly zero-allocation.
  • New midi2::Bridge (alias m2bridge) 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.properties declares depends=midi2 (>=0.3.3). library.json declares dependencies."sauloverissimo/midi2": "^0.3.3".
  • Root CMakeLists.txt exposes a three-layer fallback: parent target -> find_package(midi2 0.3.3 CONFIG) -> FetchContent_Declare(midi2 GIT_TAG v0.3.3). midi2_cpp links PUBLIC midi2::midi2.
  • Vendored src/midi2.{h,c} removed (5155 lines).
  • All 20 recipes under examples/ migrated to pull midi2 externally.

Recipes migrated

Build system Mechanism Count
Pico SDK FetchContent_Declare(midi2 GIT_TAG v0.3.3) + target_link_libraries midi2::midi2 8
TinyUSB native CMake same FetchContent pattern 2
ESP-IDF idf_component.yml declares midi2 git: ..., version: ">=0.3.3"; idf_component_register lists midi2 in REQUIRES 7
PlatformIO + ESP32_Host_MIDI lib_deps += sauloverissimo/midi2 @ ^0.3.3 3

Test plan

  • Local cmake configure pulls midi2 v0.3.3 via FetchContent
  • Host suite (7 executables, including new test_midi2_bridge) builds and passes
  • ASan + UBSan run clean on the m2bridge suite (50x construct/begin/destroy stress)
  • CI host-tests matrix on this PR (Ubuntu + macOS)
  • CI warnings job
  • CI pico-sdk-example builds at least one Pico SDK recipe end-to-end
  • CI arduino-compile passes (no .ino in examples/, expected compiled=0)

Commits

10 atomic commits, one per build system + final cleanup:

  1. 5e65b93 docs(readme,logo): replace zero-allocation claim
  2. ddf05b1 test(bridge): host-side ASan + UBSan suite
  3. c52b007 build(library): declare midi2 as Arduino + PlatformIO dependency
  4. 945f041 build(cmake): expose midi2 externally at root
  5. 572a01f build(pico-sdk): 8 recipes pull midi2 via FetchContent
  6. 4d01c0a build(tinyusb-cmake): xiao-samd21 + nrf52840 via FetchContent
  7. b33e017 build(esp-idf): 7 recipes via Component Manager
  8. 05b97dd build(platformio): 3 recipes via lib_deps
  9. d13a62a build: drop vendored midi2.{h,c} + link midi2_cpp PUBLIC midi2::midi2
  10. aabd99d release: v0.2.0

- 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
@sauloverissimo sauloverissimo merged commit 225c6dd into main May 9, 2026
6 checks passed
@sauloverissimo sauloverissimo deleted the chore/honest-allocation-claims branch May 9, 2026 03:43
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 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
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge 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 👍 / 👎.

sauloverissimo added a commit that referenced this pull request May 9, 2026
…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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant