File: midi_file_player.py

package info (click to toggle)
python-jack-client 0.5.3-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, forky, sid, trixie
  • size: 356 kB
  • sloc: python: 2,123; makefile: 6
file content (74 lines) | stat: -rwxr-xr-x 1,735 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#!/usr/bin/env python3
"""Play a MIDI file.

This uses the "mido" module for handling MIDI: https://mido.readthedocs.io/

Pass the MIDI file name as first command line argument.

If a MIDI port name is passed as second argument, a connection is made.

"""
import sys
import threading

import jack
from mido import MidiFile

argv = iter(sys.argv)
next(argv)
filename = next(argv, '')
connect_to = next(argv, '')
if not filename:
    sys.exit('Please specify a MIDI file')
try:
    mid = iter(MidiFile(filename))
except Exception as e:
    sys.exit(type(e).__name__ + ' while loading MIDI: ' + str(e))

client = jack.Client('MIDI-File-Player')
port = client.midi_outports.register('output')
event = threading.Event()
msg = next(mid)
fs = None  # sampling rate
offset = 0


@client.set_process_callback
def process(frames):
    global offset
    global msg
    port.clear_buffer()
    while True:
        if offset >= frames:
            offset -= frames
            return  # We'll take care of this in the next block ...
        # Note: This may raise an exception:
        port.write_midi_event(offset, msg.bytes())
        try:
            msg = next(mid)
        except StopIteration:
            event.set()
            raise jack.CallbackExit
        offset += round(msg.time * fs)


@client.set_samplerate_callback
def samplerate(samplerate):
    global fs
    fs = samplerate


@client.set_shutdown_callback
def shutdown(status, reason):
    print('JACK shutdown:', reason, status)
    event.set()


with client:
    if connect_to:
        port.connect(connect_to)
    print('Playing', repr(filename), '... press Ctrl+C to stop')
    try:
        event.wait()
    except KeyboardInterrupt:
        print('\nInterrupted by user')