Skip to content
Open
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
108 changes: 108 additions & 0 deletions lib/guid.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
class Guid {
final List<int> bytes;

Guid.empty() : bytes = List.filled(16, 0);

Guid.fromBytes(this.bytes)
: assert(_checkLen(bytes.length), 'GUID must be 16, 32, or 128 bit.');

Guid.fromString(String input) : bytes = _fromString(input);

Guid(String input) : bytes = _fromString(input);

static List<int> _fromString(String input) {
if (input.isEmpty) {
return List.filled(16, 0);
}

input = input.replaceAll('-', '');

List<int>? bytes = _tryHexDecode(input);
if (bytes == null) {
throw FormatException("GUID not hex format: $input");
}

_checkLen(bytes.length);

return bytes;
}

static bool _checkLen(int len) {
if (!(len == 16 || len == 4 || len == 2)) {
throw FormatException(
"GUID must be 16, 32, or 128 bit, yours: ${len * 8}-bit",
);
}
return true;
}

static List<int>? _tryHexDecode(String hex) {
List<int> numbers = [];
for (int i = 0; i < hex.length; i += 2) {
String hexPart = hex.substring(i, i + 2);
int? num = int.tryParse(hexPart, radix: 16);
if (num == null) {
return null;
}
numbers.add(num);
}
return numbers;
}

// 128-bit representation
String get str128 {
if (bytes.length == 2) {
// 16-bit uuid
return '0000${_hexEncode(bytes)}-0000-1000-8000-00805f9b34fb'
.toLowerCase();
}
if (bytes.length == 4) {
// 32-bit uuid
return '${_hexEncode(bytes)}-0000-1000-8000-00805f9b34fb'.toLowerCase();
}
// 128-bit uuid
String one = _hexEncode(bytes.sublist(0, 4));
String two = _hexEncode(bytes.sublist(4, 6));
String three = _hexEncode(bytes.sublist(6, 8));
String four = _hexEncode(bytes.sublist(8, 10));
String five = _hexEncode(bytes.sublist(10, 16));
return "$one-$two-$three-$four-$five".toLowerCase();
}

// shortest representation
String get str {
bool starts = str128.startsWith('0000');
bool ends = str128.contains('-0000-1000-8000-00805f9b34fb');
if (starts && ends) {
// 16-bit
return str128.substring(4, 8);
}
if (ends) {
// 32-bit
return str128.substring(0, 8);
}
// 128-bit
return str128;
}

@override
String toString() => str;

@override
operator ==(other) => other is Guid && hashCode == other.hashCode;

@override
int get hashCode => str128.hashCode;

@Deprecated('use str128 instead')
String get uuid128 => str128;

@Deprecated('use str instead')
String get uuid => str;

String _hexEncode(List<int> numbers) {
return numbers
.map((n) => (n & 0xFF).toRadixString(16).padLeft(2, '0'))
.join();
}
}
5 changes: 5 additions & 0 deletions lib/method_channel_midi_command.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ class MethodChannelMidiCommand extends MidiCommandPlatform {
map["type"], map["connected"] == "true");
dev.inputPorts = _portsFromDevice(map["inputs"], MidiPortType.IN);
dev.outputPorts = _portsFromDevice(map["outputs"], MidiPortType.OUT);
dev.serviceUUIDs = (map["serviceUUIDs"] is List)
? (map["serviceUUIDs"] as List)
.map((e) => Guid(e.toString()))
.toList()
: [];
return dev;
}).toList();
}
Expand Down
4 changes: 4 additions & 0 deletions lib/midi_device.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import 'package:flutter_midi_command_platform_interface/midi_port.dart';
import 'package:flutter_midi_command_platform_interface/guid.dart';

export 'guid.dart';

class MidiDevice {
String name;
Expand All @@ -7,6 +10,7 @@ class MidiDevice {
List<MidiPort> inputPorts = [];
List<MidiPort> outputPorts = [];
bool connected;
List<Guid> serviceUUIDs = [];

MidiDevice(this.id, this.name, this.type, this.connected);

Expand Down