diff --git a/Makefile b/Makefile index 8517754..e979335 100644 --- a/Makefile +++ b/Makefile @@ -172,11 +172,12 @@ install: # Install script files and binaries install -m 755 \ + data/cadence_* \ + data/cadence-aloop-daemon \ data/catarina \ data/catia \ data/claudia \ data/carla \ - data/cadence_* \ src/carla-bridge-ui/carla-bridge-lv2-gtk2 \ src/carla-bridge-ui/carla-bridge-lv2-qt4 \ src/carla-bridge-ui/carla-bridge-lv2-x11 \ @@ -232,6 +233,7 @@ install: uninstall: rm -f $(DESTDIR)$(PREFIX)/bin/cadence_* + rm -f $(DESTDIR)$(PREFIX)/bin/cadence-aloop-daemon rm -f $(DESTDIR)$(PREFIX)/bin/catarina rm -f $(DESTDIR)$(PREFIX)/bin/catia rm -f $(DESTDIR)$(PREFIX)/bin/claudia diff --git a/data/cadence-aloop-daemon b/data/cadence-aloop-daemon new file mode 100755 index 0000000..e1ff692 --- /dev/null +++ b/data/cadence-aloop-daemon @@ -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)