circuitpython-tmidi 1.0.5__tar.gz → 2.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. {circuitpython_tmidi-1.0.5 → circuitpython_tmidi-2.0.0}/PKG-INFO +10 -3
  2. {circuitpython_tmidi-1.0.5 → circuitpython_tmidi-2.0.0}/README.rst +9 -2
  3. {circuitpython_tmidi-1.0.5 → circuitpython_tmidi-2.0.0}/circuitpython_tmidi.egg-info/PKG-INFO +10 -3
  4. {circuitpython_tmidi-1.0.5 → circuitpython_tmidi-2.0.0}/circuitpython_tmidi.egg-info/SOURCES.txt +3 -0
  5. circuitpython_tmidi-2.0.0/docs/examples.rst +37 -0
  6. circuitpython_tmidi-2.0.0/examples/tmidi_simple_arpeggiator.py +58 -0
  7. {circuitpython_tmidi-1.0.5 → circuitpython_tmidi-2.0.0}/examples/tmidi_simple_receiver.py +16 -2
  8. {circuitpython_tmidi-1.0.5 → circuitpython_tmidi-2.0.0}/examples/tmidi_simpletest.py +2 -2
  9. {circuitpython_tmidi-1.0.5 → circuitpython_tmidi-2.0.0}/pyproject.toml +1 -1
  10. circuitpython_tmidi-2.0.0/tests/__init__.py +2 -0
  11. circuitpython_tmidi-2.0.0/tests/test_tmidi_messages.py +46 -0
  12. {circuitpython_tmidi-1.0.5 → circuitpython_tmidi-2.0.0}/tests/test_tmidi_one.py +1 -1
  13. {circuitpython_tmidi-1.0.5 → circuitpython_tmidi-2.0.0}/tmidi.py +79 -21
  14. circuitpython_tmidi-1.0.5/docs/examples.rst +0 -18
  15. {circuitpython_tmidi-1.0.5 → circuitpython_tmidi-2.0.0}/.github/PULL_REQUEST_TEMPLATE/adafruit_circuitpython_pr.md +0 -0
  16. {circuitpython_tmidi-1.0.5 → circuitpython_tmidi-2.0.0}/.github/workflows/build.yml +0 -0
  17. {circuitpython_tmidi-1.0.5 → circuitpython_tmidi-2.0.0}/.github/workflows/failure-help-text.yml +0 -0
  18. {circuitpython_tmidi-1.0.5 → circuitpython_tmidi-2.0.0}/.github/workflows/release_gh.yml +0 -0
  19. {circuitpython_tmidi-1.0.5 → circuitpython_tmidi-2.0.0}/.github/workflows/release_pypi.yml +0 -0
  20. {circuitpython_tmidi-1.0.5 → circuitpython_tmidi-2.0.0}/.gitignore +0 -0
  21. {circuitpython_tmidi-1.0.5 → circuitpython_tmidi-2.0.0}/.pre-commit-config.yaml +0 -0
  22. {circuitpython_tmidi-1.0.5 → circuitpython_tmidi-2.0.0}/.pylintrc +0 -0
  23. {circuitpython_tmidi-1.0.5 → circuitpython_tmidi-2.0.0}/.readthedocs.yaml +0 -0
  24. {circuitpython_tmidi-1.0.5 → circuitpython_tmidi-2.0.0}/CODE_OF_CONDUCT.md +0 -0
  25. {circuitpython_tmidi-1.0.5 → circuitpython_tmidi-2.0.0}/LICENSE +0 -0
  26. {circuitpython_tmidi-1.0.5 → circuitpython_tmidi-2.0.0}/LICENSES/CC-BY-4.0.txt +0 -0
  27. {circuitpython_tmidi-1.0.5 → circuitpython_tmidi-2.0.0}/LICENSES/MIT.txt +0 -0
  28. {circuitpython_tmidi-1.0.5 → circuitpython_tmidi-2.0.0}/LICENSES/Unlicense.txt +0 -0
  29. {circuitpython_tmidi-1.0.5 → circuitpython_tmidi-2.0.0}/README.rst.license +0 -0
  30. {circuitpython_tmidi-1.0.5 → circuitpython_tmidi-2.0.0}/circuitpython_tmidi.egg-info/dependency_links.txt +0 -0
  31. {circuitpython_tmidi-1.0.5 → circuitpython_tmidi-2.0.0}/circuitpython_tmidi.egg-info/requires.txt +0 -0
  32. {circuitpython_tmidi-1.0.5 → circuitpython_tmidi-2.0.0}/circuitpython_tmidi.egg-info/top_level.txt +0 -0
  33. {circuitpython_tmidi-1.0.5 → circuitpython_tmidi-2.0.0}/docs/_static/favicon.ico +0 -0
  34. {circuitpython_tmidi-1.0.5 → circuitpython_tmidi-2.0.0}/docs/_static/favicon.ico.license +0 -0
  35. {circuitpython_tmidi-1.0.5 → circuitpython_tmidi-2.0.0}/docs/api.rst +0 -0
  36. {circuitpython_tmidi-1.0.5 → circuitpython_tmidi-2.0.0}/docs/api.rst.license +0 -0
  37. {circuitpython_tmidi-1.0.5 → circuitpython_tmidi-2.0.0}/docs/conf.py +0 -0
  38. {circuitpython_tmidi-1.0.5 → circuitpython_tmidi-2.0.0}/docs/examples.rst.license +0 -0
  39. {circuitpython_tmidi-1.0.5 → circuitpython_tmidi-2.0.0}/docs/index.rst +0 -0
  40. {circuitpython_tmidi-1.0.5 → circuitpython_tmidi-2.0.0}/docs/index.rst.license +0 -0
  41. {circuitpython_tmidi-1.0.5 → circuitpython_tmidi-2.0.0}/docs/requirements.txt +0 -0
  42. {circuitpython_tmidi-1.0.5 → circuitpython_tmidi-2.0.0}/examples/tmidi_midiforwarder.py +0 -0
  43. {circuitpython_tmidi-1.0.5 → circuitpython_tmidi-2.0.0}/examples/tmidi_multiple_receiver.py +0 -0
  44. {circuitpython_tmidi-1.0.5 → circuitpython_tmidi-2.0.0}/optional_requirements.txt +0 -0
  45. {circuitpython_tmidi-1.0.5 → circuitpython_tmidi-2.0.0}/requirements.txt +0 -0
  46. {circuitpython_tmidi-1.0.5 → circuitpython_tmidi-2.0.0}/setup.cfg +0 -0
  47. {circuitpython_tmidi-1.0.5 → circuitpython_tmidi-2.0.0}/tests/test_one.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: circuitpython-tmidi
3
- Version: 1.0.5
3
+ Version: 2.0.0
4
4
  Summary: MIDI library for CircuitPython
5
5
  Author-email: Tod Kurt <tod@todbot.com>
6
6
  License: MIT
@@ -109,8 +109,9 @@ Usage Example
109
109
 
110
110
  midi_usb = tmidi.MIDI(midi_in=usb_midi.ports[0], midi_out=usb_midi.ports[1])
111
111
 
112
- def send_midi_panic(channel=1):
113
- msg = tmidi.Message(tmidi.NOTE_OFF, channel-1) # channels are 0-indexed
112
+ def send_midi_panic(midi_channel=1):
113
+ ch = midi_channel-1
114
+ msg = tmidi.Message(tmidi.NOTE_OFF, channel=ch) # channels are 0-indexed
114
115
  for notenum in range(128):
115
116
  msg.note = notenum
116
117
  msg.velocity = 0
@@ -128,6 +129,12 @@ API documentation for this library can be found on `Read the Docs <https://circu
128
129
  For information on building library documentation, please check out
129
130
  `this guide <https://learn.adafruit.com/creating-and-sharing-a-circuitpython-library/sharing-our-docs-on-readthedocs#sphinx-5-1>`_.
130
131
 
132
+ Testing
133
+ =======
134
+
135
+ Install ``pytest`` with ``pip3 install pytest --upgrade`` and run ``pytest -v``
136
+ To build docs:
137
+
131
138
  Contributing
132
139
  ============
133
140
 
@@ -89,8 +89,9 @@ Usage Example
89
89
 
90
90
  midi_usb = tmidi.MIDI(midi_in=usb_midi.ports[0], midi_out=usb_midi.ports[1])
91
91
 
92
- def send_midi_panic(channel=1):
93
- msg = tmidi.Message(tmidi.NOTE_OFF, channel-1) # channels are 0-indexed
92
+ def send_midi_panic(midi_channel=1):
93
+ ch = midi_channel-1
94
+ msg = tmidi.Message(tmidi.NOTE_OFF, channel=ch) # channels are 0-indexed
94
95
  for notenum in range(128):
95
96
  msg.note = notenum
96
97
  msg.velocity = 0
@@ -108,6 +109,12 @@ API documentation for this library can be found on `Read the Docs <https://circu
108
109
  For information on building library documentation, please check out
109
110
  `this guide <https://learn.adafruit.com/creating-and-sharing-a-circuitpython-library/sharing-our-docs-on-readthedocs#sphinx-5-1>`_.
110
111
 
112
+ Testing
113
+ =======
114
+
115
+ Install ``pytest`` with ``pip3 install pytest --upgrade`` and run ``pytest -v``
116
+ To build docs:
117
+
111
118
  Contributing
112
119
  ============
113
120
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: circuitpython-tmidi
3
- Version: 1.0.5
3
+ Version: 2.0.0
4
4
  Summary: MIDI library for CircuitPython
5
5
  Author-email: Tod Kurt <tod@todbot.com>
6
6
  License: MIT
@@ -109,8 +109,9 @@ Usage Example
109
109
 
110
110
  midi_usb = tmidi.MIDI(midi_in=usb_midi.ports[0], midi_out=usb_midi.ports[1])
111
111
 
112
- def send_midi_panic(channel=1):
113
- msg = tmidi.Message(tmidi.NOTE_OFF, channel-1) # channels are 0-indexed
112
+ def send_midi_panic(midi_channel=1):
113
+ ch = midi_channel-1
114
+ msg = tmidi.Message(tmidi.NOTE_OFF, channel=ch) # channels are 0-indexed
114
115
  for notenum in range(128):
115
116
  msg.note = notenum
116
117
  msg.velocity = 0
@@ -128,6 +129,12 @@ API documentation for this library can be found on `Read the Docs <https://circu
128
129
  For information on building library documentation, please check out
129
130
  `this guide <https://learn.adafruit.com/creating-and-sharing-a-circuitpython-library/sharing-our-docs-on-readthedocs#sphinx-5-1>`_.
130
131
 
132
+ Testing
133
+ =======
134
+
135
+ Install ``pytest`` with ``pip3 install pytest --upgrade`` and run ``pytest -v``
136
+ To build docs:
137
+
131
138
  Contributing
132
139
  ============
133
140
 
@@ -35,7 +35,10 @@ docs/_static/favicon.ico
35
35
  docs/_static/favicon.ico.license
36
36
  examples/tmidi_midiforwarder.py
37
37
  examples/tmidi_multiple_receiver.py
38
+ examples/tmidi_simple_arpeggiator.py
38
39
  examples/tmidi_simple_receiver.py
39
40
  examples/tmidi_simpletest.py
41
+ tests/__init__.py
40
42
  tests/test_one.py
43
+ tests/test_tmidi_messages.py
41
44
  tests/test_tmidi_one.py
@@ -0,0 +1,37 @@
1
+ Simple test
2
+ ------------
3
+
4
+ Show how to send MIDI messages.
5
+
6
+ .. literalinclude:: ../examples/tmidi_simpletest.py
7
+ :caption: examples/tmidi_simpletest.py
8
+ :linenos:
9
+
10
+
11
+ Simple receiver
12
+ ---------------
13
+
14
+ Show to to receive MIDI messages.
15
+
16
+ .. literalinclude:: ../examples/tmidi_simple_receiver.py
17
+ :caption: examples/tmidi_simple_receiver.py
18
+ :linenos:
19
+
20
+
21
+ Multiple receivers
22
+ ------------------
23
+
24
+ Show to to receive MIDI messages from multiple receivers.
25
+
26
+ .. literalinclude:: ../examples/tmidi_multiple_receiver.py
27
+ :caption: examples/tmidi_multiple_receiver.py
28
+ :linenos:
29
+
30
+ Simple arpeggiator
31
+ ------------------
32
+
33
+ Implement a simple arpeggiator that receives MIDI and sends it
34
+
35
+ .. literalinclude:: ../examples/tmidi_simple_arpeggiator.py
36
+ :caption: examples/tmidi_simple_arpeggiator.py
37
+ :linenos:
@@ -0,0 +1,58 @@
1
+ # SPDX-FileCopyrightText: Copyright (c) 2024 Tod Kurt
2
+ #
3
+ # SPDX-License-Identifier: MIT
4
+
5
+ # This example shows both receiving and sending MIDI messages
6
+ # by implementing a simple arpeggiator.
7
+ # MIDI notes send to MIDI In are arpeggiated to MIDI Output.
8
+
9
+ import time
10
+ import usb_midi
11
+ import tmidi
12
+
13
+ midi = tmidi.MIDI(midi_in=usb_midi.ports[0], midi_out=usb_midi.ports[1])
14
+ # if serial midi
15
+ # uart = busio.UART(rx=board.RX, tx=board.TX, timeout=0.000)
16
+ # midi = tmidi.MIDI(midi_in=uart, midi_out=uart)
17
+
18
+ tempo = 120 # bpm
19
+ notes_per_beat = 2 # 1 = quarter-note, 2 = 8th, 4 = 16th
20
+ note_time = 60 / tempo / notes_per_beat
21
+ gate_percent = 0.5
22
+
23
+ pressed_notes = []
24
+ note_i = 0
25
+ last_note_time = 0
26
+ gate_time = 0
27
+ while True:
28
+ # handle midi input
29
+ if msg := midi.receive():
30
+ if msg.type == tmidi.NOTE_ON and msg.velocity > 0:
31
+ print("note on", msg)
32
+ pressed_notes.append(msg.note)
33
+ elif msg.type == tmidi.NOTE_OFF or (
34
+ msg.type == tmidi.NOTE_ON and msg.velocity == 0
35
+ ):
36
+ if msg.note in pressed_notes:
37
+ midi.send(msg) # send the note off
38
+ pressed_notes.remove(msg.note)
39
+ note_i = 0
40
+
41
+ # do midi output
42
+ if len(pressed_notes) == 0:
43
+ continue
44
+
45
+ now = time.monotonic()
46
+ if now - last_note_time >= note_time:
47
+ last_note_time = now
48
+ note_on = tmidi.Message(tmidi.NOTE_ON, pressed_notes[note_i], 127)
49
+ print("arp note_on: ", note_on)
50
+ midi.send(note_on)
51
+ gate_time = note_time * gate_percent
52
+
53
+ if gate_time > 0 and now - last_note_time >= gate_time:
54
+ gate_time = 0
55
+ note_off = tmidi.Message(tmidi.NOTE_OFF, pressed_notes[note_i], 127)
56
+ print("arp note_off:", note_off)
57
+ midi.send(note_off)
58
+ note_i = (note_i + 1) % len(pressed_notes)
@@ -12,6 +12,20 @@ midi_usb = tmidi.MIDI(midi_in=usb_midi.ports[0], midi_out=usb_midi.ports[1])
12
12
  while True:
13
13
  if msg := midi_usb.receive():
14
14
  if msg.type == tmidi.NOTE_ON and msg.velocity > 0:
15
- print("note on: ", msg.note, msg.velocity)
15
+ print(
16
+ "note on: note:",
17
+ msg.note,
18
+ "vel:",
19
+ msg.velocity,
20
+ "channel:",
21
+ msg.channel,
22
+ )
16
23
  elif msg.type == tmidi.NOTE_OFF or msg.velocity == 0:
17
- print("note off:", msg.note, msg.velocity)
24
+ print(
25
+ "note off: note:",
26
+ msg.note,
27
+ "vel:",
28
+ msg.velocity,
29
+ "channel:",
30
+ msg.channel,
31
+ )
@@ -18,12 +18,12 @@ while True:
18
18
  notenum = random.randint(36, 72)
19
19
  velocity = 127
20
20
 
21
- msg_on = tmidi.Message(tmidi.NOTE_ON, midi_channel - 1, notenum, velocity)
21
+ msg_on = tmidi.Message(tmidi.NOTE_ON, notenum, velocity, channel=midi_channel - 1)
22
22
  print("sending note on msg:", msg_on)
23
23
  midi_usb.send(msg_on)
24
24
  time.sleep(0.1)
25
25
 
26
- msg_off = tmidi.Message(tmidi.NOTE_OFF, midi_channel - 1, notenum, 0)
26
+ msg_off = tmidi.Message(tmidi.NOTE_OFF, notenum, 0, channel=midi_channel - 1)
27
27
  print("sending note off msg:", msg_off)
28
28
  midi_usb.send(msg_off)
29
29
  time.sleep(0.2)
@@ -13,7 +13,7 @@ requires = [
13
13
  [project]
14
14
  name = "circuitpython-tmidi"
15
15
  description = "MIDI library for CircuitPython"
16
- version = "1.0.5"
16
+ version = "2.0.0"
17
17
  readme = "README.rst"
18
18
  authors = [
19
19
  {name = "Tod Kurt", email = "tod@todbot.com"}
@@ -0,0 +1,2 @@
1
+ # SPDX-FileCopyrightText: Copyright (c) 2024 Tod Kurt
2
+ # SPDX-License-Identifier: MIT
@@ -0,0 +1,46 @@
1
+ # SPDX-FileCopyrightText: Copyright (c) 2024 Tod Kurt
2
+ # SPDX-License-Identifier: MIT
3
+
4
+
5
+ import tmidi
6
+
7
+
8
+ class PortStub:
9
+ def __init__(self, data):
10
+ self.data = data
11
+ self.expected = None
12
+
13
+ def write(self, buf, nbytes):
14
+ assert self.expected == list(buf)
15
+
16
+
17
+ def test_message_note_on():
18
+ msg = tmidi.Message(tmidi.NOTE_ON, 64, 123)
19
+ assert str(msg) == "Message(NoteOn ch:0 64 123)"
20
+
21
+
22
+ def test_message_program_change():
23
+ msg = tmidi.Message(tmidi.PROGRAM_CHANGE, 120, channel=11)
24
+ assert str(msg) == "Message(ProgramChange ch:11 120)"
25
+
26
+
27
+ def test_message_note_on_send():
28
+ port = PortStub(iter([]))
29
+ midi_out = tmidi.MIDI(midi_out=port)
30
+
31
+ msg = tmidi.Message(tmidi.NOTE_ON, 64, 123)
32
+ port.expected = [0x90, 64, 123]
33
+ midi_out.send(msg)
34
+
35
+ msg = tmidi.Message(tmidi.NOTE_ON, 32, 111, channel=3)
36
+ port.expected = [0x93, 32, 111]
37
+ midi_out.send(msg)
38
+
39
+
40
+ def test_message_program_change_send():
41
+ port = PortStub(iter([]))
42
+ midi_out = tmidi.MIDI(midi_out=port)
43
+
44
+ msg = tmidi.Message(tmidi.PROGRAM_CHANGE, 33)
45
+ port.expected = [0xC0, 33]
46
+ midi_out.send(msg)
@@ -32,7 +32,7 @@ class PortStub:
32
32
 
33
33
  return bytes_read
34
34
 
35
- def write(self, buf):
35
+ def write(self, buf, n):
36
36
  pass
37
37
 
38
38
 
@@ -32,7 +32,7 @@ Implementation Notes
32
32
 
33
33
  # imports
34
34
 
35
- __version__ = "1.0.5"
35
+ __version__ = "2.0.0"
36
36
  __repo__ = "https://github.com/todbot/CircuitPython_TMIDI.git"
37
37
 
38
38
  # Portions of this library come from Winterbloom_SmolMIDI:
@@ -144,7 +144,6 @@ _MSG_TYPE_NAMES = {
144
144
  }
145
145
 
146
146
 
147
- # pylint: disable=chained-comparison
148
147
  def _is_channel_message(status_byte):
149
148
  return status_byte >= NOTE_OFF and status_byte < SYSEX
150
149
 
@@ -174,25 +173,37 @@ class Message:
174
173
  MIDI Message.
175
174
 
176
175
  :param mtype: The type of message, e.g. tmidi.NOTE_ON.
177
- :param channel: The MIDI channel for this message, if applicable (0-15)
178
176
  :param data0: The first data byte for this message,
179
177
  e.g. the note number as an ``int`` (0-127) for NOTE_ON messages.
180
178
  :param data1: The second data byte for this message,
181
179
  e.g. the velocity (0-127) for NOTE_ON messages.
180
+ :param channel: The MIDI channel for this message, if applicable (0-15)
181
+
182
+ Example of creating Messages:
183
+
184
+ .. code-block:: python
185
+
186
+ # create Note On middle-C message on ch 1 (0-indexed)
187
+ m = Message(tmidi.NOTE_ON, 60, 127, channel=0)
188
+ # create CC 74 with val 63 on ch 4
189
+ m = Message(tmidi.CC, 74, 63, channel=4-1)
190
+ # create a pitch bend full up on ch 1
191
+ m = Message(tmidi.PITCH_BEND, 8191)
192
+
193
+ Example of creating accessing Message attributes:
194
+
195
+ .. code-block:: python
196
+
197
+ if msg := midi.receive():
198
+ if msg.type == tmidi.NOTE_ON:
199
+ print("note on:", msg.note, msg.velocity)
200
+ elif msg.type == tmidi.NOTE_OFF:
201
+ print("note off:", msg.note, msg.velocity)
202
+ elif msg.type == tmidi.PROGRAM_CHANGE:
203
+ print("program change:", msg.value)
182
204
  """
183
205
 
184
- def __init__(self, mtype=SYSTEM_RESET, channel=None, data0=0, data1=0):
185
- """
186
- Create a MIDI Message.
187
-
188
- Example::
189
- # create Note On middle-C message on ch1 (0-indexed)
190
- m = Message(tmidi.NOTE_ON, 0, 60, 127)
191
- # create CC 74 with val 63 on ch 4
192
- m = Message(tmidi.CC, 3, 74, 63)
193
- # create a pitch bend full up on ch 1
194
- m = Message(tmidi.PITCH_BEND, 0, 8191)
195
- """
206
+ def __init__(self, mtype=SYSTEM_RESET, data0=0, data1=0, channel=0):
196
207
  self.type = mtype
197
208
  self.channel = channel
198
209
  self.data0 = data0
@@ -204,16 +215,15 @@ class Message:
204
215
  status_byte = self.type
205
216
  if _is_channel_message(status_byte):
206
217
  status_byte |= self.channel
207
- if status_byte in _LEN_2_MESSAGES:
218
+ if self.type in _LEN_2_MESSAGES:
208
219
  return bytes([status_byte, self.data0, self.data1])
209
- if status_byte in _LEN_1_MESSAGES:
220
+ elif self.type in _LEN_1_MESSAGES:
210
221
  return bytes([status_byte, self.data0])
211
222
  return bytes([status_byte])
212
223
 
213
224
  def __repr__(self):
214
225
  return self.__str__()
215
226
 
216
- # pylint: disable=consider-using-f-string
217
227
  def __str__(self):
218
228
  mtype = self.type
219
229
  type_str = "Message(" + _MSG_TYPE_NAMES.get(mtype, "Unknown")
@@ -246,7 +256,7 @@ class Message:
246
256
 
247
257
  @property
248
258
  def pitch_bend(self):
249
- """Pitch bend value of message (only for PITCH_BEND msgs)"""
259
+ """Pitch bend value of message (only valid for PITCH_BEND msgs)"""
250
260
  return (self.data1 << 7 | self.data0) - 8192
251
261
 
252
262
  @pitch_bend.setter
@@ -255,10 +265,19 @@ class Message:
255
265
  self.data0 = pbval & 0x7F
256
266
  self.data1 = pbval >> 7
257
267
 
268
+ @property
269
+ def value(self):
270
+ """Message value, only valid for len1 messages (Program Change, etc)"""
271
+ return self.data0
272
+
273
+ @value.setter
274
+ def value(self, val):
275
+ self.data0 = val
276
+
258
277
 
259
278
  class MIDI:
260
279
  """
261
- MIDI Parser and sender
280
+ MIDI Parser, receiver and sender
262
281
  ``midi_in`` or ``midi_out`` *must* be set or both together.
263
282
 
264
283
  :param midi_in: an object which implements ``read(length)``,
@@ -266,6 +285,46 @@ class MIDI:
266
285
  :param midi_out: an object which implements ``write(buffer, length)``,
267
286
  set to ``usb_midi.ports[1]`` for USB MIDI, default None.
268
287
  :param bool enable_running_status: Allow running status messages to work, default False.
288
+
289
+ Example of sending MIDI over USB:
290
+
291
+ .. code-block:: python
292
+
293
+ import usb_midi
294
+ import tmidi
295
+ midi_usb = tmidi.MIDI(midi_out=usb_midi.ports[1])
296
+ msg_on = tmidi.Message(tmidi.NOTE_ON, notenum, velocity)
297
+ midi_usb.send(msg_on)
298
+
299
+ Example of sending MIDI over UART (TRS or 5-pin):
300
+
301
+ .. code-block:: python
302
+
303
+ import board
304
+ import busio
305
+ import tmidi
306
+ uart = busio.UART(tx=board.TX, rx=board.RX, timeout=0.001)
307
+ midi_uart = tmidi.MIDI(midi_out=uart)
308
+ msg_on = tmidi.Message(tmidi.NOTE_ON, notenum, velocity)
309
+ midi_uart.send(msg_on)
310
+
311
+ Example of receiving MIDI:
312
+
313
+ .. code-block:: python
314
+
315
+ import board
316
+ import busio
317
+ import usb_midi
318
+ import tmidi
319
+ uart = busio.UART(tx=board.TX, rx=board.RX, timeout=0.001)
320
+ midi_uart = tmidi.MIDI(midi_in=uart, midi_out=uart)
321
+ midi_usb = tmidi.MIDI(midi_in=usb_midi.ports[0], midi_out=usb_midi.ports[1])
322
+
323
+ while True:
324
+ if msg := midi_usb.receive():
325
+ print("usb midi:", msg)
326
+ if msg := midi_uart.receive():
327
+ print("uart midi:", msg)
269
328
  """
270
329
 
271
330
  def __init__(self, midi_in=None, midi_out=None, enable_running_status=False):
@@ -341,7 +400,6 @@ class MIDI:
341
400
 
342
401
  return message
343
402
 
344
- # pylint: disable=unnecessary-dunder-call
345
403
  def send(self, msg, channel=None):
346
404
  """Send a MIDI message.
347
405
 
@@ -1,18 +0,0 @@
1
- Simple test
2
- ------------
3
-
4
- Show how to send MIDI messages.
5
-
6
- .. literalinclude:: ../examples/tmidi_simpletest.py
7
- :caption: examples/tmidi_simpletest.py
8
- :linenos:
9
-
10
-
11
- Simple receiver
12
- ---------------
13
-
14
- Show to to receive MIDI messages.
15
-
16
- .. literalinclude:: ../examples/tmidi_simple_receiver.py
17
- :caption: examples/tmidi_simple_receiver.py
18
- :linenos: