From f04e50fdbff0984f994876e92fdabda4ed15864b Mon Sep 17 00:00:00 2001 From: Maksim Lin Date: Thu, 10 Feb 2022 09:10:16 +1100 Subject: [PATCH 1/5] add sending midi messages --- example/lib/fire_midi.dart | 26 +++++++++++++++++++++++++ example/lib/main.dart | 8 ++++++++ lib/flutter_midi_command_web.dart | 16 +++++++++------ test/flutter_midi_command_web_test.dart | 18 +---------------- 4 files changed, 45 insertions(+), 23 deletions(-) create mode 100644 example/lib/fire_midi.dart diff --git a/example/lib/fire_midi.dart b/example/lib/fire_midi.dart new file mode 100644 index 0000000..4197076 --- /dev/null +++ b/example/lib/fire_midi.dart @@ -0,0 +1,26 @@ +List fireAllPads(int r, int g, int b) { + const sysexHeader = [ + 0xF0, + 0x47, + 0x7F, + 0x43, + 0x65, + 0x02, + 0x00, // mesg length - low byte + ]; + const sysexFooter = [ + 0xF7, // End of Exclusive + ]; + final allLeds = []; + for (int idx = 0; idx < 64; idx++) { + final ledData = [ + idx, + r, + g, + b, + ]; + allLeds.addAll(ledData); + } + final midiData = [...sysexHeader, ...allLeds, ...sysexFooter]; + return midiData; +} diff --git a/example/lib/main.dart b/example/lib/main.dart index e37b6a4..b422930 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -4,6 +4,7 @@ import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:flutter_midi_command/flutter_midi_command.dart'; +import 'package:flutter_midi_command_web_example/fire_midi.dart'; void main() { runApp(const MyApp()); @@ -76,6 +77,13 @@ class _MyAppState extends State { }), ), Text('Last midi: $lastMidiMesg'), + MaterialButton( + child: Text('FIRE ALL PADS OFF'), + onPressed: () { + print('send all off'); + _midiCommand.sendData( + Uint8List.fromList(fireAllPads(0, 10, 70))); + }) ], ); })), diff --git a/lib/flutter_midi_command_web.dart b/lib/flutter_midi_command_web.dart index 4fc62f4..1127f1d 100644 --- a/lib/flutter_midi_command_web.dart +++ b/lib/flutter_midi_command_web.dart @@ -122,18 +122,22 @@ class FlutterMidiCommandWeb extends MidiCommandPlatform { @override void teardown() { - //TODO: go through and call disconnect on all devics, then close rx stream + //TODO: go through and call disconnect on all devices, then close rx stream } - /// Sends data to the currently connected device.wmidi hardware driver name + /// Sends data to the currently connected devices /// /// Data is an UInt8List of individual MIDI command bytes. @override void sendData(Uint8List data, {int? timestamp, String? deviceId}) { - // _connectedDevices.values.forEach((device) { - // // print("send to $device"); - // device.send(data, data.length); - // }); + final outputPorts = []; + _connectedDevices.forEach((device) { + outputPorts.addAll(_webMidiOutputs.where((p) => p.name == device.name)); + }); + print("send to devices: $data"); + for (var outport in outputPorts) { + outport.send(data, 1); + } } /// Stream firing events whenever a midi package is received. diff --git a/test/flutter_midi_command_web_test.dart b/test/flutter_midi_command_web_test.dart index e9375b3..5c7e0ba 100644 --- a/test/flutter_midi_command_web_test.dart +++ b/test/flutter_midi_command_web_test.dart @@ -1,19 +1,3 @@ -import 'package:flutter/services.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:flutter_midi_command_web/flutter_midi_command_web.dart'; - void main() { - const MethodChannel channel = MethodChannel('flutter_midi_command_web'); - - TestWidgetsFlutterBinding.ensureInitialized(); - - setUp(() { - channel.setMockMethodCallHandler((MethodCall methodCall) async { - return '42'; - }); - }); - - tearDown(() { - channel.setMockMethodCallHandler(null); - }); + //TODO } From dc7d0aff8fce7cded1aa3b218c64d80c2cbba7c4 Mon Sep 17 00:00:00 2001 From: Maksim Lin Date: Thu, 10 Feb 2022 13:04:13 +1100 Subject: [PATCH 2/5] use latest js bindings, remove js_utils workaround --- example/lib/main.dart | 2 +- example/pubspec.lock | 2 +- lib/flutter_midi_command_web.dart | 11 ++++++++--- pubspec.lock | 2 +- pubspec.yaml | 2 +- 5 files changed, 12 insertions(+), 7 deletions(-) diff --git a/example/lib/main.dart b/example/lib/main.dart index b422930..1a715b3 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -82,7 +82,7 @@ class _MyAppState extends State { onPressed: () { print('send all off'); _midiCommand.sendData( - Uint8List.fromList(fireAllPads(0, 10, 70))); + Uint8List.fromList(fireAllPads(0, 0, 0))); }) ], ); diff --git a/example/pubspec.lock b/example/pubspec.lock index c520c22..7c97ef2 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -120,7 +120,7 @@ packages: name: js_bindings url: "https://pub.dartlang.org" source: hosted - version: "0.0.5" + version: "0.0.6-dev" matcher: dependency: transitive description: diff --git a/lib/flutter_midi_command_web.dart b/lib/flutter_midi_command_web.dart index 1127f1d..b523408 100644 --- a/lib/flutter_midi_command_web.dart +++ b/lib/flutter_midi_command_web.dart @@ -1,5 +1,4 @@ import 'dart:async'; -import 'dart:js_util' as js_util; import 'dart:typed_data'; import 'package:flutter/foundation.dart'; @@ -41,8 +40,14 @@ class FlutterMidiCommandWeb extends MidiCommandPlatform { .requestMIDIAccess(html.MIDIOptions(sysex: true, software: false)); // deal with bug: https://github.com/dart-lang/sdk/issues/33248 - js_util.callMethod(access.inputs, 'forEach', [allowInterop(_getInputs)]); - js_util.callMethod(access.outputs, 'forEach', [allowInterop(_getOutputs)]); + // js_util.callMethod(access.inputs, 'forEach', [allowInterop(_getInputs)]); + // js_util.callMethod(access.outputs, 'forEach', [allowInterop(_getOutputs)]); + access.inputs.forEach((a, b, c) { + _getInputs(a, b, c); + }); + access.outputs.forEach((a, b, c) { + _getOutputs(a, b, c); + }); } void _getInputs(dynamic a, dynamic b, dynamic c) { diff --git a/pubspec.lock b/pubspec.lock index 810854a..efcb082 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -92,7 +92,7 @@ packages: name: js_bindings url: "https://pub.dartlang.org" source: hosted - version: "0.0.5" + version: "0.0.6-dev" lints: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 4aad713..d5fc2bd 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -21,7 +21,7 @@ dependencies: sdk: flutter flutter_midi_command_platform_interface: ^0.3.2 js: ^0.6.4 - js_bindings: 0.0.5 + js_bindings: 0.0.6-dev dev_dependencies: flutter_lints: ^1.0.0 From b5c7a78a957ca73d8daa52ac5d9c72abfa421886 Mon Sep 17 00:00:00 2001 From: Maksim Lin Date: Thu, 10 Feb 2022 14:28:29 +1100 Subject: [PATCH 3/5] handle exception thrown due to Flutter SDK bug --- lib/flutter_midi_command_web.dart | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/flutter_midi_command_web.dart b/lib/flutter_midi_command_web.dart index b523408..1548759 100644 --- a/lib/flutter_midi_command_web.dart +++ b/lib/flutter_midi_command_web.dart @@ -141,7 +141,12 @@ class FlutterMidiCommandWeb extends MidiCommandPlatform { }); print("send to devices: $data"); for (var outport in outputPorts) { - outport.send(data, 1); + try { + outport.send(data, 1); + } catch (e, _) { + // currently bug in Dart-JS interop: https://github.com/flutter/flutter/issues/94945#issuecomment-1033596770 + print('Flutter Bug: #94945 caught: $e'); + } } } From 8905e52e00b26d8f493035dac4f682c70d788f02 Mon Sep 17 00:00:00 2001 From: Maksim Lin Date: Thu, 10 Feb 2022 17:00:52 +1100 Subject: [PATCH 4/5] add docs for example app --- example/README.md | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/example/README.md b/example/README.md index 507fc14..30af8bf 100644 --- a/example/README.md +++ b/example/README.md @@ -4,13 +4,6 @@ Demonstrates how to use the flutter_midi_command_web plugin. ## Getting Started -This project is a starting point for a Flutter application. +This example is intended to work with an Akai Fire midi-controller, but incoming midi events should be displayed for any midi controller, while the demonstration of sending midi data is Fire specific. -A few resources to get you started if this is your first Flutter project: - -- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) -- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) - -For help getting started with Flutter, view our -[online documentation](https://flutter.dev/docs), which offers tutorials, -samples, guidance on mobile development, and a full API reference. +Note: currently there is a bug with displaying the listview of available midi devices on app start, so you need to do a hot-reload in order to get the listview items ui to appear. \ No newline at end of file From c2e4081f6e37f24e844a69ab4b4e58af115dca84 Mon Sep 17 00:00:00 2001 From: Maksim Lin Date: Thu, 10 Feb 2022 18:19:44 +1100 Subject: [PATCH 5/5] update to latest ver of platform interface --- example/pubspec.lock | 19 ++++++------------- lib/flutter_midi_command_web.dart | 3 ++- pubspec.lock | 2 +- pubspec.yaml | 2 +- 4 files changed, 10 insertions(+), 16 deletions(-) diff --git a/example/pubspec.lock b/example/pubspec.lock index 7c97ef2..4acc3a2 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -75,21 +75,21 @@ packages: path: "../../FlutterMidiCommand" relative: true source: path - version: "0.3.0" + version: "0.4.2" flutter_midi_command_linux: dependency: transitive description: - path: "../../flutter_midi_command_linux" - relative: true - source: path - version: "0.2.0" + name: flutter_midi_command_linux + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.5" flutter_midi_command_platform_interface: dependency: transitive description: name: flutter_midi_command_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "0.3.4" + version: "0.4.0" flutter_midi_command_web: dependency: transitive description: @@ -142,13 +142,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.7.0" - midi: - dependency: transitive - description: - name: midi - url: "https://pub.dartlang.org" - source: hosted - version: "0.0.2" path: dependency: transitive description: diff --git a/lib/flutter_midi_command_web.dart b/lib/flutter_midi_command_web.dart index 1548759..e3830da 100644 --- a/lib/flutter_midi_command_web.dart +++ b/lib/flutter_midi_command_web.dart @@ -94,7 +94,8 @@ class FlutterMidiCommandWeb extends MidiCommandPlatform { /// Connects to the device. @override - void connectToDevice(MidiDevice device, {List? ports}) { + Future connectToDevice(MidiDevice device, + {List? ports}) async { // connect up incoming webmidi data to our rx stream of MidiPackets final inputPorts = _webMidiInputs.where((p) => p.name == device.name); for (var inport in inputPorts) { diff --git a/pubspec.lock b/pubspec.lock index efcb082..08ecdf7 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -68,7 +68,7 @@ packages: name: flutter_midi_command_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "0.3.4" + version: "0.4.0" flutter_test: dependency: "direct dev" description: flutter diff --git a/pubspec.yaml b/pubspec.yaml index d5fc2bd..fb1aaba 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -19,7 +19,7 @@ dependencies: sdk: flutter flutter_web_plugins: sdk: flutter - flutter_midi_command_platform_interface: ^0.3.2 + flutter_midi_command_platform_interface: ^0.4.0 js: ^0.6.4 js_bindings: 0.0.6-dev