Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
e5dc7c1
Split Android and Linux CI builds for platform-specific wrappers
mortenboye Feb 15, 2026
b1cac01
AIOL
mortenboye Feb 15, 2026
3c76f08
web
mortenboye Feb 15, 2026
e1e4299
flutter version
mortenboye Feb 15, 2026
8ad135b
build fix
mortenboye Feb 16, 2026
eae2fa4
build wip
mortenboye Feb 16, 2026
25c6302
wip
mortenboye Feb 16, 2026
687ca3a
ios fix
mortenboye Feb 16, 2026
541a87f
polish
mortenboye Feb 16, 2026
c996702
vbump and pub update
mortenboye Feb 16, 2026
fa8227b
versions
mortenboye Feb 16, 2026
59517d6
badges
mortenboye Feb 16, 2026
2ad7cdf
readme
mortenboye Feb 16, 2026
db06c18
Android connect idempotency guard
mortenboye Feb 16, 2026
0086005
added parser and updated tests and example app
mortenboye Feb 16, 2026
69747fa
Example app tests
mortenboye Feb 16, 2026
df48674
ios smoke test fix
mortenboye Feb 16, 2026
d1f55ac
updated test structure
mortenboye Feb 16, 2026
d355e0d
android ndk
mortenboye Feb 16, 2026
b9f0289
order
mortenboye Feb 16, 2026
7afa2ac
docs
mortenboye Feb 16, 2026
4ba5113
native tests
mortenboye Feb 16, 2026
1dc898e
android emu
mortenboye Feb 16, 2026
1233596
ignore
mortenboye Feb 17, 2026
8e2c7cf
ios hard
mortenboye Feb 17, 2026
49394bf
adnroid
mortenboye Feb 17, 2026
78770fc
wip
mortenboye Feb 23, 2026
9825ed3
typed midi RX stream
mortenboye Feb 23, 2026
8aa2beb
rename
mortenboye Feb 23, 2026
c9b9e4d
docs
mortenboye Feb 23, 2026
7a9c6d7
background check
mortenboye Feb 23, 2026
8fa7b64
linux wip
mortenboye May 19, 2026
23d87e2
ci
mortenboye May 19, 2026
9a14c5a
midi log in recorder
mortenboye Mar 16, 2026
1b33340
Update .gitignore
mortenboye May 21, 2026
c1984ef
dart fix
mortenboye May 21, 2026
3f08284
ci
mortenboye May 21, 2026
5b57f68
One device per port, Gradle update
mortenboye May 21, 2026
02e6544
auto update on device appear/disappear
mortenboye May 22, 2026
59d1e48
darwin device enumeration filter
mortenboye May 22, 2026
5132731
windows fix
mortenboye Jun 13, 2026
9c25dd2
Improve Windows MIDI hot-plug handling and refresh example transport UI
mortenboye Jun 13, 2026
54b0e8c
exports
mortenboye Jun 13, 2026
8fa4ba8
`Improve web MIDI multi-port pairing and add example analyzer coverag…
mortenboye Jun 13, 2026
83be934
upgraded universal_ble
mortenboye Jun 13, 2026
20b1a50
Upgrade universal_ble to 2.0.4 and align CI/tooling constraints
mortenboye Jun 13, 2026
7bd299e
Upgrade universal_ble to 2.0.4 and align platform toolchains
mortenboye Jun 13, 2026
d866c01
example app refresh
mortenboye Jun 14, 2026
cab1b42
Fix Windows native MIDI disconnect teardown and add regression tests
mortenboye Jun 14, 2026
8dcfcba
test fix
mortenboye Jun 14, 2026
dc8ad1d
Update gradle.properties
mortenboye Jun 14, 2026
9640f8c
pub publish
mortenboye Jun 29, 2026
5f21bf2
typo
mortenboye Jun 29, 2026
cb89549
publish prep
mortenboye Jun 29, 2026
365c1d9
log
mortenboye Jun 29, 2026
a7997c9
format
mortenboye Jun 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
194 changes: 194 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
name: CI

on:
pull_request:
push:
branches:
- main
- master
- codex/restructure-repo-into-mono-repo-with-melon

env:
FLUTTER_VERSION: '3.44.2'

jobs:
pigeon_contracts:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: subosito/flutter-action@v2
with:
flutter-version: ${{ env.FLUTTER_VERSION }}
- run: dart run melos bootstrap
- run: dart run pigeon --input pigeons/midi_api.dart
- run: git diff --exit-code -- packages/flutter_midi_command_platform_interface/lib/src/pigeon packages/flutter_midi_command_android/android/src/main/kotlin/com/invisiblewrench/fluttermidicommand/pigeon packages/flutter_midi_command_darwin/ios/Classes/pigeon

dart_checks:
runs-on: ubuntu-latest
needs: pigeon_contracts
steps:
- uses: actions/checkout@v6
- uses: subosito/flutter-action@v2
with:
flutter-version: ${{ env.FLUTTER_VERSION }}
- run: dart pub global activate melos
- run: melos bootstrap
- run: melos run analyze
- run: melos run analyze:example
- run: melos run test
- run: melos run test:web:chrome

native_android_checks:
runs-on: ubuntu-latest
needs: pigeon_contracts
steps:
- uses: actions/checkout@v6
- uses: subosito/flutter-action@v2
with:
flutter-version: ${{ env.FLUTTER_VERSION }}
- run: dart pub global activate melos
- run: melos bootstrap
- name: Android native unit tests
run: bash ./example/android/gradlew -p example/android :flutter_midi_command_android:testDebugUnitTest

native_darwin_checks:
runs-on: macos-latest
needs: pigeon_contracts
steps:
- uses: actions/checkout@v6
- uses: subosito/flutter-action@v2
with:
flutter-version: ${{ env.FLUTTER_VERSION }}
- run: dart pub global activate melos
- run: melos bootstrap
- name: Darwin native tests
run: melos run test:native:darwin

native_linux_checks:
runs-on: ubuntu-latest
needs: pigeon_contracts
steps:
- uses: actions/checkout@v6
- uses: subosito/flutter-action@v2
with:
flutter-version: ${{ env.FLUTTER_VERSION }}
- run: dart pub global activate melos
- run: melos bootstrap
- name: Linux backend tests
run: melos run test:native:linux

native_windows_checks:
runs-on: windows-latest
needs: pigeon_contracts
steps:
- uses: actions/checkout@v6
- uses: subosito/flutter-action@v2
with:
flutter-version: ${{ env.FLUTTER_VERSION }}
- run: dart pub global activate melos
- run: melos bootstrap
- name: Windows backend tests
run: melos run test:native:windows

example_android:
runs-on: ubuntu-latest
needs: [dart_checks, native_android_checks]
steps:
- uses: actions/checkout@v6
- uses: subosito/flutter-action@v2
with:
flutter-version: ${{ env.FLUTTER_VERSION }}
- run: dart pub global activate melos
- run: melos bootstrap
- name: Build example app (Android)
run: melos run build:example:android
- name: Enable KVM
run: |
sudo tee /etc/udev/rules.d/99-kvm4all.rules <<'EOF'
KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"
EOF
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm
- name: Run smoke test (Android emulator)
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: 35
arch: x86_64
target: google_apis
profile: pixel_6
disable-animations: true
emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -no-snapshot -no-snapshot-save
script: melos run test:example:integration:android
env:
ANDROID_DEVICE_ID: emulator-5554
ANDROID_SMOKE_MAX_ATTEMPTS: "3"

example_linux:
runs-on: ubuntu-latest
needs: [dart_checks, native_linux_checks]
steps:
- uses: actions/checkout@v6
- uses: subosito/flutter-action@v2
with:
flutter-version: ${{ env.FLUTTER_VERSION }}
- name: Install Linux build dependencies
run: |
sudo apt-get update
sudo apt-get install -y clang cmake ninja-build pkg-config libgtk-3-dev xvfb
- run: dart pub global activate melos
- run: melos bootstrap
- name: Build example app (Linux)
run: melos run build:example:linux
- name: Run smoke test (Linux)
run: xvfb-run -a melos run test:example:integration:linux

example_apple:
runs-on: macos-latest
needs: [dart_checks, native_darwin_checks]
steps:
- uses: actions/checkout@v6
- uses: subosito/flutter-action@v2
with:
flutter-version: ${{ env.FLUTTER_VERSION }}
- run: dart pub global activate melos
- run: melos bootstrap
- name: Build example app (iOS)
run: melos run build:example:ios
- name: Build example app (macOS)
run: melos run build:example:macos
- name: Run smoke test (macOS)
run: melos run test:example:integration:macos
- name: Run smoke test (iOS simulator)
run: melos run test:example:integration:ios
env:
IOS_SMOKE_MAX_ATTEMPTS: "3"

example_windows:
runs-on: windows-latest
needs: [dart_checks, native_windows_checks]
steps:
- uses: actions/checkout@v6
- uses: subosito/flutter-action@v2
with:
flutter-version: ${{ env.FLUTTER_VERSION }}
- run: dart pub global activate melos
- run: melos bootstrap
- name: Build example app (Windows)
run: melos run build:example:windows
- name: Run smoke test (Windows)
run: melos run test:example:integration:windows

example_web:
runs-on: ubuntu-latest
needs: dart_checks
steps:
- uses: actions/checkout@v6
- uses: subosito/flutter-action@v2
with:
flutter-version: ${{ env.FLUTTER_VERSION }}
- run: dart pub global activate melos
- run: melos bootstrap
- name: Build example app (Web)
run: melos run build:example:web
- name: Run smoke test (Web Chrome)
run: melos run test:example:integration:web
109 changes: 109 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
name: Publish to pub.dev

on:
push:
tags:
- 'flutter_midi_command-v*'
- 'flutter_midi_command_android-v*'
- 'flutter_midi_command_ble-v*'
- 'flutter_midi_command_darwin-v*'
- 'flutter_midi_command_linux-v*'
- 'flutter_midi_command_platform_interface-v*'
- 'flutter_midi_command_web-v*'
- 'flutter_midi_command_windows-v*'

env:
FLUTTER_VERSION: '3.44.2'

jobs:
publish:
runs-on: ubuntu-latest
environment: pub.dev
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@v6

- uses: subosito/flutter-action@v2
with:
flutter-version: ${{ env.FLUTTER_VERSION }}

- name: Resolve package from tag
id: package
shell: bash
run: |
set -euo pipefail

tag="${GITHUB_REF_NAME}"

case "$tag" in
flutter_midi_command_platform_interface-v*)
package_name="flutter_midi_command_platform_interface"
package_dir="packages/flutter_midi_command_platform_interface"
version="${tag#flutter_midi_command_platform_interface-v}"
;;
flutter_midi_command_android-v*)
package_name="flutter_midi_command_android"
package_dir="packages/flutter_midi_command_android"
version="${tag#flutter_midi_command_android-v}"
;;
flutter_midi_command_darwin-v*)
package_name="flutter_midi_command_darwin"
package_dir="packages/flutter_midi_command_darwin"
version="${tag#flutter_midi_command_darwin-v}"
;;
flutter_midi_command_windows-v*)
package_name="flutter_midi_command_windows"
package_dir="packages/flutter_midi_command_windows"
version="${tag#flutter_midi_command_windows-v}"
;;
flutter_midi_command_linux-v*)
package_name="flutter_midi_command_linux"
package_dir="packages/flutter_midi_command_linux"
version="${tag#flutter_midi_command_linux-v}"
;;
flutter_midi_command_web-v*)
package_name="flutter_midi_command_web"
package_dir="packages/flutter_midi_command_web"
version="${tag#flutter_midi_command_web-v}"
;;
flutter_midi_command_ble-v*)
package_name="flutter_midi_command_ble"
package_dir="packages/flutter_midi_command_ble"
version="${tag#flutter_midi_command_ble-v}"
;;
flutter_midi_command-v*)
package_name="flutter_midi_command"
package_dir="."
version="${tag#flutter_midi_command-v}"
;;
*)
echo "Unsupported tag: $tag" >&2
exit 1
;;
esac

echo "package_name=$package_name" >> "$GITHUB_OUTPUT"
echo "package_dir=$package_dir" >> "$GITHUB_OUTPUT"
echo "version=$version" >> "$GITHUB_OUTPUT"

- name: Verify tag matches pubspec version
shell: bash
working-directory: ${{ steps.package.outputs.package_dir }}
run: |
set -euo pipefail

package_name="$(grep '^name:' pubspec.yaml | head -n1 | cut -d' ' -f2)"
pubspec_version="$(grep '^version:' pubspec.yaml | head -n1 | cut -d' ' -f2)"

test "$package_name" = "${{ steps.package.outputs.package_name }}"
test "$pubspec_version" = "${{ steps.package.outputs.version }}"

- name: Run publish dry run
working-directory: ${{ steps.package.outputs.package_dir }}
run: flutter pub publish --dry-run

- name: Publish package
working-directory: ${{ steps.package.outputs.package_dir }}
run: flutter pub publish --force
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,15 @@
.packages
.pub/
pubspec.lock
pubspec_overrides.yaml

build/
local.properties
.idea/
*.iml
packages/flutter_midi_command_darwin/ios/.build/
/example/.vscode
/.vscode
/example/ios/Flutter/ephemeral
packages/flutter_midi_command_ble/.flutter-plugins-dependencies
example/android/app/.cxx
28 changes: 28 additions & 0 deletions .pubignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Workspace-only dependency linking.
pubspec_overrides.yaml
example/pubspec_overrides.yaml
packages/**/pubspec_overrides.yaml

# Keep federated package sources publishable from their own directories.
# Ignoring `packages/` here hides nested package pubspecs during `pub publish`.

# Local IDE/workspace artifacts.
*.iml
.idea/
.vscode/

# Generated API docs are published separately.
doc/api/

# Build and tool caches.
build/
**/build/
.dart_tool/
**/.dart_tool/
.pub/
**/.pub/

# Flutter-generated local files.
local.properties
example/ios/Flutter/ephemeral/
example/android/app/.cxx/
16 changes: 15 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
## 1.0.0
- Aligned CI to Flutter `3.44.2` so the newer BLE dependency resolves in GitHub Actions.
- Resolved the Windows example build failure caused by deprecated coroutine headers in older `universal_ble` releases.
- Restructured into a melos-managed federated monorepo.
- Bumped federated subpackages to 1.0.0 for the major API transition.
- Introduced shared BLE transport package (`flutter_midi_command_ble`) and optional BLE wiring via `configureBleTransport`.
- Migrated host API contracts to generated Pigeon interfaces.
- Added typed host models (`MidiDeviceType`, `MidiHostDevice`, `MidiPort`, `MidiPacket`) across platform bridges.
- Added web implementation package (`flutter_midi_command_web`) using browser Web MIDI.
- Added transport capabilities/policies and stronger async connection semantics (`connectToDevice` completes on connection).
- Added a typed MIDI parser/generator API (`MidiMessageParser` and `MidiMessage.parse`) with support for running status, realtime interleaving, SysEx, and NRPN/RPN message flows.
- Expanded test coverage across shared logic, platform interface, BLE transport, and web backend.
- Updated the example app with separate transport toggles plus distinct `Refresh Devices` and `Scan BLE` controls.
- Improved Windows MIDI enumeration with hot-plug device updates and better multi-port full-duplex pairing.

## 0.5.3
Adds a runtime check to ensure MIDI is available on the android device before starting. See #125 for further details.
Make plugin work with Flutter 3.27.0 and Android Studio Lady Bug. #127
Expand Down Expand Up @@ -238,4 +253,3 @@ Readme and formatting
Initial Release.
Functioning discovery and connection to MIDI devices on Android and iOS, as well as BLE MIDI devices on Android.
Functioning sending and receiving of MIDI data

Loading
Loading