Skip to content

Give all MIDIMessage objects a useful repr() #53

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
May 20, 2023
Merged
Show file tree
Hide file tree
Changes from 2 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
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
17 changes: 9 additions & 8 deletions examples/midi_inoutdemo.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,11 @@
# 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

# pylint: disable=unused-import
from adafruit_midi.timing_clock import TimingClock
import adafruit_midi
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 @@ -23,7 +18,13 @@
from adafruit_midi.stop import Stop
from adafruit_midi.system_exclusive import SystemExclusive

from adafruit_midi.midi_message import MIDIUnknownEvent
# pylint: disable=unused-import
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


midi = adafruit_midi.MIDI(
midi_in=usb_midi.ports[0],
Expand Down
24 changes: 9 additions & 15 deletions examples/midi_intest1.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,30 @@
# 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
import adafruit_midi

# 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

# A subset of messages/events
# pylint: disable=unused-import
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