@@ -42,3 +42,6 @@ src/dist/ | |||
# Other | |||
data/templates/energyXT.xt | |||
# IDEs | |||
.idea/ |
@@ -1,44 +1,48 @@ | |||
#!/bin/bash | |||
#! /usr/bin/env bash | |||
# Script to bridge/start pulseaudio into JACK mode | |||
INSTALL_PREFIX="X-PREFIX-X" | |||
PULSE_CONFIG_DIR=${PULSE_CONFIG_DIR:-"$HOME/.pulse"} | |||
JACK_CONNFILE="$PULSE_CONFIG_DIR/jack-connections" | |||
PA_CTLFILE="$PULSE_CONFIG_DIR/ctl.pa" | |||
# ---------------------------------------------- | |||
if [ ! -d ~/.pulse ]; then | |||
mkdir -p ~/.pulse | |||
if [ ! -d $PULSE_CONFIG_DIR ]; then | |||
mkdir -p $PULSE_CONFIG_DIR | |||
fi | |||
if [ ! -f ~/.pulse/client.conf ]; then | |||
echo "autospawn = no" > ~/.pulse/client.conf | |||
if [ ! -f $PULSE_CONFIG_DIR/client.conf ]; then | |||
echo "autospawn = no" > $PULSE_CONFIG_DIR/client.conf | |||
else | |||
if (! cat ~/.pulse/client.conf | grep "autospawn = no" > /dev/null); then | |||
sed -i '/autospawn =/d' ~/.pulse/client.conf | |||
echo "autospawn = no" >> ~/.pulse/client.conf | |||
if (! cat $PULSE_CONFIG_DIR/client.conf | grep "autospawn = no" > /dev/null); then | |||
sed -i '/autospawn =/d' $PULSE_CONFIG_DIR/client.conf | |||
echo "autospawn = no" >> $PULSE_CONFIG_DIR/client.conf | |||
fi | |||
fi | |||
if [ ! -f ~/.pulse/daemon.conf ]; then | |||
echo "default-sample-format = float32le" > ~/.pulse/daemon.conf | |||
echo "realtime-scheduling = yes" >> ~/.pulse/daemon.conf | |||
echo "rlimit-rttime = -1" >> ~/.pulse/daemon.conf | |||
echo "exit-idle-time = -1" >> ~/.pulse/daemon.conf | |||
if [ ! -f $PULSE_CONFIG_DIR/daemon.conf ]; then | |||
echo "default-sample-format = float32le" > $PULSE_CONFIG_DIR/daemon.conf | |||
echo "realtime-scheduling = yes" >> $PULSE_CONFIG_DIR/daemon.conf | |||
echo "rlimit-rttime = -1" >> $PULSE_CONFIG_DIR/daemon.conf | |||
echo "exit-idle-time = -1" >> $PULSE_CONFIG_DIR/daemon.conf | |||
else | |||
if (! cat ~/.pulse/daemon.conf | grep "default-sample-format = float32le" > /dev/null); then | |||
sed -i '/default-sample-format = /d' ~/.pulse/daemon.conf | |||
echo "default-sample-format = float32le" >> ~/.pulse/daemon.conf | |||
if (! cat $PULSE_CONFIG_DIR/daemon.conf | grep "default-sample-format = float32le" > /dev/null); then | |||
sed -i '/default-sample-format = /d' $PULSE_CONFIG_DIR/daemon.conf | |||
echo "default-sample-format = float32le" >> $PULSE_CONFIG_DIR/daemon.conf | |||
fi | |||
if (! cat ~/.pulse/daemon.conf | grep "realtime-scheduling = yes" > /dev/null); then | |||
sed -i '/realtime-scheduling = /d' ~/.pulse/daemon.conf | |||
echo "realtime-scheduling = yes" >> ~/.pulse/daemon.conf | |||
if (! cat $PULSE_CONFIG_DIR/daemon.conf | grep "realtime-scheduling = yes" > /dev/null); then | |||
sed -i '/realtime-scheduling = /d' $PULSE_CONFIG_DIR/daemon.conf | |||
echo "realtime-scheduling = yes" >> $PULSE_CONFIG_DIR/daemon.conf | |||
fi | |||
if (! cat ~/.pulse/daemon.conf | grep "rlimit-rttime = -1" > /dev/null); then | |||
sed -i '/rlimit-rttime =/d' ~/.pulse/daemon.conf | |||
echo "rlimit-rttime = -1" >> ~/.pulse/daemon.conf | |||
if (! cat $PULSE_CONFIG_DIR/daemon.conf | grep "rlimit-rttime = -1" > /dev/null); then | |||
sed -i '/rlimit-rttime =/d' $PULSE_CONFIG_DIR/daemon.conf | |||
echo "rlimit-rttime = -1" >> $PULSE_CONFIG_DIR/daemon.conf | |||
fi | |||
if (! cat ~/.pulse/daemon.conf | grep "exit-idle-time = -1" > /dev/null); then | |||
sed -i '/exit-idle-time =/d' ~/.pulse/daemon.conf | |||
echo "exit-idle-time = -1" >> ~/.pulse/daemon.conf | |||
if (! cat $PULSE_CONFIG_DIR/daemon.conf | grep "exit-idle-time = -1" > /dev/null); then | |||
sed -i '/exit-idle-time =/d' $PULSE_CONFIG_DIR/daemon.conf | |||
echo "exit-idle-time = -1" >> $PULSE_CONFIG_DIR/daemon.conf | |||
fi | |||
fi | |||
@@ -56,7 +60,7 @@ echo "usage: $0 [command] | |||
--dummy Don't do anything, just create the needed files | |||
NOTE: | |||
When runned with no arguments, pulse2jack will | |||
When ran with no arguments, pulse2jack will | |||
activate PulseAudio with both playback and record modes. | |||
" | |||
exit | |||
@@ -68,18 +72,56 @@ exit | |||
-p|--p|--play) | |||
PLAY_ONLY="yes" | |||
FILE=$INSTALL_PREFIX/share/cadence/pulse2jack/play.pa | |||
;; | |||
*) | |||
FILE=$INSTALL_PREFIX/share/cadence/pulse2jack/play+rec.pa | |||
;; | |||
esac | |||
TEMPLATE_PA_FILE=$INSTALL_PREFIX/share/cadence/pulse2jack/template.pa | |||
# ---------------------------------------------- | |||
IsPulseAudioRunning() | |||
{ | |||
addJackConnectionsToPAFile() { | |||
PAFILE=$1 | |||
OUTFILE=$2 | |||
cp $PAFILE $OUTFILE | |||
tac $JACK_CONNFILE | while IFS=\| read name type channels connect; do | |||
sed -i "/### Load Jack modules/a load-module module-jack-$type channels=$channels connect=$connect client_name=\"$name\"" $OUTFILE | |||
done | |||
} | |||
loadConnectionsIntoPA() { | |||
CONNTYPE=$1 | |||
while IFS=\| read name type channels connect; do | |||
if [ $CONNTYPE == "$type" ] ; then | |||
pactl load-module module-jack-$type channels=$channels connect=$connect client_name="$name" > /dev/null | |||
fi | |||
done < $JACK_CONNFILE | |||
} | |||
addDefaultSink() { | |||
INFILE=$1 | |||
sed -i "/### Make Jack default/a set-default-sink jack_out" $INFILE | |||
} | |||
addDefaultSource() { | |||
INFILE=$1 | |||
sed -i "/### Make Jack default/a set-default-source jack_in" $INFILE | |||
} | |||
if [ ! -f $PULSE_CONFIG_DIR/jack-connections ] ; then | |||
# safety in case there's no config generated yet from GUI | |||
sed "/### Load Jack modules/a load-module module-jack-sink | |||
/### Load Jack modules/a load-module module-jack-source" $TEMPLATE_PA_FILE > $PA_CTLFILE | |||
else | |||
addJackConnectionsToPAFile $TEMPLATE_PA_FILE $PA_CTLFILE | |||
fi | |||
addDefaultSource $PA_CTLFILE | |||
addDefaultSink $PA_CTLFILE | |||
IsPulseAudioRunning() { | |||
PROCESS=`ps -u $USER | grep pulseaudio` | |||
if [ "$PROCESS" == "" ]; then | |||
false | |||
@@ -89,39 +131,29 @@ IsPulseAudioRunning() | |||
} | |||
if (IsPulseAudioRunning); then | |||
{ | |||
if (`jack_lsp | grep "PulseAudio JACK Sink:" > /dev/null`); then | |||
{ | |||
# get the first sink name from the table | |||
FIRST_SINK_NAME=$(grep '|sink|' $JACK_CONNFILE | head -1 | cut -d\| -f1) | |||
if ($(jack_lsp 2>/dev/null | grep "$FIRST_SINK_NAME" > /dev/null)); then | |||
echo "PulseAudio is already running and bridged to JACK" | |||
} | |||
else | |||
{ | |||
echo "PulseAudio is already running, bridge it..." | |||
if [ "$PLAY_ONLY" == "yes" ]; then | |||
{ | |||
pactl load-module module-jack-sink > /dev/null | |||
loadConnectionsIntoPA "sink" | |||
pacmd set-default-source jack_in > /dev/null | |||
} | |||
else | |||
{ | |||
pactl load-module module-jack-sink > /dev/null | |||
pactl load-module module-jack-source > /dev/null | |||
loadConnectionsIntoPA "source" | |||
loadConnectionsIntoPA "sink" | |||
pacmd set-default-sink jack_out > /dev/null | |||
pacmd set-default-source jack_in > /dev/null | |||
} | |||
fi | |||
echo "Done" | |||
} | |||
fi | |||
} | |||
else | |||
{ | |||
if (`pulseaudio --daemonize --high-priority --realtime --exit-idle-time=-1 --file=$FILE -n`); then | |||
if ($(pulseaudio --daemonize --high-priority --realtime --exit-idle-time=-1 --file=$PA_CTLFILE -n)); then | |||
echo "Initiated PulseAudio successfully!" | |||
else | |||
echo "Failed to initialize PulseAudio!" | |||
fi | |||
} | |||
fi |
@@ -28,7 +28,6 @@ load-module module-stream-restore | |||
load-module module-card-restore | |||
### Load Jack modules | |||
load-module module-jack-sink | |||
### Load unix protocol | |||
load-module module-native-protocol-unix | |||
@@ -47,4 +46,4 @@ load-module module-rescue-streams | |||
load-module module-always-sink | |||
### Make Jack default | |||
set-default-sink jack_out | |||
@@ -0,0 +1,271 @@ | |||
#!/usr/bin/env python3 | |||
# -*- coding: utf-8 -*- | |||
# Custom QTableWidget that handles pulseaudio source and sinks | |||
# Copyright (C) 2011-2018 Filipe Coelho <falktx@falktx.com> | |||
# | |||
# This program is free software; you can redistribute it and/or modify | |||
# it under the terms of the GNU General Public License as published by | |||
# the Free Software Foundation; either version 2 of the License, or | |||
# any later version. | |||
# | |||
# This program is distributed in the hope that it will be useful, | |||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
# GNU General Public License for more details. | |||
# | |||
# For a full copy of the GNU General Public License see the COPYING file | |||
# --------------------------------------------------------------------- | |||
# Imports (Global) | |||
from collections import namedtuple | |||
from PyQt5.QtCore import Qt, QRegExp, pyqtSignal | |||
from PyQt5.QtGui import QRegExpValidator | |||
from PyQt5.QtWidgets import QTableWidget, QTableWidgetItem, QHeaderView, QComboBox, QLineEdit, QSpinBox, QPushButton, QCheckBox, QHBoxLayout, QWidget | |||
from shared import * | |||
from shared_cadence import GlobalSettings | |||
# Python3/4 function name normalisation | |||
try: | |||
range = xrange | |||
except NameError: | |||
pass | |||
PULSE_USER_CONFIG_DIR = os.getenv("PULSE_USER_CONFIG_DIR") | |||
if not PULSE_USER_CONFIG_DIR: | |||
PULSE_USER_CONFIG_DIR = os.path.join(HOME, ".pulse") | |||
if not os.path.exists(PULSE_USER_CONFIG_DIR): | |||
os.path.mkdir(PULSE_USER_CONFIG_DIR) | |||
# a data class to hold the Sink/Source Data. Use strings in tuple for easy map(_make) | |||
# but convert to type in table for editor | |||
SSData = namedtuple('SSData', 'name s_type channels connected') | |||
# --------------------------------------------------------------------- | |||
# Extend QTableWidget to hold Sink/Source data | |||
class BridgeSourceSink(QTableWidget): | |||
defaultPASourceData = SSData( | |||
name="PulseAudio JACK Source", | |||
s_type="source", | |||
channels="2", | |||
connected="True") | |||
defaultPASinkData = SSData( | |||
name="PulseAudio JACK Sink", | |||
s_type="sink", | |||
channels="2", | |||
connected="True") | |||
customChanged = pyqtSignal() | |||
def __init__(self, parent): | |||
QTableWidget.__init__(self, parent) | |||
self.bridgeData = [] | |||
if not GlobalSettings.contains("Pulse2JACK/PABridges"): | |||
self.initialise_settings() | |||
self.load_from_settings() | |||
def load_data_into_cells(self): | |||
self.setHorizontalHeaderLabels(['Name', 'Type', 'Channels', 'Conn?']) | |||
self.setRowCount(0) | |||
for data in self.bridgeData: | |||
row = self.rowCount() | |||
self.insertRow(row) | |||
# Name | |||
name_col = QLineEdit() | |||
name_col.setText(data.name) | |||
name_col.textChanged.connect(self.customChanged.emit) | |||
rx = QRegExp("[^|]+") | |||
validator = QRegExpValidator(rx, self) | |||
name_col.setValidator(validator) | |||
self.setCellWidget(row, 0, name_col) | |||
# Type | |||
combo_box = QComboBox() | |||
microphone_icon = QIcon.fromTheme('audio-input-microphone') | |||
if microphone_icon.isNull(): | |||
microphone_icon = QIcon.fromTheme('microphone') | |||
loudspeaker_icon = QIcon.fromTheme('audio-volume-high') | |||
if loudspeaker_icon.isNull(): | |||
loudspeaker_icon = QIcon.fromTheme('player-volume') | |||
combo_box.addItem(microphone_icon, "source") | |||
combo_box.addItem(loudspeaker_icon, "sink") | |||
combo_box.setCurrentIndex(0 if data.s_type == "source" else 1) | |||
combo_box.currentTextChanged.connect(self.customChanged.emit) | |||
self.setCellWidget(row, 1, combo_box) | |||
# Channels | |||
chan_col = QSpinBox() | |||
chan_col.setValue(int(data.channels)) | |||
chan_col.setMinimum(1) | |||
chan_col.setAlignment(Qt.AlignCenter) | |||
chan_col.valueChanged.connect(self.customChanged.emit) | |||
self.setCellWidget(row, 2, chan_col) | |||
# Auto connect? | |||
auto_cb = QCheckBox() | |||
auto_cb.setObjectName("auto_cb") | |||
auto_cb.setCheckState(Qt.Checked if data.connected in ['true', 'True', 'TRUE'] else Qt.Unchecked) | |||
auto_cb.stateChanged.connect(self.customChanged.emit) | |||
widget = QWidget() | |||
h_layout = QHBoxLayout(widget) | |||
h_layout.addWidget(auto_cb) | |||
h_layout.setAlignment(Qt.AlignCenter) | |||
h_layout.setContentsMargins(0, 0, 0, 0) | |||
widget.setLayout(h_layout) | |||
self.setCellWidget(row, 3, widget) | |||
self.horizontalHeader().setSectionResizeMode(QHeaderView.Fixed) | |||
def defaults(self): | |||
self.bridgeData = [self.defaultPASourceData, self.defaultPASinkData] | |||
self.load_data_into_cells() | |||
self.customChanged.emit() | |||
def undo(self): | |||
self.load_from_settings() | |||
self.load_data_into_cells() | |||
self.customChanged.emit() | |||
def initialise_settings(self): | |||
GlobalSettings.setValue( | |||
"Pulse2JACK/PABridges", | |||
self.encode_bridge_data([self.defaultPASourceData, self.defaultPASinkData])) | |||
def load_from_settings(self): | |||
bridgeDataText = GlobalSettings.value("Pulse2JACK/PABridges") | |||
self.bridgeData = self.decode_bridge_data(bridgeDataText) | |||
def hasChanges(self)->bool: | |||
bridgeDataText = GlobalSettings.value("Pulse2JACK/PABridges") | |||
saved_data = self.decode_bridge_data(bridgeDataText) | |||
if self.rowCount() != len(saved_data): | |||
return True | |||
for row in range(self.rowCount()): | |||
orig_data = saved_data[row] | |||
name = self.cellWidget(row, 0).text() | |||
if name != orig_data[0]: | |||
return True | |||
type = self.cellWidget(row, 1).currentText() | |||
if type != orig_data[1]: | |||
return True | |||
channels = self.cellWidget(row, 2).value() | |||
if channels != int(orig_data[2]): | |||
return True | |||
auto_cb = self.cellWidget(row, 3).findChild(QCheckBox, "auto_cb") | |||
connected = auto_cb.isChecked() | |||
if connected != bool(orig_data[3]): | |||
return True | |||
return False | |||
def hasValidValues(self)->bool: | |||
used_names = [] | |||
row_count = self.rowCount() | |||
# Prevent save without any bridge | |||
if not row_count: | |||
return False | |||
for row in range(row_count): | |||
line_edit = self.cellWidget(row, 0) | |||
name = line_edit.text() | |||
if not name or name in used_names: | |||
# prevent double name entries | |||
return False | |||
used_names.append(name) | |||
return True | |||
def add_row(self): | |||
# first, search in table which bridge exists | |||
# to add the most pertinent new bridge | |||
has_source = False | |||
has_sink = False | |||
for row in range(self.rowCount()): | |||
cell_widget = self.cellWidget(row, 1) | |||
group_type = "" | |||
if cell_widget: | |||
group_type = cell_widget.currentText() | |||
if group_type == "source": | |||
has_source = True | |||
elif group_type == "sink": | |||
has_sink = True | |||
if has_source and has_sink: | |||
break | |||
ss_data = SSData(name="", s_type="source", channels="2", connected="False") | |||
if not has_sink: | |||
ss_data = self.defaultPASinkData | |||
elif not has_source: | |||
ss_data = self.defaultPASourceData | |||
self.bridgeData.append(ss_data) | |||
self.load_data_into_cells() | |||
self.editItem(self.item(self.rowCount() - 1, 0)) | |||
self.customChanged.emit() | |||
def remove_row(self): | |||
del self.bridgeData[self.currentRow()] | |||
self.load_data_into_cells() | |||
self.customChanged.emit() | |||
def save_bridges(self): | |||
self.bridgeData = [] | |||
for row in range(0, self.rowCount()): | |||
new_name = self.cellWidget(row, 0).property("text") | |||
new_type = self.cellWidget(row, 1).currentText() | |||
new_channels = self.cellWidget(row, 2).value() | |||
auto_cb = self.cellWidget(row, 3).findChild(QCheckBox, "auto_cb") | |||
new_conn = auto_cb.checkState() == Qt.Checked | |||
self.bridgeData.append( | |||
SSData(name=new_name, | |||
s_type=new_type, | |||
channels=new_channels, | |||
connected=str(new_conn))) | |||
GlobalSettings.setValue("Pulse2JACK/PABridges", self.encode_bridge_data(self.bridgeData)) | |||
conn_file_path = os.path.join(PULSE_USER_CONFIG_DIR, "jack-connections") | |||
conn_file = open(conn_file_path, "w") | |||
conn_file.write("\n".join(self.encode_bridge_data(self.bridgeData))) | |||
# Need an extra line at the end | |||
conn_file.write("\n") | |||
conn_file.close() | |||
self.customChanged.emit() | |||
# encode and decode from tuple so it isn't stored in the settings file as a type, and thus the | |||
# configuration is backwards compatible with versions that don't understand SSData types. | |||
# Uses PIPE symbol as separator | |||
def encode_bridge_data(self, data): | |||
return list(map(lambda s: s.name + "|" + s.s_type + "|" + str(s.channels) + "|" + str(s.connected), data)) | |||
def decode_bridge_data(self, data): | |||
return list(map(lambda d: SSData._make(d.split("|")), data)) | |||
def resizeEvent(self, event): | |||
self.setColumnWidth(0, int(self.width() * 0.49)) | |||
self.setColumnWidth(1, int(self.width() * 0.17)) | |||
self.setColumnWidth(2, int(self.width() * 0.17)) | |||
self.setColumnWidth(3, int(self.width() * 0.17)) |
@@ -23,10 +23,10 @@ from platform import architecture | |||
if True: | |||
from PyQt5.QtCore import QFileSystemWatcher, QThread, QSemaphore | |||
from PyQt5.QtWidgets import QApplication, QDialogButtonBox, QLabel, QMainWindow, QSizePolicy | |||
from PyQt5.QtWidgets import QApplication, QDialogButtonBox, QLabel, QMainWindow #, QSizePolicy, QTableWidget, QTableWidgetItem, QHeaderView | |||
else: | |||
from PyQt4.QtCore import QFileSystemWatcher, QThread, QSemaphore | |||
from PyQt4.QtGui import QApplication, QDialogButtonBox, QLabel, QMainWindow, QSizePolicy | |||
from PyQt4.QtGui import QApplication, QDialogButtonBox, QLabel, QMainWindow # , QSizePolicy, QTableWidget, QTableWidgetItem, QHeaderView | |||
# ------------------------------------------------------------------------------------------------------------ | |||
# Imports (Custom Stuff) | |||
@@ -985,6 +985,8 @@ class CadenceMainW(QMainWindow, ui_cadence.Ui_CadenceMainW): | |||
if self.cb_app_browser.count() == 0: | |||
self.ch_app_browser.setEnabled(False) | |||
self.tableSinkSourceData.load_data_into_cells() | |||
mimeappsPath = os.path.join(HOME, ".local", "share", "applications", "mimeapps.list") | |||
if os.path.exists(mimeappsPath): | |||
@@ -1135,6 +1137,14 @@ class CadenceMainW(QMainWindow, ui_cadence.Ui_CadenceMainW): | |||
self.b_pulse_stop.clicked.connect(self.slot_PulseAudioBridgeStop) | |||
self.tb_pulse_options.clicked.connect(self.slot_PulseAudioBridgeOptions) | |||
self.b_bridge_add.clicked.connect(self.slot_PulseAudioBridgeAdd) | |||
self.b_bridge_remove.clicked.connect(self.slot_PulseAudioBridgeRemove) | |||
self.b_bridge_undo.clicked.connect(self.slot_PulseAudioBridgeUndo) | |||
self.b_bridge_save.clicked.connect(self.slot_PulseAudioBridgeSave) | |||
self.b_bridge_defaults.clicked.connect(self.slot_PulseAudioBridgeDefaults) | |||
self.tableSinkSourceData.customChanged.connect(self.slot_PulseAudioBridgeTableChanged) | |||
self.tableSinkSourceData.doubleClicked.connect(self.slot_PulseAudioBridgeTableChanged) | |||
self.pic_catia.clicked.connect(self.func_start_catia) | |||
self.pic_claudia.clicked.connect(self.func_start_claudia) | |||
self.pic_meter_in.clicked.connect(self.func_start_jackmeter_in) | |||
@@ -1229,11 +1239,13 @@ class CadenceMainW(QMainWindow, ui_cadence.Ui_CadenceMainW): | |||
except: | |||
version, groups, conns = (list(), list(), list()) | |||
pa_first_group_name = self.getFirstPulseAudioGroupName() | |||
for group_id, group_name, ports in groups: | |||
if group_name == "alsa2jack": | |||
global jackClientIdALSA | |||
jackClientIdALSA = group_id | |||
elif group_name == "PulseAudio JACK Sink": | |||
elif group_name in (pa_first_group_name, "PulseAudio JACK Sink"): | |||
global jackClientIdPulse | |||
jackClientIdPulse = group_id | |||
@@ -1408,6 +1420,14 @@ class CadenceMainW(QMainWindow, ui_cadence.Ui_CadenceMainW): | |||
self.systray.setActionEnabled("a2j_stop", False) | |||
self.label_bridge_a2j.setText(self.tr("ALSA MIDI Bridge is stopped")) | |||
def getFirstPulseAudioGroupName(self)->str: | |||
# search PulseAudio JACK first group in settings | |||
pa_bridges_settings = GlobalSettings.value("Pulse2JACK/PABridges", type=list) | |||
if pa_bridges_settings: | |||
return pa_bridges_settings[0].partition('|')[0] | |||
return "PulseAudio JACK Sink" | |||
def checkAlsaAudio(self): | |||
asoundrcFile = os.path.join(HOME, ".asoundrc") | |||
@@ -1617,11 +1637,13 @@ class CadenceMainW(QMainWindow, ui_cadence.Ui_CadenceMainW): | |||
@pyqtSlot(int, str) | |||
def slot_DBusJackClientAppearedCallback(self, group_id, group_name): | |||
pa_first_group_name = self.getFirstPulseAudioGroupName() | |||
if group_name == "alsa2jack": | |||
global jackClientIdALSA | |||
jackClientIdALSA = group_id | |||
self.checkAlsaAudio() | |||
elif group_name == "PulseAudio JACK Sink": | |||
elif group_name in ("PulseAudio JACK Sink", pa_first_group_name): | |||
global jackClientIdPulse | |||
jackClientIdPulse = group_id | |||
self.checkPulseAudio() | |||
@@ -1798,6 +1820,33 @@ class CadenceMainW(QMainWindow, ui_cadence.Ui_CadenceMainW): | |||
def slot_PulseAudioBridgeStop(self): | |||
os.system("pulseaudio -k") | |||
@pyqtSlot() | |||
def slot_PulseAudioBridgeTableChanged(self): | |||
has_changes = self.tableSinkSourceData.hasChanges() | |||
has_valid_values = self.tableSinkSourceData.hasValidValues() | |||
self.b_bridge_save.setEnabled(has_changes and has_valid_values) | |||
self.b_bridge_undo.setEnabled(has_changes) | |||
@pyqtSlot() | |||
def slot_PulseAudioBridgeAdd(self): | |||
self.tableSinkSourceData.add_row() | |||
@pyqtSlot() | |||
def slot_PulseAudioBridgeRemove(self): | |||
self.tableSinkSourceData.remove_row() | |||
@pyqtSlot() | |||
def slot_PulseAudioBridgeUndo(self): | |||
self.tableSinkSourceData.undo() | |||
@pyqtSlot() | |||
def slot_PulseAudioBridgeSave(self): | |||
self.tableSinkSourceData.save_bridges() | |||
@pyqtSlot() | |||
def slot_PulseAudioBridgeDefaults(self): | |||
self.tableSinkSourceData.defaults() | |||
@pyqtSlot() | |||
def slot_PulseAudioBridgeOptions(self): | |||
ToolBarPADialog(self).exec_() | |||
@@ -168,7 +168,7 @@ class ClaudiaLauncher(QWidget, ui_claudia_launcher.Ui_ClaudiaLauncherW): | |||
self.clearInfo_DAW() | |||
self.clearInfo_Host() | |||
self.clearInfo_Intrument() | |||
self.clearInfo_Instrument() | |||
self.clearInfo_Bristol() | |||
self.clearInfo_Plugin() | |||
self.clearInfo_Effect() | |||
@@ -547,7 +547,7 @@ class ClaudiaLauncher(QWidget, ui_claudia_launcher.Ui_ClaudiaLauncherW): | |||
self.frame_Host.setEnabled(False) | |||
self.showDoc_Host("", "") | |||
def clearInfo_Intrument(self): | |||
def clearInfo_Instrument(self): | |||
self.ico_app_ins.setPixmap(self.getIcon("start-here").pixmap(48, 48)) | |||
self.label_name_ins.setText("App Name") | |||
self.ico_builtin_fx_ins.setPixmap(self.getIconForYesNo(False).pixmap(16, 16)) | |||
@@ -983,7 +983,7 @@ class ClaudiaLauncher(QWidget, ui_claudia_launcher.Ui_ClaudiaLauncherW): | |||
Docs0 = Docs[0] if (os.path.exists(Docs[0].replace("file://", ""))) else "" | |||
self.showDoc_Instrument(Docs0, Docs[1]) | |||
else: | |||
self.clearInfo_Intrument() | |||
self.clearInfo_Instrument() | |||
self.callback_checkGUI(row >= 0) | |||