cadence/src/cadence_aloop_daemon.py

169 lines
5.4 KiB
Python
Executable File

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Imports (Global)
import os, sys
from signal import signal, SIGINT, SIGTERM
from time import sleep
from PyQt4.QtCore import QProcess
# Imports (Custom Stuff)
import jacklib
# --------------------------------------------------
# Global loop check
global doLoop, doRunNow, useZita, procIn, procOut
doLoop = True
doRunNow = True
useZita = False
procIn = QProcess()
procOut = QProcess()
checkFile = "/tmp/.cadence-aloop-daemon.x"
# --------------------------------------------------
# Global JACK variables
global bufferSize, sampleRate, channels
bufferSize = 1024
sampleRate = 44100
channels = 2
# --------------------------------------------------
# quit on SIGINT or SIGTERM
def signal_handler(sig, frame=0):
global doLoop
doLoop = False
# --------------------------------------------------
# listen to jack buffer-size and sample-rate changes
def buffer_size_callback(newBufferSize, arg):
global doRunNow, bufferSize
bufferSize = newBufferSize
doRunNow = True
return 0
def sample_rate_callback(newSampleRate, arg):
global doRunNow, sampleRate
sampleRate = newSampleRate
doRunNow = True
return 0
# --------------------------------------------------
# listen to jack2 master switch
def client_registration_callback(clientName, register, arg):
global doRunNow
if clientName == b"system" and register:
print("NOTICE: Possible JACK2 master switch")
global bufferSize, sampleRate
doRunNow = True
sampleRate = jacklib.get_sample_rate(client)
bufferSize = jacklib.get_buffer_size(client)
elif clientName in (b"alsa2jack", b"jack2alsa") and not register:
global doLoop, useZita
if doLoop and not doRunNow:
doLoop = False
print("NOTICE: %s have been stopped, quitting now..." % ("zita-a2j/j2a" if useZita else "alsa_in/out"))
# --------------------------------------------------
# listen to jack shutdown
def shutdown_callback(arg):
global doLoop
doLoop = False
# --------------------------------------------------
# run alsa_in and alsa_out
def run_alsa_bridge():
global bufferSize, sampleRate, channels
global procIn, procOut
global useZita
if procIn.state() != QProcess.NotRunning:
procIn.terminate()
procIn.waitForFinished(1000)
if procOut.state() != QProcess.NotRunning:
procOut.terminate()
procOut.waitForFinished(1000)
if useZita:
procIn.start("env", ["JACK_SAMPLE_RATE=%i" % sampleRate, "JACK_PERIOD_SIZE=%i" % bufferSize, "zita-a2j", "-L", "-j", "alsa2jack", "-d", "hw:Loopback,1,0"])
procOut.start("env", ["JACK_SAMPLE_RATE=%i" % sampleRate, "JACK_PERIOD_SIZE=%i" % bufferSize, "zita-j2a", "-L", "-j", "jack2alsa", "-d", "hw:Loopback,1,1"])
else:
procIn.start("env", ["JACK_SAMPLE_RATE=%i" % sampleRate, "JACK_PERIOD_SIZE=%i" % bufferSize, "alsa_in", "-j", "alsa2jack", "-d", "cloop", "-q", "1", "-c", "%i" % channels])
procOut.start("env", ["JACK_SAMPLE_RATE=%i" % sampleRate, "JACK_PERIOD_SIZE=%i" % bufferSize, "alsa_out", "-j", "jack2alsa", "-d", "ploop", "-q", "1", "-c", "%i" % channels])
if procIn.waitForStarted():
sleep(1)
jacklib.connect(client, "alsa2jack:capture_1", "system:playback_1")
jacklib.connect(client, "alsa2jack:capture_2", "system:playback_2")
if procOut.waitForStarted():
sleep(1)
jacklib.connect(client, "system:capture_1", "jack2alsa:playback_1")
jacklib.connect(client, "system:capture_2", "jack2alsa:playback_2")
#--------------- main ------------------
if __name__ == '__main__':
useZita = bool(len(sys.argv) == 2 and sys.argv[1] in ("-zita", "--zita"))
# TODO - check consistency, and check channels value
# Init JACK client
client = jacklib.client_open("cadence-aloop-daemon", jacklib.JackUseExactName, None)
if not client:
print("cadence-aloop-daemon is already running, delete \"/tmp/.cadence-aloop-daemon.x\" to close it")
quit()
if jacklib.JACK2:
jacklib.set_client_registration_callback(client, client_registration_callback, None)
jacklib.set_buffer_size_callback(client, buffer_size_callback, None)
jacklib.set_sample_rate_callback(client, sample_rate_callback, None)
jacklib.on_shutdown(client, shutdown_callback, None)
jacklib.activate(client)
# Quit when requested
signal(SIGINT, signal_handler)
signal(SIGTERM, signal_handler)
# Get initial values
sampleRate = jacklib.get_sample_rate(client)
bufferSize = jacklib.get_buffer_size(client)
# Create check file
if not os.path.exists(checkFile):
os.mknod(checkFile)
# Keep running until told otherwise
firstStart = True
while doLoop and os.path.exists(checkFile):
if doRunNow:
run_alsa_bridge()
doRunNow = False
if firstStart:
firstStart = False
print("cadence-aloop-daemon started, using %s" % ("zita-a2j/j2a" if useZita else "alsa_in/out"))
sleep(1)
# Close JACK client
jacklib.deactivate(client)
jacklib.client_close(client)
if os.path.exists(checkFile):
os.remove(checkFile)
if procIn.state() != QProcess.NotRunning:
procIn.terminate()
procIn.waitForFinished(1000)
if procOut.state() != QProcess.NotRunning:
procOut.terminate()
procOut.waitForFinished(1000)