Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
10 changes: 5 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
- uses: actions/checkout@v4

- name: Configure
run: cmake -B build -DMIDI2_CPP_BUILD_TESTS=ON
run: cmake -B build -DMIDI2CPP_BUILD_TESTS=ON

- name: Build
run: cmake --build build --parallel
Expand All @@ -43,7 +43,7 @@ jobs:
env:
CC: ${{ matrix.compiler.cc }}
CXX: ${{ matrix.compiler.cxx }}
run: cmake -B build -DMIDI2_CPP_BUILD_TESTS=ON
run: cmake -B build -DMIDI2CPP_BUILD_TESTS=ON

- name: Build with -Werror
run: cmake --build build --parallel -- CXXFLAGS=-Werror CFLAGS=-Werror
Expand Down Expand Up @@ -122,10 +122,10 @@ jobs:
- name: Symlink lib for arduino-cli sketch resolution
run: |
mkdir -p ~/Arduino/libraries
ln -s "$GITHUB_WORKSPACE" ~/Arduino/libraries/midi2_cpp
ln -s "$GITHUB_WORKSPACE" ~/Arduino/libraries/midi2cpp

- name: Install midi2 dependency from Library Manager
# midi2_cpp depends on midi2 (>=0.3.3) but arduino-cli does not
# midi2cpp depends on midi2 (>=0.3.4) but arduino-cli does not
# walk depends= entries automatically. Install it explicitly.
# Falls back to the GitHub git URL if the registry index has
# not propagated yet (Library Manager indexes within 24h of a
Expand All @@ -134,7 +134,7 @@ jobs:
arduino-cli lib update-index
arduino-cli lib install midi2 || \
(arduino-cli config set library.enable_unsafe_install true && \
arduino-cli lib install --git-url https://github.com/sauloverissimo/midi2.git#v0.3.3)
arduino-cli lib install --git-url https://github.com/sauloverissimo/midi2.git#v0.3.4)

- name: Compile Arduino sketches (skip non-sketch dirs)
run: |
Expand Down
91 changes: 64 additions & 27 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,50 @@
# Changelog

All notable changes to `midi2_cpp` are recorded here. Format follows
All notable changes to `midi2cpp` are recorded here. Format follows
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and this project
adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html),
mirrored from the upstream midi2 C99 policy.

## [0.3.0]

Renamed from `midi2_cpp` to `midi2cpp` in deference to [`starfishmod/MIDI2_CPP`](https://github.com/starfishmod/MIDI2_CPP) (maintained since 2021 by Andrew Mee, MIDI Association TSB Rep), which operates in the same domain. Keeping the namespaces disjoint avoids confusion in package managers and search.

This is a **breaking** rename. Every consumer-facing identifier moved:

### Breaking

- **Repository:** `github.com/sauloverissimo/midi2_cpp` -> `github.com/sauloverissimo/midi2cpp` (the old URL redirects on the GitHub side, but new code should pin the new name).
- **Header:** `<midi2_cpp.h>` -> `<midi2cpp.h>`. `using namespace midi2;` is unchanged; the C++ API surface (`m2device`, `m2host`, `m2bridge`, `m2ci`, `Bridge`, `Device`, ...) is unchanged.
- **CMake target:** `midi2_cpp` -> `midi2cpp`; alias `midi2_cpp::midi2_cpp` -> `midi2cpp::midi2cpp`. `target_link_libraries(... midi2cpp)` replaces `... midi2_cpp`.
- **Preprocessor macros:** `MIDI2_CPP_*` -> `MIDI2CPP_*` (`MIDI2CPP_BUILD_TESTS`, `MIDI2CPP_MAX_PROFILES`, `MIDI2CPP_MAX_PROPERTIES`, `MIDI2CPP_MAX_SUBSCRIBERS`, `MIDI2CPP_HOST_MAX_DEVICES`, `MIDI2CPP_BRIDGE_MAX_SLOTS`).
- **Manifests:** `library.properties` `name=midi2cpp`, `library.json` `"name": "midi2cpp"`. The Arduino Library Manager and the PlatformIO Registry treat the rename as a new entry; the previous `midi2_cpp` listings will be retired in a follow-up PR to `arduino/library-registry`.

### Changed

- **Dependency on midi2 bumped to v0.3.4** across every install path (Arduino LM `depends=midi2 (>=0.3.4)`, PlatformIO `^0.3.4`, ESP-IDF `version: "v0.3.4"`, CMake `find_package(midi2 0.3.4 CONFIG)` + `FetchContent_Declare(... GIT_TAG v0.3.4)`). midi2 v0.3.4 fixes the ESP-IDF Component Manager gate (`dist/` filtered from the dependency tarball); without it, ESP-IDF recipes failed configure.

### Migration

```diff
-#include <midi2_cpp.h>
+#include <midi2cpp.h>
```

CMake:
```diff
-FetchContent_Declare(midi2_cpp ...)
-target_link_libraries(my_target PRIVATE midi2_cpp)
+FetchContent_Declare(midi2cpp ...)
+target_link_libraries(my_target PRIVATE midi2cpp)
```

Arduino Library Manager: search `midi2cpp` (the previous `midi2_cpp` entry will be removed once the registry PR lands).

PlatformIO: `lib_deps = sauloverissimo/midi2cpp @ ^0.3.0`.

## [0.2.0]

Single source of truth for the MIDI 2.0 stack: midi2_cpp no longer
Single source of truth for the MIDI 2.0 stack: midi2cpp no longer
vendors the C99 core and is published as a regular Arduino /
PlatformIO library that depends on midi2 explicitly. Every recipe
under `examples/` was migrated to pull midi2 externally through the
Expand All @@ -16,23 +53,23 @@ native CMake, IDF Component Manager for ESP-IDF, lib_deps for
PlatformIO).

This is a breaking release. Consumers that previously vendored
`midi2_cpp/src/midi2.{h,c}` directly will break; the migration path
`midi2cpp/src/midi2.{h,c}` directly will break; the migration path
is documented in the manifest below and in the per-build-system
patterns shipped under `examples/`.

### Breaking

- **Vendored `src/midi2.{h,c}` removed.** midi2_cpp now declares
- **Vendored `src/midi2.{h,c}` removed.** midi2cpp now declares
midi2 as an external dependency:
- `library.properties` carries `depends=midi2 (>=0.3.3)`. Arduino
- `library.properties` carries `depends=midi2 (>=0.3.4)`. Arduino
Library Manager auto-installs midi2 when a sketch includes
midi2_cpp.
midi2cpp.
- `library.json` carries `dependencies."sauloverissimo/midi2":
"^0.3.3"`. PlatformIO resolves midi2 from its registry.
"^0.3.4"`. PlatformIO resolves midi2 from its registry.
- The root `CMakeLists.txt` exposes a three-layer fallback at the
top (`if(NOT TARGET midi2)` -> `find_package(midi2 0.3.3 CONFIG)`
-> `FetchContent_Declare(midi2 GIT_TAG v0.3.3)`), then links
midi2_cpp `PUBLIC midi2::midi2` so downstream targets see the
top (`if(NOT TARGET midi2)` -> `find_package(midi2 0.3.4 CONFIG)`
-> `FetchContent_Declare(midi2 GIT_TAG v0.3.4)`), then links
midi2cpp `PUBLIC midi2::midi2` so downstream targets see the
C99 core transitively.

### Added
Expand All @@ -56,23 +93,23 @@ patterns shipped under `examples/`.
- **CMake entry surface for downstream consumers**: the root
`CMakeLists.txt` follows the same `find_package` -> `FetchContent`
fallback pattern that midi2 itself ships. Subprojects pulling
midi2_cpp via `add_subdirectory` or `FetchContent` skip the
midi2cpp via `add_subdirectory` or `FetchContent` skip the
`find_package` step (`if(NOT TARGET midi2)` guard).

### Changed

- **README tagline** drops the `zero-allocation` claim. midi2_cpp
- **README tagline** drops the `zero-allocation` claim. midi2cpp
allocates in two narrow places (`m2bridge::begin()` slot tables and
`std::function` callback storage), so the wrapper is now described
as `static-by-default`. The C99 core (midi2) remains strictly
zero-allocation. Same shift applied to the logo and to the
`.intern/decisoes.md` design heritage notes.
- **README "Manual vendor" path** rewritten: pre-v0.2 builds vendored
a single `midi2_cpp/src/midi2.{h,c}` copy; today the consumer
a single `midi2cpp/src/midi2.{h,c}` copy; today the consumer
downloads both repositories side by side and adds `midi2/dist/`
plus `midi2_cpp/src/` to its include path.
plus `midi2cpp/src/` to its include path.
- **`paragraph` in `library.properties`** rewritten: drops
comparisons with other libraries, focuses on what midi2_cpp itself
comparisons with other libraries, focuses on what midi2cpp itself
ships and the embedded targets validated.

### Examples / Recipes
Expand All @@ -81,16 +118,16 @@ patterns shipped under `examples/`.

| Build system | Mechanism | Recipes |
|---|---|---|
| Pico SDK | `FetchContent_Declare(midi2 GIT_TAG v0.3.3)` plus `target_link_libraries(midi2_cpp PUBLIC midi2::midi2)` | `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` |
| Pico SDK | `FetchContent_Declare(midi2 GIT_TAG v0.3.4)` plus `target_link_libraries(midi2cpp PUBLIC midi2::midi2)` | `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` |
| TinyUSB native CMake | same FetchContent pattern as Pico SDK | `xiao-samd21-midi2`, `nrf52840-promicro-midi2` |
| ESP-IDF | `idf_component.yml` declares `midi2: { git: ..., version: ">=0.3.3" }` and `idf_component_register` lists `midi2` in `REQUIRES` | `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` |
| PlatformIO + ESP32_Host_MIDI | `lib_deps += sauloverissimo/midi2 @ ^0.3.3` | `esp32-c6-devkitc-multi-midi2`, `esp32-s3-devkitc-host-midi2`, `t-display-s3-shield-host-midi2` |
| ESP-IDF | `idf_component.yml` declares `midi2: { git: ..., version: ">=0.3.4" }` and `idf_component_register` lists `midi2` in `REQUIRES` | `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` |
| PlatformIO + ESP32_Host_MIDI | `lib_deps += sauloverissimo/midi2 @ ^0.3.4` | `esp32-c6-devkitc-multi-midi2`, `esp32-s3-devkitc-host-midi2`, `t-display-s3-shield-host-midi2` |

Each recipe drops the `${MIDI2_CPP_ROOT}/src/midi2.c` (or `midi2_c99`
helper library) from its source list. Other midi2_cpp sources
Each recipe drops the `${MIDI2CPP_ROOT}/src/midi2.c` (or `midi2_c99`
helper library) from its source list. Other midi2cpp sources
(`midi2_device.cpp`, `midi2_ci.cpp`, `midi2_host.cpp`,
`midi2_bridge.cpp`) keep being compiled inline from the parent tree
via `${MIDI2_CPP_ROOT}/src` until the host helper-library shape is
via `${MIDI2CPP_ROOT}/src` until the host helper-library shape is
finalised in a future cycle.

#### New recipes since v0.1.0
Expand Down Expand Up @@ -178,16 +215,16 @@ library (vendored stb-style at `src/midi2.{h,c}` from v0.3.0+).
- Profile (M2-101 §7): `addProfile`, `removeProfile`, callbacks for
`onProfileInquiry`, `onProfileEnable`, `onProfileDisable`,
`onProfileAdded`, `onProfileRemoved`, `onProfileDetailsInquiry`,
`onProfileSpecificData`. Storage tunable via `MIDI2_CPP_MAX_PROFILES`
`onProfileSpecificData`. Storage tunable via `MIDI2CPP_MAX_PROFILES`
(default 8).
- Property Exchange (M2-101 §8, M2-103, M2-105):
- Registry: `addProperty(name, getter, setter=nullptr)` (read-only by
default), `addPropertyStatic(name, value)`, `removeProperty`.
Storage tunable via `MIDI2_CPP_MAX_PROPERTIES` (default 8).
Storage tunable via `MIDI2CPP_MAX_PROPERTIES` (default 8).
- Subscribe / Notify state machine:
`setPropertySubscribable(name, true)`, `notifyPropertyChanged(name)`
for fan-out, `subscriberCount()`. Subscriber registry tunable via
`MIDI2_CPP_MAX_SUBSCRIBERS` (default 4).
`MIDI2CPP_MAX_SUBSCRIBERS` (default 4).
- PE callbacks deliver raw bytes (header + body) instead of
NUL-terminated strings, to avoid silent truncation of large JSON
payloads.
Expand All @@ -196,7 +233,7 @@ library (vendored stb-style at `src/midi2.{h,c}` from v0.3.0+).

### `midi2::Host` — USB MIDI 2.0 host shape

- Reactive multi-device host (`MIDI2_CPP_HOST_MAX_DEVICES`, default 4).
- Reactive multi-device host (`MIDI2CPP_HOST_MAX_DEVICES`, default 4).
Caller wires `tuh_midi2_*` (or platform-equivalent) into
`notifyDeviceMounted/Unmounted`, `feedRx(idx, words, count)` and
`setWriteFn(idx, words, count)`.
Expand Down Expand Up @@ -261,14 +298,14 @@ library (vendored stb-style at `src/midi2.{h,c}` from v0.3.0+).
platform-conditional RNG `#if` chain from `midi2_ci.cpp`. The library
no longer pulls `<Arduino.h>`, `pico/time.h`, `esp_timer.h`, or any
USB stack header.
- Removed the `MIDI2_CPP_TEST_MODE` build option. Tests now consume the
- Removed the `MIDI2CPP_TEST_MODE` build option. Tests now consume the
same public hooks platforms wire. One contract, one code path.
- `Device::begin()` no longer claims to call `tusb_init` internally. It
initialises the library's own dispatcher and returns; the caller owns
the platform USB stack lifecycle.
- `Device::task()` drops the commented `tud_task` stubs.
- C++17 floor enforced via `static_assert(__cplusplus >= 201703L)` in
`midi2_cpp.h`.
`midi2cpp.h`.
- `lib/tinyusb` git submodule and the `.gitmodules` entry removed. The
library has zero external dependencies: midi2 C99 stays vendored,
every USB stack and clock and RNG source is caller-wired. `git clone`
Expand Down
32 changes: 16 additions & 16 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.14)
project(midi2_cpp VERSION 0.2.0 LANGUAGES C CXX)
project(midi2cpp VERSION 0.3.0 LANGUAGES C CXX)

set(CMAKE_C_STANDARD 99)
set(CMAKE_C_STANDARD_REQUIRED ON)
Expand All @@ -11,59 +11,59 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Three-layer fallback: parent project's target -> system install
# (vcpkg / conan / system package) -> FetchContent from GitHub.
# This is the same pattern the midi2 README documents for downstream
# consumers, applied to midi2_cpp itself.
# consumers, applied to midi2cpp itself.
if(NOT TARGET midi2)
find_package(midi2 0.3.3 QUIET CONFIG)
find_package(midi2 0.3.4 QUIET CONFIG)
if(NOT midi2_FOUND)
include(FetchContent)
FetchContent_Declare(midi2
GIT_REPOSITORY https://github.com/sauloverissimo/midi2.git
GIT_TAG v0.3.3
GIT_TAG v0.3.4
)
FetchContent_MakeAvailable(midi2)
endif()
endif()

# Library target.
#
# midi2_cpp ships the C++ wrapper sources only; the C99 core lives in
# midi2cpp ships the C++ wrapper sources only; the C99 core lives in
# the external midi2 target this CMakeLists pulls above. Consumers
# linking midi2_cpp transitively see midi2::midi2 because of the
# linking midi2cpp transitively see midi2::midi2 because of the
# PUBLIC link below.
add_library(midi2_cpp
add_library(midi2cpp
src/midi2_device.cpp
src/midi2_ci.cpp
src/midi2_host.cpp
src/midi2_bridge.cpp
)

target_link_libraries(midi2_cpp PUBLIC midi2::midi2)
target_link_libraries(midi2cpp PUBLIC midi2::midi2)

target_include_directories(midi2_cpp
target_include_directories(midi2cpp
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
$<INSTALL_INTERFACE:include>
)

# Warnings
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
target_compile_options(midi2_cpp PRIVATE
target_compile_options(midi2cpp PRIVATE
-Wall -Wextra -Wpedantic
-Wno-unused-parameter # spec uses many unused params in stubs
)
endif()

# Exportable alias for consumers: midi2_cpp::midi2_cpp
add_library(midi2_cpp::midi2_cpp ALIAS midi2_cpp)
# Exportable alias for consumers: midi2cpp::midi2cpp
add_library(midi2cpp::midi2cpp ALIAS midi2cpp)

# Tests: build only if this is the top-level project or tests explicitly requested
if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
set(MIDI2_CPP_BUILD_TESTS_DEFAULT ON)
set(MIDI2CPP_BUILD_TESTS_DEFAULT ON)
else()
set(MIDI2_CPP_BUILD_TESTS_DEFAULT OFF)
set(MIDI2CPP_BUILD_TESTS_DEFAULT OFF)
endif()
option(MIDI2_CPP_BUILD_TESTS "Build host-side unit tests" ${MIDI2_CPP_BUILD_TESTS_DEFAULT})
if(MIDI2_CPP_BUILD_TESTS AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/tests/CMakeLists.txt")
option(MIDI2CPP_BUILD_TESTS "Build host-side unit tests" ${MIDI2CPP_BUILD_TESTS_DEFAULT})
if(MIDI2CPP_BUILD_TESTS AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/tests/CMakeLists.txt")
# Tests use the same public hooks the platforms wire (setWriteFn,
# setNowFn, feedRx). No special test mode — the contract is the contract.
enable_testing()
Expand Down
Loading
Loading