Browse Source

Cadence: Implement ALSA-MIDI Bridge

tags/v0.9.0
falkTX 13 years ago
parent
commit
7c1ebf643e
5 changed files with 272 additions and 54 deletions
  1. +4
    -1
      Makefile
  2. +101
    -35
      src/cadence.py
  3. +95
    -17
      src/ui/cadence.ui
  4. +71
    -0
      src/ui/cadence_tb_a2j.ui
  5. +1
    -1
      src/ui/cadence_tb_jack.ui

+ 4
- 1
Makefile View File

@@ -26,7 +26,7 @@ all: UI RES CPP

UI: cadence catarina catia claudia carla tools

cadence: src/ui_cadence.py src/ui_cadence_tb_jack.py src/ui_cadence_rwait.py
cadence: src/ui_cadence.py src/ui_cadence_tb_jack.py src/ui_cadence_tb_a2j.py src/ui_cadence_rwait.py

catarina: src/ui_catarina.py \
src/ui_catarina_addgroup.py src/ui_catarina_removegroup.py src/ui_catarina_renamegroup.py \
@@ -54,6 +54,9 @@ src/ui_cadence.py: src/ui/cadence.ui
src/ui_cadence_tb_jack.py: src/ui/cadence_tb_jack.ui
$(PYUIC) $< -o $@

src/ui_cadence_tb_a2j.py: src/ui/cadence_tb_a2j.ui
$(PYUIC) $< -o $@

src/ui_cadence_rwait.py: src/ui/cadence_rwait.ui
$(PYUIC) $< -o $@



+ 101
- 35
src/cadence.py View File

@@ -24,7 +24,7 @@ from subprocess import getoutput

# Imports (Custom Stuff)
import ui_cadence
import ui_cadence_tb_jack, ui_cadence_rwait
import ui_cadence_tb_jack, ui_cadence_tb_a2j, ui_cadence_rwait
import systray
from shared_cadence import *
from shared_jack import *
@@ -464,17 +464,18 @@ class ToolBarJackDialog(QDialog, ui_cadence_tb_jack.Ui_Dialog):
GlobalSettings.setValue("JACK/LadishStudioName", self.cb_studio_name.currentText())

# Additional A2J MIDI options
#class ToolBarA2JDialog(QDialog, ui_cadence_tb_a2j.Ui_Dialog):
#def __init__(self, parent=None):
#super(ToolBarA2JDialog, self).__init__(parent)
#self.setupUi(self)
class ToolBarA2JDialog(QDialog, ui_cadence_tb_a2j.Ui_Dialog):
def __init__(self, parent):
QDialog.__init__(self, parent)
self.setupUi(self)

#self.cb_export_hw.setChecked(GlobalSettings.value("A2J/ExportHW", True).toBool())
self.cb_export_hw.setChecked(GlobalSettings.value("A2J/ExportHW", True, type=bool))

#self.connect(self, SIGNAL("accepted()"), self.setOptions)
self.connect(self, SIGNAL("accepted()"), SLOT("slot_setOptions()"))

#def setOptions(self):
#GlobalSettings.setValue("A2J/ExportHW", self.cb_export_hw.isChecked())
@pyqtSlot()
def slot_setOptions(self):
GlobalSettings.setValue("A2J/ExportHW", self.cb_export_hw.isChecked())

# Additional Pulse-JACK options
#class ToolBarPADialog(QDialog, ui_cadence_tb_pa.Ui_Dialog):
@@ -496,7 +497,8 @@ class CadenceMainW(QMainWindow, ui_cadence.Ui_CadenceMainW):
self.setupUi(self)

# TODO - uninplemented
self.groupBox_bridges.setEnabled(False)
self.toolBox_alsaaudio.setEnabled(False)
self.toolBox_pulseaudio.setEnabled(False)

self.settings = QSettings("Cadence", "Cadence")
self.loadSettings(True)
@@ -741,10 +743,10 @@ class CadenceMainW(QMainWindow, ui_cadence.Ui_CadenceMainW):
self.systray.addAction("jack_stop", self.tr("Stop JACK"))
self.systray.addAction("jack_configure", self.tr("Configure JACK"))
self.systray.addSeparator("sep1")
#self.systray.addMenu("a2j", self.tr("A2J Bridge"))
#self.systray.addMenuAction("a2j", "a2j_start", self.tr("Start"))
#self.systray.addMenuAction("a2j", "a2j_stop", self.tr("Stop"))
#self.systray.addMenuAction("a2j", "a2j_export_hw", self.tr("Export Hardware Ports..."))
self.systray.addMenu("a2j", self.tr("ALSA MIDI Bridge"))
self.systray.addMenuAction("a2j", "a2j_start", self.tr("Start"))
self.systray.addMenuAction("a2j", "a2j_stop", self.tr("Stop"))
self.systray.addMenuAction("a2j", "a2j_export_hw", self.tr("Export Hardware Ports..."))
#self.systray.addMenu("pulse", self.tr("Pulse2JACK Bridge"))
#self.systray.addMenuAction("pulse", "pulse_start", self.tr("Start"))
#self.systray.addMenuAction("pulse", "pulse_stop", self.tr("Stop"))
@@ -763,17 +765,17 @@ class CadenceMainW(QMainWindow, ui_cadence.Ui_CadenceMainW):
self.systray.setActionIcon("jack_start", "media-playback-start")
self.systray.setActionIcon("jack_stop", "media-playback-stop")
self.systray.setActionIcon("jack_configure", "configure")
#self.systray.setActionIcon("a2j_start", "media-playback-start")
#self.systray.setActionIcon("a2j_stop", "media-playback-stop")
self.systray.setActionIcon("a2j_start", "media-playback-start")
self.systray.setActionIcon("a2j_stop", "media-playback-stop")
#self.systray.setActionIcon("pulse_start", "media-playback-start")
#self.systray.setActionIcon("pulse_stop", "media-playback-stop")

self.systray.connect("jack_start", self.slot_JackServerStart)
self.systray.connect("jack_stop", self.slot_JackServerStop)
self.systray.connect("jack_configure", self.slot_JackServerConfigure)
#self.systray.connect("a2j_start", self.A2JBridgeStart)
#self.systray.connect("a2j_stop", self.A2JBridgeStop)
#self.systray.connect("a2j_export_hw", self.A2JBridgeExportHW)
self.systray.connect("a2j_start", self.slot_A2JBridgeStart)
self.systray.connect("a2j_stop", self.slot_A2JBridgeStop)
self.systray.connect("a2j_export_hw", self.slot_A2JBridgeExportHW)
#self.systray.connect("pulse_start", self.PABridgeStart)
#self.systray.connect("pulse_stop", self.PABridgeStop)
self.systray.connect("app_catarina", lambda tool="catarina": self.func_start_tool(tool))
@@ -797,6 +799,11 @@ class CadenceMainW(QMainWindow, ui_cadence.Ui_CadenceMainW):
self.connect(self.b_jack_configure, SIGNAL("clicked()"), SLOT("slot_JackServerConfigure()"))
self.connect(self.tb_jack_options, SIGNAL("clicked()"), SLOT("slot_JackOptions()"))

self.connect(self.b_a2j_start, SIGNAL("clicked()"), SLOT("slot_A2JBridgeStart()"))
self.connect(self.b_a2j_stop, SIGNAL("clicked()"), SLOT("slot_A2JBridgeStop()"))
self.connect(self.b_a2j_export_hw, SIGNAL("clicked()"), SLOT("slot_A2JBridgeExportHW()"))
self.connect(self.tb_a2j_options, SIGNAL("clicked()"), SLOT("slot_A2JBridgeOptions()"))

self.connect(self.pic_catia, SIGNAL("clicked()"), lambda tool="catia": self.func_start_tool(tool))
self.connect(self.pic_claudia, SIGNAL("clicked()"), lambda tool="claudia": self.func_start_tool(tool))
self.connect(self.pic_carla, SIGNAL("clicked()"), lambda tool="carla": self.func_start_tool(tool))
@@ -889,6 +896,17 @@ class CadenceMainW(QMainWindow, ui_cadence.Ui_CadenceMainW):
self.systray.setActionEnabled("jack_stop", False)
self.systray.setActionEnabled("jack_configure", False)

if DBus.a2j:
if DBus.a2j.is_started():
self.a2jStarted()
else:
self.a2jStopped()
else:
self.toolBox_alsamidi.setEnabled(False)
self.cb_a2j_autostart.setChecked(False)
self.label_bridge_a2j.setText("ALSA MIDI Bridge is not installed")
self.settings.setValue("A2J/AutoStart", False)

self.updateSystrayTooltip()

def DBusSignalReceiver(self, *args, **kwds):
@@ -897,10 +915,10 @@ class CadenceMainW(QMainWindow, ui_cadence.Ui_CadenceMainW):

if not newId:
# Something crashed
if appInterface == "org.gna.home.a2jmidid":
QTimer.singleShot(0, self, SLOT("slot_handleCrash_a2j()"))
elif appInterface == "org.jackaudio.service":
if appInterface == "org.jackaudio.service":
QTimer.singleShot(0, self, SLOT("slot_handleCrash_jack()"))
elif appInterface == "org.gna.home.a2jmidid":
QTimer.singleShot(0, self, SLOT("slot_handleCrash_a2j()"))

elif kwds['interface'] == "org.jackaudio.JackControl":
if DEBUG: print("org.jackaudio.JackControl", kwds['member'])
@@ -908,11 +926,12 @@ class CadenceMainW(QMainWindow, ui_cadence.Ui_CadenceMainW):
self.jackStarted()
elif kwds['member'] == "ServerStopped":
self.jackStopped()
#elif kwds['interface'] == "org.gna.home.a2jmidid.control":
#if kwds['member'] == "bridge_started":
#self.a2jStarted()
#elif kwds['member'] == "bridge_stopped":
#self.a2jStopped()
elif kwds['interface'] == "org.gna.home.a2jmidid.control":
if DEBUG: print("org.gna.home.a2jmidid.control", kwds['member'])
if kwds['member'] == "bridge_started":
self.a2jStarted()
elif kwds['member'] == "bridge_stopped":
self.a2jStopped()

def jackStarted(self):
self.m_last_dsp_load = DBus.jack.GetLoad()
@@ -942,6 +961,10 @@ class CadenceMainW(QMainWindow, ui_cadence.Ui_CadenceMainW):

self.m_timer500 = self.startTimer(500)

if DBus.a2j and not DBus.a2j.is_started():
self.b_a2j_start.setEnabled(True)
self.systray.setActionEnabled("a2j_start", True)

def jackStopped(self):
if self.m_timer500:
self.killTimer(self.m_timer500)
@@ -965,6 +988,28 @@ class CadenceMainW(QMainWindow, ui_cadence.Ui_CadenceMainW):
self.label_jack_srate.setText("---")
self.label_jack_latency.setText("---")

if DBus.a2j:
self.b_a2j_start.setEnabled(False)
self.systray.setActionEnabled("a2j_start", False)

def a2jStarted(self):
self.label_bridge_a2j.setText(self.tr("ALSA MIDI Bridge is running"))
self.b_a2j_start.setEnabled(False)
self.b_a2j_stop.setEnabled(True)
self.b_a2j_export_hw.setEnabled(False)
self.systray.setActionEnabled("a2j_start", False)
self.systray.setActionEnabled("a2j_stop", True)
self.systray.setActionEnabled("a2j_export_hw", False)

def a2jStopped(self):
self.label_bridge_a2j.setText(self.tr("ALSA MIDI Bridge is stopped"))
self.b_a2j_start.setEnabled(True)
self.b_a2j_stop.setEnabled(False)
self.b_a2j_export_hw.setEnabled(True)
self.systray.setActionEnabled("a2j_start", True)
self.systray.setActionEnabled("a2j_stop", False)
self.systray.setActionEnabled("a2j_export_hw", True)

def setAppDetails(self, desktop):
appContents = getDesktopFileContents(desktop)
name = getXdgProperty(appContents, "Name")
@@ -1023,8 +1068,8 @@ class CadenceMainW(QMainWindow, ui_cadence.Ui_CadenceMainW):
def slot_JackServerForceRestart(self):
if DBus.jack.IsStarted():
ask = CustomMessageBox(self, QMessageBox.Warning, self.tr("Warning"),
self.tr("This will force kill all JACK applications!<br>Make sure to save your projects before continue."),
self.tr("Are you sure you want to force the restart of JACK?"))
self.tr("This will force kill all JACK applications!<br>Make sure to save your projects before continue."),
self.tr("Are you sure you want to force the restart of JACK?"))

if ask != QMessageBox.Yes:
return
@@ -1051,13 +1096,34 @@ class CadenceMainW(QMainWindow, ui_cadence.Ui_CadenceMainW):
DBus.jack.ResetXruns()

@pyqtSlot()
def slot_handleCrash_a2j(self):
pass
def slot_A2JBridgeStart(self):
DBus.a2j.start()

@pyqtSlot()
def slot_A2JBridgeStop(self):
DBus.a2j.stop()

@pyqtSlot()
def slot_A2JBridgeExportHW(self):
ask = QMessageBox.question(self, self.tr("ALSA MIDI Hardware Export"), self.tr("Enable Hardware Export on the ALSA MIDI Bridge?"), QMessageBox.Yes|QMessageBox.No|QMessageBox.Cancel, QMessageBox.Yes)

if ask == QMessageBox.Yes:
DBus.a2j.set_hw_export(True)
elif ask == QMessageBox.No:
DBus.a2j.set_hw_export(False)

@pyqtSlot()
def slot_A2JBridgeOptions(self):
ToolBarA2JDialog(self).exec_()

@pyqtSlot()
def slot_handleCrash_jack(self):
self.DBusReconnect()

@pyqtSlot()
def slot_handleCrash_a2j(self):
pass

@pyqtSlot()
def slot_tweaksApply(self):
if "plugins" in self.settings_changed_types:
@@ -1500,8 +1566,8 @@ class CadenceMainW(QMainWindow, ui_cadence.Ui_CadenceMainW):
self.settings.setValue("Geometry", self.saveGeometry())

GlobalSettings.setValue("JACK/AutoStart", self.cb_jack_autostart.isChecked())
#GlobalSettings.setValue("A2J-MIDI/AutoStart", self.cb_a2jmidi_autostart.isChecked())
#GlobalSettings.setValue("Pulse2JACK/AutoStart", (havePulseAudio and self.cb_pulse_autostart.isChecked()))
GlobalSettings.setValue("A2J-MIDI/AutoStart", self.cb_a2j_autostart.isChecked())
GlobalSettings.setValue("Pulse2JACK/AutoStart", (havePulseAudio and self.cb_pulse_autostart.isChecked()))

def loadSettings(self, geometry):
if geometry:
@@ -1513,8 +1579,8 @@ class CadenceMainW(QMainWindow, ui_cadence.Ui_CadenceMainW):
}

self.cb_jack_autostart.setChecked(GlobalSettings.value("JACK/AutoStart", True, type=bool))
#self.cb_a2j_autostart.setChecked(GlobalSettings.value("A2J/AutoStart", True).toBool())
#self.cb_pulse_autostart.setChecked(GlobalSettings.value("Pulse2JACK/AutoStart", havePulseAudio).toBool())
self.cb_a2j_autostart.setChecked(GlobalSettings.value("A2J/AutoStart", True, type=bool))
self.cb_pulse_autostart.setChecked(GlobalSettings.value("Pulse2JACK/AutoStart", havePulseAudio, type=bool))

def timerEvent(self, event):
if event.timerId() == self.m_timer500:


+ 95
- 17
src/ui/cadence.ui View File

@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>753</width>
<height>581</height>
<height>579</height>
</rect>
</property>
<property name="windowTitle">
@@ -472,6 +472,9 @@
<string>JACK Bridges</string>
</property>
<layout class="QGridLayout" name="gridLayout_5">
<property name="margin">
<number>2</number>
</property>
<item row="0" column="0">
<widget class="QToolBox" name="toolBox_2">
<widget class="QWidget" name="toolBox_alsaaudio">
@@ -479,16 +482,28 @@
<rect>
<x>0</x>
<y>0</y>
<width>343</width>
<height>108</height>
<width>351</width>
<height>114</height>
</rect>
</property>
<attribute name="label">
<string>ALSA Audio</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_18">
<property name="leftMargin">
<number>2</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>2</number>
</property>
<property name="bottomMargin">
<number>2</number>
</property>
<item>
<widget class="QLabel" name="label_3">
<widget class="QLabel" name="label_bridge_alsa">
<property name="text">
<string>No bridge in use</string>
</property>
@@ -592,6 +607,19 @@
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_14">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="toolBox_alsamidi">
@@ -599,18 +627,30 @@
<rect>
<x>0</x>
<y>0</y>
<width>298</width>
<height>81</height>
<width>351</width>
<height>114</height>
</rect>
</property>
<attribute name="label">
<string>ALSA MIDI</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_20">
<property name="leftMargin">
<number>2</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>2</number>
</property>
<property name="bottomMargin">
<number>2</number>
</property>
<item>
<widget class="QLabel" name="label_4">
<widget class="QLabel" name="label_bridge_a2j">
<property name="text">
<string>A2J state</string>
<string>ALSA MIDI State</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
@@ -636,21 +676,21 @@
</spacer>
</item>
<item>
<widget class="QPushButton" name="pushButton_5">
<widget class="QPushButton" name="b_a2j_start">
<property name="text">
<string>Start</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_6">
<widget class="QPushButton" name="b_a2j_stop">
<property name="text">
<string>Stop</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton">
<widget class="QPushButton" name="b_a2j_export_hw">
<property name="text">
<string>Export HW...</string>
</property>
@@ -690,14 +730,14 @@
</spacer>
</item>
<item>
<widget class="QCheckBox" name="checkBox">
<widget class="QCheckBox" name="cb_a2j_autostart">
<property name="text">
<string>Auto-start at login</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="toolButton_3">
<widget class="QToolButton" name="tb_a2j_options">
<property name="text">
<string>...</string>
</property>
@@ -705,6 +745,19 @@
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_12">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="toolBox_pulseaudio">
@@ -712,16 +765,28 @@
<rect>
<x>0</x>
<y>0</y>
<width>212</width>
<height>81</height>
<width>351</width>
<height>114</height>
</rect>
</property>
<attribute name="label">
<string>PulseAudio</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_19">
<property name="leftMargin">
<number>2</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>2</number>
</property>
<property name="bottomMargin">
<number>2</number>
</property>
<item>
<widget class="QLabel" name="label_5">
<widget class="QLabel" name="label_bridge_pulse">
<property name="text">
<string>PulseAudio state</string>
</property>
@@ -796,7 +861,7 @@
</spacer>
</item>
<item>
<widget class="QCheckBox" name="checkBox_2">
<widget class="QCheckBox" name="cb_pulse_autostart">
<property name="text">
<string>Auto-start at login</string>
</property>
@@ -811,6 +876,19 @@
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_13">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>


+ 71
- 0
src/ui/cadence_tb_a2j.ui View File

@@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Dialog</class>
<widget class="QDialog" name="Dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>319</width>
<height>68</height>
</rect>
</property>
<property name="windowTitle">
<string>A2J MIDI Options</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QCheckBox" name="cb_export_hw">
<property name="text">
<string>Export Hardware ports before starting</string>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>Dialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>Dialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

+ 1
- 1
src/ui/cadence_tb_jack.ui View File

@@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>389</width>
<width>390</width>
<height>118</height>
</rect>
</property>


Loading…
Cancel
Save