Parsing and Encoding Messages¶
MIDI is a binary protocol, which means when sending a message to a device, it is encoded as one or more consecutive bytes.
The input and output ports will decode and encode messages for you, so unless you’re implementing a new MIDI backend or a file reader / writer, there is little use for this.
Message objects have a few methods that make encoding easy:
>>> n = Message('note_on', channel=2, note=60, velocity=100, time=3)
>>> n.bytes()
[146, 60, 100]
>>> n.hex()
'92 3C 64'
>>> n.hex(sep='-')
'92-3C-64'
>>> n.bin()
bytearray(b'\x92<d')
System Exclusive messages include the end byte (0xf7):
>>> Message('sysex', data=[1, 2, 3]).hex()
'F0 01 02 03 F7'
This means, the sysex_end() message type is needed.
For the full table of MIDI binary encoding, see: http://www.midi.org/techspecs/midimessages.php
Parsing Messages¶
If you’re implementing a new port type or support for a binary file format, you may need to parse binary MIDI messages. Mido has a few functions and one class that make this easy.
To parse a single message:
>>> mido.parse([0x92, 0x10, 0x20])
<note_on message channel=0, note=16, velocity=32, time=0>
parse()
will only return the first message in the byte stream. To
get all messages, use parse_all()
.
The functions are just shortcuts for the full Parser
class. This is the parser used inside input ports to parse incoming
messages. Here are a few examples of how it can be used:
>>> p = mido.Parser()
>>> p.feed([0x90, 0x10, 0x20])
>>> p.pending()
1
>>> p.get_message()
<note_on message channel=0, note=16, velocity=32, time=0>
>>> p.feed_byte(0x90)
>>> p.feed_byte(0x10)
>>> p.feed_byte(0x20)
>>> p.get_message()
<note_on message channel=0, note=16, velocity=32, time=0>
get_message() will return None if there are no messages ready to be gotten.
feed() accepts any iterable that generates integers in 0..255. This includes:
p.feed([0x90, 0x10, 0x20])
p.feed((i for i in range(256)))
The messages will stay in an internal queue intil you pull them out with get_message() or for message in parser:.
The parser will skip and stray status bytes or data bytes, so you can safely feed it random data and see what comes out the other end.