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 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
|
#!/usr/bin/env python3
"""Create a JACK client that copies input audio directly to the outputs.
This is somewhat modeled after the "thru_client.c" example of JACK 2:
http://github.com/jackaudio/jack2/blob/master/example-clients/thru_client.c
If you have a microphone and loudspeakers connected, this might cause an
acoustical feedback!
"""
import sys
import signal
import os
import jack
import threading
if sys.version_info < (3, 0):
# In Python 2.x, event.wait() cannot be interrupted with Ctrl+C.
# Therefore, we disable the whole KeyboardInterrupt mechanism.
# This will not close the JACK client properly, but at least we can
# use Ctrl+C.
signal.signal(signal.SIGINT, signal.SIG_DFL)
else:
# If you use Python 3.x, everything is fine.
pass
argv = iter(sys.argv)
# By default, use script name without extension as client name:
defaultclientname = os.path.splitext(os.path.basename(next(argv)))[0]
clientname = next(argv, defaultclientname)
servername = next(argv, None)
client = jack.Client(clientname, servername=servername)
if client.status.server_started:
print('JACK server started')
if client.status.name_not_unique:
print('unique name {0!r} assigned'.format(client.name))
event = threading.Event()
@client.set_process_callback
def process(frames):
assert len(client.inports) == len(client.outports)
assert frames == client.blocksize
for i, o in zip(client.inports, client.outports):
o.get_buffer()[:] = i.get_buffer()
@client.set_shutdown_callback
def shutdown(status, reason):
print('JACK shutdown!')
print('status:', status)
print('reason:', reason)
event.set()
# create two port pairs
for number in 1, 2:
client.inports.register('input_{0}'.format(number))
client.outports.register('output_{0}'.format(number))
with client:
# When entering this with-statement, client.activate() is called.
# This tells the JACK server that we are ready to roll.
# Our process() callback will start running now.
# Connect the ports. You can't do this before the client is activated,
# because we can't make connections to clients that aren't running.
# Note the confusing (but necessary) orientation of the driver backend
# ports: playback ports are "input" to the backend, and capture ports
# are "output" from it.
capture = client.get_ports(is_physical=True, is_output=True)
if not capture:
raise RuntimeError('No physical capture ports')
for src, dest in zip(capture, client.inports):
client.connect(src, dest)
playback = client.get_ports(is_physical=True, is_input=True)
if not playback:
raise RuntimeError('No physical playback ports')
for src, dest in zip(client.outports, playback):
client.connect(src, dest)
print('Press Ctrl+C to stop')
try:
event.wait()
except KeyboardInterrupt:
print('\nInterrupted by user')
# When the above with-statement is left (either because the end of the
# code block is reached, or because an exception was raised inside),
# client.deactivate() and client.close() are called automatically.
|