Skip to content

Commit

Permalink
Merge pull request #53 from adafruit/useful-repr
Browse files Browse the repository at this point in the history
Give all MIDIMessage objects a useful repr()
  • Loading branch information
jepler committed May 20, 2023
2 parents 100b723 + f89b137 commit c041f8a
Show file tree
Hide file tree
Showing 22 changed files with 60 additions and 36 deletions.
1 change: 1 addition & 0 deletions adafruit_midi/channel_pressure.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class ChannelPressure(MIDIMessage):
:param int pressure: The pressure, 0-127.
"""

_message_slots = ["pressure", "channel"]
_STATUS = 0xD0
_STATUSMASK = 0xF0
LENGTH = 2
Expand Down
1 change: 1 addition & 0 deletions adafruit_midi/control_change.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class ControlChange(MIDIMessage):
"""

_message_slots = ["control", "value", "channel"]
_STATUS = 0xB0
_STATUSMASK = 0xF0
LENGTH = 3
Expand Down
2 changes: 2 additions & 0 deletions adafruit_midi/midi_continue.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
class Continue(MIDIMessage):
"""Continue MIDI message."""

_message_slots = []

_STATUS = 0xFB
_STATUSMASK = 0xFF
LENGTH = 1
Expand Down
17 changes: 17 additions & 0 deletions adafruit_midi/midi_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,20 @@ def from_bytes(cls, msg_bytes):
representation of the MIDI message."""
return cls()

def __str__(self):
"""Print an instance"""
cls = self.__class__
if slots := getattr(cls, "_message_slots", None):
# pylint: disable=not-an-iterable
args = ", ".join(
f"{name}={repr(getattr(self, name, None))}" for name in slots
)
else:
args = "..."
return f"{self.__class__.__name__}({args})"

__repr__ = __str__


# DO NOT try to register these messages
class MIDIUnknownEvent(MIDIMessage):
Expand All @@ -296,6 +310,7 @@ class MIDIUnknownEvent(MIDIMessage):
or because it is not imported.
"""

_message_slots = ["status"]
LENGTH = -1

def __init__(self, status):
Expand All @@ -316,6 +331,8 @@ class MIDIBadEvent(MIDIMessage):

LENGTH = -1

_message_slots = ["msg_bytes", "exception"]

def __init__(self, msg_bytes, exception):
self.data = bytes(msg_bytes)
self.exception_text = repr(exception)
Expand Down
2 changes: 2 additions & 0 deletions adafruit_midi/mtc_quarter_frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ class MtcQuarterFrame(MIDIMessage):
:param value: The quarter frame value for the specified type.
"""

_message_slots = ["msgtype", "value"]

_STATUS = 0xF1
_STATUSMASK = 0xFF
LENGTH = 2
Expand Down
1 change: 1 addition & 0 deletions adafruit_midi/note_off.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class NoteOff(MIDIMessage): # pylint: disable=duplicate-code
"""

_message_slots = ["note", "velocity", "channel"]
_STATUS = 0x80
_STATUSMASK = 0xF0
LENGTH = 3
Expand Down
2 changes: 2 additions & 0 deletions adafruit_midi/note_on.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ class NoteOn(MIDIMessage):
to a Note Off, defaults to 127.
"""

_message_slots = ["note", "velocity", "channel"]

_STATUS = 0x90
_STATUSMASK = 0xF0
LENGTH = 3
Expand Down
1 change: 1 addition & 0 deletions adafruit_midi/pitch_bend.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class PitchBend(MIDIMessage):
bend from 0 through 8192 (midpoint, no bend) to 16383.
"""

_message_slots = ["pitch_bend", "channel"]
_STATUS = 0xE0
_STATUSMASK = 0xF0
LENGTH = 3
Expand Down
1 change: 1 addition & 0 deletions adafruit_midi/polyphonic_key_pressure.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class PolyphonicKeyPressure(MIDIMessage):
:param int pressure: The pressure, 0-127.
"""

_message_slots = ["note", "pressure", "channel"]
_STATUS = 0xA0
_STATUSMASK = 0xF0
LENGTH = 3
Expand Down
1 change: 1 addition & 0 deletions adafruit_midi/program_change.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class ProgramChange(MIDIMessage):
:param int patch: The new program/patch number to use, 0-127.
"""

_message_slots = ["patch", "channel"]
_STATUS = 0xC0
_STATUSMASK = 0xF0
LENGTH = 2
Expand Down
1 change: 1 addition & 0 deletions adafruit_midi/start.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class Start(MIDIMessage):
_STATUS = 0xFA
_STATUSMASK = 0xFF
LENGTH = 1
_message_slots = []


Start.register_message_type()
1 change: 1 addition & 0 deletions adafruit_midi/stop.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class Stop(MIDIMessage):
_STATUS = 0xFC
_STATUSMASK = 0xFF
LENGTH = 1
_message_slots = []


Stop.register_message_type()
1 change: 1 addition & 0 deletions adafruit_midi/system_exclusive.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class SystemExclusive(MIDIMessage):
This message can only be parsed if it fits within the input buffer in :class:MIDI.
"""

_message_slots = ["manufacturer_id", "data"]
_STATUS = 0xF0
_STATUSMASK = 0xFF
LENGTH = -1
Expand Down
1 change: 1 addition & 0 deletions adafruit_midi/timing_clock.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class TimingClock(MIDIMessage):
_STATUS = 0xF8
_STATUSMASK = 0xFF
LENGTH = 1
_slots = []


TimingClock.register_message_type()
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
#
# SPDX-License-Identifier: MIT

import datetime
import os
import sys
import datetime

sys.path.insert(0, os.path.abspath(".."))

Expand Down
13 changes: 7 additions & 6 deletions examples/midi_inoutdemo.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,13 @@
# midi_inoutdemo - demonstrates receiving and sending MIDI events

import usb_midi
import adafruit_midi

# TimingClock is worth importing first if present as it
# will make parsing more efficient for this high frequency event
# Only importing what is used will save a little bit of memory
import adafruit_midi

# pylint: disable=unused-import
from adafruit_midi.timing_clock import TimingClock
from adafruit_midi.channel_pressure import ChannelPressure
from adafruit_midi.control_change import ControlChange
from adafruit_midi.midi_message import MIDIUnknownEvent
from adafruit_midi.note_off import NoteOff
from adafruit_midi.note_on import NoteOn
from adafruit_midi.pitch_bend import PitchBend
Expand All @@ -22,8 +19,12 @@
from adafruit_midi.start import Start
from adafruit_midi.stop import Stop
from adafruit_midi.system_exclusive import SystemExclusive
from adafruit_midi.timing_clock import TimingClock

# TimingClock is worth importing first if present as it
# will make parsing more efficient for this high frequency event
# Only importing what is used will save a little bit of memory

from adafruit_midi.midi_message import MIDIUnknownEvent

midi = adafruit_midi.MIDI(
midi_in=usb_midi.ports[0],
Expand Down
22 changes: 7 additions & 15 deletions examples/midi_intest1.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,28 @@
# SPDX-License-Identifier: MIT

import time

import usb_midi

import adafruit_midi

# A subset of messages/events
# pylint: disable=unused-import
from adafruit_midi.timing_clock import TimingClock

# from adafruit_midi.channel_pressure import ChannelPressure
from adafruit_midi.control_change import ControlChange
from adafruit_midi.note_off import NoteOff
from adafruit_midi.note_on import NoteOn
from adafruit_midi.pitch_bend import PitchBend

from adafruit_midi.timing_clock import TimingClock

# 0 is MIDI channel 1
midi = adafruit_midi.MIDI(midi_in=usb_midi.ports[0], in_channel=0)

print("Midi input test with pauses")
print("Midi input test")

# Convert channel numbers at the presentation layer to the ones musicians use
print("Input channel:", midi.in_channel + 1)

# play with the pause to simulate code doing other stuff
# in the loop
pauses = [0] * 10 + [0.010] * 10 + [0.100] * 10 + [1.0] * 10

while True:
for pause in pauses:
msg = midi.receive()
if msg is not None:
print(time.monotonic(), msg)
if pause:
time.sleep(pause)
msg = midi.receive()
if msg is not None:
print(time.monotonic(), msg)
4 changes: 2 additions & 2 deletions examples/midi_memorycheck.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
#
# E: 8,21: Module 'gc' has no 'mem_free' member (no-member)

import time
import random
import gc
import random
import time

gc.collect()
print(gc.mem_free())
Expand Down
4 changes: 3 additions & 1 deletion examples/midi_simpletest.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
# SPDX-License-Identifier: MIT
# simple_test
import time
import random
import time

import usb_midi

import adafruit_midi
from adafruit_midi.control_change import ControlChange
from adafruit_midi.note_off import NoteOff
Expand Down
4 changes: 1 addition & 3 deletions tests/test_MIDIMessage_unittests.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@

# pylint: disable=invalid-name

import unittest


import os
import unittest

verbose = int(os.getenv("TESTVERBOSE", "2"))

Expand Down
11 changes: 5 additions & 6 deletions tests/test_MIDI_unittests.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,11 @@

# pylint: disable=invalid-name

import os
import random
import unittest
from unittest.mock import Mock, call

import random
import os

verbose = int(os.getenv("TESTVERBOSE", "2"))

# pylint: disable=wrong-import-position
Expand All @@ -21,6 +20,9 @@
# Borrowing the dhalbert/tannewt technique from adafruit/Adafruit_CircuitPython_Motor
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))

# Import after messages - opposite to other test file
import adafruit_midi

# Full monty
from adafruit_midi.channel_pressure import ChannelPressure
from adafruit_midi.control_change import ControlChange
Expand All @@ -29,9 +31,6 @@
from adafruit_midi.pitch_bend import PitchBend
from adafruit_midi.system_exclusive import SystemExclusive

# Import after messages - opposite to other test file
import adafruit_midi

# pylint: enable=wrong-import-position


Expand Down
3 changes: 1 addition & 2 deletions tests/test_note_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@
#
# SPDX-License-Identifier: MIT

import unittest

import os
import unittest

verbose = int(os.getenv("TESTVERBOSE", "2"))

Expand Down

0 comments on commit c041f8a

Please sign in to comment.