Skip to content

Commit

Permalink
fix: handle iter-/generators correctly in MidiOut.send_message (#186)
Browse files Browse the repository at this point in the history
Signed-off-by: Christopher Arndt <[email protected]>
  • Loading branch information
SpotlightKid authored Oct 23, 2023
1 parent c0b9381 commit c77fb34
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 8 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ help:
@echo "release - package a release"
@echo "release_upload - package a release and upload it to PyPI"
@echo "requirements - generate 'requirement-dev.txt' from 'requirements-dev.in'"
@echo "test - run tests on every supported Python version with tox"
@echo "test - run tests with pytest"

build: $(SOURCES)
if [[ -d "$(BUILDDIR)" ]]; then \
Expand Down
11 changes: 8 additions & 3 deletions src/_rtmidi.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -1101,11 +1101,16 @@ cdef class MidiOut(MidiBase):
if not message:
raise ValueError("'message' must not be empty.")

if len(message) > 3 and message[0] != 0xF0:
raise ValueError("'message' longer than 3 bytes but does not "
"start with 0xF0.")
try:
msg_v.reserve(len(message))
except TypeError:
pass

for c in message:
msg_v.push_back(c)

if msg_v.size() > 3 and msg_v.at(0) != 0xF0:
raise ValueError("'message' longer than 3 bytes but does not "
"start with 0xF0.")

self.thisptr.sendMessage(&msg_v)
31 changes: 27 additions & 4 deletions tests/test_rtmidi.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
class BaseTests:
NOTE_ON = [0x90, 48, 100]
NOTE_OFF = [0x80, 48, 16]
SYSEX_IDENTITY_REQUEST = [0xF0, 0x7E, 0x7F, 6, 1, 0xF7]
IN_CLIENT_NAME = "RtMidiTestCase In"
OUT_CLIENT_NAME = "RtMidiTestCase Out"
IN_PORT_NAME = 'testin'
Expand Down Expand Up @@ -67,10 +68,32 @@ def test_send_and_get_message(self):
self.midi_out.send_message(self.NOTE_ON)
self.midi_out.send_message(self.NOTE_OFF)
time.sleep(self.DELAY)
message_1, _ = self.midi_in.get_message()
message_2, _ = self.midi_in.get_message()
self.assertEqual(message_1, self.NOTE_ON)
self.assertEqual(message_2, self.NOTE_OFF)
event_1 = self.midi_in.get_message()
event_2 = self.midi_in.get_message()
self.assertTrue(isinstance(event_1, tuple))
self.assertTrue(isinstance(event_2, tuple))
self.assertEqual(event_1[0], self.NOTE_ON)
self.assertEqual(event_2[0], self.NOTE_OFF)

def test_send_supports_iterator(self):
self.set_up_loopback()
self.midi_out.send_message(iter(self.NOTE_ON))
time.sleep(self.DELAY)
event = self.midi_in.get_message()
self.assertTrue(isinstance(event, tuple))
self.assertEqual(event[0], self.NOTE_ON)

def test_send_raises_if_message_too_long(self):
self.assertRaises(ValueError, self.midi_out.send_message, [1, 2, 3, 4])

def test_send_accepts_sysex(self):
self.set_up_loopback()
self.midi_in.ignore_types(sysex=False)
self.midi_out.send_message(self.SYSEX_IDENTITY_REQUEST)
time.sleep(self.DELAY)
event = self.midi_in.get_message()
self.assertTrue(isinstance(event, tuple))
self.assertEqual(event[0], self.SYSEX_IDENTITY_REQUEST)

def test_callback(self):
messages = []
Expand Down

0 comments on commit c77fb34

Please sign in to comment.