|
|
@@ -0,0 +1,181 @@ |
|
|
|
#!/usr/bin/env python |
|
|
|
# -*- coding: utf-8 -*- |
|
|
|
|
|
|
|
# Imports (Global) |
|
|
|
from ctypes import * |
|
|
|
from os import system |
|
|
|
from sys import version_info |
|
|
|
from signal import signal, SIGINT, SIGTERM |
|
|
|
from time import sleep |
|
|
|
|
|
|
|
# -------------------------------------------------- |
|
|
|
# Test for python 3.x |
|
|
|
|
|
|
|
if (version_info >= (3,0)): |
|
|
|
PYTHON3 = True |
|
|
|
else: |
|
|
|
PYTHON3 = False |
|
|
|
|
|
|
|
# -------------------------------------------------- |
|
|
|
# Global loop check |
|
|
|
|
|
|
|
global doLoop, doRunNow |
|
|
|
doLoop = True |
|
|
|
doRunNow = True |
|
|
|
|
|
|
|
# -------------------------------------------------- |
|
|
|
# Global JACK variables |
|
|
|
|
|
|
|
global sample_rate, buffer_size |
|
|
|
sample_rate = 44100 |
|
|
|
buffer_size = 1024 |
|
|
|
|
|
|
|
# -------------------------------------------------- |
|
|
|
# JACK ctypes implementation |
|
|
|
|
|
|
|
jacklib = cdll.LoadLibrary("libjack.so.0") |
|
|
|
|
|
|
|
class jack_client_t(Structure): |
|
|
|
_fields_ = [] |
|
|
|
|
|
|
|
jack_nframes_t = c_uint32 |
|
|
|
|
|
|
|
JackBufferSizeCallback = CFUNCTYPE(c_int, jack_nframes_t, c_void_p) |
|
|
|
JackShutdownCallback = CFUNCTYPE(None, c_void_p) |
|
|
|
|
|
|
|
jacklib.jack_client_open.argtypes = [c_char_p, c_int, POINTER(c_int)] |
|
|
|
jacklib.jack_client_open.restype = POINTER(jack_client_t) |
|
|
|
|
|
|
|
jacklib.jack_client_close.argtypes = [POINTER(jack_client_t)] |
|
|
|
jacklib.jack_client_close.restype = c_int |
|
|
|
|
|
|
|
jacklib.jack_activate.argtypes = [POINTER(jack_client_t)] |
|
|
|
jacklib.jack_activate.restype = c_int |
|
|
|
|
|
|
|
jacklib.jack_deactivate.argtypes = [POINTER(jack_client_t)] |
|
|
|
jacklib.jack_deactivate.restype = c_int |
|
|
|
|
|
|
|
jacklib.jack_connect.argtypes = [POINTER(jack_client_t), c_char_p, c_char_p] |
|
|
|
jacklib.jack_connect.restype = c_int |
|
|
|
|
|
|
|
jacklib.jack_get_sample_rate.argtypes = [POINTER(jack_client_t)] |
|
|
|
jacklib.jack_get_sample_rate.restype = jack_nframes_t |
|
|
|
|
|
|
|
jacklib.jack_get_buffer_size.argtypes = [POINTER(jack_client_t)] |
|
|
|
jacklib.jack_get_buffer_size.restype = jack_nframes_t |
|
|
|
|
|
|
|
jacklib.jack_on_shutdown.argtypes = [POINTER(jack_client_t), JackShutdownCallback, c_void_p] |
|
|
|
jacklib.jack_on_shutdown.restype = None |
|
|
|
|
|
|
|
jacklib.jack_set_buffer_size_callback.argtypes = [POINTER(jack_client_t), JackBufferSizeCallback, c_void_p] |
|
|
|
jacklib.jack_set_buffer_size_callback.restype = c_int |
|
|
|
|
|
|
|
def jack_client_open(client_name, options, status): |
|
|
|
if (PYTHON3): client_name = client_name.encode("ascii") |
|
|
|
return jacklib.jack_client_open(client_name, options, status) |
|
|
|
|
|
|
|
def jack_client_close(client): |
|
|
|
return jacklib.jack_client_close(client) |
|
|
|
|
|
|
|
def jack_activate(client): |
|
|
|
return jacklib.jack_activate(client) |
|
|
|
|
|
|
|
def jack_deactivate(client): |
|
|
|
return jacklib.jack_deactivate(client) |
|
|
|
|
|
|
|
def jack_connect(client, source_port, destination_port): |
|
|
|
if (PYTHON3): source_port = source_port.encode("ascii") |
|
|
|
if (PYTHON3): destination_port = destination_port.encode("ascii") |
|
|
|
return jacklib.jack_connect(client, source_port, destination_port) |
|
|
|
|
|
|
|
def jack_get_sample_rate(client): |
|
|
|
return jacklib.jack_get_sample_rate(client) |
|
|
|
|
|
|
|
def jack_get_buffer_size(client): |
|
|
|
return jacklib.jack_get_buffer_size(client) |
|
|
|
|
|
|
|
def jack_on_shutdown(client, shutdown_callback, arg): |
|
|
|
global _shutdown_callback |
|
|
|
_shutdown_callback = JackShutdownCallback(shutdown_callback) |
|
|
|
jacklib.jack_on_shutdown(client, _shutdown_callback, arg) |
|
|
|
|
|
|
|
def jack_set_buffer_size_callback(client, bufsize_callback, arg): |
|
|
|
global _bufsize_callback |
|
|
|
_bufsize_callback = JackBufferSizeCallback(bufsize_callback) |
|
|
|
return jacklib.jack_set_buffer_size_callback(client, _bufsize_callback, arg) |
|
|
|
|
|
|
|
# -------------------------------------------------- |
|
|
|
# quit on SIGINT or SIGTERM |
|
|
|
|
|
|
|
def signal_handler(sig, frame=0): |
|
|
|
global doLoop |
|
|
|
doLoop = False |
|
|
|
|
|
|
|
# -------------------------------------------------- |
|
|
|
# listen to jack buffer size changes |
|
|
|
|
|
|
|
def buffer_size_callback(new_buffer_size, arg): |
|
|
|
global doRunNow, buffer_size |
|
|
|
buffer_size = new_buffer_size |
|
|
|
doRunNow = True |
|
|
|
return 0 |
|
|
|
|
|
|
|
# -------------------------------------------------- |
|
|
|
# listen to jack shutdown |
|
|
|
|
|
|
|
def shutdown_callback(arg): |
|
|
|
global doLoop |
|
|
|
doLoop = False |
|
|
|
|
|
|
|
# -------------------------------------------------- |
|
|
|
# run alsa_in and alsa_out |
|
|
|
def run_alsa_bridge(): |
|
|
|
global sample_rate, buffer_size |
|
|
|
system("killall alsa_in alsa_out zita-a2j zita-j2a pulseaudio") |
|
|
|
|
|
|
|
#if (False): |
|
|
|
system("env JACK_SAMPLE_RATE=%i JACK_PERIOD_SIZE=%i alsa_in -j alsa2jack -d cloop -q 1 2>&1 1> /dev/null &" % (sample_rate, buffer_size)) |
|
|
|
system("env JACK_SAMPLE_RATE=%i JACK_PERIOD_SIZE=%i alsa_out -j jack2alsa -d ploop -q 1 2>&1 1> /dev/null &" % (sample_rate, buffer_size)) |
|
|
|
#else: |
|
|
|
#system("env JACK_SAMPLE_RATE=%i JACK_PERIOD_SIZE=%i zita-a2j -j alsa2jack -d hw:Loopback,1,0 -r 44100 &" % (sample_rate, buffer_size)) |
|
|
|
#system("env JACK_SAMPLE_RATE=%i JACK_PERIOD_SIZE=%i zita-j2a -j jack2alsa -d hw:Loopback,1,1 -r 44100 &" % (sample_rate, buffer_size)) |
|
|
|
|
|
|
|
# Pause it for a bit, and connect to the system ports |
|
|
|
sleep(1) |
|
|
|
jack_connect(client, "alsa2jack:capture_1", "system:playback_1") |
|
|
|
jack_connect(client, "alsa2jack:capture_2", "system:playback_2") |
|
|
|
jack_connect(client, "system:capture_1", "jack2alsa:playback_1") |
|
|
|
jack_connect(client, "system:capture_2", "jack2alsa:playback_2") |
|
|
|
|
|
|
|
#--------------- main ------------------ |
|
|
|
if __name__ == '__main__': |
|
|
|
|
|
|
|
# Init JACK client |
|
|
|
client = jack_client_open("jack-aloop-daemon", 0, None) |
|
|
|
|
|
|
|
if (not client): |
|
|
|
quit() |
|
|
|
|
|
|
|
jack_set_buffer_size_callback(client, buffer_size_callback, None) |
|
|
|
jack_on_shutdown(client, shutdown_callback, None) |
|
|
|
|
|
|
|
jack_activate(client) |
|
|
|
|
|
|
|
# Quit when requested |
|
|
|
signal(SIGINT, signal_handler) |
|
|
|
signal(SIGTERM, signal_handler) |
|
|
|
|
|
|
|
# Get initial values |
|
|
|
sample_rate = jack_get_sample_rate(client) |
|
|
|
buffer_size = jack_get_buffer_size(client) |
|
|
|
|
|
|
|
# Keep running until told otherwise |
|
|
|
while (doLoop): |
|
|
|
if (doRunNow): |
|
|
|
doRunNow = False |
|
|
|
run_alsa_bridge() |
|
|
|
sleep(1) |
|
|
|
|
|
|
|
# Close JACK client |
|
|
|
jack_deactivate(client) |
|
|
|
jack_client_close(client) |